Codecs.cpp

Go to the documentation of this file.
00001 #include "ace/Codecs.h"
00002 #include "ace/Log_Msg.h"
00003 #include "ace/OS_Memory.h"
00004 #include "ace/OS_NS_ctype.h"
00005 
00006 ACE_RCSID (ace,
00007            Codecs,
00008            "$Id: Codecs.cpp 80826 2008-03-04 14:51:23Z wotte $")
00009 
00010 namespace
00011 {
00012   // Just in case ...
00013 #undef alphabet
00014 #undef pad
00015 #undef max_columns
00016 
00017   // Symbols which form the Base64 alphabet (Defined as per RFC 2045)
00018   ACE_Byte const alphabet[] =
00019      "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
00020 
00021   // The padding character used in the encoding
00022   ACE_Byte const pad = '=';
00023 
00024   // Number of columns per line of encoded output (Can have a maximum
00025   // value of 76).
00026   int const max_columns = 72;
00027 }
00028 
00029 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
00030 
00031 bool ACE_Base64::init_ = false;
00032 
00033 ACE_Byte ACE_Base64::decoder_[256];
00034 
00035 ACE_Byte ACE_Base64::member_[256];
00036 
00037 ACE_Byte*
00038 ACE_Base64::encode (const ACE_Byte* input,
00039                     const size_t input_len,
00040                     size_t* output_len,
00041                     bool is_chunked)
00042 {
00043   if (!ACE_Base64::init_)
00044     ACE_Base64::init();
00045 
00046   if (!input)
00047     return 0;
00048 
00049   ACE_Byte* result = 0;
00050 
00051   size_t length = ((input_len + 2) / 3) * 4;
00052   size_t num_lines = length / max_columns + 1;
00053   length += num_lines + 1;
00054   ACE_NEW_RETURN (result, ACE_Byte[length], 0);
00055 
00056   int char_count = 0;
00057   int bits = 0;
00058   size_t pos = 0;
00059   int cols = 0;
00060 
00061   for (size_t i = 0; i < input_len; ++i)
00062     {
00063       bits += input[i];
00064       ++char_count;
00065 
00066       if (char_count == 3)
00067         {
00068           result[pos++] = alphabet[bits >> 18];
00069           result[pos++] = alphabet[(bits >> 12) & 0x3f];
00070           result[pos++] = alphabet[(bits >> 6) & 0x3f];
00071           result[pos++] = alphabet[bits & 0x3f];
00072           cols += 4;
00073           if (cols == max_columns) {
00074             if (is_chunked) 
00075               result[pos++] = '\n';
00076             cols = 0;
00077           }
00078           bits = 0;
00079           char_count = 0;
00080         }
00081       else
00082         {
00083           bits <<= 8;
00084         }
00085     }
00086 
00087   if (char_count != 0)
00088     {
00089       bits <<= (16 - (8 * char_count));
00090       result[pos++] = alphabet[bits >> 18];
00091       result[pos++] = alphabet[(bits >> 12) & 0x3f];
00092       cols += 2;
00093       if (char_count == 1)
00094         {
00095           result[pos++] = pad;
00096           result[pos++] = pad;
00097           cols += 2;
00098         }
00099       else
00100         {
00101           result[pos++] = alphabet[(bits >> 6) & 0x3f];
00102           result[pos++] = pad;
00103           cols += 2;
00104         }
00105     }
00106 
00107   if (cols > 0 && is_chunked)
00108     result[pos++] = '\n';
00109 
00110   result[pos] = 0;
00111   *output_len = pos;
00112   return result;
00113 }
00114 
00115 size_t
00116 ACE_Base64::length (const ACE_Byte* input)
00117 {
00118   if (!ACE_Base64::init_)
00119     ACE_Base64::init();
00120 
00121   ACE_Byte* ptr = const_cast<ACE_Byte*> (input);
00122   while (*ptr != 0 &&
00123          (member_[*(ptr)] == 1 || *ptr == pad
00124           || ACE_OS::ace_isspace (*ptr)))
00125     ++ptr;
00126   size_t len = ptr - input;
00127   len = ((len + 3) / 4) * 3 + 1 ;
00128   return len;
00129 }
00130 
00131 ACE_Byte*
00132 ACE_Base64::decode (const ACE_Byte* input, size_t* output_len)
00133 {
00134   if (!ACE_Base64::init_)
00135     ACE_Base64::init();
00136 
00137   if (!input)
00138     return 0;
00139 
00140   size_t result_len = ACE_Base64::length (input);
00141   ACE_Byte* result = 0;
00142   ACE_NEW_RETURN (result, ACE_Byte[result_len], 0);
00143 
00144   ACE_Byte* ptr = const_cast<ACE_Byte*> (input);
00145   while (*ptr != 0 &&
00146          (member_[*(ptr)] == 1 || *ptr == pad
00147           || ACE_OS::ace_isspace (*ptr)))
00148     ++ptr;
00149   size_t input_len = ptr - input;
00150 
00151   int char_count = 0;
00152   int bits = 0;
00153   size_t pos = 0;
00154 
00155   size_t i = 0;
00156   for (; i < input_len; ++i)
00157     {
00158       if (input[i] == pad)
00159         break;
00160       if (!ACE_Base64::member_[input[i]])
00161         continue;
00162       bits += decoder_[input[i]];
00163       ++char_count;
00164 
00165       if (char_count == 4)
00166         {
00167           result[pos++] = static_cast<ACE_Byte> (bits >> 16);
00168           result[pos++] = static_cast<ACE_Byte> ((bits >> 8) & 0xff);
00169           result[pos++] = static_cast<ACE_Byte> (bits & 0xff);
00170           bits = 0;
00171           char_count = 0;
00172         }
00173       else
00174         {
00175           bits <<= 6;
00176         }
00177     }
00178 
00179   int errors = 0;
00180   if ( i == input_len)
00181     {
00182       if (char_count)
00183         {
00184           ACE_ERROR ((LM_ERROR,
00185                       ACE_TEXT ("Decoding incomplete: atleast %d bits truncated\n"),
00186                       (4 - char_count) * 6));
00187           ++errors;
00188         }
00189     }
00190   else
00191     {
00192       switch (char_count)
00193         {
00194         case 1:
00195           ACE_ERROR ((LM_ERROR,
00196                       ACE_TEXT ("Decoding incomplete: atleast 2 bits missing\n")));
00197           ++errors;
00198           break;
00199         case 2:
00200           result[pos++] = static_cast<ACE_Byte> (bits >> 10);
00201           break;
00202         case 3:
00203           result[pos++] = static_cast<ACE_Byte> (bits >> 16);
00204           result[pos++] = static_cast<ACE_Byte> ((bits >> 8) & 0xff);
00205           break;
00206         }
00207     }
00208 
00209   if (errors)
00210     {
00211       delete[] result;
00212       return 0;
00213     }
00214   result[pos] = 0;
00215   *output_len = pos;
00216   return result;
00217 }
00218 
00219 void
00220 ACE_Base64::init ()
00221 {
00222   if (!ACE_Base64::init_)
00223     {
00224       for (ACE_Byte i = 0; i < sizeof (alphabet); ++i)
00225         {
00226           ACE_Base64::decoder_[alphabet[i]] = i;
00227           ACE_Base64::member_ [alphabet[i]] = 1;
00228         }
00229       ACE_Base64::init_ = true;
00230     }
00231   return;
00232 }
00233 
00234 ACE_END_VERSIONED_NAMESPACE_DECL

Generated on Tue Feb 2 17:18:38 2010 for ACE by  doxygen 1.4.7