mirror of
https://github.com/ipxe/ipxe
synced 2025-12-15 00:12:19 +03:00
[base16] Generalise base16_decode() to hex_decode()
Provide a generic hex_decode() routine which can be shared between the Base16 code and the "hex" and "hexhyp" settings parsers. Signed-off-by: Michael Brown <mcb30@ipxe.org>
This commit is contained in:
@@ -60,6 +60,48 @@ void base16_encode ( const uint8_t *raw, size_t len, char *encoded ) {
|
|||||||
assert ( strlen ( encoded ) == base16_encoded_len ( len ) );
|
assert ( strlen ( encoded ) == base16_encoded_len ( len ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decode hexadecimal string
|
||||||
|
*
|
||||||
|
* @v encoded Encoded string
|
||||||
|
* @v separator Byte separator character, or 0 for no separator
|
||||||
|
* @v data Buffer
|
||||||
|
* @v len Length of buffer
|
||||||
|
* @ret len Length of data, or negative error
|
||||||
|
*/
|
||||||
|
int hex_decode ( const char *encoded, char separator, void *data, size_t len ) {
|
||||||
|
uint8_t *out = data;
|
||||||
|
unsigned int count = 0;
|
||||||
|
unsigned int sixteens;
|
||||||
|
unsigned int units;
|
||||||
|
|
||||||
|
while ( *encoded ) {
|
||||||
|
|
||||||
|
/* Check separator, if applicable */
|
||||||
|
if ( count && separator && ( ( *(encoded++) != separator ) ) )
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
/* Extract digits. Note that either digit may be NUL,
|
||||||
|
* which would be interpreted as an invalid value by
|
||||||
|
* strtoul_charval(); there is therefore no need for an
|
||||||
|
* explicit end-of-string check.
|
||||||
|
*/
|
||||||
|
sixteens = strtoul_charval ( *(encoded++) );
|
||||||
|
if ( sixteens >= 16 )
|
||||||
|
return -EINVAL;
|
||||||
|
units = strtoul_charval ( *(encoded++) );
|
||||||
|
if ( units >= 16 )
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
/* Store result */
|
||||||
|
if ( count < len )
|
||||||
|
out[count] = ( ( sixteens << 4 ) | units );
|
||||||
|
count++;
|
||||||
|
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base16-decode data
|
* Base16-decode data
|
||||||
*
|
*
|
||||||
@@ -75,33 +117,15 @@ void base16_encode ( const uint8_t *raw, size_t len, char *encoded ) {
|
|||||||
* to provide a buffer of the correct size.
|
* to provide a buffer of the correct size.
|
||||||
*/
|
*/
|
||||||
int base16_decode ( const char *encoded, uint8_t *raw ) {
|
int base16_decode ( const char *encoded, uint8_t *raw ) {
|
||||||
const char *encoded_bytes = encoded;
|
int len;
|
||||||
uint8_t *raw_bytes = raw;
|
|
||||||
char buf[3];
|
|
||||||
char *endp;
|
|
||||||
size_t len;
|
|
||||||
|
|
||||||
while ( encoded_bytes[0] ) {
|
len = hex_decode ( encoded, 0, raw, -1UL );
|
||||||
if ( ! encoded_bytes[1] ) {
|
if ( len < 0 )
|
||||||
DBG ( "Base16-encoded string \"%s\" has invalid "
|
return len;
|
||||||
"length\n", encoded );
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
memcpy ( buf, encoded_bytes, 2 );
|
|
||||||
buf[2] = '\0';
|
|
||||||
*(raw_bytes++) = strtoul ( buf, &endp, 16 );
|
|
||||||
if ( *endp != '\0' ) {
|
|
||||||
DBG ( "Base16-encoded string \"%s\" has invalid "
|
|
||||||
"byte \"%s\"\n", encoded, buf );
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
encoded_bytes += 2;
|
|
||||||
}
|
|
||||||
len = ( raw_bytes - raw );
|
|
||||||
|
|
||||||
DBG ( "Base16-decoded \"%s\" to:\n", encoded );
|
DBG ( "Base16-decoded \"%s\" to:\n", encoded );
|
||||||
DBG_HDA ( 0, raw, len );
|
DBG_HDA ( 0, raw, len );
|
||||||
assert ( len <= base16_decoded_max_len ( encoded ) );
|
assert ( len <= base16_decoded_max_len ( encoded ) );
|
||||||
|
|
||||||
return ( len );
|
return len;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,6 +33,19 @@ int inet_aton ( const char *cp, struct in_addr *inp ) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned int strtoul_charval ( unsigned int charval ) {
|
||||||
|
|
||||||
|
if ( charval >= 'a' ) {
|
||||||
|
charval = ( charval - 'a' + 10 );
|
||||||
|
} else if ( charval >= 'A' ) {
|
||||||
|
charval = ( charval - 'A' + 10 );
|
||||||
|
} else if ( charval <= '9' ) {
|
||||||
|
charval = ( charval - '0' );
|
||||||
|
}
|
||||||
|
|
||||||
|
return charval;
|
||||||
|
}
|
||||||
|
|
||||||
unsigned long strtoul ( const char *p, char **endp, int base ) {
|
unsigned long strtoul ( const char *p, char **endp, int base ) {
|
||||||
unsigned long ret = 0;
|
unsigned long ret = 0;
|
||||||
int negative = 0;
|
int negative = 0;
|
||||||
|
|||||||
@@ -33,6 +33,8 @@ static inline size_t base16_decoded_max_len ( const char *encoded ) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
extern void base16_encode ( const uint8_t *raw, size_t len, char *encoded );
|
extern void base16_encode ( const uint8_t *raw, size_t len, char *encoded );
|
||||||
|
extern int hex_decode ( const char *string, char separator, void *data,
|
||||||
|
size_t len );
|
||||||
extern int base16_decode ( const char *encoded, uint8_t *raw );
|
extern int base16_decode ( const char *encoded, uint8_t *raw );
|
||||||
|
|
||||||
#endif /* _IPXE_BASE16_H */
|
#endif /* _IPXE_BASE16_H */
|
||||||
|
|||||||
@@ -34,19 +34,7 @@ static inline int strtoul_base ( const char **pp, int base )
|
|||||||
return base;
|
return base;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline unsigned int strtoul_charval ( unsigned int charval )
|
extern unsigned int strtoul_charval ( unsigned int charval );
|
||||||
{
|
|
||||||
if ( charval >= 'a' ) {
|
|
||||||
charval = ( charval - 'a' + 10 );
|
|
||||||
} else if ( charval >= 'A' ) {
|
|
||||||
charval = ( charval - 'A' + 10 );
|
|
||||||
} else if ( charval <= '9' ) {
|
|
||||||
charval = ( charval - '0' );
|
|
||||||
}
|
|
||||||
|
|
||||||
return charval;
|
|
||||||
}
|
|
||||||
|
|
||||||
extern unsigned long strtoul ( const char *p, char **endp, int base );
|
extern unsigned long strtoul ( const char *p, char **endp, int base );
|
||||||
extern unsigned long long strtoull ( const char *p, char **endp, int base );
|
extern unsigned long long strtoull ( const char *p, char **endp, int base );
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user