00001
00004
00005
00006
00007
00008 #ifndef _cel_base64_h_
00009 #define _cel_base64_h_
00010
00011 #include "cel_string.h"
00012 #include "cel_memory.h"
00013
00014 namespace Celartem
00015 {
00020 template<typename Base64Traits> struct Base64T
00021 {
00031 static String encode(const u8 * CEL_RESTRICT src, size_t size)
00032 {
00033 if(size == 0)
00034 return String(L"");
00035
00036 String str;
00037 UChar1 *p = str.allocate((size + 2) / 3 * 4);
00038 for(;;)
00039 {
00040 if(size <= 3)
00041 {
00042 encode_3bytes(p, src, size);
00043 return str;
00044 }
00045
00046 encode_3bytes(p, src, 3);
00047 p += 4;
00048 src += 3;
00049 size -= 3;
00050 }
00051 }
00052
00060 static void decode(SimpleArray<u8>& buffer, const String& src)
00061 {
00062 size_t n = src.getLength() / 4;
00063 buffer.resize(n * 3);
00064 u8 *p = &buffer[0];
00065 const UChar1 *q = src.c_str();
00066 size_t realSize = 0;
00067 for(size_t i = 0; i < n; i++)
00068 {
00069 realSize += decode_4chars(p, q);
00070 p += 3;
00071 q += 4;
00072 }
00073 buffer.resize(realSize);
00074 return;
00075 }
00076
00077 static void encode_3bytes(
00078 char * CEL_RESTRICT buffer,
00079 const u8 * CEL_RESTRICT src, size_t size)
00080 {
00081 u8 tmp[3] = {0, 0, 0};
00082 for(size_t i = 0; i < size; i++)
00083 tmp[i] = src[i];
00084
00085 buffer[0] = (char)Base64Traits::enc(tmp[0] >> 2);
00086 buffer[1] = (char)Base64Traits::enc(((tmp[0] & 3) << 4) | (tmp[1] >> 4));
00087 buffer[2] = (char)Base64Traits::enc(((tmp[1] & 15) << 2) | (tmp[2] >> 6));
00088 buffer[3] = (char)Base64Traits::enc(tmp[2] & 63);
00089
00090 if(size == 1) buffer[2] = '=';
00091 if(size <= 2) buffer[3] = '=';
00092 }
00093
00094 static size_t decode_4chars(
00095 u8 * CEL_RESTRICT buffer,
00096 const UChar1 * CEL_RESTRICT src)
00097 {
00098 int tmp[4];
00099 for(size_t i = 0; i < 4; i++)
00100 tmp[i] = Base64Traits::dec(src[i]);
00101
00102 buffer[0] = (tmp[0] << 2) | (tmp[1] >> 4);
00103 if(tmp[2] < 0)
00104 return 1;
00105
00106 buffer[1] = ((tmp[1] & 15) << 4) | (tmp[2] >> 2);
00107 if(tmp[3] < 0)
00108 return 2;
00109
00110 buffer[2] = ((tmp[2] & 3) << 6) | tmp[3];
00111 return 3;
00112 }
00113 };
00114
00118 struct Base64Traits_A
00119 {
00120 static int dec(int c)
00121 {
00122 if(c >= 'A' && c <= 'Z') return c - 'A';
00123 if(c >= 'a' && c <= 'z') return c - 'a' + 26;
00124 if(c >= '0' && c <= '9') return c - '0' + 52;
00125 if(c == '+') return 62;
00126 if(c == '/') return 63;
00127 return -1;
00128 }
00129
00130 static int enc(int w)
00131 {
00132 if(w <= 25) return (int)w + 'A';
00133 if(w <= 51) return (int)w - 26 + 'a';
00134 if(w <= 61) return (int)w - 52 + '0';
00135 if(w == 62) return '+';
00136 return '/';
00137 }
00138 };
00139
00143 struct UrlSafeBase64Traits
00144 {
00145 static int dec(int c)
00146 {
00147 if(c >= 'A' && c <= 'Z') return c - 'A';
00148 if(c >= 'a' && c <= 'z') return c - 'a' + 26;
00149 if(c >= '0' && c <= '9') return c - '0' + 52;
00150 if(c == '-') return 62;
00151 if(c == '!') return 63;
00152 return -1;
00153 }
00154
00155 static int enc(int w)
00156 {
00157 if(w <= 25) return (int)w + 'A';
00158 if(w <= 51) return (int)w - 26 + 'a';
00159 if(w <= 61) return (int)w - 52 + '0';
00160 if(w == 62) return '-';
00161 return '!';
00162 }
00163 };
00164
00179 typedef Base64T<Base64Traits_A> Base64;
00180
00186 typedef Base64T<UrlSafeBase64Traits> UrlSafeBase64;
00187
00188
00189 }
00190
00191 #endif // _cel_base64_h_
00192