]> git.mar77i.info Git - otp_nano/commitdiff
from_b32_inplace: use a lut
authormar77i <mar77i@protonmail.ch>
Thu, 25 Jun 2026 17:07:12 +0000 (19:07 +0200)
committermar77i <mar77i@protonmail.ch>
Thu, 25 Jun 2026 17:07:12 +0000 (19:07 +0200)
encoding.h

index a288c52295fcda067721246454dd98d4454c859a..b01ac1eaa2b627e28ce61ff54b0ffcb1832f355b 100644 (file)
@@ -63,50 +63,44 @@ static inline void to_hex(char c, char *s) {
 }
 
 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) {