lib: unify conversions to/from hex

Curl_hexbyte - output a byte as a two-digit ASCII hex number

Curl_hexval - convert an ASCII hex digit to its binary value

... instead of duplicating similar code and hexdigit strings in numerous
places.

Closes #16888
This commit is contained in:
Daniel Stenberg 2025-03-31 23:12:09 +02:00
parent 1d84d683bb
commit 0c6e63a1be
No known key found for this signature in database
GPG key ID: 5CC908FDB71E12C2
8 changed files with 69 additions and 71 deletions

View file

@ -35,6 +35,8 @@ struct Curl_easy;
#include "warnless.h"
#include "escape.h"
#include "strdup.h"
#include "strparse.h"
/* The last 3 #include files should be in this order */
#include "curl_printf.h"
#include "curl_memory.h"
@ -82,10 +84,8 @@ char *curl_easy_escape(CURL *data, const char *string,
}
else {
/* encode it */
const char hex[] = "0123456789ABCDEF";
char out[3]={'%'};
out[1] = hex[in >> 4];
out[2] = hex[in & 0xf];
unsigned char out[3]={'%'};
Curl_hexbyte(&out[1], in, FALSE);
if(Curl_dyn_addn(&d, out, 3))
return NULL;
}
@ -94,16 +94,6 @@ char *curl_easy_escape(CURL *data, const char *string,
return Curl_dyn_ptr(&d);
}
static const unsigned char hextable[] = {
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0, /* 0x30 - 0x3f */
0, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x40 - 0x4f */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x50 - 0x5f */
0, 10, 11, 12, 13, 14, 15 /* 0x60 - 0x66 */
};
/* the input is a single hex digit */
#define onehex2dec(x) hextable[x - '0']
/*
* Curl_urldecode() URL decodes the given string.
*
@ -144,8 +134,8 @@ CURLcode Curl_urldecode(const char *string, size_t length,
if(('%' == in) && (alloc > 2) &&
ISXDIGIT(string[1]) && ISXDIGIT(string[2])) {
/* this is two hexadecimal digits following a '%' */
in = (unsigned char)(onehex2dec(string[1]) << 4) | onehex2dec(string[2]);
in = (unsigned char)((Curl_hexval(string[1]) << 4) |
Curl_hexval(string[2]));
string += 3;
alloc -= 3;
}
@ -219,13 +209,12 @@ void curl_free(void *p)
void Curl_hexencode(const unsigned char *src, size_t len, /* input length */
unsigned char *out, size_t olen) /* output buffer size */
{
const char *hex = "0123456789abcdef";
DEBUGASSERT(src && len && (olen >= 3));
if(src && len && (olen >= 3)) {
while(len-- && (olen >= 3)) {
*out++ = (unsigned char)hex[(*src & 0xF0) >> 4];
*out++ = (unsigned char)hex[*src & 0x0F];
Curl_hexbyte(out, *src, TRUE);
++src;
out += 2;
olen -= 2;
}
*out = 0;
@ -233,3 +222,19 @@ void Curl_hexencode(const unsigned char *src, size_t len, /* input length */
else if(olen)
*out = 0;
}
/* Curl_hexbyte
*
* Output a single unsigned char as a two-digit hex number, lowercase or
* uppercase
*/
void Curl_hexbyte(unsigned char *dest, /* must fit two bytes */
unsigned char val,
bool lowercase)
{
const unsigned char uhex[] = "0123456789ABCDEF";
const unsigned char lhex[] = "0123456789abcdef";
const unsigned char *t = lowercase ? lhex : uhex;
dest[0] = t[val >> 4];
dest[1] = t[val & 0x0F];
}