Base32 是一种将任意字符串重新编码成5bit一组的可显字符串的编码算法
#ifndef YBASE32_H
#define YBASE32_H
#include <string>
class YBase32{
public:
static int toBase32Length(int count);
static int fromBase32Length(int count);
static void toBase32(char* dest, const char* src, int length);
static void fromBase32(char* dest, const char* src, int length);
static std::string toBase32(const std::string& string);
static std::string fromBase32(const std::string& string);
};
#endif // YBASE32_H
#include "YBase32.h"
#include "string.h"
static char map[33] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ012345";
static uint8_t reverse_map[96] = {
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 24, 25, 26, 27, 28, 29, 30, 31, 255, 255, 255, 255, 255, 255,
255, 0, 1, 2, 3, 4, 5, 6, 7, 255, 8, 9, 10, 11, 12, 255,
13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 255, 255, 255, 255, 255,
};
int YBase32::toBase32Length(int count)
{
int byteCount = count * 8;
int length = byteCount / 5;
if(byteCount % 5 != 0){
++length;
}
return length;
}
int YBase32::fromBase32Length(int count)
{
return count * 5 / 8;
}
//https://gitee.com/YuanDad
namespace YBase32NameSpace {
template <typename T>
inline T QyAbs(const T &t) { return t >= 0 ? t : -t; }
}
//https://gitee.com/YuanDad
using namespace YBase32NameSpace;
//https://gitee.com/YuanDad
static char mask[5] = {1, 3, 7, 15, 31};
void YBase32::toBase32(char *dest, const char *src, int length)
{
int left = 0, maxLength = length * 8, cursor = 0;
while(true){
int right = left + 5;
if(right < maxLength){
int x = left / 8, used = left % 8, remain = 8 - used;
int tmp = 0;
if(remain < 5){
tmp = (src[x] & mask[remain - 1]) << (5 - remain);
tmp += uchar(src[x + 1]) >> (3 + remain);
}else{
tmp = (src[x] >> (remain - 5) & mask[4]);
}
dest[cursor] = map[QyAbs(tmp)];
}else if(right > maxLength){
int tmp = (src[length - 1] & mask[maxLength - left - 1]) << (right - maxLength);
dest[cursor] = map[QyAbs(tmp)];
return;
}else{
int tmp = src[length - 1] & mask[4];
dest[cursor] = map[QyAbs(tmp)];
return;
}
++cursor;
left = right;
}
}
void YBase32::fromBase32(char *dest, const char *src, int length)
{
int left = 0, maxLength = fromBase32Length(length) * 8, cursor = 0;
while(true){
int right = left + 8;
int x = left / 5, used = left % 5, count = 5 - used, sum = count;
dest[cursor] = static_cast<char>(reverse_map[static_cast<uint>(src[x])] & mask[count - 1]);
if(count < 3){
++x;
sum += 5;
dest[cursor] = static_cast<char>(dest[cursor] << 5) + reverse_map[static_cast<uint>(src[x])];
}
if(sum < 8){
int remain = 8 - sum;
dest[cursor] = static_cast<char>(dest[cursor] << remain) + (reverse_map[static_cast<uint>(src[x + 1])] >> (5 - remain));
}
if(right == maxLength){
return;
}
++cursor;
left = right;
}
}
std::string YBase32::toBase32(const std::string &string)
{
std::string result(static_cast<size_t>(toBase32Length(static_cast<int>(string.size()))), '\0');
toBase32(const_cast<char*>(result.data()), string.data(), static_cast<int>(string.size()));
return result;
}
std::string YBase32::fromBase32(const std::string &string)
{
std::string result(static_cast<size_t>(fromBase32Length(static_cast<int>(string.size()))), '\0');
fromBase32(const_cast<char*>(result.data()), string.data(), static_cast<int>(string.size()));
return result;
}