$treeview $search $mathjax
Palabos  Version 1.1
$projectbrief
$projectbrief
$searchbox

base64.hh

Go to the documentation of this file.
00001 /* This file is part of the Palabos library.
00002  *
00003  * Copyright (C) 2011 FlowKit Sarl
00004  * Avenue de Chailly 23
00005  * 1012 Lausanne, Switzerland
00006  * E-mail contact: contact@flowkit.com
00007  *
00008  * The most recent release of Palabos can be downloaded at 
00009  * <http://www.palabos.org/>
00010  *
00011  * The library Palabos is free software: you can redistribute it and/or
00012  * modify it under the terms of the GNU Affero General Public License as
00013  * published by the Free Software Foundation, either version 3 of the
00014  * License, or (at your option) any later version.
00015  *
00016  * The library is distributed in the hope that it will be useful,
00017  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00018  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019  * GNU Affero General Public License for more details.
00020  *
00021  * You should have received a copy of the GNU Affero General Public License
00022  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
00023 */
00024 
00025 /* Acknowledgment: The strategy adopted here to encode
00026  * and decode Base64, and in particular the expression of the
00027  * arrays Base64Encoder::enc64 and Base64Decoder::dec64, 
00028  * is inspired by the open source library b64 by Bob Trower,
00029  * which is distributed with a MIT license at the address
00030  * http://base64.sourceforge.net/b64.c
00031  */
00032 
00033 #ifndef BASE64_HH
00034 #define BASE64_HH
00035 
00036 #include "io/base64.h"
00037 #include "core/plbDebug.h"
00038 #include <ostream>
00039 #include <istream>
00040 
00041 
00042 namespace plb {
00043 
00045 
00046 template<typename T>
00047 const char Base64Encoder<T>::enc64[65]=
00048     "ABCDEFGHIJKLMNOPQRSTUVWXYZ" \
00049     "abcdefghijklmnopqrstuvwxyz0123456789+/";
00050 
00051 template<typename T>
00052 Base64Encoder<T>::Base64Encoder(std::ostream& ostr_, pluint fullLength_)
00053     : ostr(ostr_),
00054       charFullLength(fullLength_ * sizeof(T)),
00055       numWritten(0),
00056       numOverflow(0)
00057 { }
00058 
00059 template<typename T>
00060 void Base64Encoder<T>::encode(const T* data, pluint length) {
00061     const unsigned char* charData = reinterpret_cast<const unsigned char*>(data);
00062     pluint charLength = length * sizeof(T);
00063     PLB_PRECONDITION( numWritten+charLength <= charFullLength );
00064 
00065     pluint pos=0;
00066     fillOverflow(charData, charLength, pos);
00067     while (pos+3 <= charLength) {
00068         encodeBlock(charData+pos);
00069         pos += 3;
00070     }
00071     fillOverflow(charData, charLength, pos);
00072     numWritten += charLength;
00073     if (numWritten == charFullLength) {
00074         flushOverflow();
00075     }
00076 }
00077 
00078 template<typename T>
00079 void Base64Encoder<T>::fillOverflow(const unsigned char* charData, pluint charLength, pluint& pos) {
00080     while (numOverflow < 3 && pos < charLength) {
00081         overflow[numOverflow] = charData[pos];
00082         ++numOverflow;
00083         ++pos;
00084     }
00085     if (numOverflow == 3) {
00086         encodeBlock(overflow);
00087         numOverflow = 0;
00088     }
00089 }
00090 
00091 template<typename T>
00092 void Base64Encoder<T>::flushOverflow() {
00093     if (numOverflow > 0) {
00094         for (plint iOverflow = numOverflow; iOverflow<3; ++iOverflow) {
00095             overflow[iOverflow] = 0;
00096         }
00097         encodeUnfinishedBlock(overflow, numOverflow);
00098         numOverflow = 0;
00099     }
00100 }
00101 
00102 template<typename T>
00103 void Base64Encoder<T>::encodeBlock( const unsigned char* data) {
00104     ostr << enc64[ data[0] >> 2 ];
00105     ostr << enc64[ ((data[0] & 0x03) << 4) | ((data[1] & 0xf0) >> 4) ];
00106     ostr << (unsigned char) (enc64[ ((data[1] & 0x0f) << 2) | ((data[2] & 0xc0) >> 6) ]);
00107     ostr << (unsigned char) (enc64[ data[2] & 0x3f ]);
00108 }
00109 
00110 template<typename T>
00111 void Base64Encoder<T>::encodeUnfinishedBlock( const unsigned char* data, plint length ) {
00112     ostr << enc64[ data[0] >> 2 ];
00113     ostr << enc64[ ((data[0] & 0x03) << 4) | ((data[1] & 0xf0) >> 4) ];
00114     ostr << (unsigned char) (
00115                 length == 2 ?
00116                     enc64[ ((data[1] & 0x0f) << 2) | ((data[2] & 0xc0) >> 6) ] :
00117                     '='
00118              );
00119     ostr << (unsigned char) ( '=' );
00120 }
00121 
00122 
00124 
00125 template<typename T>
00126 const char Base64Decoder<T>::dec64[82]=
00127     "|###}rstuvwxyz{#######>?@"\
00128     "ABCDEFGHIJKLMNOPQRSTUVW######XYZ"\
00129     "[\\]^_`abcdefghijklmnopq";
00130 
00131 
00132 template<typename T>
00133 Base64Decoder<T>::Base64Decoder(std::istream& istr_, pluint fullLength_)
00134     : istr(istr_),
00135       charFullLength(fullLength_ * sizeof(T)),
00136       numRead(0),
00137       posOverflow(3)
00138 { }
00139 
00140 template<typename T>
00141 void Base64Decoder<T>::decode(T* data, pluint length) {
00142     unsigned char* charData = reinterpret_cast<unsigned char*>(data);
00143     pluint charLength = length * sizeof(T);
00144     PLB_PRECONDITION( numRead+charLength <= charFullLength );
00145 
00146     pluint pos = 0;
00147     flushOverflow(charData, charLength, pos);
00148     while (pos+3 <= charLength) {
00149         decodeBlock(charData+pos);
00150         pos += 3;
00151     }
00152     if (pos < charLength) {
00153         decodeBlock(overflow); posOverflow=0;
00154         flushOverflow(charData, charLength, pos);
00155     }
00156     numRead += charLength;
00157 }
00158 
00159 template<typename T>
00160 void Base64Decoder<T>::flushOverflow(unsigned char* charData, pluint charLength, pluint& pos) {
00161     while (posOverflow < 3 && pos < charLength) {
00162         charData[pos] = overflow[posOverflow];
00163         ++pos;
00164         ++posOverflow;
00165     }
00166 }
00167 
00168 template<typename T>
00169 unsigned char Base64Decoder<T>::getNext() {
00170     unsigned char nextChar;
00171     istr >> nextChar;
00172     return (unsigned char) (dec64[nextChar - 43] - 62);
00173 }
00174 
00175 template<typename T>
00176 void Base64Decoder<T>::decodeBlock(unsigned char* data) {
00177     unsigned char input[4];
00178     input[0] = getNext(); 
00179     input[1] = getNext(); 
00180     input[2] = getNext(); 
00181     input[3] = getNext(); 
00182     data[0] = (unsigned char) (input[0] << 2 | input[1] >> 4);
00183     data[1] = (unsigned char) (input[1] << 4 | input[2] >> 2);
00184     data[2] = (unsigned char) (((input[2] << 6) & 0xc0) | input[3]);
00185 }
00186 
00187 }  // namespace plb
00188 
00189 #endif  // BASE64_HH
00190 
00191