00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #ifndef OPENMS_FORMAT_BASE64_H
00028 #define OPENMS_FORMAT_BASE64_H
00029
00030 #ifndef OPENMS_IS_BIG_ENDIAN
00031 #if defined OPENMS_BIG_ENDIAN
00032 #define OPENMS_IS_BIG_ENDIAN true
00033 #else
00034 #define OPENMS_IS_BIG_ENDIAN false
00035 #endif
00036 #endif
00037
00038 #include <cmath>
00039 #include <OpenMS/CONCEPT/Types.h>
00040
00041 #include <string>
00042 #include <vector>
00043
00044 namespace OpenMS
00045 {
00052 class Base64
00053 {
00054 public:
00056 Base64();
00057
00059 virtual ~Base64();
00060
00061 enum ByteOrder{BYTEORDER_BIGENDIAN,BYTEORDER_LITTLEENDIAN};
00062
00068 template <typename FromType>
00069 void encode(std::vector<FromType>& in, ByteOrder to_byte_order, std::string& out);
00070
00076 template <typename ToType>
00077 void decode(const std::string& in, ByteOrder from_byte_order, std::vector<ToType>& out);
00078
00079 private:
00080 static const char encoder_[];
00081 static const char decoder_[];
00082 };
00083
00084
00085 template <typename FromType>
00086 void Base64::encode(std::vector<FromType>& in, ByteOrder to_byte_order, std::string& out)
00087 {
00088 bool convert = false;
00089 out = std::string();
00090 if (in.size() == 0) return;
00091
00092 if ((OPENMS_IS_BIG_ENDIAN && to_byte_order == Base64::BYTEORDER_LITTLEENDIAN) ||
00093 (!OPENMS_IS_BIG_ENDIAN && to_byte_order == Base64::BYTEORDER_BIGENDIAN))
00094 {
00095 convert = true;
00096 }
00097
00098 UInt element_size = sizeof (FromType);
00099 UInt size = element_size * in.size();
00100 UInt padding = 0;
00101 if (size%3 == 2) padding=1;
00102 if (size%3 == 1) padding=2;
00103
00104 register unsigned char a;
00105 register unsigned char b;
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151 UInt i = 0;
00152 UInt pos = 0;
00153 UInt offset = 0;
00154 int inc = 1;
00155
00156 if (convert == false) inc = 1;
00157 else inc = -1;
00158
00159 for (i=0; i<size-3; i+=3)
00160 {
00161 pos = i / element_size;
00162
00163 if (convert == false)
00164 {
00165 offset = i % element_size;
00166 }
00167 else
00168 {
00169 offset = (element_size - 1) - (i % element_size);
00170 }
00171
00172
00173
00174
00175
00176
00177 a = ((char*) &(in[pos]))[offset];
00178
00179
00180 pos = (i+1) / element_size;
00181 offset = (offset+inc) % element_size;
00182
00183 b = ((char*) &(in[pos]))[offset];
00184 out.push_back(encoder_[a>>2]);
00185 out.push_back(encoder_[((a&3)<<4) | (b>>4)]);
00186
00187
00188 pos = (i+2) / element_size;
00189 offset = (offset+inc) % element_size;
00190
00191 a = ((char*) &(in[pos]))[offset];
00192
00193 out.push_back(encoder_[((b&15)<<2) | (a>>6)]);
00194 out.push_back(encoder_[a&63]);
00195 }
00196
00197
00198 pos = i / element_size;
00199 offset = (offset+inc) % element_size;
00200
00201 a = ((char*) &(in[pos]))[offset];
00202 out.push_back(encoder_[a>>2]);
00203
00204 if (padding == 2)
00205 {
00206
00207
00208
00209
00210
00211
00212
00213 out.push_back(encoder_[(a&3)<<4]);
00214 out.push_back('=');
00215 out.push_back('=');
00216 }
00217 else if (padding)
00218 {
00219
00220
00221
00222
00223
00224
00225
00226
00227 i++;
00228 pos = i / element_size;
00229 offset = (offset+inc) % element_size;
00230 b = ((char*) &(in[pos]))[offset];
00231 out.push_back(encoder_[((a&3)<<4) | (b>>4)]);
00232 out.push_back(encoder_[(b&15)<<2]);
00233 out.push_back('=');
00234 }
00235 else
00236 {
00237 i++;
00238 pos = i / element_size;
00239 offset = (offset+inc) % element_size;
00240 b = ((char*) &(in[pos]))[offset];
00241 out.push_back(encoder_[((a&3)<<4) | (b>>4)]);
00242
00243 i++;
00244 pos = i / element_size;
00245 offset = (offset+inc) % element_size;
00246 a = ((char*) &(in[pos]))[offset];
00247 out.push_back(encoder_[((b&15)<<2) | (a>>6)]);
00248 out.push_back(encoder_[a&63]);
00249 }
00250 }
00251
00253 template <typename ToType>
00254 void Base64::decode(const std::string& in, ByteOrder from_byte_order, std::vector<ToType>& out)
00255 {
00256 out = std::vector<ToType>();
00257 if (in == "") return;
00258
00259 UInt src_size = in.size();
00260
00261 int padding = 0;
00262 if (in[src_size-1] == '=') padding++;
00263 if (in[src_size-2] == '=') padding++;
00264
00265 src_size -= padding;
00266
00267 register UInt a;
00268 register UInt b;
00269
00270 UInt offset = 0;
00271 bool convert = false;
00272 int inc = 1;
00273 UInt written = 0;
00274
00275 UInt element_size = sizeof(ToType);
00276
00277
00278 char element[8] = "\x00\x00\x00\x00\x00\x00\x00";
00279
00280 if ((OPENMS_IS_BIG_ENDIAN && from_byte_order == Base64::BYTEORDER_LITTLEENDIAN) ||
00281 (!OPENMS_IS_BIG_ENDIAN && from_byte_order == Base64::BYTEORDER_BIGENDIAN))
00282 {
00283 convert = true;
00284 offset = (element_size - 1);
00285 inc = -1;
00286 }
00287 else
00288 {
00289 offset = 0;
00290 inc = 1;
00291 }
00292
00293
00294
00295 for (UInt i=0; i<src_size; i+=4)
00296 {
00297
00298
00299
00300 a = decoder_[(int)in[i]-43]-62;
00301 b = decoder_[(int)in[i+1]-43]-62;
00302 if (i+1 >= src_size) b=0;
00303 element[offset] = (unsigned char) ((a<<2) | (b>>4));
00304 written++;
00305
00306 offset = (offset + inc) % element_size;
00307
00308 if (written % sizeof(ToType) == 0)
00309 {
00310 out.push_back(((ToType*)element)[0]);
00311 strcpy(element, "");
00312 }
00313
00314 a = decoder_[(int)in[i+2]-43]-62;
00315 if (i+2 >= src_size) a=0;
00316 element[offset] = (unsigned char) (((b&15)<<4) | (a>>2));
00317 written++;
00318
00319 offset = (offset + inc) % element_size;
00320
00321 if (written % sizeof(ToType) == 0)
00322 {
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334 out.push_back(((ToType*)element)[0]);
00335 strcpy(element, "");
00336 }
00337
00338 b = decoder_[(int)in[i+3]-43]-62;
00339 if (i+3 >= src_size) b=0;
00340 element[offset] = (unsigned char) (((a&3)<<6) | b);
00341 written++;
00342
00343 offset = (offset + inc) % element_size;
00344
00345 if (written % sizeof(ToType) == 0)
00346 {
00347 out.push_back(((ToType*)element)[0]);
00348 strcpy(element, "");
00349 }
00350 }
00351 }
00352
00353 }
00354
00355 #endif