Ver código fonte

[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>
tags/v1.20.1
Michael Brown 11 anos atrás
pai
commit
076f58c4bf
4 arquivos alterados com 64 adições e 37 exclusões
  1. 48
    24
      src/core/base16.c
  2. 13
    0
      src/core/misc.c
  3. 2
    0
      src/include/ipxe/base16.h
  4. 1
    13
      src/include/stdlib.h

+ 48
- 24
src/core/base16.c Ver arquivo

@@ -60,6 +60,48 @@ void base16_encode ( const uint8_t *raw, size_t len, char *encoded ) {
60 60
 	assert ( strlen ( encoded ) == base16_encoded_len ( len ) );
61 61
 }
62 62
 
63
+/**
64
+ * Decode hexadecimal string
65
+ *
66
+ * @v encoded		Encoded string
67
+ * @v separator		Byte separator character, or 0 for no separator
68
+ * @v data		Buffer
69
+ * @v len		Length of buffer
70
+ * @ret len		Length of data, or negative error
71
+ */
72
+int hex_decode ( const char *encoded, char separator, void *data, size_t len ) {
73
+	uint8_t *out = data;
74
+	unsigned int count = 0;
75
+	unsigned int sixteens;
76
+	unsigned int units;
77
+
78
+	while ( *encoded ) {
79
+
80
+		/* Check separator, if applicable */
81
+		if ( count && separator && ( ( *(encoded++) != separator ) ) )
82
+			return -EINVAL;
83
+
84
+		/* Extract digits.  Note that either digit may be NUL,
85
+		 * which would be interpreted as an invalid value by
86
+		 * strtoul_charval(); there is therefore no need for an
87
+		 * explicit end-of-string check.
88
+		 */
89
+		sixteens = strtoul_charval ( *(encoded++) );
90
+		if ( sixteens >= 16 )
91
+			return -EINVAL;
92
+		units = strtoul_charval ( *(encoded++) );
93
+		if ( units >= 16 )
94
+			return -EINVAL;
95
+
96
+		/* Store result */
97
+		if ( count < len )
98
+			out[count] = ( ( sixteens << 4 ) | units );
99
+		count++;
100
+
101
+	}
102
+	return count;
103
+}
104
+
63 105
 /**
64 106
  * Base16-decode data
65 107
  *
@@ -75,33 +117,15 @@ void base16_encode ( const uint8_t *raw, size_t len, char *encoded ) {
75 117
  * to provide a buffer of the correct size.
76 118
  */
77 119
 int base16_decode ( const char *encoded, uint8_t *raw ) {
78
-	const char *encoded_bytes = encoded;
79
-	uint8_t *raw_bytes = raw;
80
-	char buf[3];
81
-	char *endp;
82
-	size_t len;
83
-
84
-	while ( encoded_bytes[0] ) {
85
-		if ( ! encoded_bytes[1] ) {
86
-			DBG ( "Base16-encoded string \"%s\" has invalid "
87
-			      "length\n", encoded );
88
-			return -EINVAL;
89
-		}
90
-		memcpy ( buf, encoded_bytes, 2 );
91
-		buf[2] = '\0';
92
-		*(raw_bytes++) = strtoul ( buf, &endp, 16 );
93
-		if ( *endp != '\0' ) {
94
-			DBG ( "Base16-encoded string \"%s\" has invalid "
95
-			      "byte \"%s\"\n", encoded, buf );
96
-			return -EINVAL;
97
-		}
98
-		encoded_bytes += 2;
99
-	}
100
-	len = ( raw_bytes - raw );
120
+	int len;
121
+
122
+	len = hex_decode ( encoded, 0, raw, -1UL );
123
+	if ( len < 0 )
124
+		return len;
101 125
 
102 126
 	DBG ( "Base16-decoded \"%s\" to:\n", encoded );
103 127
 	DBG_HDA ( 0, raw, len );
104 128
 	assert ( len <= base16_decoded_max_len ( encoded ) );
105 129
 
106
-	return ( len );
130
+	return len;
107 131
 }

+ 13
- 0
src/core/misc.c Ver arquivo

@@ -33,6 +33,19 @@ int inet_aton ( const char *cp, struct in_addr *inp ) {
33 33
 	return 0;
34 34
 }
35 35
 
36
+unsigned int strtoul_charval ( unsigned int charval ) {
37
+
38
+	if ( charval >= 'a' ) {
39
+		charval = ( charval - 'a' + 10 );
40
+	} else if ( charval >= 'A' ) {
41
+		charval = ( charval - 'A' + 10 );
42
+	} else if ( charval <= '9' ) {
43
+		charval = ( charval - '0' );
44
+	}
45
+
46
+	return charval;
47
+}
48
+
36 49
 unsigned long strtoul ( const char *p, char **endp, int base ) {
37 50
 	unsigned long ret = 0;
38 51
 	int negative = 0;

+ 2
- 0
src/include/ipxe/base16.h Ver arquivo

@@ -33,6 +33,8 @@ static inline size_t base16_decoded_max_len ( const char *encoded ) {
33 33
 }
34 34
 
35 35
 extern void base16_encode ( const uint8_t *raw, size_t len, char *encoded );
36
+extern int hex_decode ( const char *string, char separator, void *data,
37
+			size_t len );
36 38
 extern int base16_decode ( const char *encoded, uint8_t *raw );
37 39
 
38 40
 #endif /* _IPXE_BASE16_H */

+ 1
- 13
src/include/stdlib.h Ver arquivo

@@ -34,19 +34,7 @@ static inline int strtoul_base ( const char **pp, int base )
34 34
 	return base;
35 35
 }
36 36
 
37
-static inline unsigned int strtoul_charval ( unsigned int charval )
38
-{
39
-	if ( charval >= 'a' ) {
40
-		charval = ( charval - 'a' + 10 );
41
-	} else if ( charval >= 'A' ) {
42
-		charval = ( charval - 'A' + 10 );
43
-	} else if ( charval <= '9' ) {
44
-		charval = ( charval - '0' );
45
-	}
46
-
47
-	return charval;
48
-}
49
-
37
+extern unsigned int strtoul_charval ( unsigned int charval );
50 38
 extern unsigned long strtoul ( const char *p, char **endp, int base );
51 39
 extern unsigned long long strtoull ( const char *p, char **endp, int base );
52 40
 

Carregando…
Cancelar
Salvar