diff options
Diffstat (limited to 'src/base32.c')
-rw-r--r-- | src/base32.c | 93 |
1 files changed, 93 insertions, 0 deletions
diff --git a/src/base32.c b/src/base32.c new file mode 100644 index 0000000..82c5b48 --- /dev/null +++ b/src/base32.c @@ -0,0 +1,93 @@ +#include <assert.h> + +#include "base32.h" +#include "common.h" + +static inline bool b32blktoa(uint8_t *restrict, const uint8_t *restrict) + __attribute__((always_inline)); + +static const uint8_t lookup[] = { + /* [00…07] = */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + /* [08…0F] = */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + /* [10…17] = */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + /* [18…1F] = */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + /* [20…27] = */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + /* [28…2F] = */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + /* [30…37] = */ 0xFF, 0xFF, 26, 27, 28, 29, 30, 31, + /* [38…3F] = */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0, 0xFF, 0xFF, + /* [40…47] = */ 0xFF, 0, 1, 2, 3, 4, 5, 6, + /* [48…4F] = */ 7, 8, 9, 10, 11, 12, 13, 14, + /* [50…57] = */ 15, 16, 17, 18, 19, 20, 21, 22, + /* [58…5F] = */ 23, 24, 25, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + /* [60…67] = */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + /* [68…6F] = */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + /* [70…77] = */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + /* [78…7F] = */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + /* [80…87] = */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + /* [88…8F] = */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + /* [90…97] = */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + /* [98…9F] = */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + /* [A0…A7] = */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + /* [A8…AF] = */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + /* [B0…B7] = */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + /* [B8…BF] = */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + /* [C0…C7] = */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + /* [C8…CF] = */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + /* [D0…D7] = */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + /* [D8…DF] = */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + /* [E0…E7] = */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + /* [E8…EF] = */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + /* [F0…F7] = */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + /* [F8…FF] = */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +}; + +bool +b32toa(uint8_t *restrict dst, const char *restrict src, size_t len) +{ + assert(len != 0); + + size_t i, j; + for (i = j = 0; len - i >= 8; i += 8, j += 5) { + uint8_t bits[] = { + lookup[(uint8_t)src[i + 0]], + lookup[(uint8_t)src[i + 1]], + lookup[(uint8_t)src[i + 2]], + lookup[(uint8_t)src[i + 3]], + lookup[(uint8_t)src[i + 4]], + lookup[(uint8_t)src[i + 5]], + lookup[(uint8_t)src[i + 6]], + lookup[(uint8_t)src[i + 7]], + }; + if (!b32blktoa(dst + j, bits)) + return false; + } + + uint8_t bits[8] = {0}; + switch (len - i) { + case 7: bits[6] = lookup[(uint8_t)src[i + 6]]; /* fallthrough */ + case 6: bits[5] = lookup[(uint8_t)src[i + 5]]; /* fallthrough */ + case 5: bits[4] = lookup[(uint8_t)src[i + 4]]; /* fallthrough */ + case 4: bits[3] = lookup[(uint8_t)src[i + 3]]; /* fallthrough */ + case 3: bits[2] = lookup[(uint8_t)src[i + 2]]; /* fallthrough */ + case 2: bits[1] = lookup[(uint8_t)src[i + 1]]; /* fallthrough */ + case 1: bits[0] = lookup[(uint8_t)src[i + 0]]; + return b32blktoa(dst + j, bits); + } + return true; +} + +bool +b32blktoa(uint8_t *restrict dst, const uint8_t *restrict src) +{ + uint8_t or = src[0] | src[1] | src[2] | src[3] + | src[4] | src[5] | src[6] | src[7]; + if (or == 0xFF) + return false; + + dst[0] = src[0]<<3 | src[1]>>2; + dst[1] = src[1]<<6 | src[2]<<1 | src[3]>>4; + dst[2] = src[3]<<4 | src[4]>>1; + dst[3] = src[4]<<7 | src[5]<<2 | src[6]>>3; + dst[4] = src[6]<<5 | src[7]>>0; + return true; +} |