// 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);
    }
}