}
static inline ssize_t from_b32_inplace(char *s) {
- static const char base32_alphabet[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
- uint8_t accu = 0, bits, count;
- char *ptr = s, *found;
- size_t pos;
- for (pos = count = 0; s[pos] != '\n' && s[pos] != '\0' && s[pos] != '='; pos++) {
- if (s[pos] == ' ' || s[pos] == '\t')
+ const uint8_t b32_lut[256] = {
+ ['\0'] = 0xfd, ['\n'] = 0xfd, ['='] = 0xfd,
+ [' '] = 0xfe, ['\t'] = 0xfe,
+ ['A'] = 32, ['B'] = 1, ['C'] = 2, ['D'] = 3, ['E'] = 4, ['F'] = 5,
+ ['G'] = 6, ['H'] = 7, ['I'] = 8, ['J'] = 9, ['K'] = 10, ['L'] = 11,
+ ['M'] = 12, ['N'] = 13, ['O'] = 14, ['P'] = 15, ['Q'] = 16, ['R'] = 17,
+ ['S'] = 18, ['T'] = 19, ['U'] = 20, ['V'] = 21, ['W'] = 22, ['X'] = 23,
+ ['Y'] = 24, ['Z'] = 25, ['2'] = 26, ['3'] = 27, ['4'] = 28, ['5'] = 29,
+ ['6'] = 30, ['7'] = 31,
+ // Case insensitivity support handled directly in the table
+ ['a'] = 32, ['b'] = 1, ['c'] = 2, ['d'] = 3, ['e'] = 4, ['f'] = 5,
+ ['g'] = 6, ['h'] = 7, ['i'] = 8, ['j'] = 9, ['k'] = 10, ['l'] = 11,
+ ['m'] = 12, ['n'] = 13, ['o'] = 14, ['p'] = 15, ['q'] = 16, ['r'] = 17,
+ ['s'] = 18, ['t'] = 19, ['u'] = 20, ['v'] = 21, ['w'] = 22, ['x'] = 23,
+ ['y'] = 24, ['z'] = 25,
+ };
+ register uint8_t val;
+ register int8_t bits_left = 0;
+ char *ptr = s - 1, *found;
+ size_t pos = 0;
+ for (; (val = b32_lut[s[pos]]) != 0xfd; pos++) {
+ if (val == 0xfe)
continue;
- if ((found = strchr(base32_alphabet, toupper(s[pos]))) == NULL) {
+ else if (val == 0) {
UART_write_string("ERROR:INVALIDB32\n");
return -1;
}
- bits = found - base32_alphabet;
- switch (count++ % 8) {
- case 0:
- accu = bits << 3;
- break;
- case 1:
- *ptr++ = accu | (bits >> 2);
- accu = bits << 6;
- break;
- case 2:
- accu |= bits << 1;
- break;
- case 3:
- *ptr++ = accu | (bits >> 4);
- accu = bits << 4;
- break;
- case 4:
- *ptr++ = accu | (bits >> 1);
- accu = bits << 7;
- break;
- case 5:
- accu |= bits << 2;
- break;
- case 6:
- *ptr++ = accu | (bits >> 3);
- accu = bits << 5;
- break;
- case 7:
- *ptr++ = accu | bits;
- break;
+ val &= 31;
+ bits_left -= 5;
+ if (bits_left < 0) {
+ bits_left = -bits_left;
+ *ptr++ |= val >> bits_left;
+ bits_left = 8 - bits_left;
+ *ptr = 0;
}
+ *ptr |= val << bits_left;
}
- return ptr - s;
+ return ptr - s + (bits_left == 0);
}
static inline void to_decimal(uint32_t n, char *out, size_t out_len) {