ofstd内部的Base64编码
// Base64 translation table as described in RFC 2045 (MIME)
static const char enc_base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
OFCondition OFStandard::encodeBase64(STD_NAMESPACE ostream &out,
const unsigned char *data,
const size_t length,
const size_t width)
{
OFCondition status = EC_IllegalParameter;
/* check data buffer to be encoded */
if (data != NULL)
{
unsigned char c;
size_t w = 0;
/* iterate over all data elements */
for (size_t i = 0; i < length; i++)
{
/* encode first 6 bits */
out << enc_base64[(data[i] >> 2) & 0x3f];
/* insert line break (if width > 0) */
if (++w == width)
{
out << OFendl;
w = 0;
}
/* encode remaining 2 bits of the first byte and 4 bits of the second byte */
c = (data[i] << 4) & 0x3f;
if (++i < length)
c |= (data[i] >> 4) & 0x0f;
out << enc_base64[c];
/* insert line break (if width > 0) */
if (++w == width)
{
out << OFendl;
w = 0;
}
/* encode remaining 4 bits of the second byte and 2 bits of the third byte */
if (i < length)
{
c = (data[i] << 2) & 0x3f;
if (++i < length)
c |= (data[i] >> 6) & 0x03;
out << enc_base64[c];
} else {
i++;
/* append fill char */
out << '=';
}
/* insert line break (if width > 0) */
if (++w == width)
{
out << OFendl;
w = 0;
}
/* encode remaining 6 bits of the third byte */
if (i < length)
out << enc_base64[data[i] & 0x3f];
else /* append fill char */
out << '=';
/* insert line break (if width > 0) */
if (++w == width)
{
out << OFendl;
w = 0;
}
}
/* flush stream */
out.flush();
status = EC_Normal;
}
return status;
}
const OFString &OFStandard::encodeBase64(const unsigned char *data,
const size_t length,
OFString &result,
const size_t width)
{
OFStringStream stream;
/* call stream variant of base64 encoder */
if (OFStandard::encodeBase64(stream, data, length, width).good())
{
stream << OFStringStream_ends;
/* convert string stream into a character string */
OFSTRINGSTREAM_GETSTR(stream, buffer_str)
result.assign(buffer_str);
OFSTRINGSTREAM_FREESTR(buffer_str)
} else
result.clear();
return result;
}
ofstd内部的Base64解码
// Base64 decoding table: maps #43..#122 to #0..#63 (255 means invalid)
static const unsigned char dec_base64[] =
{ 62, 255, 255, 255, 63, // '+' .. '/'
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, // '0' .. '9'
255, 255, 255, 255, 255, 255, 255, // ':' .. '@'
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, // 'A' .. 'Z'
255, 255, 255, 255, 255, 255, // '[' .. '`'
26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51 // 'a' .. 'z'
};
size_t OFStandard::decodeBase64(const OFString &data,
unsigned char *&result)
{
size_t count = 0;
/* search for fill char to determine the real length of the input string */
const size_t fillPos = data.find('=');
const size_t length = (fillPos != OFString_npos) ? fillPos : data.length();
/* check data buffer to be decoded */
if (length > 0)
{
/* allocate sufficient memory for the decoded data */
result = new unsigned char[((length + 3) / 4) * 3];
if (result != NULL)
{
unsigned char c1 = 0;
unsigned char c2 = 0;
/* iterate over all data elements */
for (size_t i = 0; i < length; i++)
{
/* skip invalid characters and assign first decoded char */
while ((i < length) && ((data.at(i) < '+') || (data.at(i) > 'z') || ((c1 = dec_base64[data.at(i) - '+']) > 63)))
i++;
if (++i < length)
{
/* skip invalid characters and assign second decoded char */
while ((i < length) && ((data.at(i) < '+') || (data.at(i) > 'z') || ((c2 = dec_base64[data.at(i) - '+']) > 63)))
i++;
if (i < length)
{
/* decode first byte */
result[count++] = OFstatic_cast(unsigned char, (c1 << 2) | ((c2 >> 4) & 0x3));
if (++i < length)
{
/* skip invalid characters and assign third decoded char */
while ((i < length) && ((data.at(i) < '+') || (data.at(i) > 'z') || ((c1 = dec_base64[data.at(i) - '+']) > 63)))
i++;
if (i < length)
{
/* decode second byte */
result[count++] = OFstatic_cast(unsigned char, ((c2 << 4) & 0xf0) | ((c1 >> 2) & 0xf));
if (++i < length)
{
/* skip invalid characters and assign fourth decoded char */
while ((i < length) && ((data.at(i) < '+') || (data.at(i) > 'z') || ((c2 = dec_base64[data.at(i) - '+']) > 63)))
i++;
/* decode third byte */
if (i < length)
result[count++] = OFstatic_cast(unsigned char, ((c1 << 6) & 0xc0) | c2);
}
}
}
}
}
}
/* delete buffer if no data has been written to the output */
if (count == 0)
delete[] result;
}
} else
result = NULL;
return count;
}
自己实现的Base64编码;
将待处理的字符串,按照3个字节为一组进行处理;
void base64_encode(std::vector<unsigned char>& s, std::string& code) {
code.clear();
code.reserve((s.size() / 3 + 1) * 4);
int i = 0;
int j = 0;
unsigned char char_array_3[3];
unsigned char char_array_4[4];
int last_pos = s.size() / 3 * 3;
for (size_t vs = 0; vs < last_pos; vs += 3) {
memcpy(char_array_3, s.data() + vs, 3);
char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
char_array_4[3] = char_array_3[2] & 0x3f;
for (int i = 0; i < 4; i++)
code += base64_chars[char_array_4[i]];
}
int remainder_numb = s.size() % 3;
if (remainder_numb != 0) {
memset(char_array_3, 0, 3);
memcpy(char_array_3, s.data() + last_pos, s.size() % 3);
char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
char_array_4[3] = char_array_3[2] & 0x3f;
for (j = 0; j < remainder_numb + 1; j++)
code += base64_chars[char_array_4[j]];
code.append(4 - (remainder_numb + 1), '=');
}
}
多线程处理Base64转换
将一个待处理的字符串,根据3个字节为一块,N个块为一组;开启一个线程处理一组字符串转为base64字符串,处理完后append拼接在一起;
void base64_encode_mult(std::vector<unsigned char>& s, std::string& code) {
code.clear();
const int N = std::thread::hardware_concurrency() / 2;
size_t num_block = s.size() / 3;
size_t mid_pos = num_block / N * 3;
std::vector<std::string> base64_strs;
base64_strs.resize(N);
std::vector<std::thread> th_list;
using Func = void(*)(unsigned char * bytes_to_encode, unsigned int in_len, std::string& code);
Func f1 = &base64_encode;
for (int i = 0; i < N - 1; i++) {
th_list.push_back(std::thread(f1, s.data() + mid_pos * i, mid_pos, std::ref(base64_strs[i])));
}
th_list.push_back(std::thread(f1, s.data() + mid_pos * (N - 1), s.size() - mid_pos * (N - 1), std::ref(base64_strs[N - 1])));
for (std::size_t i = 0; i < th_list.size(); i++) {
th_list[i].join();
code.append(base64_strs[i]);
}
}
void base64_encode(unsigned char * bytes_to_encode, unsigned int in_len, std::string& code) {
code.clear();
code.reserve((in_len / 3 + 1) * 4);
int i = 0;
int j = 0;
unsigned char char_array_3[3];
unsigned char char_array_4[4];
int last_pos = in_len / 3 * 3;
for (size_t vs = 0; vs < last_pos; vs += 3) {
memcpy(char_array_3, bytes_to_encode + vs, 3);
char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
char_array_4[3] = char_array_3[2] & 0x3f;
for (int i = 0; i < 4; i++)
code += base64_chars[char_array_4[i]];
}
int remainder_numb = in_len % 3;
if (remainder_numb != 0) {
memset(char_array_3, 0, 3);
memcpy(char_array_3, bytes_to_encode + last_pos, in_len % 3);
char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
char_array_4[3] = char_array_3[2] & 0x3f;
for (j = 0; j < remainder_numb + 1; j++)
code += base64_chars[char_array_4[j]];
code.append(4 - (remainder_numb + 1), '=');
}
}