/* This file is part of the OpenLB library
*
* Copyright (C) 2007 Jonas Latt
* E-mail contact: info@openlb.net
* The most recent release of OpenLB can be downloaded at
*
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this program; if not, write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
/* Acknowledgment: The strategy adopted here to encode
* and decode Base64, and in particular the expression of the
* arrays Base64Encoder::enc64 and Base64Decoder::dec64,
* is inspired by the open source library b64 by Bob Trower,
* which is distributed with a MIT license at the address
* http://base64.sourceforge.net/b64.c
*/
#ifndef BASE64_HH
#define BASE64_HH
#include "base64.h"
#include "core/olbDebug.h"
#include
#include
namespace olb {
////////////// class Base64Encoder ////////////////////////////////////////////
template
const char Base64Encoder::enc64[65]=
"ABCDEFGHIJKLMNOPQRSTUVWXYZ" \
"abcdefghijklmnopqrstuvwxyz0123456789+/";
template
Base64Encoder::Base64Encoder(std::ostream& ostr_, size_t fullLength_)
: ostr(ostr_),
charFullLength(fullLength_ * sizeof(T)),
numWritten(0),
numOverflow(0)
{ }
template
void Base64Encoder::encode(const T* data, size_t length)
{
const unsigned char* charData = reinterpret_cast(data);
size_t charLength = length * sizeof(T);
OLB_PRECONDITION( numWritten+charLength <= charFullLength );
size_t pos=0;
fillOverflow(charData, charLength, pos);
while (pos+3 <= charLength) {
encodeBlock(charData+pos);
pos += 3;
}
fillOverflow(charData, charLength, pos);
numWritten += charLength;
if (numWritten == charFullLength) {
flushOverflow();
}
}
template
void Base64Encoder::fillOverflow(const unsigned char* charData, size_t charLength, size_t& pos)
{
while (numOverflow < 3 && pos < charLength) {
overflow[numOverflow] = charData[pos];
++numOverflow;
++pos;
}
if (numOverflow == 3) {
encodeBlock(overflow);
numOverflow = 0;
}
}
template
void Base64Encoder::flushOverflow()
{
if (numOverflow > 0) {
for (int iOverflow = numOverflow; iOverflow<3; ++iOverflow) {
overflow[iOverflow] = 0;
}
encodeUnfinishedBlock(overflow, numOverflow);
numOverflow = 0;
}
}
template
void Base64Encoder::encodeBlock( const unsigned char* data)
{
ostr << enc64[ data[0] >> 2 ];
ostr << enc64[ ((data[0] & 0x03) << 4) | ((data[1] & 0xf0) >> 4) ];
ostr << (unsigned char) (enc64[ ((data[1] & 0x0f) << 2) | ((data[2] & 0xc0) >> 6) ]);
ostr << (unsigned char) (enc64[ data[2] & 0x3f ]);
}
template
void Base64Encoder::encodeUnfinishedBlock( const unsigned char* data, int length )
{
ostr << enc64[ data[0] >> 2 ];
ostr << enc64[ ((data[0] & 0x03) << 4) | ((data[1] & 0xf0) >> 4) ];
ostr << (unsigned char) (
length == 2 ?
enc64[ ((data[1] & 0x0f) << 2) | ((data[2] & 0xc0) >> 6) ] :
'='
);
ostr << (unsigned char) ( '=' );
}
////////////// struct Base64Decoder ////////////////////////////////////////////
template
const char Base64Decoder::dec64[82]=
"|###}rstuvwxyz{#######>?@"\
"ABCDEFGHIJKLMNOPQRSTUVW######XYZ"\
"[\\]^_`abcdefghijklmnopq";
template
Base64Decoder::Base64Decoder(std::istream& istr_, size_t fullLength_)
: istr(istr_),
charFullLength(fullLength_ * sizeof(T)),
numRead(0),
posOverflow(3)
{ }
template
void Base64Decoder::decode(T* data, size_t length)
{
unsigned char* charData = reinterpret_cast(data);
size_t charLength = length * sizeof(T);
OLB_PRECONDITION( numRead+charLength <= charFullLength );
size_t pos = 0;
flushOverflow(charData, charLength, pos);
while (pos+3 <= charLength) {
decodeBlock(charData+pos);
pos += 3;
}
if (pos < charLength) {
decodeBlock(overflow);
posOverflow=0;
flushOverflow(charData, charLength, pos);
}
numRead += charLength;
}
template
void Base64Decoder::flushOverflow(unsigned char* charData, size_t charLength, size_t& pos)
{
while (posOverflow < 3 && pos < charLength) {
charData[pos] = overflow[posOverflow];
++pos;
++posOverflow;
}
}
template
unsigned char Base64Decoder::getNext()
{
unsigned char nextChar;
istr >> nextChar;
return (unsigned char) (dec64[nextChar - 43] - 62);
}
template
void Base64Decoder::decodeBlock(unsigned char* data)
{
unsigned char input[4];
input[0] = getNext();
input[1] = getNext();
input[2] = getNext();
input[3] = getNext();
data[0] = (unsigned char) (input[0] << 2 | input[1] >> 4);
data[1] = (unsigned char) (input[1] << 4 | input[2] >> 2);
data[2] = (unsigned char) (((input[2] << 6) & 0xc0) | input[3]);
}
} // namespace olb
#endif