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 件のコメント:
コメントを投稿