libmicrohttpd

HTTP/1.x server C library (MHD 1.x, stable)
Log | Files | Refs | Submodules | README | LICENSE

commit 8dc93b0834b25e71cc6307df2484ea4ef0b142db
parent 4993c1520285889790c505b77a5f34c0353e99fb
Author: Evgeny Grin (Karlson2k) <k2k@narod.ru>
Date:   Fri,  9 Jun 2023 13:11:12 +0300

base64 decoding: added more compact code version

Also added more base64 test sequencies

Diffstat:
Msrc/microhttpd/mhd_str.c | 98++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----------------
Msrc/microhttpd/test_str_base64.c | 47+++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 124 insertions(+), 21 deletions(-)

diff --git a/src/microhttpd/mhd_str.c b/src/microhttpd/mhd_str.c @@ -2199,18 +2199,68 @@ MHD_str_quote (const char *unquoted, #ifdef BAUTH_SUPPORT +/* + * MHD_BASE64_FUNC_VERSION + * 1 = smallest, + * 2 = medium, + * 3 = fastest + */ +#ifndef MHD_BASE64_FUNC_VERSION +#ifdef MHD_FAVOR_SMALL_CODE +#define MHD_BASE64_FUNC_VERSION 1 +#else /* ! MHD_FAVOR_SMALL_CODE */ +#define MHD_BASE64_FUNC_VERSION 3 +#endif /* ! MHD_FAVOR_SMALL_CODE */ +#endif /* ! MHD_BASE64_FUNC_VERSION */ + +#if MHD_BASE64_FUNC_VERSION < 1 || MHD_BASE64_FUNC_VERSION > 3 +#error Wrong MHD_BASE64_FUNC_VERSION value +#endif /* MHD_BASE64_FUNC_VERSION < 1 || MHD_BASE64_FUNC_VERSION > 3 */ + +#if MHD_BASE64_FUNC_VERSION == 3 +#define MHD_base64_map_type_ int +#else /* MHD_BASE64_FUNC_VERSION < 3 */ +#define MHD_base64_map_type_ int8_t +#endif /* MHD_BASE64_FUNC_VERSION < 3 */ + +#if MHD_BASE64_FUNC_VERSION == 1 +static MHD_base64_map_type_ +base64_char_to_value_ (uint8_t c) +{ + if ('Z' >= c) + { + if ('A' <= c) + return (MHD_base64_map_type_) (c - 'A') + 0; + if ('0' <= c) + { + if ('9' >= c) + return (MHD_base64_map_type_) (c - '0') + 52; + if ('=' == c) + return -2; + return -1; + } + if ('+' == c) + return 62; + if ('/' == c) + return 63; + return -1; + } + if (('z' >= c) && ('a' <= c)) + return (MHD_base64_map_type_) (c - 'a') + 26; + return -1; +} + + +#endif /* MHD_BASE64_FUNC_VERSION == 1 */ + size_t MHD_base64_to_bin_n (const char *base64, size_t base64_len, void *bin, size_t bin_size) { -#ifndef MHD_FAVOR_SMALL_CODE -#define map_type int -#else /* MHD_FAVOR_SMALL_CODE */ -#define map_type int8_t -#endif /* MHD_FAVOR_SMALL_CODE */ - static const map_type map[] = { +#if MHD_BASE64_FUNC_VERSION >= 2 + static const MHD_base64_map_type_ map[] = { /* -1 = invalid char, -2 = padding 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, NUL, SOH, STX, ETX, EOT, ENQ, ACK, BEL, */ @@ -2276,7 +2326,7 @@ MHD_base64_to_bin_n (const char *base64, 'x', 'y', 'z', '{', '|', '}', '~', DEL, */ 49, 50, 51, -1, -1, -1, -1, -1 -#ifndef MHD_FAVOR_SMALL_CODE +#if MHD_BASE64_FUNC_VERSION == 3 , -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 80..8F */ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 90..9F */ @@ -2286,8 +2336,10 @@ MHD_base64_to_bin_n (const char *base64, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* D0..DF */ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* E0..EF */ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* F0..FF */ -#endif /* ! MHD_FAVOR_SMALL_CODE */ +#endif /* ! MHD_BASE64_FUNC_VERSION == 3 */ }; +#define base64_char_to_value_(c) map[(c)] +#endif /* MHD_BASE64_FUNC_VERSION >= 2 */ const uint8_t *const in = (const uint8_t *) base64; uint8_t *const out = (uint8_t *) bin; size_t i; @@ -2302,16 +2354,16 @@ MHD_base64_to_bin_n (const char *base64, j = 0; for (i = 0; i < (base64_len - 4); i += 4) { -#ifdef MHD_FAVOR_SMALL_CODE +#if MHD_BASE64_FUNC_VERSION == 2 if (0 != (0x80 & (in[i] | in[i + 1] | in[i + 2] | in[i + 3]))) return 0; -#endif /* MHD_FAVOR_SMALL_CODE */ +#endif /* MHD_BASE64_FUNC_VERSION == 2 */ if (1) { - const map_type v1 = map[in[i + 0]]; - const map_type v2 = map[in[i + 1]]; - const map_type v3 = map[in[i + 2]]; - const map_type v4 = map[in[i + 3]]; + const MHD_base64_map_type_ v1 = base64_char_to_value_ (in[i + 0]); + const MHD_base64_map_type_ v2 = base64_char_to_value_ (in[i + 1]); + const MHD_base64_map_type_ v3 = base64_char_to_value_ (in[i + 2]); + const MHD_base64_map_type_ v4 = base64_char_to_value_ (in[i + 3]); if ((0 > v1) || (0 > v2) || (0 > v3) || (0 > v4)) return 0; out[j + 0] = (uint8_t) ((((uint8_t) v1) << 2) | (((uint8_t) v2) >> 4)); @@ -2320,16 +2372,16 @@ MHD_base64_to_bin_n (const char *base64, } j += 3; } -#ifdef MHD_FAVOR_SMALL_CODE +#if MHD_BASE64_FUNC_VERSION == 2 if (0 != (0x80 & (in[i] | in[i + 1] | in[i + 2] | in[i + 3]))) return 0; -#endif /* MHD_FAVOR_SMALL_CODE */ +#endif /* MHD_BASE64_FUNC_VERSION == 2 */ if (1) { /* The last four chars block */ - const map_type v1 = map[in[i + 0]]; - const map_type v2 = map[in[i + 1]]; - const map_type v3 = map[in[i + 2]]; - const map_type v4 = map[in[i + 3]]; + const MHD_base64_map_type_ v1 = base64_char_to_value_ (in[i + 0]); + const MHD_base64_map_type_ v2 = base64_char_to_value_ (in[i + 1]); + const MHD_base64_map_type_ v3 = base64_char_to_value_ (in[i + 2]); + const MHD_base64_map_type_ v4 = base64_char_to_value_ (in[i + 3]); if ((0 > v1) || (0 > v2)) return 0; /* Invalid char or padding at first two positions */ mhd_assert (j < bin_size); @@ -2358,8 +2410,12 @@ MHD_base64_to_bin_n (const char *base64, out[j++] = (uint8_t) ((((uint8_t) v3) << 6) | (((uint8_t) v4))); } return j; -#undef map_type +#if MHD_BASE64_FUNC_VERSION >= 2 +#undef base64_char_to_value_ +#endif /* MHD_BASE64_FUNC_VERSION >= 2 */ } +#undef MHD_base64_map_type_ + #endif /* BAUTH_SUPPORT */ diff --git a/src/microhttpd/test_str_base64.c b/src/microhttpd/test_str_base64.c @@ -579,6 +579,53 @@ check_decode_bin (void) "gUEAwIBAP/+/Q==", bin); } + if (1) + { + static const uint8_t bin[48] = + {0x00, 0x10, 0x83, 0x10, 0x51, 0x87, 0x20, 0x92, 0x8b, 0x30, 0xd3, 0x8f, + 0x41, 0x14, 0x93, 0x51, 0x55, 0x97, 0x61, 0x96, 0x9b, 0x71, 0xd7, 0x9f, + 0x82, 0x18, 0xa3, 0x92, 0x59, 0xa7, 0xa2, 0x9a, 0xab, 0xb2, 0xdb, 0xaf, + 0xc3, 0x1c, 0xb3, 0xd3, 0x5d, 0xb7, 0xe3, 0x9e, 0xbb, 0xf3, 0xdf, 0xbf }; + r += expect_decoded_arr ("ABCDEFGHIJKLMNOPQRSTUVWXYZ" \ + "abcdefghijklmnopqrstuvwxyz0123456789+/", bin); + } + + if (1) + { + static const uint8_t bin[49] = + {0x00, 0x10, 0x83, 0x10, 0x51, 0x87, 0x20, 0x92, 0x8b, 0x30, 0xd3, 0x8f, + 0x41, 0x14, 0x93, 0x51, 0x55, 0x97, 0x61, 0x96, 0x9b, 0x71, 0xd7, 0x9f, + 0x82, 0x18, 0xa3, 0x92, 0x59, 0xa7, 0xa2, 0x9a, 0xab, 0xb2, 0xdb, 0xaf, + 0xc3, 0x1c, 0xb3, 0xd3, 0x5d, 0xb7, 0xe3, 0x9e, 0xbb, 0xf3, 0xdf, 0xbf, + 0x00 }; + r += expect_decoded_arr ("ABCDEFGHIJKLMNOPQRSTUVWXYZ" \ + "abcdefghijklmnopqrstuvwxyz0123456789+/" \ + "AA==", bin); + } + + if (1) + { + static const uint8_t bin[48] = + {0xff, 0xef, 0x7c, 0xef, 0xae, 0x78, 0xdf, 0x6d, 0x74, 0xcf, 0x2c, 0x70, + 0xbe, 0xeb, 0x6c, 0xae, 0xaa, 0x68, 0x9e, 0x69, 0x64, 0x8e, 0x28, 0x60, + 0x7d, 0xe7, 0x5c, 0x6d, 0xa6, 0x58, 0x5d, 0x65, 0x54, 0x4d, 0x24, 0x50, + 0x3c, 0xe3, 0x4c, 0x2c, 0xa2, 0x48, 0x1c, 0x61, 0x44, 0x0c, 0x20, 0x40 }; + r += expect_decoded_arr ("/+9876543210zyxwvutsrqponmlkjihgfedcba" \ + "ZYXWVUTSRQPONMLKJIHGFEDCBA", bin); + } + + if (1) + { + static const uint8_t bin[49] = + {0xff, 0xef, 0x7c, 0xef, 0xae, 0x78, 0xdf, 0x6d, 0x74, 0xcf, 0x2c, 0x70, + 0xbe, 0xeb, 0x6c, 0xae, 0xaa, 0x68, 0x9e, 0x69, 0x64, 0x8e, 0x28, 0x60, + 0x7d, 0xe7, 0x5c, 0x6d, 0xa6, 0x58, 0x5d, 0x65, 0x54, 0x4d, 0x24, 0x50, + 0x3c, 0xe3, 0x4c, 0x2c, 0xa2, 0x48, 0x1c, 0x61, 0x44, 0x0c, 0x20, 0x40, + 0x00 }; + r += expect_decoded_arr ("/+9876543210zyxwvutsrqponmlkjihgfedcba" \ + "ZYXWVUTSRQPONMLKJIHGFEDCBAAA==", bin); + } + return r; }