/*
IoBind Library License:
--------------------------
The zlib/libpng License Copyright (c) 2003 Jonathan de Halleux
This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution
*/
// base64.hpp
// Autor Konstantin Pilipchuk
// mailto:lostd@ukr.net
//
//
#ifndef IOBIND_BASE64_HPP
#define IOBIND_BASE64_HPP
#include <iterator>
#include <sstream>
static
int _base64Chars[]= {'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',
'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z',
'0','1','2','3','4','5','6','7','8','9',
'+','/' };
#define _0000_0011 0x03
#define _1111_1100 0xFC
#define _1111_0000 0xF0
#define _0011_0000 0x30
#define _0011_1100 0x3C
#define _0000_1111 0x0F
#define _1100_0000 0xC0
#define _0011_1111 0x3F
#define _EQUAL_CHAR (-1)
#define _UNKNOWN_CHAR (-2)
#define _IOS_FAILBIT std::ios_base::failbit
#define _IOS_EOFBIT std::ios_base::eofbit
#define _IOS_BADBIT std::ios_base::badbit
#define _IOS_GOODBIT std::ios_base::goodbit
namespace iobind{
namespace base64{
// TEMPLATE CLASS base64_put
template<class _E = char, class _Tr = std::char_traits<_E> >
class base64
{
public:
typedef unsigned char byte_t;
typedef _E char_type;
typedef _Tr traits_type;
// base64 requires max line length <= 72 characters
// you can fill end of line
// it may be crlf, crlfsp, noline or other class like it
struct crlf
{
template<class _OI>
_OI operator()(_OI _To) const{
*_To = _Tr::to_char_type('\r'); ++_To;
*_To = _Tr::to_char_type('\n'); ++_To;
return (_To);
}
};
struct crlfsp
{
template<class _OI>
_OI operator()(_OI _To) const{
*_To = _Tr::to_char_type('\r'); ++_To;
*_To = _Tr::to_char_type('\n'); ++_To;
*_To = _Tr::to_char_type(' '); ++_To;
return (_To);
}
};
struct noline
{
template<class _OI>
_OI operator()(_OI _To) const{
return (_To);
}
};
struct three2four
{
void zero()
{
_data[0] = 0;
_data[1] = 0;
_data[2] = 0;
}
byte_t get_0() const
{
return _data[0];
}
byte_t get_1() const
{
return _data[1];
}
byte_t get_2() const
{
return _data[2];
}
void set_0(byte_t _ch)
{
_data[0] = _ch;
}
void set_1(byte_t _ch)
{
_data[1] = _ch;
}
void set_2(byte_t _ch)
{
_data[2] = _ch;
}
// 0000 0000 1111 1111 2222 2222
// xxxx xxxx xxxx xxxx xxxx xxxx
// 0000 0011 1111 2222 2233 3333
int b64_0() const {return (_data[0] & _1111_1100) >> 2;}
int b64_1() const {return ((_data[0] & _0000_0011) << 4) + ((_data[1] & _1111_0000)>>4);}
int b64_2() const {return ((_data[1] & _0000_1111) << 2) + ((_data[2] & _1100_0000)>>6);}
int b64_3() const {return (_data[2] & _0011_1111);}
void b64_0(int _ch) {_data[0] = ((_ch & _0011_1111) << 2) | (_0000_0011 & _data[0]);}
void b64_1(int _ch) {
_data[0] = ((_ch & _0011_0000) >> 4) | (_1111_1100 & _data[0]);
_data[1] = ((_ch & _0000_1111) << 4) | (_0000_1111 & _data[1]); }
void b64_2(int _ch) {
_data[1] = ((_ch & _0011_1100) >> 2) | (_1111_0000 & _data[1]);
_data[2] = ((_ch & _0000_0011) << 6) | (_0011_1111 & _data[2]); }
void b64_3(int _ch){
_data[2] = (_ch & _0011_1111) | (_1100_0000 & _data[2]);}
private:
byte_t _data[3];
};
template<class _II, class _OI, class _State, class _Endline>
_II put(_II _First, _II _Last, _OI _To, _State& _St, _Endline _Endl) const
{
three2four _3to4;
int line_octets = 0;
while(_First != _Last)
{
_3to4.zero();
// ���� �� 3 �������
_3to4.set_0(*_First);
_First++;
if(_First == _Last)
{
*_To = _Tr::to_char_type(_base64Chars[_3to4.b64_0()]); ++_To;
*_To = _Tr::to_char_type(_base64Chars[_3to4.b64_1()]); ++_To;
*_To = _Tr::to_char_type('='); ++_To;
*_To = _Tr::to_char_type('='); ++_To;
goto __end;
}
_3to4.set_1(*_First);
_First++;
if(_First == _Last)
{
*_To = _Tr::to_char_type(_base64Chars[_3to4.b64_0()]); ++_To;
*_To = _Tr::to_char_type(_base64Chars[_3to4.b64_1()]); ++_To;
*_To = _Tr::to_char_type(_base64Chars[_3to4.b64_2()]); ++_To;
*_To = _Tr::to_char_type('='); ++_To;
goto __end;
}
_3to4.set_2(*_First);
_First++;
*_To = _Tr::to_char_type(_base64Chars[_3to4.b64_0()]); ++_To;
*_To = _Tr::to_char_type(_base64Chars[_3to4.b64_1()]); ++_To;
*_To = _Tr::to_char_type(_base64Chars[_3to4.b64_2()]); ++_To;
*_To = _Tr::to_char_type(_base64Chars[_3to4.b64_3()]); ++_To;
if(line_octets == 17) // base64 ��������� ����� ������ �� ����� 72 ��������
{
_To = _Endl(_To);
line_octets = 0;
}
else
++line_octets;
}
__end: ;
return (_First);
}
template<class _II, class _OI, class _State>
_II get(_II _First, _II _Last, _OI _To, _State& _St) const
{
three2four _3to4;
int _Char;
while(_First != _Last)
{
// Take octet
_3to4.zero();
// -- 0 --
// Search next valid char...
while((_Char = get_char_type(*_First)) < 0 && _Char == _UNKNOWN_CHAR)
{
if(++_First == _Last)
{
_St |= _IOS_FAILBIT|_IOS_EOFBIT; return _First; // unexpected EOF
}
}
if(_Char == _EQUAL_CHAR){
// Error! First character in octet can't be '='
_St |= _IOS_FAILBIT;
return _First;
}
else
_3to4.b64_0(_Char);
// -- 1 --
// Search next valid char...
while(++_First != _Last)
if((_Char = get_char_type(*_First)) != _UNKNOWN_CHAR)
break;
if(_First == _Last) {
_St |= _IOS_FAILBIT|_IOS_EOFBIT; // unexpected EOF
return _First;
}
if(_Char == _EQUAL_CHAR){
// Error! Second character in octet can't be '='
_St |= _IOS_FAILBIT;
return _First;
}
else
_3to4.b64_1(_Char);
// -- 2 --
// Search next valid char...
while(++_First != _Last)
if((_Char = get_char_type(*_First)) != _UNKNOWN_CHAR)
break;
if(_First == _Last) {
// Error! Unexpected EOF. Must be '=' or base64 character
_St |= _IOS_FAILBIT|_IOS_EOFBIT;
return _First;
}
if(_Char == _EQUAL_CHAR){
// OK!
_3to4.b64_2(0);
_3to4.b64_3(0);
// chek for EOF
if(++_First == _Last)
{
// Error! Unexpected EOF. Must be '='. Ignore it.
//_St |= _IOS_BADBIT|_IOS_EOFBIT;
_St |= _IOS_EOFBIT;
}
else
if(get_char_type(*_First) != _EQUAL_CHAR)
{
// Error! Must be '='. Ignore it.
//_St |= _IOS_BADBIT;
}
else
++_First; // Skip '='
// write 1 byte to output
*_To = (byte_t) _3to4.get_0();
return _First;
}
else
_3to4.b64_2(_Char);
// -- 3 --
// Search next valid char...
while(++_First != _Last)
if((_Char = get_char_type(*_First)) != _UNKNOWN_CHAR)
break;
if(_First == _Last) {
// Unexpected EOF. It's error. But ignore it.
//_St |= _IOS_FAILBIT|_IOS_EOFBIT;
_St |= _IOS_EOFBIT;
return _First;
}
if(_Char == _EQUAL_CHAR)
{
// OK!
_3to4.b64_3(0);
// write to output 2 bytes
*_To = (byte_t) _3to4.get_0();
*_To = (byte_t) _3to4.get_1();
++_First; // set position to next character
return _First;
}
else
_3to4.b64_3(_Char);
// write to output 3 bytes
*_To = (byte_t) _3to4.get_0();
*_To = (byte_t) _3to4.get_1();
*_To = (byte_t) _3to4.get_2();
++_First;
} // while(_First != _Last)
return (_First);
};
protected:
int get_char_type(int C_) const
{
if(_base64Chars[62] == C_)
return 62;
if(_base64Chars[63] == C_)
return 63;
if((_base64Chars[0] <= C_) && (_base64Chars[25] >= C_))
return C_ - _base64Chars[0];
if((_base64Chars[26] <= C_) && (_base64Chars[51] >= C_))
return C_ - _base64Chars[26] + 26;
if((_base64Chars[52] <= C_) && (_base64Chars[61] >= C_))
return C_ - _base64Chars[52] + 52;
if(C_ == _Tr::to_int_type('='))
return _EQUAL_CHAR;
return _UNKNOWN_CHAR;
};
};
}; // base64
// base64 encode
template<typename T>
std::string base64_encode( T const& value_)
{
int _State = 0;
base64::base64<char> encoder;
// converting value to string
std::ostringstream ostr;
ostr<<value_;
// get istream
std::istringstream istr(ostr.str());
std::istreambuf_iterator<char> _From(istr.rdbuf());
std::istreambuf_iterator<char> _To(0);
// encode to output string
std::ostringstream ostr_64;
std::ostreambuf_iterator<char> _Out(ostr_64);
// encoding string
encoder.put(_From, _To, _Out, _State, base64::base64<>::crlf());
return ostr_64.str();
};
// base64 encode
template<typename IteratorT>
std::string base64_encode( IteratorT const& begin_, IteratorT const& end_)
{
int _State = 0;
base64::base64<char> encoder;
// converting value to string
std::ostringstream ostr;
IteratorT it = begin_;
while (it != end_)
ostr<<*(it++);
// get istream
std::istringstream istr(ostr.str());
std::istreambuf_iterator<char> _From(istr.rdbuf());
std::istreambuf_iterator<char> _To(0);
// encode to output string
std::ostringstream ostr_64;
std::ostreambuf_iterator<char> _Out(ostr_64);
// encoding string
encoder.put(_From, _To, _Out, _State, base64::base64<>::crlf());
return ostr_64.str();
};
// base64 decode
template<typename T>
std::string base64_decode( T const& value_)
{
int _State = 0;
base64::base64<char> encoder;
// converting value to string
std::ostringstream ostr;
ostr<<value_;
// get istream
std::istringstream istr(ostr.str());
std::istreambuf_iterator<char> _From(istr.rdbuf());
std::istreambuf_iterator<char> _To(0);
// encode to output string
std::ostringstream ostr_64;
std::ostreambuf_iterator<char> _Out(ostr_64);
// encoding string
encoder.get(_From, _To, _Out, _State);
return ostr_64.str();
};
}; //iobind
#endif