mogmail - Base64変換
まだ改良の余地はあると思う。
・base64.h
1: // Copyright (c) 2011 Mog Project. All rights reserved.
2: 3: #ifndef _MOG_UTIL_BASE64_H_
4: #define _MOG_UTIL_BASE64_H_
5: #pragma once
6: 7: #include <vector>
8: #include <string>
9: 10: namespace mog {
11: namespace util {
12: 13: // A class manages Base64 encoding/decoding.
14: class Base64 {
15: public:
16: // Plain data to Base64.
17: static std::string Encode(std::string const& in_value, bool insert_line_breaks = true);
18: static void Encode(std::string const& in_value, std::string * out_value, bool insert_line_breaks = true);
19: // Base64 to plain data.
20: static std::string Decode(std::string const& in_value);
21: static void Decode(std::string const& in_value, std::string * out_value);
22: private:
23: Base64();24: explicit Base64(Base64 const&);
25: void operator=(Base64 const&);
26: }; 27: 28: } // namespace util
29: } // namespace mog
30: #endif // _MOG_UTIL_BASE64_H_
・base64.cc
1: // Copyright (c) 2011 Mog Project. All rights reserved.
2: 3: #include "base64.h"
4: #include <assert.h>
5: #include <stdint.h>
6: #include <algorithm>
7: 8: namespace mog {
9: namespace util {
10: 11: ////////////////////////////////////////////////////////////////////////////////
12: // Base64
13: namespace {
14: 15: static std::string const kEncodeTable = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
16: static char const kEncodePadding = '=';
17: 18: class Base64Buffer {
19: public:
20: explicit Base64Buffer(bool insert_line_breaks = true)
21: : insert_line_breaks_(insert_line_breaks), current_bits_(0), total_bits_(0), data_(0) {}22: bool IsEmpty() { return 0 == current_bits_; }
23: bool IsFull() { return current_bits_ >= 24; }
24: void Push6Bits(char ch) { PushData(ch, 6); }
25: void Push8Bits(char ch) { PushData(ch, 8); }
26: void PopEncoded(std::string * out_value) {
27: assert(current_bits_ != 0); 28: 29: for (int i = 0; i < 24; i += 6) {
30: if (i <= current_bits_) {
31: out_value->push_back(kEncodeTable.at((data_ >> (18 - i)) & 0x3f));32: } else {
33: out_value->push_back(kEncodePadding); 34: } 35: } 36: current_bits_ = 0; 37: data_ = 0; 38: 39: if (insert_line_breaks_ && total_bits_ >= kMaxLineLength * 8) {
40: out_value->push_back('\n');
41: total_bits_ = 0; 42: } 43: }44: void PopDecoded(std::string * out_value) {
45: assert(current_bits_ >= 12); 46: 47: for (int i = 0; i < current_bits_ - 7; i += 8) {
48: out_value->push_back(static_cast<char>((data_ >> (16 - i)) & 0xff));
49: } 50: current_bits_ = 0; 51: data_ = 0; 52: } 53: 54: private:
55: static int const kMaxLineLength = 72;
56: bool insert_line_breaks_;
57: int current_bits_;
58: int total_bits_;
59: uint32_t data_; 60: 61: void PushData(char ch, int bits) {
62: current_bits_ += bits; 63: total_bits_ += bits; 64: assert(current_bits_ <= 24);65: data_ |= static_cast<uint8_t>(ch) << (24 - current_bits_);
66: } 67: }; 68: 69: } // namespace
70: 71: void Base64::Encode(std::string const& in_value, std::string * out_value, bool insert_line_breaks) {
72: out_value->clear(); 73: Base64Buffer buffer(insert_line_breaks); 74: 75: for (std::string::const_iterator it = in_value.begin(); it != in_value.end(); ++it) {
76: buffer.Push8Bits(*it);77: if (buffer.IsFull()) { buffer.PopEncoded(out_value); }
78: }79: if (!buffer.IsEmpty()) { buffer.PopEncoded(out_value); }
80: }81: std::string Base64::Encode(std::string const& in_value, bool insert_line_breaks) {
82: std::string out_value; 83: Encode(in_value, &out_value, insert_line_breaks);84: return out_value;
85: } 86: 87: void Base64::Decode(std::string const& in_value, std::string * out_value) {
88: out_value->clear(); 89: Base64Buffer buffer; 90: 91: for (std::string::const_iterator it = in_value.begin(); it != in_value.end(); ++it) {
92: switch (*it) {
93: case kEncodePadding: // End of data.
94: buffer.PopDecoded(out_value);95: return;
96: case '\r': case '\n':
97: break; // Ignore new line.
98: default:
99: std::string::const_iterator it_find = std::find(kEncodeTable.begin(), kEncodeTable.end(), *it);100: if (kEncodeTable.end() == it_find) {
101: throw std::runtime_error("Base64: invalid character found.");
102: }103: buffer.Push6Bits(static_cast<char>(std::distance(kEncodeTable.begin(), it_find)));
104: if (buffer.IsFull()) {
105: buffer.PopDecoded(out_value); 106: }107: break;
108: } 109: } 110: }111: std::string Base64::Decode(std::string const& in_value) {
112: std::string out_value; 113: Decode(in_value, &out_value);114: return out_value;
115: } 116: 117: } // namespace util
118: } // namespace mog
0 件のコメント:
コメントを投稿