base64.cc
Go to the documentation of this file.
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); // this appends to the most significant bit
00017       src <<= 1; // Instead, append to the least significant bit
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 (/*0 <= c &&*/ c <= 25)   // A..Z
00030       dst[dst.size()-1-i] = static_cast<char>(c+65);
00031     else if (26 <= c && c <= 51) // a..z 
00032       dst[dst.size()-1-i] = static_cast<char>(c+97-26);
00033     else if (52 <= c && c <= 61) // 0..9
00034       dst[dst.size()-1-i] = static_cast<char>(c+48-52);
00035     else if (c == 62)
00036       dst[dst.size()-1-i] = '-'; // for URL instread of '+'
00037     else if (c == 63)
00038       dst[dst.size()-1-i] = '_'; // for URL instread of '/'
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)       // 0..9
00080       tmp = c -48+52;
00081     else if (65 <= c && c <= 65+25) // A..Z
00082       tmp = c - 65;
00083     else if (97 <= c && c <= 97+25) // a..z
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(/*0 <= tmp &&*/ 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 // ;;; Local Variables:
00106 // ;;; mode:c++
00107 // ;;; c-basic-offset:2
00108 // ;;; End:
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines