2.03.2011

mogmail – JIStoSJIS converter

mogmail - JIStoSJIS変換

・character_converter.h

   1: // Copyright (c) 2011 Mog Project. All rights reserved.
   2:  
   3: #ifndef _MOG_UTIL_CHARACTER_CONVERTER_H_
   4: #define _MOG_UTIL_CHARACTER_CONVERTER_H_
   5: #pragma once
   6:  
   7: #include <string>
   8:  
   9: namespace mog {
  10: namespace util {
  11:  
  12: // A class manages character-code converting.
  13: class CharacterConverter {
  14:  public:
  15:   // convert JIS(ISO-2022-JP) std::string to Shift-JIS
  16:   static void JIStoSJIS(std::string const& jis, std::string * sjis);
  17:   static std::string JIStoSJIS(std::string const& jis);
  18:  
  19:  private:
  20:   enum JISFlags { FLAG_SINGLE_BYTE, FLAG_DOUBLE_BYTE, };
  21:   struct JISEscapeSequences {
  22:     char const* sequence;
  23:     JISFlags    flag;
  24:   };
  25:   static JISEscapeSequences const kJISEscapeSequences[];
  26: };
  27:  
  28: }  // namespace util
  29: }  // namespace mog
  30: #endif  // _MOG_UTIL_CHARACTER_CONVERTER_H_

・character_converter.cc

   1: // Copyright (c) 2011 Mog Project. All rights reserved.
   2:  
   3: #include "character_converter.h"
   4: #include <mbstring.h>
   5: #include <boost/foreach.hpp>
   6:  
   7: namespace mog {
   8: namespace util {
   9:  
  10: ////////////////////////////////////////////////////////////////////////////////
  11: // CharacterConverter
  12: CharacterConverter::JISEscapeSequences const CharacterConverter::kJISEscapeSequences[] = {
  13:   { "\x1b\x28\x42", CharacterConverter::FLAG_SINGLE_BYTE },  // reg#06 ASCII
  14:   { "\x1b\x28\x4a", CharacterConverter::FLAG_SINGLE_BYTE },  // reg#14 JIS X 0201-Roman
  15:   { "\x1b\x24\x40", CharacterConverter::FLAG_DOUBLE_BYTE },  // reg#42 old JIS kanji(JIS C 6226-1978)
  16:   { "\x1b\x24\x42", CharacterConverter::FLAG_DOUBLE_BYTE },  // reg#87 new JIS kanji(JIS X 0208-1983)
  17: };
  18:  
  19: void CharacterConverter::JIStoSJIS(std::string const& jis, std::string * sjis) {
  20:   sjis->clear();
  21:   JISFlags current_flag = FLAG_SINGLE_BYTE;
  22:  
  23:   for (std::string::const_iterator it = jis.begin(); it != jis.end(); ++it) {
  24:     if ('\x1b' == *it) {
  25:       BOOST_FOREACH(JISEscapeSequences esc, kJISEscapeSequences ) {
  26:         std::string::const_iterator it_end = it + std::string(esc.sequence).size();
  27:         if (esc.sequence == std::string(it, it_end)) {
  28:           current_flag = esc.flag;
  29:           it = it_end - 1;
  30:           break;
  31:         }
  32:       }
  33:       continue;
  34:     }
  35:     if (FLAG_DOUBLE_BYTE == current_flag) {
  36:       union {
  37:         struct {
  38:           char high;
  39:           char low;
  40:         } byte;
  41:         unsigned int word;
  42:       } double_byte;
  43:  
  44:       double_byte.byte.low = *it;
  45:       double_byte.byte.high = *(++it);
  46:       double_byte.word = _mbcjistojms(double_byte.word);
  47:       sjis->push_back(double_byte.byte.low);
  48:       sjis->push_back(double_byte.byte.high);
  49:     } else {
  50:       sjis->push_back(*it);
  51:     }
  52:   }
  53: }
  54:  
  55: std::string CharacterConverter::JIStoSJIS(std::string const& jis) {
  56:   std::string out_value;
  57:   JIStoSJIS(jis, &out_value);
  58:   return out_value;
  59: }
  60:  
  61: }  // namespace util
  62: }  // namespace mog

1.25.2011

mogmail – Base64 converter

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