llbase32.cpp

Go to the documentation of this file.
00001 
00067 #include "linden_common.h"
00068 
00069 #include "llbase32.h"
00070 
00071 #include <string>
00072 
00073 // bitter - base32.c starts here
00074 
00075 /*
00076  * See RFC 3548 for details about Base 32 encoding:
00077  *  http://www.faqs.org/rfcs/rfc3548.html
00078  */
00079 
00080 static const char base32_alphabet[32] = {
00081   'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
00082   'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
00083   'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
00084   'Y', 'Z', '2', '3', '4', '5', '6', '7'
00085 };
00086 
00087 size_t
00088 base32_encode(char *dst, size_t size, const void *data, size_t len)
00089 {
00090   size_t i = 0;
00091   const U8 *p = (const U8*)data;
00092   const char *end = &dst[size];
00093   char *q = dst;
00094 
00095   do {
00096     size_t j, k;
00097     U8 x[5];
00098     char s[8];
00099 
00100     switch (len - i) {
00101     case 4: k = 7; break;
00102     case 3: k = 5; break;
00103     case 2: k = 3; break;
00104     case 1: k = 2; break;
00105     default:
00106       k = 8;
00107     }
00108 
00109     for (j = 0; j < 5; j++)
00110       x[j] = i < len ? p[i++] : 0;
00111 
00112 /*
00113   +-------+-----------+--------+
00114   | target| source    | source |
00115   | byte  | bits      | byte   |
00116   +-------+-----------+--------+
00117   |     0 | 7 6 5 4 3 | 0      |
00118   |     1 | 2 1 0 7 6 | 0-1    |
00119   |     2 | 5 4 3 2 1 | 1      |
00120   |     3 | 0 7 6 5 4 | 1-2    |
00121   |     4 | 3 2 1 0 7 | 2-3    |
00122   |     5 | 6 5 4 3 2 | 3      |
00123   |     6 | 1 0 7 6 5 | 3-4    |
00124   |     7 | 4 3 2 1 0 | 4      |
00125   +-------+-----------+--------+
00126   
00127 */
00128     
00129     s[0] =  (x[0] >> 3);
00130     s[1] = ((x[0] & 0x07) << 2) | (x[1] >> 6);
00131     s[2] =  (x[1] >> 1) & 0x1f;
00132     s[3] = ((x[1] & 0x01) << 4) | (x[2] >> 4);
00133     s[4] = ((x[2] & 0x0f) << 1) | (x[3] >> 7);
00134     s[5] =  (x[3] >> 2) & 0x1f;
00135     s[6] = ((x[3] & 0x03) << 3) | (x[4] >> 5);
00136     s[7] =   x[4] & 0x1f;
00137 
00138     for (j = 0; j < k && q != end; j++)
00139       *q++ = base32_alphabet[(U8) s[j]];
00140 
00141   } while (i < len);
00142 
00143   return q - dst;
00144 }
00145 
00146 /* *TODO: Implement base32 encode.
00147 
00148 #define ARRAY_LEN(a) (sizeof (a) / sizeof((a)[0]))
00149 
00150 static inline int
00151 ascii_toupper(int c)
00152 {
00153   return c >= 97 && c <= 122 ? c - 32 : c;
00154 }
00155 
00156 static inline int
00157 ascii_tolower(int c)
00158 {
00159   return c >= 65 && c <= 90 ? c + 32 : c;
00160 }
00161 
00162 
00163 static char base32_map[(unsigned char) -1];
00164 
00165 size_t
00166 base32_decode(char *dst, size_t size, const void *data, size_t len)
00167 {
00168   const char *end = &dst[size];
00169   const unsigned char *p = data;
00170   char *q = dst;
00171   size_t i;
00172   unsigned max_pad = 3;
00173 
00174   if (0 == base32_map[0]) {
00175     for (i = 0; i < ARRAY_LEN(base32_map); i++) {
00176       const char *x;
00177       
00178       x = memchr(base32_alphabet, ascii_toupper(i), sizeof base32_alphabet);
00179       base32_map[i] = x ? (x - base32_alphabet) : (unsigned char) -1;
00180     }
00181   }
00182   
00183   for (i = 0; i < len && max_pad > 0; i++) {
00184     unsigned char c;
00185     char s[8];
00186     size_t j;
00187 
00188     c = p[i];
00189     if ('=' == c) {
00190       max_pad--;
00191       c = 0;
00192     } else {
00193       c = base32_map[c];
00194       if ((unsigned char) -1 == c) {
00195         return -1;
00196       }
00197     }
00198 
00199     j = i % ARRAY_LEN(s);
00200     s[j] = c;
00201 
00202     if (7 == j) {
00203       char b[5];
00204 
00205       b[0] = ((s[0] << 3) & 0xf8) | ((s[1] >> 2) & 0x07);
00206       b[1] = ((s[1] & 0x03) << 6) | ((s[2] & 0x1f) << 1) | ((s[3] >> 4) & 1);
00207       b[2] = ((s[3] & 0x0f) << 4) | ((s[4] >> 1) & 0x0f);
00208       b[3] = ((s[4] & 1) << 7) | ((s[5] & 0x1f) << 2) | ((s[6] >> 3) & 0x03);
00209       b[4] = ((s[6] & 0x07) << 5) | (s[7] & 0x1f);
00210 
00211       for (j = 0; j < ARRAY_LEN(b); j++) {
00212         if (q != end)
00213           *q = b[j];
00214         q++;
00215       }
00216     }
00217   }
00218 
00219   return q - dst;
00220 }
00221 */
00222 
00223 
00224 // The following is
00225 // Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
00226 // static
00227 std::string LLBase32::encode(const U8* input, size_t input_size)
00228 {
00229         std::string output;
00230         if (input)
00231         {
00232                 // Each 5 byte chunk of input is represented by an
00233                 // 8 byte chunk of output.
00234                 size_t input_chunks = (input_size + 4) / 5;
00235                 size_t output_size = input_chunks * 8;
00236 
00237                 output.resize(output_size);
00238 
00239                 size_t encoded = base32_encode(&output[0], output_size, input, input_size);
00240 
00241                 llinfos << "encoded " << encoded << " into buffer of size "
00242                         << output_size << llendl;
00243         }
00244         return output;
00245 }

Generated on Thu Jul 1 06:08:19 2010 for Second Life Viewer by  doxygen 1.4.7