//
// Created by Amazing on 2024/12/22.
//
#ifndef BASE3264_H
#define BASE3264_H
#include <string>
#include <string.h>
class Base32 {
public:
static std::string encode(const std::string& data);
static char* encode(const char* data, size_t dataSize);
static std::string decode(const std::string& code);
static char* decode(const char* code, size_t& dataSize);
private:
static const std::string _32keyStr;
};
const std::string Base32::_32keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567=";
class Base64 {
public:
static std::string encode(const std::string& data);
static char* encode(const char* data, size_t dataSize);
static std::string decode(const std::string& code);
static char* decode(const char* code, size_t& dataSize);
private:
static const std::string _64keyStr;
};
const std::string Base64::_64keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
char* Base32::encode(const char *data, size_t dataSize) {
if (dataSize == 0) return nullptr;
// Base32 是每5个bit编码成一个字符,一个char8个bit,那么每次需要拿5个char共40(5*8=40)个bit,然后拆分成8个5bit
// |xxxxxxxx|xxxxxxxx|xxxxxxxx|xxxxxxxx|xxxxxxxx|
// |xxxxx|xxxxx|xxxxx|xxxxx|xxxxx|xxxxx|xxxxx|xxxxx|
std::string encodeStr;
size_t codeSize = (dataSize / 5 + (dataSize % 5 ? 1 : 0)) * 8 + 1;
char* code = (char*) malloc(codeSize);
memset(code, 0, codeSize);
unsigned char c5[5], c8[8];
size_t index = 0, tail = 0;
while (index < dataSize) {
memset(c5, 0, sizeof(c5));
memset(c8, 0, sizeof(c8));
size_t cSize = 5 < dataSize - index ? 5 : dataSize - index;
for (int i = 0; i < cSize; ++i) c5[i] = data[index++];
c8[0]=c5[0]>>3;
c8[1]=(c5[0]&7)<<2|(c5[1]>>6);
c8[2]=(c5[1]>>1)&31;
c8[3]=((c5[1]&1)<<4)|(c5[2]>>4);
c8[4]=((c5[2]&15)<<1)|(c5[3]>>7);
c8[5]=(c5[3]>>2)&31;
c8[6]=((c5[3]&3)<<3)|(c5[4]>>5);
c8[7]=c5[4]&31;
for (size_t i=cSize*8/5+1;i<8;++i) c8[i]=32;
for (int i=0;i<8;++i) code[tail++]=_32keyStr[c8[i]];
}
return code;
}
std::string Base32::encode(const std::string &data) {
// Base32 是每5个bit编码成一个字符,一个char8个bit,那么每次需要拿5个char共40(5*8=40)个bit,然后拆分成8个5bit
// |xxxxxxxx|xxxxxxxx|xxxxxxxx|xxxxxxxx|xxxxxxxx|
// |xxxxx|xxxxx|xxxxx|xxxxx|xxxxx|xxxxx|xxxxx|xxxxx|
const size_t dataSize = data.size();
if (dataSize == 0) return "";
std::string encodeStr;
size_t codeSize = (data.size() / 5 + (data.size() % 5 ? 1 : 0)) * 8;
std::string code(codeSize, '\0');
unsigned char c5[5], c8[8];
size_t index = 0, tail = 0;
while (index < dataSize) {
memset(c5, 0, sizeof(c5));
memset(c8, 0, sizeof(c8));
size_t cSize = 5 < dataSize - index ? 5 : dataSize - index;
for (int i = 0; i < cSize; ++i) c5[i] = data[index++];
c8[0]=c5[0]>>3;
c8[1]=(c5[0]&7)<<2|(c5[1]>>6);
c8[2]=(c5[1]>>1)&31;
c8[3]=((c5[1]&1)<<4)|(c5[2]>>4);
c8[4]=((c5[2]&15)<<1)|(c5[3]>>7);
c8[5]=(c5[3]>>2)&31;
c8[6]=((c5[3]&3)<<3)|(c5[4]>>5);
c8[7]=c5[4]&31;
for (size_t i=cSize*8/5+1;i<8;++i) c8[i]=32;
for (int i=0;i<8;++i) code[tail++]=_32keyStr[c8[i]];
}
return code;
}
char *Base32::decode(const char* code, size_t& dataSize) {
const size_t codeSize = strlen(code);
size_t maxDataSize = codeSize * 5 / 8;
char* data = (char*)malloc(maxDataSize);
memset(data, 0, maxDataSize);
unsigned char c5[5], c8[8];
size_t index = 0;
dataSize = 0;
while (index < codeSize) {
memset(c5, 0, sizeof(c5));
memset(c8, 0, sizeof(c8));
size_t cSize = 8 < codeSize - index ? 8 : codeSize - index;
for (int i = 0; i < cSize; ++i) c8[i] = _32keyStr.find(code[index++]);
for (int i = cSize; i < 8; ++i) c8[i] = 32;
c5[0] = (c8[0]<<3)|(c8[1]>>2);
c5[1] = ((c8[1]&3)<<6)|(c8[2]<<1)|(c8[3]>>4);
c5[2] = ((c8[3]&15)<<4)|(c8[4]>>1);
c5[3] = ((c8[4]&1)<<7)|(c8[5]<<2)|(c8[6]>>3);
c5[4] = ((c8[6]&7)<<5)|c8[7];
int valiedSize = 7;
while(valiedSize >= 0 && c8[valiedSize]==32) --valiedSize;
valiedSize = (valiedSize + 1) * 5 / 8;
for (int i=0;i<valiedSize;++i) data[dataSize++] = c5[i];
}
return data;
}
std::string Base32::decode(const std::string &code) {
const size_t codeSize = code.size();
if (codeSize * 5 % 8 != 0) return "";
size_t maxDataSize = codeSize * 5 / 8;
std::string data(maxDataSize, '\0');
unsigned char c5[5], c8[8];
size_t index = 0, dataSize = 0;
while (index < codeSize) {
memset(c5, 0, sizeof(c5));
memset(c8, 0, sizeof(c8));
size_t cSize = 8 < codeSize - index ? 8 : codeSize - index;
for (int i = 0; i < cSize; ++i) c8[i] = _32keyStr.find(code[index++]);
for (int i = cSize; i < 8; ++i) c8[i] = 32;
c5[0] = (c8[0]<<3)|(c8[1]>>2);
c5[1] = ((c8[1]&3)<<6)|(c8[2]<<1)|(c8[3]>>4);
c5[2] = ((c8[3]&15)<<4)|(c8[4]>>1);
c5[3] = ((c8[4]&1)<<7)|(c8[5]<<2)|(c8[6]>>3);
c5[4] = ((c8[6]&7)<<5)|c8[7];
int valiedSize = 7;
while(valiedSize >= 0 && c8[valiedSize]==32) --valiedSize;
valiedSize = (valiedSize + 1) * 5 / 8;
for (int i=0;i<valiedSize;++i) data[dataSize++] = c5[i];
}
data.resize(dataSize);
return data;
}
char *Base64::encode(const char *data, size_t dataSize) {
// Base64 是每6个bit编码成一个字符,一个char8个bit,那么每次需要拿3个char共24(3*8=24)个bit,然后拆分成4个6bit
// |xxxxxxxx|xxxxxxxx|xxxxxxxx|
// |xxxxxx|xxxxxx|xxxxxx|xxxxxx|
if (dataSize <= 0) return nullptr;
size_t codeSize = (dataSize / 3 + (dataSize % 3 ? 1 : 0)) * 4 + 1;
char* code = (char*)malloc(codeSize);
memset(code, 0, codeSize);
unsigned char c3[3], c4[4];
size_t index = 0, tail = 0;
while (index < dataSize) {
memset(c3, 0, sizeof(c3));
memset(c4, 0, sizeof(c4));
size_t cSize = 3 < dataSize - index ? 3 : dataSize - index;
for (int i = 0; i < cSize; ++i) c3[i] = data[index++];
c4[0] = c3[0] >> 2;
c4[1] = (c3[0] & 3) << 4 | c3[1] >> 4;
c4[2] = (c3[1] & 15) << 2 | c3[2] >> 6;
c4[3] = c3[2] & 63;
for (size_t i=cSize*4/3+1;i<4;++i) c4[i]=64;
for (int i=0;i<4;++i) code[tail++]=_64keyStr[c4[i]];
}
return code;
}
std::string Base64::encode(const std::string &data) {
// Base64 是每6个bit编码成一个字符,一个char8个bit,那么每次需要拿3个char共24(3*8=24)个bit,然后拆分成4个6bit
// |xxxxxxxx|xxxxxxxx|xxxxxxxx|
// |xxxxxx|xxxxxx|xxxxxx|xxxxxx|
const size_t dataSize = data.size();
if (dataSize == 0) return "";
std::string encodeStr;
size_t codeSize = (data.size() / 3 + (data.size() % 3 ? 1 : 0)) * 4;
std::string code(codeSize, '\0');
unsigned char c3[3], c4[4];
size_t index = 0, tail = 0;
while (index < dataSize) {
memset(c3, 0, sizeof(c3));
memset(c4, 0, sizeof(c4));
size_t cSize = 3 < dataSize - index ? 3 : dataSize - index;
for (int i = 0; i < cSize; ++i) c3[i] = data[index++];
c4[0] = c3[0] >> 2;
c4[1] = (c3[0] & 3) << 4 | c3[1] >> 4;
c4[2] = (c3[1] & 15) << 2 | c3[2] >> 6;
c4[3] = c3[2] & 63;
for (size_t i=cSize*4/3+1;i<4;++i) c4[i]=64;
for (int i=0;i<4;++i) code[tail++]=_64keyStr[c4[i]];
}
return code;
}
char *Base64::decode(const char *code, size_t& dataSize) {
const size_t codeSize = strlen(code);
if (codeSize * 3 % 4 != 0) return nullptr;
size_t maxDataSize = codeSize * 3 / 4;
char* data = (char*)malloc(maxDataSize);
memset(data, 0, maxDataSize);
unsigned char c3[3], c4[4];
size_t index = 0;
dataSize = 0;
while (index < codeSize) {
memset(c3, 0, sizeof(c3));
memset(c4, 0, sizeof(c4));
size_t cSize = 4 < codeSize - index ? 4 : codeSize - index;
for (int i = 0; i < cSize; ++i) c4[i] = _64keyStr.find(code[index++]);
for (int i = cSize; i < 4; ++i) c4[i] = 64;
c3[0] = (c4[0] << 2) | (c4[1] >> 4);
c3[1] = ((c4[1] & 15) << 4) | (c4[2] >> 2);
c3[2] = ((c4[2] & 3) << 6) | c4[3];
int valiedSize = 3;
while(valiedSize >= 0 && c4[valiedSize]==64) --valiedSize;
valiedSize = (valiedSize + 1) * 6 / 8;
for (int i=0;i<valiedSize;++i) data[dataSize++] = c3[i];
}
return data;
}
std::string Base64::decode(const std::string &code) {
const size_t codeSize = code.size();
if (codeSize * 3 % 4 != 0) return "";
size_t maxDataSize = codeSize * 3 / 4;
std::string data(maxDataSize, '\0');
unsigned char c3[3], c4[4];
size_t index = 0, dataSize = 0;
while (index < codeSize) {
memset(c3, 0, sizeof(c3));
memset(c4, 0, sizeof(c4));
size_t cSize = 4 < codeSize - index ? 4 : codeSize - index;
for (int i = 0; i < cSize; ++i) c4[i] = _64keyStr.find(code[index++]);
for (int i = cSize; i < 4; ++i) c4[i] = 64;
c3[0] = (c4[0] << 2) | (c4[1] >> 4);
c3[1] = ((c4[1] & 15) << 4) | (c4[2] >> 2);
c3[2] = ((c4[2] & 3) << 6) | c4[3];
int valiedSize = 3;
while(valiedSize >= 0 && c4[valiedSize]==64) --valiedSize;
valiedSize = (valiedSize + 1) * 6 / 8;
for (int i=0;i<valiedSize;++i) data[dataSize++] = c3[i];
}
data.resize(dataSize);
return data;
}
#endif //BASE3264_H