ZenLib
base64.h
Go to the documentation of this file.
00001 //  //
00002 // ####   ###     ##                -= Base64 library =-                 //
00003 // #   # #       # # Base64.h - Base64 encoder/decoder                   //
00004 // ####  ####   #  #                                                     //
00005 // #   # #   # ##### Encodes and decodes base64 strings                  //
00006 // #   # #   #     # Ideas taken from work done by Bob Withers           //
00007 // ####   ###      # R1                      2002-05-07 by Markus Ewald  //
00008 //  //
00009 #ifndef B64_BASE64_H
00010 #define B64_BASE64_H
00011 
00012 #include <string>
00013 
00014 namespace Base64 {
00015 
00016   /// Encode string to base64
00017   inline std::string encode(const std::string &sString);
00018   /// Encode base64 into string
00019   inline std::string decode(const std::string &sString);
00020 
00021 }; // namespace Base64
00022 
00023 // ####################################################################### //
00024 // # Base64::encode()                                                    # //
00025 // ####################################################################### //
00026 /** Encodes the specified string to base64
00027 
00028     @param  sString  String to encode
00029     @return Base64 encoded string
00030 */
00031 inline std::string Base64::encode(const std::string &sString) {
00032   static const std::string sBase64Table(
00033   // 0000000000111111111122222222223333333333444444444455555555556666
00034   // 0123456789012345678901234567890123456789012345678901234567890123
00035     "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
00036   );
00037   static const char cFillChar = '=';
00038   std::string::size_type   nLength = sString.length();
00039   std::string              sResult;
00040 
00041   // Allocate memory for the converted string
00042   sResult.reserve(nLength * 8 / 6 + 1);
00043 
00044   for(std::string::size_type nPos = 0; nPos < nLength; nPos++) {
00045     char cCode;
00046   
00047     // Encode the first 6 bits
00048     cCode = (sString[nPos] >> 2) & 0x3f;
00049     sResult.append(1, sBase64Table[cCode]);
00050 
00051     // Encode the remaining 2 bits with the next 4 bits (if present)
00052     cCode = (sString[nPos] << 4) & 0x3f;
00053     if(++nPos < nLength)
00054       cCode |= (sString[nPos] >> 4) & 0x0f;
00055     sResult.append(1, sBase64Table[cCode]);
00056 
00057     if(nPos < nLength) {
00058       cCode = (sString[nPos] << 2) & 0x3f;
00059       if(++nPos < nLength)
00060         cCode |= (sString[nPos] >> 6) & 0x03;
00061 
00062       sResult.append(1, sBase64Table[cCode]);
00063     } else {
00064       ++nPos;
00065       sResult.append(1, cFillChar);
00066     }
00067 
00068     if(nPos < nLength) {
00069       cCode = sString[nPos] & 0x3f;
00070       sResult.append(1, sBase64Table[cCode]);
00071     } else {
00072       sResult.append(1, cFillChar);
00073     }
00074   }
00075 
00076   return sResult;
00077 }
00078 
00079 // ####################################################################### //
00080 // # Base64::decode()                                                    # //
00081 // ####################################################################### //
00082 /** Decodes the specified base64 string
00083 
00084     @param  sString  Base64 string to decode
00085     @return Decoded string
00086 */
00087 inline std::string Base64::decode(const std::string &sString) {
00088   static const std::string::size_type np = std::string::npos;
00089   static const std::string::size_type DecodeTable[] = {
00090   // 0   1   2   3   4   5   6   7   8   9 
00091     np, np, np, np, np, np, np, np, np, np,  //   0 -   9
00092     np, np, np, np, np, np, np, np, np, np,  //  10 -  19
00093     np, np, np, np, np, np, np, np, np, np,  //  20 -  29
00094     np, np, np, np, np, np, np, np, np, np,  //  30 -  39
00095     np, np, np, 62, np, np, np, 63, 52, 53,  //  40 -  49
00096     54, 55, 56, 57, 58, 59, 60, 61, np, np,  //  50 -  59
00097     np, np, np, np, np,  0,  1,  2,  3,  4,  //  60 -  69
00098      5,  6,  7,  8,  9, 10, 11, 12, 13, 14,  //  70 -  79
00099     15, 16, 17, 18, 19, 20, 21, 22, 23, 24,  //  80 -  89
00100     25, np, np, np, np, np, np, 26, 27, 28,  //  90 -  99
00101     29, 30, 31, 32, 33, 34, 35, 36, 37, 38,  // 100 - 109
00102     39, 40, 41, 42, 43, 44, 45, 46, 47, 48,  // 110 - 119
00103     49, 50, 51, np, np, np, np, np, np, np,  // 120 - 129
00104     np, np, np, np, np, np, np, np, np, np,  // 130 - 139
00105     np, np, np, np, np, np, np, np, np, np,  // 140 - 149
00106     np, np, np, np, np, np, np, np, np, np,  // 150 - 159
00107     np, np, np, np, np, np, np, np, np, np,  // 160 - 169
00108     np, np, np, np, np, np, np, np, np, np,  // 170 - 179
00109     np, np, np, np, np, np, np, np, np, np,  // 180 - 189
00110     np, np, np, np, np, np, np, np, np, np,  // 190 - 199
00111     np, np, np, np, np, np, np, np, np, np,  // 200 - 209
00112     np, np, np, np, np, np, np, np, np, np,  // 210 - 219
00113     np, np, np, np, np, np, np, np, np, np,  // 220 - 229
00114     np, np, np, np, np, np, np, np, np, np,  // 230 - 239
00115     np, np, np, np, np, np, np, np, np, np,  // 240 - 249
00116     np, np, np, np, np, np                   // 250 - 256
00117   };
00118   static const char cFillChar = '=';
00119 
00120   std::string::size_type nLength = sString.length();
00121   std::string            sResult;
00122 
00123   sResult.reserve(nLength);
00124 
00125   for(std::string::size_type nPos = 0; nPos < nLength; nPos++) {
00126     unsigned char c, c1;
00127 
00128     c = (char) DecodeTable[(unsigned char)sString[nPos]];
00129     nPos++;
00130     c1 = (char) DecodeTable[(unsigned char)sString[nPos]];
00131     c = (c << 2) | ((c1 >> 4) & 0x3);
00132     sResult.append(1, c);
00133 
00134     if(++nPos < nLength) {
00135       c = sString[nPos];
00136       if(cFillChar == c)
00137         break;
00138 
00139       c = (char) DecodeTable[(unsigned char)sString[nPos]];
00140       c1 = ((c1 << 4) & 0xf0) | ((c >> 2) & 0xf);
00141       sResult.append(1, c1);
00142     }
00143 
00144     if(++nPos < nLength) {
00145       c1 = sString[nPos];
00146       if(cFillChar == c1)
00147         break;
00148 
00149       c1 = (char) DecodeTable[(unsigned char)sString[nPos]];
00150       c = ((c << 6) & 0xc0) | c1;
00151       sResult.append(1, c);
00152     }
00153   }
00154 
00155   return sResult;
00156 }
00157 
00158 #endif // B64_BASE64_H