Skip to content

Instantly share code, notes, and snippets.

@yni3
Created February 7, 2018 11:25
Show Gist options
  • Save yni3/b693fb2e58965c54ccf229cb7cef16e2 to your computer and use it in GitHub Desktop.
Save yni3/b693fb2e58965c54ccf229cb7cef16e2 to your computer and use it in GitHub Desktop.
Base32 implemenation
/*
Base32.hpp -- Base32 implemenation
Copyright 2018 yni3
License : Public Domain
*/
#pragma once
#ifndef __BASE32
#define __BASE32
class Base32
{
static constexpr unsigned char INVALID_DECODE_CHAR = 0xFF;
static constexpr unsigned char PADDING_CHAR = '=';
static constexpr unsigned char SHIFT_FAST = 64 - 5;
static constexpr auto base32 = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
static inline unsigned char b32(unsigned long long c)
{
return base32[c & 0x0000001F]; // 0001 1111
}
static inline unsigned char d32(unsigned char c)
{
char r = INVALID_DECODE_CHAR;
if (c >= 'A' && c <= 'Z')
r = (c & 0x1F) - 1;
if (c >= '2' && c <= '7')
r = c - '2' + 26;
return r;
}
union Buff {
unsigned char c[8];
unsigned long long l;
Buff() {
l = 0;
}
};
Base32() {};
~Base32() {};
public:
static inline bool IsLittleEndian()
{
int x = 0x00000001;
return *(char *)&x;
}
static void encode(unsigned char *dst, const int dstlen, const unsigned char *src, const int srclen)
{
Buff buff;
for (int i = 0, di = 0, shift = SHIFT_FAST; i < srclen && di < dstlen; i += 5, di += 8, shift = SHIFT_FAST)
{
if (IsLittleEndian()) {
for (int k = 7, j = 0; k >= 0; k--, j++) {
if (k > 2 && (i + j) < srclen) {
buff.c[k] = src[i + j];
}
else {
buff.c[k] = '\0';
}
}
}
else
{
for (int k = 0; k < 8; k++) {
if (k < 5 && (i + k) < srclen) {
buff.c[k] = src[i + k];
}
else {
buff.c[k] = '\0';
}
}
}
int pad_char = 0;
if (srclen < (i + 5)) {
int x = (i + 5) - srclen;
pad_char = ((x * 8) / 5);
}
for (int k = di; k < di + 8; k++) {
if (k < dstlen) {
if (k < ((di + 8) - pad_char)) {
dst[k] = b32(buff.l >> shift);
shift = shift - 5;
}
else {
dst[k] = '=';
}
}
else {
break;
}
}
}
}
static void decode(unsigned char *dst, const int dstlen, const unsigned char *src, const int srclen)
{
bool is_end = false;
for (int i = 0, di = 0; i < srclen; i += 8, di += 5)
{
Buff buff;
if (IsLittleEndian()) {
for (int k = 7, j = 0; k >= 0 && (i + j) < srclen; k--, j++) {
Buff temp;
temp.c[k] = d32(src[i + j]);
if (temp.c[k] == INVALID_DECODE_CHAR) {
is_end = true;
break;
}
buff.l = buff.l | temp.l << (j + 1) * 3;
}
for (int k = 7, j = 0; k >= 2; k--, j++) {
if ((di + j) < dstlen) {
dst[di + j] = buff.c[k];
}
}
}
else
{
for (int k = 0; k < 8 && (i + k) < srclen; k++) {
Buff temp;
temp.c[k] = d32(src[i + k]);
if (temp.c[k] == INVALID_DECODE_CHAR) {
is_end = true;
break;
}
buff.l = buff.l | temp.l << (k + 1) * 3;
}
for (int k = 0; k < 5; k++) {
if ((di + k) < dstlen) {
dst[di + k] = buff.c[k];
}
}
}
if (is_end) {
break;
}
}
}
};
#endif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment