00001 #include "osl/misc/base64.h"
00002 #include "osl/stl/vector.h"
00003 #include <boost/foreach.hpp>
00004
00005 std::string osl::misc::
00006 base64Encode(boost::dynamic_bitset<> src)
00007 {
00008 if (src.empty())
00009 return "";
00010
00011 const size_t bits_to_add = 6 - src.size()%6;
00012 if (bits_to_add < 6)
00013 {
00014 for (size_t i=0; i<bits_to_add; ++i)
00015 {
00016 src.push_back(0ul);
00017 src <<= 1;
00018 }
00019 }
00020 assert(src.size()%6 == 0);
00021 assert(src.size()/6 > 0);
00022
00023 vector<char> dst(src.size()/6, 0);
00024 const boost::dynamic_bitset<> mask(src.size(), 63ul);
00025 for (size_t i=0; i<dst.size(); ++i)
00026 {
00027 const unsigned long c = ((src >> i*6) & mask).to_ulong();
00028 assert (c <= 63);
00029 if ( c <= 25)
00030 dst[dst.size()-1-i] = static_cast<char>(c+65);
00031 else if (26 <= c && c <= 51)
00032 dst[dst.size()-1-i] = static_cast<char>(c+97-26);
00033 else if (52 <= c && c <= 61)
00034 dst[dst.size()-1-i] = static_cast<char>(c+48-52);
00035 else if (c == 62)
00036 dst[dst.size()-1-i] = '-';
00037 else if (c == 63)
00038 dst[dst.size()-1-i] = '_';
00039 else
00040 {
00041 assert(false);
00042 return "";
00043 }
00044 }
00045
00046 const size_t char_to_add = 4 - dst.size()%4;
00047 if (char_to_add < 4)
00048 {
00049 for (size_t i=0; i<char_to_add; ++i)
00050 dst.push_back('=');
00051 }
00052
00053 return std::string(dst.begin(), dst.end());
00054 }
00055
00056 boost::dynamic_bitset<> osl::misc::
00057 base64Decode(std::string src)
00058 {
00059 if (src.empty() || src.size()%4 != 0)
00060 return boost::dynamic_bitset<>(0);
00061
00062 {
00063 int count = 0;
00064 while (src[src.size()-1] == '=')
00065 {
00066 src.erase(src.end()-1);
00067 ++count;
00068 }
00069 if (count >= 4)
00070 return boost::dynamic_bitset<>(0);
00071 }
00072
00073 const size_t dst_size = src.size()*6;
00074 const size_t redundant = dst_size%8;
00075 boost::dynamic_bitset<> dst(dst_size, 0ul);
00076 BOOST_FOREACH(char c, src)
00077 {
00078 unsigned long tmp = 0;
00079 if (48 <= c && c <= 48+9)
00080 tmp = c -48+52;
00081 else if (65 <= c && c <= 65+25)
00082 tmp = c - 65;
00083 else if (97 <= c && c <= 97+25)
00084 tmp = c -97+26;
00085 else if (c == '-')
00086 tmp = 62;
00087 else if (c == '_')
00088 tmp = 63;
00089 else
00090 {
00091 assert(false);
00092 return boost::dynamic_bitset<>(0);
00093 }
00094 assert( tmp <= 63);
00095 const boost::dynamic_bitset<> mask(dst_size, tmp);
00096 dst = (dst << 6) | mask;
00097 }
00098 if (redundant > 0)
00099 {
00100 dst >>= redundant;
00101 dst.resize(dst.size()-redundant);
00102 }
00103 return dst;
00104 }
00105
00106
00107
00108