Велосипед отечественного производства для кодирования бинарных данных в текст с кодировкой Base64 и обратно.
Файл check_helpers.hpp //------------------------------------------------------------------------
#ifndef __CHERCKHELPERS_HEADER_INCLUDED__
#define __CHERCKHELPERS_HEADER_INCLUDED__
//------------------------------------------------------------------------
#include <boost/type_traits.hpp>
//------------------------------------------------------------------------
template<class IterTypeT>
struct IsRandomAccesIterator
{
static const bool value = false;
};
template<>
struct IsRandomAccesIterator<std::random_access_iterator_tag>
{
static const bool value = true;
};
//------------------------------------------------------------------------
#define CHARTYPE_SOURCE_SEQUENCE_CHECK(stl_container_t) \
BOOST_STATIC_ASSERT ( \
boost::is_fundamental<typename stl_container_t::value_type>::value ); \
BOOST_STATIC_ASSERT ( \
sizeof(typename stl_container_t::value_type) == static_cast<std::size_t>(1) );
//------------------------------------------------------------------------
#define CHARTYPE_SOURCE_ITERATOR_CHECK(iterator_t) \
BOOST_STATIC_ASSERT ( \
boost::is_fundamental<typename std::iterator_traits<iterator_t>::value_type>::value ); \
BOOST_STATIC_ASSERT ( \
sizeof(typename std::iterator_traits<iterator_t>::value_type) == static_cast<std::size_t>(1) );
//------------------------------------------------------------------------
#define RANDOM_ACCESS_ITERATOR_CHECK(iterator_t) \
BOOST_STATIC_ASSERT ( \
IsRandomAccesIterator< \
typename std::iterator_traits<iterator_t>::iterator_category>::value );
//------------------------------------------------------------------------
//------------------------------------------------------------------------
#endif // __CHERCKHELPERS_HEADER_INCLUDED__
//------------------------------------------------------------------------
Файл base64_conv.h //------------------------------------------------------------------------
#ifndef __BASE64_CONVERTER_HEADER_INCLUDED__
#define __BASE64_CONVERTER_HEADER_INCLUDED__
//------------------------------------------------------------------------
#include <boost/noncopyable.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/type_traits.hpp>
#include <vector>
#include <string>
#include <iterator>
#include <algorithm>
#include "check_helpers.hpp"
//------------------------------------------------------------------------
class base64_conv : private boost::noncopyable
{
public:
typedef std::vector<char> buffer_t;
typedef boost::shared_ptr<buffer_t> p_buffer_t;
public:
base64_conv();
~base64_conv();
template<typename stl_container_t>
void to_base64 ( const stl_container_t & sourse_data )
{
// This code can not be compiled, because a sequence is contained
// by a wrong type; need sequence which contained by predefined char type
CHARTYPE_SOURCE_SEQUENCE_CHECK(stl_container_t);
std::vector<typename stl_container_t::value_type> tmp_buffer (
sourse_data.begin(), sourse_data.end() );
to_base64(tmp_buffer);
}
template<typename char_t, typename allocator_t>
void to_base64 (
const std::vector<char_t, allocator_t> & sourse_data )
{
if ( sourse_data.empty() )
{
p_buffer->clear();
return;
}
to_base64_for_vector_or_string ( sourse_data.begin(), sourse_data.end() );
}
template<typename char_t, typename char_traits_t, typename allocator_t>
void to_base64(
const std::basic_string<char_t, char_traits_t, allocator_t> & sourse_data )
{
if ( sourse_data.empty() )
{
p_buffer->clear();
return;
}
to_base64_for_vector_or_string ( sourse_data.begin(), sourse_data.end() );
}
template<typename stl_container_t>
void from_base64( const stl_container_t & sourse_data )
{
// This code can not be compiled, because a sequence is contained
// by a wrong type; need sequence which contained by predefined char type
CHARTYPE_SOURCE_SEQUENCE_CHECK(stl_container_t);
std::vector<typename stl_container_t::value_type> tmp_buffer (
sourse_data.begin(), sourse_data.end() );
from_base64(tmp_buffer);
}
template<typename char_t, typename allocator_t>
void from_base64 (
const std::vector<char_t, allocator_t> & sourse_data )
{
if ( sourse_data.empty() )
{
p_buffer->clear();
return;
}
from_base64_for_vector_or_string (
sourse_data.begin(), sourse_data.end() );
}
template<typename char_t, typename char_traits_t, typename allocator_t>
void from_base64 (
const std::basic_string<char_t, char_traits_t, allocator_t> & sourse_data )
{
if ( sourse_data.empty() )
{
p_buffer->clear();
return;
}
from_base64_for_vector_or_string (
sourse_data.begin(), sourse_data.end() );
}
p_buffer_t get_result();
void get_result ( std::string & out_str );
void get_result ( std::vector<char> & out_buffer );
private:
template<typename in_rait_t>
void to_base64_for_vector_or_string (
const in_rait_t it_begin, const in_rait_t it_end )
{
// This code can not be compiled, because a sequence is contained
// by a wrong type; need sequence which contained by predefined char type
CHARTYPE_SOURCE_ITERATOR_CHECK(in_rait_t);
// This code can not be compiled, because iterator_category of in_rait_t
// is not equal std::random_access_iterator_tag
RANDOM_ACCESS_ITERATOR_CHECK(in_rait_t);
std::size_t data_length = std::distance(it_begin, it_end);
if ( data_length <= 0 )
{
p_buffer->clear();
return;
}
const char * p_data_begin = reinterpret_cast<const char*>( & * it_begin );
do_encode_to_base64 ( p_data_begin, data_length );
}
template<typename in_rait_t>
void from_base64_for_vector_or_string (
const in_rait_t it_begin, const in_rait_t it_end )
{
// This code can not be compiled, because a sequence is contained
// by a wrong type; need sequence which contained by predefined char type
CHARTYPE_SOURCE_ITERATOR_CHECK(in_rait_t);
// This code can not be compiled, because iterator_category of in_rait_t
// is not equal std::random_access_iterator_tag
RANDOM_ACCESS_ITERATOR_CHECK(in_rait_t);
std::size_t data_length = std::distance(it_begin, it_end);
if ( data_length <= 0 )
{
p_buffer->clear();
return;
}
const char * p_data_begin = reinterpret_cast<const char*>( & * it_begin );
do_decode_from_base64 ( p_data_begin, data_length );
}
void do_encode_to_base64 (
const char * sourse_data,
std::size_t sourse_data_size );
void do_decode_from_base64 (
const char * sourse_data,
std::size_t sourse_data_size );
private:
enum { MAX_LINE_LENGTH = 72 };
p_buffer_t p_buffer;
};
//------------------------------------------------------------------------
#endif // __BASE64_CONVERTER_HEADER_INCLUDED__
//------------------------------------------------------------------------
Файл base64_conv.cpp //------------------------------------------------------------------------
#include "stdafx.h"
#include "base64_conv.h"
//------------------------------------------------------------------------
namespace {
// Translation Table as described in RFC1113
//------------------------------------------------------------------------
const char cb64[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
// Translation Table to decode (created by author)
//------------------------------------------------------------------------
const char cd64[]="|$$$}rstuvwxyz{$$$$$$$>?@ABCDEFGHIJKLMNOPQRSTUVW$$$$$$XYZ[\\]^_`abcdefghijklmnopq";
// encode 3 8-bit binary bytes as 4 '6-bit' characters
//------------------------------------------------------------------------
void encodeblock ( unsigned char in[3], unsigned char out[4], int len )
{
out[0] = cb64[ in[0] >> 2 ];
out[1] = cb64[ ((in[0] & 0x03) << 4) | ((in[1] & 0xf0) >> 4) ];
out[2] = (unsigned char) (len > 1 ? cb64[ ((in[1] & 0x0f) << 2) | ((in[2] & 0xc0) >> 6) ] : '=');
out[3] = (unsigned char) (len > 2 ? cb64[ in[2] & 0x3f ] : '=');
}
// decode 4 '6-bit' characters into 3 8-bit binary bytes
//------------------------------------------------------------------------
void decodeblock( unsigned char in[4], unsigned char out[3] )
{
out[ 0 ] = (unsigned char ) (in[0] << 2 | in[1] >> 4);
out[ 1 ] = (unsigned char ) (in[1] << 4 | in[2] >> 2);
out[ 2 ] = (unsigned char ) (((in[2] << 6) & 0xc0) | in[3]);
}
// base64 encode a sequence adding padding and line breaks as per spec.
//------------------------------------------------------------------------
void encode (
const char * in_sequence,
std::size_t in_length,
std::vector<char> & out_sequence,
int line_size )
{
unsigned char in[3], out[4];
int i, len, blocks_out = 0;
out_sequence.clear();
out_sequence.reserve(in_length * 4/3);
const char * it_begin = in_sequence;
const char * it_end = in_sequence + in_length;
while ( it_begin < it_end )
{
len = 0;
for ( i = 0; i < 3; i++ )
{
if ( it_begin < it_end )
{
in[i] = static_cast<unsigned char>(*it_begin++);
len++;
}
else
{
in[i] = 0;
}
}
if ( len )
{
encodeblock( in, out, len );
for( i = 0; i < 4; i++ )
{
out_sequence.push_back(out[i]);
}
blocks_out++;
}
if ( blocks_out >= (line_size/4) || ( it_begin == it_end ) )
{
if ( blocks_out )
{
out_sequence.push_back('\r');
out_sequence.push_back('\n');
}
blocks_out = 0;
}
}
}
// decode a base64 encoded sequence discarding padding, line breaks and noise
//------------------------------------------------------------------------
void decode (
const char * in_sequence,
std::size_t in_length,
std::vector<char> & out_sequence )
{
unsigned char in[4], out[3], v;
int i, len;
out_sequence.clear();
out_sequence.reserve(in_length * 3/4);
const char * it_begin = in_sequence;
const char * it_end = in_sequence + in_length;
while( it_begin < it_end )
{
for( len = 0, i = 0; i < 4 && (it_begin < it_end); i++ )
{
v = 0;
for ( ; (it_begin < it_end) && v == 0 ; ++it_begin )
{
v = static_cast<unsigned char>(*it_begin);
v = static_cast<unsigned char>((v < 43 || v > 122) ? 0 : cd64[ v - 43 ]);
if( v )
{
v = static_cast<unsigned char>((v == '$') ? 0 : v - 61);
}
}
if ( v )
{
len++;
in[i] = static_cast<unsigned char>(v - 1);
}
else
{
in[i] = 0;
}
}
if( len )
{
decodeblock( in, out );
for( i = 0; i < len - 1; i++ )
{
out_sequence.push_back(out[i]);
}
}
}
}
}
//------------------------------------------------------------------------
base64_conv::base64_conv()
: p_buffer ( new std::vector<char> )
{
};
//------------------------------------------------------------------------
base64_conv::~base64_conv()
{
};
//------------------------------------------------------------------------
void base64_conv::do_encode_to_base64 (
const char * sourse_data, std::size_t sourse_data_size )
{
encode ( sourse_data, sourse_data_size, *p_buffer, MAX_LINE_LENGTH );
}
//------------------------------------------------------------------------
void base64_conv::do_decode_from_base64 (
const char * sourse_data, std::size_t sourse_data_size )
{
decode ( sourse_data, sourse_data_size, *p_buffer );
}
//------------------------------------------------------------------------
base64_conv::p_buffer_t base64_conv::get_result()
{
return p_buffer;
}
//------------------------------------------------------------------------
void base64_conv::get_result (
std::string & out_str )
{
std::string ret_val;
ret_val.reserve(p_buffer->size());
std::copy (
p_buffer->begin(),
p_buffer->end(),
std::back_inserter(ret_val) );
std::swap(out_str, ret_val);
}
//------------------------------------------------------------------------
void base64_conv::get_result (
std::vector<char> & out_buffer )
{
std::swap(out_buffer, *p_buffer);
p_buffer->clear();
}
//------------------------------------------------------------------------
Комментариев нет:
Отправить комментарий