// gcc -std=c99 -Wall -Wextra -Wpedantic -g -fsanitize=address,undefined base.c -o base && ./base /// Includes #include <stdint.h> /// Types typedef struct { int bits; char const * alphabet; } Encoding; /// Encodings // https://datatracker.ietf.org/doc/html/rfc4648#section-6 // https://datatracker.ietf.org/doc/html/rfc4648#section-4 Encoding base32 = {5, "AZ27"}; Encoding base64 = {6, "AZaz09++//"}; /// Decode int decode(Encoding const * enc, char const * i_buf, int i_len, char * o_buf) { for (int i_ind = 0; i_ind < i_len; ++i_ind) { uint8_t i = i_buf[i_ind]; for ( char const * a = enc->alphabet, ii = i; i -= a[0], !(*a && a[0] <= ii && ii <= a[1]); i += a[1] + 1, a += 2 ) if (!*a) return 0; int o_ind = i_ind * enc->bits / 8; int o_bit = i_ind * enc->bits % 8; int i_bit = 8 - enc->bits; i <<= i_bit; while (i_bit < 8) { int m_bit = i_bit > o_bit ? i_bit : o_bit; o_buf[o_ind] |= i >> o_bit; o_ind += 1; o_bit = 0; i_bit += 8 - m_bit; i <<= 8 - m_bit; } } return 1; } /// Main #include <stdio.h> #include <stdlib.h> int main() { { char const i_buf[] = "NBSWY3DPEB3W64TMMQ"; char o_buf[(sizeof(i_buf)-1) * 5 / 8 + 1] = {0}; printf("%d: %s\n", decode(&base32, i_buf, sizeof(i_buf)-1, o_buf), o_buf); } { char const i_buf[] = "aGVsbG8gd29ybGQ"; char o_buf[(sizeof(i_buf)-1) * 6 / 8 + 1] = {0}; printf("%d: %s\n", decode(&base64, i_buf, sizeof(i_buf)-1, o_buf), o_buf); } }