mirror of https://github.com/ipxe/ipxe.git
[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>pull/13/head
parent
362a628e52
commit
076f58c4bf
|
@ -60,6 +60,48 @@ void base16_encode ( const uint8_t *raw, size_t len, char *encoded ) {
|
|||
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
|
||||
*
|
||||
|
@ -75,33 +117,15 @@ void base16_encode ( const uint8_t *raw, size_t len, char *encoded ) {
|
|||
* to provide a buffer of the correct size.
|
||||
*/
|
||||
int base16_decode ( const char *encoded, uint8_t *raw ) {
|
||||
const char *encoded_bytes = encoded;
|
||||
uint8_t *raw_bytes = raw;
|
||||
char buf[3];
|
||||
char *endp;
|
||||
size_t len;
|
||||
int len;
|
||||
|
||||
while ( encoded_bytes[0] ) {
|
||||
if ( ! encoded_bytes[1] ) {
|
||||
DBG ( "Base16-encoded string \"%s\" has invalid "
|
||||
"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 );
|
||||
len = hex_decode ( encoded, 0, raw, -1UL );
|
||||
if ( len < 0 )
|
||||
return len;
|
||||
|
||||
DBG ( "Base16-decoded \"%s\" to:\n", encoded );
|
||||
DBG_HDA ( 0, raw, len );
|
||||
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;
|
||||
}
|
||||
|
||||
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 ret = 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 int hex_decode ( const char *string, char separator, void *data,
|
||||
size_t len );
|
||||
extern int base16_decode ( const char *encoded, uint8_t *raw );
|
||||
|
||||
#endif /* _IPXE_BASE16_H */
|
||||
|
|
|
@ -34,19 +34,7 @@ static inline int strtoul_base ( const char **pp, int base )
|
|||
return base;
|
||||
}
|
||||
|
||||
static inline 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 int strtoul_charval ( unsigned int charval );
|
||||
extern unsigned long strtoul ( const char *p, char **endp, int base );
|
||||
extern unsigned long long strtoull ( const char *p, char **endp, int base );
|
||||
|
||||
|
|
Loading…
Reference in New Issue