A-Z、a-z、0-9 一共只有 62 个字符,来编码二进制流,困扰了很久,后来发现采用扩展的方式编码 Base64 效果很好。 Base64 一次编码 6 个 bit,0(0x0)-63(0x3f),编码结果只出现这 62 个字符。
码表:
idx | 编码 | idx | 编码 | idx | 编码 | idx | 编码 |
---|---|---|---|---|---|---|---|
0 | "0" | 16 | "g" | 32 | "w" | 48 | "M" |
1 | "1" | 17 | "h" | 33 | "x" | 49 | "N" |
2 | "2" | 18 | "i" | 34 | "y" | 50 | "O" |
3 | "3" | 19 | "j" | 35 | "z" | 51 | "P" |
4 | "4" | 20 | "k" | 36 | "A" | 52 | "Q" |
5 | "5" | 21 | "l" | 37 | "B" | 53 | "R" |
6 | "6" | 22 | "m" | 38 | "C" | 54 | "S" |
7 | "7" | 23 | "n" | 39 | "D" | 55 | "T" |
8 | "8" | 24 | "o" | 40 | "E" | 56 | "U" |
9 | "9" | 25 | "p" | 41 | "F" | 57 | "V" |
10 | "a" | 26 | "q" | 42 | "G" | 58 | "W" |
11 | "b" | 27 | "r" | 43 | "H" | 59 | "X0" |
12 | "c" | 28 | "s" | 44 | "I" | 60 | "X1" |
13 | "d" | 29 | "t" | 45 | "J" | 61 | "X2" |
14 | "e" | 30 | "u" | 46 | "K" | 62 | "X3" |
15 | "f" | 31 | "v" | 47 | "L" | 63 | "X4" |
62 个字符 编码 64 个数字。
定义映射表 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ
,只使用 0
- W
, XYZ
作为扩展标记,进行递归编码,绝大部分(59/64=0.921875)都会编码成一个字符,只有小部分(5/64=0.078125)的概率会被编码成两个字符。
一个 6 bit,平均编码就是:$59/64 + (5/64)*2 = 1.078125$ 个字符。
0
- W
一共 59 个字符用于编码, XYZ
作为扩展标记。
0
, 1
, 2
… W
。X
表示进位,基准为 59。
X0
, X1
, X2
… XW
。Y
表示两位,基准为 118。
Y00
, Y01
, Y02
… YWW
。Z
表示三位,最高位递归处理,基准为 3599。
Z000
, Z001
, Z002
… ZWWW
, Z00X0
, Z00X1
…16 进制 | 10 进制 | 编码 |
---|---|---|
0 | 0 | "0" |
3a | 58 | "W" |
3b | 59 | "X0" |
75 | 117 | "XW" |
76 | 118 | "Y00" |
e0e | 3598 | "YWW" |
e0f | 3599 | "Z000" |
33051 | 208977 | "ZWWW" |
33052 | 208978 | "Z00X0" |
65294 | 414356 | "ZWWXW" |
65295 | 414357 | "Z00Y00" |
ffffe | 1048574 | "ZqbY53" |
fffff | 1048575 | "ZrbY53" |
bf3805 | 12531717 | "ZWWYWW" |
bf3806 | 12531718 | "Z00Z000" |
fffffe | 16777214 | "ZxAZDk0" |
ffffff | 16777215 | "ZyAZDk0" |
WCHAR L"中文 09azAZ"
加密:
BASE64(utf8) | 5Lit5paHIDA5YXpBWg== |
B62 逐字符编码 | P925Ic7rv00w00M00V01C02401601v |
B62 6bit 编码 | Pi0bkW7pi00c00V0640uw1105E0 |
B62(utf8) 6bit 编码 | Pd0VbyJVFq7830VonF1mw |
编码效果很好,比 BASE64 长一丢丢(长 $0.078125%$),但是没有任何图形符号,非常干净。
std::wstring b62base64::BBEncode(const char* buffer, const int length) {
std::wstring retv;
BBEncode(retv, BB62_TYPE);
BBEncode(retv, length);
BBEncode(retv, b62base64::BBType::BBTypeBin); // 0:bin,1:char,2:wchar。
// 一次编码 3 个字节。
for (int i = 0; i < length; i += 3) {
char a = buffer[i];
char b = i + 1 < length ? buffer[i + 1] : 0;
char c = i + 2 < length ? buffer[i + 2] : 0;
BBEncode(retv, (a & B11111100) >> 2);
BBEncode(retv, ((a & B00000011) << 4) | ((b & B11110000) >> 4));
if (i + 1 >= length) {
break;
}
BBEncode(retv, ((b & B00001111) << 2) | ((c & B11000000) >> 6));
if (i + 2 >= length) {
break;
}
BBEncode(retv, c & B00111111);
}
return retv;
}
std::wstring b62base64::BBEncode(const std::string& str) {
const int length = str.size();
const char* buffer = str.c_str();
std::wstring retv;
BBEncode(retv, BB62_TYPE);
BBEncode(retv, length);
BBEncode(retv, b62base64::BBType::BBTypeChar); // 0:bin,1:char,2:wchar。
for (int i = 0; i < length; i++) {
char ch = buffer[i]; // <= 0xff
BBEncode(retv, ch / BB59);
BBEncode(retv, ch % BB59);
}
return retv;
}
std::wstring b62base64::BBEncode(const std::wstring& str) {
const int length = str.size();
const wchar_t* buffer = str.c_str();
std::wstring retv;
BBEncode(retv, BB62_TYPE);
BBEncode(retv, length);
BBEncode(retv, b62base64::BBType::BBTypeWChar); // 0:bin,1:char,2:wchar。
for (int i = 0; i < length; i++) {
wchar_t ch = buffer[i]; // <= 0xffff
BBEncode(retv, ch / BB59 / BB59);
BBEncode(retv, ch / BB59 % BB59);
BBEncode(retv, ch % BB59);
}
return retv;
}
// 0 0 P12000
const wchar_t BB59TABLE[] = L"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
#define BB59 59
#define CHECK_RETURN(state, retv) do { \
if (state.IsError()) { return retv; } \
} while (0)
#define CHECK_ARRAY_RETURN(state, retv) do { \
if (index >= bufsize) { \
state.OnError(b62base64::BBDecodeError::BBDecodeErrArrayOverflow); \
return retv; } \
} while (0)
int b62base64::BBEncode(std::wstring& retv, unsigned long value) {
int len = 0;
if (value < BB59) {
retv.push_back(BB59TABLE[value]);
len += 1;
}
else if (value - BB59 < BB59) {
value -= BB59;
retv.push_back(L'X');
retv.push_back(BB59TABLE[value]);
len += 2;
}
else if ((value - BB59 * 2) / BB59 < BB59) {
value -= BB59 * 2;
retv.push_back(L'Y');
retv.push_back(BB59TABLE[value % BB59]);
retv.push_back(BB59TABLE[value / BB59]);
len += 3;
}
else {
const int basek = BB59 * 2 + BB59 * BB59;
assert(value >= basek); // 不能出现负数。
value -= basek;
retv.push_back(L'Z');
retv.push_back(BB59TABLE[value % BB59]);
retv.push_back(BB59TABLE[value / BB59 % BB59]);
len += 3 + BBEncode(retv, value / BB59 / BB59); // 递归最高位置。
}
return len;
}
unsigned long b62base64::BBDecode(const wchar_t* ptr, const unsigned int bufsize,
unsigned int& index, b62base64::BBDecodeState& state) {
CHECK_ARRAY_RETURN(state, 0);
const wchar_t op = ptr[index++];
if (op == L'X') {
CHECK_ARRAY_RETURN(state, 0);
wchar_t X = ptr[index++];
return BB59 + BBDecode(X, state);
}
else if (op == L'Y') {
CHECK_ARRAY_RETURN(state, 0);
wchar_t Y1 = ptr[index++];
CHECK_ARRAY_RETURN(state, 0);
wchar_t Y2 = ptr[index++];
return BB59 * 2 + BBDecode(Y1, state) + BBDecode(Y2, state) * BB59;
}
else if (op == L'Z') {
CHECK_ARRAY_RETURN(state, 0);
wchar_t Z1 = ptr[index++];
CHECK_ARRAY_RETURN(state, 0);
wchar_t Z2 = ptr[index++];
unsigned long Z3 = BBDecode(ptr, bufsize, index, state);
CHECK_RETURN(state, 0);
const int basek = BB59 * 2 + BB59 * BB59;
return basek + BBDecode(Z1, state) + BBDecode(Z2, state) * BB59 + Z3 * BB59 * BB59;
}
else {
return BBDecode(op, state);
}
}
#pragma once
#include <windows.h>
#include <assert.h>
#include <memory>
#include <string>
#include <vector>
namespace b62base64 {
enum BBType {
BBTypeNone = 0xf,
BBTypeBin = 0,
BBTypeChar = 1, // sizeof(char)
BBTypeWChar = 2, // sizeof(wchar)
};
enum BBDecodeError {
BBDecodeSuccess = 0,
BBDecodeUnknowType = 1, // 头 type 不对。
BBDecodeUnknowAlgType = 2, // 编码不能识别。
BBDecodeErrChar = 3, // 字符错误。
BBDecodeErrArrayOverflow = 4, // 数组溢出访问。
BBDecodeErrCallback = 5, // BBDecodeCallback 返回 FALSE。
BBDecodeErrSize = 6, // 最终 size 不对。
};
__interface BBDecodeState {
virtual void OnError(BBDecodeError err) = 0;
virtual BOOL IsError() = 0;
};
__interface BBDecodeCallback : public BBDecodeState {
virtual BOOL OnConfig(int size, int type) = 0;
virtual BOOL OnValue(unsigned long value) = 0;
virtual BOOL OnTheEnd() = 0;
};
// 编解码核心逻辑
int BBDecode(const wchar_t ch, BBDecodeState& state);
int BBEncode(std::wstring& retv, unsigned long value);
unsigned long BBDecode(const wchar_t* ptr, const unsigned int bufsize,
unsigned int& index, BBDecodeState& state);
// 编码
std::wstring BBEncode(const std::wstring& str);
std::wstring BBEncode(const std::string& str);
std::wstring BBEncode(const char* buffer, const int length);
std::wstring BBEncode(const std::vector<char>& buffer);
// 解码
BOOL BBDecode(const std::wstring& str, BBDecodeCallback& result);
std::wstring BBDecodeStr(const std::wstring& str);
std::string BBDecodeStrA(const std::wstring& str);
std::vector<char> BBDecodeBuffer(const std::wstring& str);
// 创建随机字符串
std::wstring MakeRandString(int size);
std::string MakeRandStringA(int size);
std::vector<char> MakeRandBuffer(int size);
// 16 进制编码
std::wstring HexEncode(const std::wstring& str);
std::wstring HexEncode(const std::string& str);
std::wstring HexEncode(const std::vector<char>& str);
// 测试接口。
int b62base64_test();
};
#pragma once
#include <windows.h>
#include <assert.h>
#include <memory>
#include <string>
#include "b62base64.h"
//#include "base64.h"
const wchar_t BB59TABLE[] = L"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
#define ISCHAR_09(ch) (ch >= L'0' && ch <= L'9')
#define ISCHAR_az(ch) (ch >= L'a' && ch <= L'z')
#define ISCHAR_AZ(ch) (ch >= L'A' && ch <= L'Z')
#define PARSE_09(ch) (ch - L'0')
#define PARSE_az(ch) (ch - L'a' + 10)
#define PARSE_AZ(ch) (ch - L'A' + 10 + 26)
#define MASK_EXT1 -1 // 扩展一位
#define MASK_EXT2 -2 // 扩展两位
#define MASK_EXTR -3 // 递归扩展
#define MASK_ERR -9
#define BB59 59
#define BB62_TYPE 0x33
const unsigned char B11111100 = 0B11111100; // 0xfc;
const unsigned char B00000011 = 0B00000011; // 0x03;
const unsigned char B11110000 = 0B11110000; // 0xf0;
const unsigned char B00001111 = 0B00001111; // 0x0f;
const unsigned char B11000000 = 0B11000000; // 0xc0;
const unsigned char B00111111 = 0B00111111; // 0x3f;
const unsigned char B110000 = 0B110000; // 0x30;
const unsigned char B001111 = 0B001111; // 0x0f;
const unsigned char B111100 = 0B111100; // 0x3c;
const unsigned char B000011 = 0B000011; // 0x03;
class MyDecodeState : public b62base64::BBDecodeState {
public:
void OnError(b62base64::BBDecodeError err) override {
m_err = err;
}
BOOL IsError() override {
return m_err != b62base64::BBDecodeError::BBDecodeSuccess;
}
private:
b62base64::BBDecodeError m_err = b62base64::BBDecodeError::BBDecodeSuccess;
};
class MyDecodeCallback : public b62base64::BBDecodeCallback, public MyDecodeState {
public:
MyDecodeCallback(std::string& str) : m_str(&str) {
}
MyDecodeCallback(std::wstring& wstr) : m_wstr(&wstr) {
}
MyDecodeCallback(std::vector<char>& buffer) : m_buffer(&buffer) {
}
public:
BOOL OnConfig(int size, int type) override {
this->m_size = size;
this->m_type = (b62base64::BBType)type;
if (type == b62base64::BBType::BBTypeChar) {
return !!m_str;
}
if (type == b62base64::BBType::BBTypeWChar) {
return !!m_wstr;
}
if (type == b62base64::BBType::BBTypeBin) {
return !!m_buffer;
}
return FALSE;
}
BOOL OnValue(unsigned long value) override {
if (m_type == b62base64::BBType::BBTypeChar && m_str) {
m_str->push_back(value);
return TRUE;
}
if (m_type == b62base64::BBType::BBTypeWChar && m_wstr) {
m_wstr->push_back(value);
return TRUE;
}
if (m_type == b62base64::BBType::BBTypeBin && m_buffer) {
m_buffer->push_back(value);
return TRUE;
}
return FALSE;
}
BOOL OnTheEnd() override {
if (m_type == b62base64::BBType::BBTypeChar && m_str) {
if (m_str->size() != m_size) {
OnError(b62base64::BBDecodeError::BBDecodeErrSize);
return FALSE;
}
return TRUE;
}
if (m_type == b62base64::BBType::BBTypeWChar && m_wstr) {
if (m_wstr->size() != m_size) {
OnError(b62base64::BBDecodeError::BBDecodeErrSize);
return FALSE;
}
return TRUE;
}
if (m_type == b62base64::BBType::BBTypeBin && m_buffer) {
if (m_buffer->size() != m_size) {
OnError(b62base64::BBDecodeError::BBDecodeErrSize);
return FALSE;
}
return TRUE;
}
return FALSE;
}
public:
void OnError(b62base64::BBDecodeError err) override {
MyDecodeState::OnError(err);
}
BOOL IsError() override {
return MyDecodeState::IsError();
}
private:
std::string* m_str = nullptr;
std::wstring* m_wstr = nullptr;
std::vector<char>* m_buffer = nullptr;
int m_size = -1;
b62base64::BBType m_type = b62base64::BBType::BBTypeNone;
};
#define CHECK_RETURN(state, retv) do { \
if (state.IsError()) { return retv; } \
} while (0)
#define CHECK_ARRAY_RETURN(state, retv) do { \
if (index >= bufsize) { \
state.OnError(b62base64::BBDecodeError::BBDecodeErrArrayOverflow); \
return retv; } \
} while (0)
int b62base64::BBDecode(const wchar_t ch, b62base64::BBDecodeState& state) {
if (ISCHAR_09(ch)) {
return PARSE_09(ch);
}
if (ISCHAR_az(ch)) {
return PARSE_az(ch);
}
if (ISCHAR_AZ(ch)) {
if (ch == L'X') {
state.OnError(b62base64::BBDecodeError::BBDecodeErrChar);
return MASK_EXT1;
}
if (ch == L'Y') {
state.OnError(b62base64::BBDecodeError::BBDecodeErrChar);
return MASK_EXT2;
}
if (ch == L'Z') {
state.OnError(b62base64::BBDecodeError::BBDecodeErrChar);
return MASK_EXTR;
}
return PARSE_AZ(ch);
}
state.OnError(b62base64::BBDecodeError::BBDecodeErrChar);
return MASK_ERR;
}
int b62base64::BBEncode(std::wstring& retv, unsigned long value) {
int len = 0;
if (value < BB59) {
retv.push_back(BB59TABLE[value]);
len += 1;
}
else if (value - BB59 < BB59) {
value -= BB59;
retv.push_back(L'X');
retv.push_back(BB59TABLE[value]);
len += 2;
}
else if ((value - BB59 * 2) / BB59 < BB59) {
value -= BB59 * 2;
retv.push_back(L'Y');
retv.push_back(BB59TABLE[value % BB59]);
retv.push_back(BB59TABLE[value / BB59]);
len += 3;
}
else {
const int basek = BB59 * 2 + BB59 * BB59;
assert(value >= basek); // 不能出现负数。
value -= basek;
retv.push_back(L'Z');
retv.push_back(BB59TABLE[value % BB59]);
retv.push_back(BB59TABLE[value / BB59 % BB59]);
len += 3 + BBEncode(retv, value / BB59 / BB59); // 递归最高位置。
}
return len;
}
unsigned long b62base64::BBDecode(const wchar_t* ptr, const unsigned int bufsize,
unsigned int& index, b62base64::BBDecodeState& state) {
CHECK_ARRAY_RETURN(state, 0);
const wchar_t op = ptr[index++];
if (op == L'X') {
CHECK_ARRAY_RETURN(state, 0);
wchar_t X = ptr[index++];
return BB59 + BBDecode(X, state);
}
else if (op == L'Y') {
CHECK_ARRAY_RETURN(state, 0);
wchar_t Y1 = ptr[index++];
CHECK_ARRAY_RETURN(state, 0);
wchar_t Y2 = ptr[index++];
return BB59 * 2 + BBDecode(Y1, state) + BBDecode(Y2, state) * BB59;
}
else if (op == L'Z') {
CHECK_ARRAY_RETURN(state, 0);
wchar_t Z1 = ptr[index++];
CHECK_ARRAY_RETURN(state, 0);
wchar_t Z2 = ptr[index++];
unsigned long Z3 = BBDecode(ptr, bufsize, index, state);
CHECK_RETURN(state, 0);
const int basek = BB59 * 2 + BB59 * BB59;
return basek + BBDecode(Z1, state) + BBDecode(Z2, state) * BB59 + Z3 * BB59 * BB59;
}
else {
return BBDecode(op, state);
}
}
std::wstring b62base64::BBEncode(const std::wstring& str) {
const int length = str.size();
const wchar_t* buffer = str.c_str();
std::wstring retv;
BBEncode(retv, BB62_TYPE);
BBEncode(retv, length);
BBEncode(retv, b62base64::BBType::BBTypeWChar); // 0:bin,1:char,2:wchar。
for (int i = 0; i < length; i++) {
wchar_t ch = buffer[i]; // <= 0xffff
BBEncode(retv, ch / BB59 / BB59);
BBEncode(retv, ch / BB59 % BB59);
BBEncode(retv, ch % BB59);
}
return retv;
}
std::wstring b62base64::BBEncode(const std::string& str) {
const int length = str.size();
const char* buffer = str.c_str();
std::wstring retv;
BBEncode(retv, BB62_TYPE);
BBEncode(retv, length);
BBEncode(retv, b62base64::BBType::BBTypeChar); // 0:bin,1:char,2:wchar。
for (int i = 0; i < length; i++) {
char ch = buffer[i]; // <= 0xff
BBEncode(retv, ch / BB59);
BBEncode(retv, ch % BB59);
}
return retv;
}
std::wstring b62base64::BBEncode(const char* buffer, const int length) {
std::wstring retv;
BBEncode(retv, BB62_TYPE);
BBEncode(retv, length);
BBEncode(retv, b62base64::BBType::BBTypeBin); // 0:bin,1:char,2:wchar。
// 一次编码 3 个字节。
for (int i = 0; i < length; i += 3) {
char a = buffer[i];
char b = i + 1 < length ? buffer[i + 1] : 0;
char c = i + 2 < length ? buffer[i + 2] : 0;
BBEncode(retv, (a & B11111100) >> 2);
BBEncode(retv, ((a & B00000011) << 4) | ((b & B11110000) >> 4));
if (i + 1 >= length) {
break;
}
BBEncode(retv, ((b & B00001111) << 2) | ((c & B11000000) >> 6));
if (i + 2 >= length) {
break;
}
BBEncode(retv, c & B00111111);
}
return retv;
}
std::wstring b62base64::BBEncode(const std::vector<char>& buffer) {
if (buffer.empty()) {
return BBEncode("", 0);
}
std::wstring retv = BBEncode(&buffer[0], buffer.size());
return retv;
}
BOOL b62base64::BBDecode(const std::wstring& str, b62base64::BBDecodeCallback& result) {
unsigned int index = 0;
const wchar_t* buffer = str.c_str();
unsigned int bufsize = str.size();
const int algType = BBDecode(buffer, bufsize, index, result);
CHECK_RETURN(result, FALSE);
if (algType != BB62_TYPE) {
result.OnError(b62base64::BBDecodeError::BBDecodeUnknowType);
return FALSE;
}
const int length = BBDecode(buffer, bufsize, index, result);
CHECK_RETURN(result, FALSE);
const int flag = BBDecode(buffer, bufsize, index, result);
CHECK_RETURN(result, FALSE);
if (!result.OnConfig(length, flag)) {
result.OnError(b62base64::BBDecodeError::BBDecodeErrCallback);
return FALSE;
}
if (flag == b62base64::BBType::BBTypeWChar) {
for (int i = 0; i < length; i++) {
wchar_t a = BBDecode(buffer, bufsize, index, result);
CHECK_RETURN(result, FALSE);
wchar_t b = BBDecode(buffer, bufsize, index, result);
CHECK_RETURN(result, FALSE);
wchar_t c = BBDecode(buffer, bufsize, index, result);
CHECK_RETURN(result, FALSE);
unsigned long value = a * BB59 * BB59 + b * BB59 + c;
if (!result.OnValue(value)) {
result.OnError(b62base64::BBDecodeError::BBDecodeErrCallback);
return FALSE;
}
}
return result.OnTheEnd();
}
if (flag == b62base64::BBType::BBTypeChar) {
for (int i = 0; i < length; i++) {
char a = BBDecode(buffer, bufsize, index, result);
CHECK_RETURN(result, FALSE);
char b = BBDecode(buffer, bufsize, index, result);
CHECK_RETURN(result, FALSE);
unsigned long value = a * BB59 + b;
if (!result.OnValue(value)) {
result.OnError(b62base64::BBDecodeError::BBDecodeErrCallback);
return FALSE;
}
}
return result.OnTheEnd();
}
if (flag == b62base64::BBType::BBTypeBin) {
unsigned int rstindex = 0;
for (int i = 0; i < length; i += 3) {
char a = BBDecode(buffer, bufsize, index, result);
CHECK_RETURN(result, FALSE);
char b = index < bufsize ? BBDecode(buffer, bufsize, index, result) : 0;
CHECK_RETURN(result, FALSE);
char c = index < bufsize ? BBDecode(buffer, bufsize, index, result) : 0;
CHECK_RETURN(result, FALSE);
char d = index < bufsize ? BBDecode(buffer, bufsize, index, result) : 0;
CHECK_RETURN(result, FALSE);
if (!result.OnValue((a << 2) | ((b & B110000) >> 4))) {
result.OnError(b62base64::BBDecodeError::BBDecodeErrCallback);
return FALSE;
}
if (++rstindex >= length) {
break;
}
if (!result.OnValue(((b & B001111) << 4) | ((c & B111100) >> 2))) {
result.OnError(b62base64::BBDecodeError::BBDecodeErrCallback);
return FALSE;
}
if (++rstindex >= length) {
break;
}
if (!result.OnValue(((c & B000011) << 6) | d)) {
result.OnError(b62base64::BBDecodeError::BBDecodeErrCallback);
return FALSE;
}
if (++rstindex >= length) {
break;
}
}
return result.OnTheEnd();
}
result.OnError(b62base64::BBDecodeError::BBDecodeUnknowAlgType);
return FALSE;
}
std::wstring b62base64::BBDecodeStr(const std::wstring& str) {
std::wstring result;
MyDecodeCallback resultw(result);
if (BBDecode(str, resultw)) {
return result;
}
assert(resultw.IsError());
return result;
}
std::string b62base64::BBDecodeStrA(const std::wstring& str) {
std::string result;
MyDecodeCallback resultw(result);
if (BBDecode(str, resultw)) {
return result;
}
assert(resultw.IsError());
return result;
}
std::vector<char> b62base64::BBDecodeBuffer(const std::wstring& str) {
std::vector<char> result;
MyDecodeCallback resultw(result);
if (BBDecode(str, resultw)) {
return result;
}
assert(resultw.IsError());
return result;
}
std::wstring b62base64::MakeRandString(int size) {
std::wstring retv;
retv.resize(size);
for (int i = 0; i < size; i++) {
retv[i] = rand() & 0xffff;
}
return retv;
}
std::string b62base64::MakeRandStringA(int size) {
std::string retv;
retv.resize(size);
for (int i = 0; i < size; i++) {
retv[i] = rand() & 0xff;
}
return retv;
}
std::vector<char> b62base64::MakeRandBuffer(int size) {
std::vector<char> retv;
retv.resize(size);
for (int i = 0; i < size; i++) {
retv[i] = rand() & 0xff;
}
return retv;
}
std::wstring b62base64::HexEncode(const std::wstring& str) {
std::wstring ret;
wchar_t buffer[10];
for (int i = 0; i < str.size(); i++) {
wsprintf(buffer, L"%04x", (unsigned wchar_t)str[i]);
assert(wcslen(buffer) == 4);
ret.append(buffer);
}
return ret;
}
std::wstring b62base64::HexEncode(const std::string& str) {
std::wstring ret;
wchar_t buffer[10];
for (int i = 0; i < str.size(); i++) {
wsprintf(buffer, L"%02x", (unsigned char)str[i]);
assert(wcslen(buffer) == 2);
ret.append(buffer);
}
return ret;
}
std::wstring b62base64::HexEncode(const std::vector<char>& str) {
std::wstring ret;
wchar_t buffer[10];
for (int i = 0; i < str.size(); i++) {
wsprintf(buffer, L"%02x", (unsigned char)str[i]);
assert(wcslen(buffer) == 2);
ret.append(buffer);
}
return ret;
}
int b62base64::b62base64_test()
{
#ifdef _DEBUG
for (int i = 0; i < 10000; i++) {
int size = rand() % 10;
std::wstring strw = MakeRandString(size);
std::string stra = MakeRandStringA(size);
std::vector<char> mystr = MakeRandBuffer(size);
assert(strw.size() == size);
assert(stra.size() == size);
assert(mystr.size() == size);
std::wstring strwE = BBEncode(strw);
std::wstring straE = BBEncode(stra);
std::wstring mystrE = BBEncode(mystr);
std::wstring strwD = BBDecodeStr(strwE);
std::string straD = BBDecodeStrA(straE);
std::vector<char> mystrD = BBDecodeBuffer(mystrE);
std::wstring t1 = HexEncode(strw);
std::wstring t2 = HexEncode(strwD);
int sizek = strwD.size();
assert(strw.compare(strwD) == 0 && size == sizek);
t1 = HexEncode(stra);
t2 = HexEncode(straD);
sizek = straD.size();
assert(stra.compare(straD) == 0 && size == sizek);
t1 = HexEncode(mystr);
t2 = HexEncode(mystrD);
sizek = mystrD.size();
assert(size == sizek);
if (sizek) {
assert(memcmp(&mystr[0], &mystrD[0], sizek) == 0);
}
}
int strlen = 0;
std::wstring preline;
for (unsigned int i = 0; i <= 0xfffff; i++) {
std::wstring temp;
BBEncode(temp, i);
MyDecodeState state;
unsigned int index = 0;
unsigned long result = BBDecode(temp.c_str(), temp.size(), index, state);
assert(result == i);
if (temp.size() != strlen || i == 0xfffff) {
wprintf(preline.c_str());
wprintf(L"| %x | %d | %s |\r\n", i, i, temp.c_str());
strlen = temp.size();
}
wchar_t kbuffer[1024];
wsprintf(kbuffer, L"| %x | %d | %s |\r\n", i, i, temp.c_str());
preline = kbuffer;
}
strlen = 0;
for (int i = 0; i < 0xfffff; i++) {
std::wstring testk(L"0");
testk[0] = i;
std::wstring temp = BBEncode(testk);
if (temp.size() != strlen) {
wprintf(L"%x %d %s \r\n", i, i, temp.c_str());
strlen = temp.size();
}
std::wstring result = BBDecodeStr(temp);
assert(result.compare(testk) == 0);
}
std::wstring test = L"中文 09azAZ";
std::wstring result = BBEncode(test);
std::wstring temp = BBDecodeStr(result);
assert(test.compare(temp) == 0);
#endif
return 0;
}