Created
February 7, 2018 11:25
-
-
Save yni3/b693fb2e58965c54ccf229cb7cef16e2 to your computer and use it in GitHub Desktop.
Base32 implemenation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
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