jigdo API
Last update by Admin on 2010-05-23
util/mimestream.hh
Go to the documentation of this file.00001 /* $Id: mimestream.hh,v 1.2 2003/09/27 21:31:04 atterer Exp $ -*- C++ -*- 00002 __ _ 00003 |_) /| Copyright (C) 2000-2002 | richard@ 00004 | \/¯| Richard Atterer | atterer.net 00005 ¯ '` ¯ 00006 This program is free software; you can redistribute it and/or modify 00007 it under the terms of the GNU General Public License, version 2. See 00008 the file COPYING for details. 00009 00010 */ 00016 #ifndef MIMESTREAM_HH 00017 #define MIMESTREAM_HH 00018 00019 #ifndef INLINE 00020 # ifdef NOINLINE 00021 # define INLINE 00022 # else 00023 # define INLINE inline 00024 # endif 00025 #endif 00026 00027 #include <config.h> 00028 00029 #include <string.h> 00030 #include <iostream> 00031 #include <string> 00032 #include <vector> 00033 00034 #include <debug.hh> 00035 //______________________________________________________________________ 00036 00047 template <class Output> 00048 class Base64Out { 00049 public: 00050 Base64Out() : bits(0) { } 00051 typename Output::ResultType result() { return out.result(); } 00052 00054 Base64Out<Output>& operator<<(char x) { return put(x); } 00055 Base64Out<Output>& operator<<(signed char x) { return put(x); } 00056 Base64Out<Output>& operator<<(unsigned char x) { return put(x); } 00058 Base64Out<Output>& operator<<(int x) { return put(x); } 00060 Base64Out<Output>& operator<<(uint32 x) { return put(x); } 00061 00063 inline Base64Out<Output>& operator<<(const char* x); 00064 inline Base64Out<Output>& operator<<(const signed char* x); 00065 Base64Out<Output>& operator<<(const unsigned char* x); 00066 inline Base64Out<Output>& operator<<(const void* x); 00067 00069 inline Base64Out<Output>& put(unsigned char x); 00070 inline Base64Out<Output>& put(signed char x); 00072 inline Base64Out<Output>& put(int x); 00073 inline Base64Out<Output>& put(char x); 00075 Base64Out<Output>& put(uint32 x); 00077 inline Base64Out<Output>& write(const char* x, unsigned n); 00078 inline Base64Out<Output>& write(const signed char* x, unsigned n); 00079 Base64Out<Output>& write(const unsigned char* x, unsigned n); 00080 inline Base64Out<Output>& write(const void* x, unsigned n); 00081 00083 Base64Out<Output>& flush(); 00086 Base64Out<Output>& trailer(streamsize n); 00087 00090 static bool hex; 00091 00092 private: 00093 /* String for MIME base64 encoding. Not entirely standard because b64 00094 strings are used as filenames by jigdo. Additionally, "+" or "/" looks 00095 weird in the .jigdo file. */ 00096 static const char* const code; 00097 static const char* const hexCode; 00098 int bits; 00099 uint32 data; 00100 Output out; 00101 }; 00102 //______________________________________________________________________ 00103 00105 class Base64StringOut { 00106 public: 00107 void put(char c) { val += c; } 00108 typedef string& ResultType; 00109 string& result() { return val; } 00110 const string& result() const { return val; } 00111 private: 00112 string val; 00113 }; 00114 00117 typedef Base64Out<Base64StringOut> Base64String; 00118 //______________________________________________________________________ 00119 00120 // Support functions to allow things like "b64Stream << flush;" 00121 00122 template <class Output> 00123 inline Base64Out<Output>& flush(Base64Out<Output>& s) { 00124 return s.flush(); 00125 } 00126 00127 template <class Output> 00128 inline Base64Out<Output>& operator<<(Base64Out<Output>& s, 00129 Base64Out<Output>& (*m)(Base64Out<Output>&)) { 00130 return (*m)(s); 00131 } 00132 //______________________________________________________________________ 00133 00134 template <class Output> 00135 bool Base64Out<Output>::hex = false; 00136 template <class Output> 00137 const char* const Base64Out<Output>::code = 00138 //"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; 00139 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"; 00140 template <class Output> 00141 const char* const Base64Out<Output>::hexCode = "0123456789abcdef"; 00142 00143 template <class Output> 00144 Base64Out<Output>& Base64Out<Output>::operator<<(const char* x) { 00145 return (*this) << reinterpret_cast<const unsigned char*>(x); 00146 } 00147 template <class Output> 00148 Base64Out<Output>& Base64Out<Output>::operator<<(const signed char* x) { 00149 return (*this) << reinterpret_cast<const unsigned char*>(x); 00150 } 00151 template <class Output> 00152 Base64Out<Output>& Base64Out<Output>::operator<<(const void* x) { 00153 return (*this) << static_cast<const unsigned char*>(x); 00154 } 00155 00156 template <class Output> 00157 Base64Out<Output>& Base64Out<Output>::put(unsigned char x) { 00158 if (hex) { 00159 out.put(hexCode[(x >> 4) & 15U]); 00160 out.put(hexCode[x & 15U]); 00161 return *this; 00162 } 00163 data = (data << 8) | x; 00164 bits += 2; // plus 8 new bits, less 6 which we output in next line 00165 out.put(code[(data >> bits) & 63U]); 00166 if (bits >= 6) { //8? 00167 bits -= 6; 00168 out.put(code[(data >> bits) & 63U]); 00169 } 00170 return *this; 00171 } 00172 template <class Output> 00173 Base64Out<Output>& Base64Out<Output>::put(signed char x) { 00174 return put(static_cast<unsigned char>(x)); 00175 } 00176 template <class Output> 00177 Base64Out<Output>& Base64Out<Output>::put(char x) { 00178 return put(static_cast<unsigned char>(x)); 00179 } 00180 template <class Output> 00181 Base64Out<Output>& Base64Out<Output>::put(int x) { 00182 return put(static_cast<unsigned char>(x)); 00183 } 00184 00185 template <class Output> 00186 Base64Out<Output>& Base64Out<Output>::write(const char* x, unsigned n) { 00187 return write(reinterpret_cast<const unsigned char*>(x), n); 00188 } 00189 template <class Output> 00190 Base64Out<Output>& Base64Out<Output>::write(const signed char* x, unsigned n) { 00191 return write(reinterpret_cast<const unsigned char*>(x), n); 00192 } 00193 template <class Output> 00194 Base64Out<Output>& Base64Out<Output>::write(const void* x, unsigned n) { 00195 return write(static_cast<const unsigned char*>(x), n); 00196 } 00197 00198 template <class Output> 00199 Base64Out<Output>& Base64Out<Output>::put(uint32 x) { 00200 (*this) 00201 .put(static_cast<unsigned char>(x & 0xff)) 00202 .put(static_cast<unsigned char>((x >> 8) & 0xff)) 00203 .put(static_cast<unsigned char>((x >> 16) & 0xff)) 00204 .put(static_cast<unsigned char>((x >> 24) & 0xff)); 00205 return *this; 00206 } 00207 00208 template <class Output> 00209 Base64Out<Output>& Base64Out<Output>::flush() { 00210 if (bits > 0) { 00211 data <<= 6 - bits; 00212 out.put(code[data & 63U]); 00213 } 00214 bits = 0; 00215 return *this; 00216 } 00217 00218 template <class Output> 00219 Base64Out<Output>& Base64Out<Output>::trailer(streamsize n) { 00220 int rest = n % 3; 00221 if (rest == 1) out.put('='); 00222 if (rest >= 1) out.put('='); 00223 return *this; 00224 } 00225 00226 // Output null-terminated string 00227 template <class Output> 00228 Base64Out<Output>& Base64Out<Output>::operator<<(const unsigned char* x) { 00229 while (*x != '\0') 00230 (*this) << static_cast<byte>(*x++); 00231 return *this; 00232 } 00233 00234 // Output n characters 00235 template <class Output> 00236 Base64Out<Output>& Base64Out<Output>::write(const unsigned char* x, 00237 unsigned n) { 00238 for (unsigned i = 0; i < n; ++i) 00239 (*this) << static_cast<byte>(*x++); 00240 return *this; 00241 } 00242 //______________________________________________________________________ 00243 00250 template <class Output> 00251 class Base64In { 00252 public: 00253 Base64In() : bits(0), data(0) { } 00254 typename Output::ResultType result() { return out.result(); } 00255 00257 Base64In<Output>& operator<<(char x) { return put(x); } 00259 inline Base64In<Output>& operator<<(const char* x); 00261 inline Base64In<Output>& operator<<(const string& x); 00263 inline Base64In<Output>& put(char x); 00265 Base64In<Output>& put(const char* x, unsigned n); 00266 00268 void reset() { bits = 0; } 00269 00270 private: 00271 static const byte table[]; 00272 int bits; 00273 uint32 data; 00274 Output out; 00275 }; 00276 //______________________________________________________________________ 00277 00280 class Base64StringIn { 00281 public: 00282 void put(byte b) { val.push_back(b); } 00283 typedef vector<byte>& ResultType; 00284 vector<byte>& result() { return val; } 00285 private: 00286 vector<byte> val; 00287 }; 00288 00289 typedef Base64In<Base64StringIn> Base64StringI; 00290 //______________________________________________________________________ 00291 00292 // Inverse mapping for both of these: 00293 //"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; 00294 //"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"; 00295 #define x 255 00296 template <class Output> 00297 const byte Base64In<Output>::table[] = { 00298 // ! " # $ % & ' ( ) * + , - . / 00299 x, x, x, x, x, x, x, x, x, x, x, 62, x, 62, x, 63, 00300 //0 1 2 3 4 5 6 7 8 9 : ; < = > ? 00301 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, x, x, x, x, x, x, 00302 //@ A B C D E F G H I J K L M N O 00303 x, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 00304 //P Q R S T U V W x Y Z [ \ ] ^ _ 00305 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, x, x, x, x, 63, 00306 //` a b c d e f g h i j k l m n o 00307 x, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 00308 //p q r s t u v w x y z { | } ~ DEL 00309 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, x, x, x, x, x 00310 }; 00311 #undef x 00312 00313 template <class Output> 00314 Base64In<Output>& Base64In<Output>::operator<<(const char* x) { 00315 unsigned len = strlen(x); 00316 return put(x, len); 00317 } 00318 00319 template <class Output> 00320 Base64In<Output>& Base64In<Output>::operator<<(const string& x) { 00321 return put(x.data(), x.length()); 00322 } 00323 00324 template <class Output> 00325 Base64In<Output>& Base64In<Output>::put(char x) { 00326 return put(&x, 1); 00327 } 00328 00329 template <class Output> 00330 Base64In<Output>& Base64In<Output>::put(const char* x, unsigned n) { 00331 --x; 00332 while (n > 0) { 00333 --n; ++x; 00334 unsigned code = static_cast<byte>(*x); 00335 if (code < 32 || code > 127) continue; // Just ignore invalid characters 00336 code = table[code - 32]; 00337 if (code > 63) continue; 00338 data = (data << 6) | code; 00339 bits += 6; 00340 if (bits >= 8) { 00341 bits -= 8; 00342 out.put(static_cast<byte>((data >> bits) & 255U)); 00343 } 00344 } 00345 return *this; 00346 } 00347 00348 #endif
Generated on Tue Sep 23 14:27:42 2008 for jigdo by
