这段两天研究base64编码与解码,基本上也搞出个大概来,主要的思想就是三个字节转换成为四个字节。还有一个小的概念性问题,就是编码后添加的=号是指原文本数量增加一或者两个字节后将满足长度能被3整除这个原则,并且这一个或者两个=号与编码后的文本合并在一起后将组成一个长度能被4整除的字符串序列。在今后的asio网络编程中,base64的编码与解码看起来应该会比较重要了。c++测试编码与解码的源代码如下,注:其中使用的测试文本为维基百科上的关于base64中提到的样例文本,但是我的程序中编码将会多编入一个字符串结束符,所以编码出来的文本会略有不同。(详情见:http://zh.wikipedia.org/zh/Base64

#include <iostream>
#include <vector>
#include <bitset>
#include <string>
#include <utility>
#include <boost/shared_ptr.hpp>
 
namespace base64 {
 
typedef unsigned char byte;
typedef boost::shared_ptr<char> ptr;
typedef std::pair<ptr, std::size_t> buffer;
 
struct delete_array_func {
    void operator ()(char* p) const {
        delete[] p;
    }
};
 
class base64_error : public std::runtime_error {
public:
    base64_error(char const* error) : std::runtime_error(error) {
    }
};
 
inline buffer make_buffer(ptr p, std::size_t size) {
    return std::make_pair(p, size);
}
 
class base64_conv {
public:
    base64_conv() {
    }
    char index_to_char(byte index) const {
        char const* chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
        if (index >= 0 && index <= 63) return chars[index];
        else throw base64_error("invalid index!");
    }
    byte char_to_index(char ch) const {
        if (ch >= 'A' && ch <= 'Z') return ch - 'A';
        else if (ch >= 'a' && ch <= 'z') return ch - 'a' + 26;
        else if (ch >= '0' && ch <= '9') return ch - '0' + 26 * 2;
        else if (ch == '+') return 26 * 2 + 10;
        else if (ch == '/') return 26 * 2 + 11;
        else throw base64_error("invalid char!");
    }
};
 
template <typename Base64Converter>
class base64 {
public:
    base64() {
    }
    std::string encode(char const* p, std::size_t size) const {
        std::string result;
        // 循环取出每三个字符作为一组
        std::size_t curr = 0;
        while (curr < size) {
            std::string bin_str;
            int padding_chars = 0;
            for (std::size_t i = 0; i < 3; ++i) {
                if (curr + i < size) {
                    // 该字节的数据存在,直接转成二进制字符串
                    std::bitset<8> b(p[curr + i]);
                    bin_str += b.to_string();
                } else {
                    // 该字节的数据不存在,直接增加8个零
                    ++padding_chars;
                }
            }
            // 补齐6的差数
            auto padding_indexes = padding_count(static_cast<int>(bin_str.size()), 6);
            for (int i = 0; i < padding_indexes; ++i) bin_str += "0";
            // 循环每6个位一组转换成为序号
            std::size_t idx = 0;
            while (idx < bin_str.size()) {
                auto six = bin_str.substr(idx, 6);
                std::bitset<6> b(six);
                result += conv_.index_to_char(static_cast<byte>(b.to_ulong()));
                idx += 6;
            }
            // 补齐=号
            for (int i = 0; i < padding_chars; ++i) result += '=';
            // 下一组
            curr += 3;
        }
        return result;
    }
    buffer decode(std::string const& str) const {
        // 首先,str的长度一定是4的倍数
        if (str.size() % 4 != 0) throw base64_error("input string length is invalid!");
        // 计算出真正的长度,并且分配存储空间
        std::size_t real_size = str.size() * 6 / 8 - std::count(str.begin(), str.end(), '='); // 真正的缓冲的长度
        ptr p(new char[real_size], delete_array_func());
        // 4个字符取出转换为3个字节的数据,然后保存到临时的buff中
        std::size_t curr = 0, out_p = 0;
        while (curr < str.size()) {
            std::string bin_str;
            std::size_t padding_chars = 0;
            for (int i = 0; i < 4; ++i) {
                if (str[curr + i] != '=')
                    bin_str += std::bitset<6>(conv_.char_to_index(str[curr + i])).to_string();
                else ++padding_chars;
            }
            for (std::size_t i = 0; i < 3 - padding_chars; ++i) {
                p.get()[out_p++] = static_cast<char>(std::bitset<8>(bin_str.substr(i * 8, 8)).to_ulong());
            }
            curr += 4;
        }
        // 返回结果
        return std::make_pair(p, real_size);
    }
private:
    template <typename T>
    T padding_count(T size, T base) const {
        auto m = base - (size % base);
        return m == base ? 0 : m;
    }
private:
    Base64Converter conv_;
};
 
typedef base64<base64_conv> base64_codec;
 
}
 
int main() {
    char const* source = "Man is distinguished, not only by his reason, but by this singular passion from other animals, which is a lust of the mind, that by a perseverance of delight in the continued and indefatigable generation of knowledge, exceeds the short vehemence of any carnal pleasure.";
    base64::base64_codec b64;
    // encode
    auto out = b64.encode(source, strlen(source) + 1);
    std::cout << "encoded size = " << out.size() << std::endl;
    std::cout << out << std::endl;
    // decode
    auto buf = b64.decode(out);
    std::cout << "decoded size = " << buf.second << std::endl;
    std::cout << buf.first.get() << std::endl;
    return 0;
}