| #ifndef __base64_h__
#define __base64_h__
#include <cstddef> // NULL
#include <istream>
#include <xutility>
#include <memory.h>
#include "boost/iterator/iterator_facade.hpp"
#include "boost/shared_array.hpp"
namespace boost { namespace archive { namespace iterators {
enum {
prebuf_default_buffer_size = 5242880 /*5 Mb*/
};
// given a type, make an input iterator based on a pointer to that type
template<class Elem = char, Elem eof_value = -1, long buffer_size = prebuf_default_buffer_size>
class base64_istream_iterator_ :
public boost::iterator_facade<base64_istream_iterator_<Elem, eof_value, buffer_size>, Elem, std::input_iterator_tag, Elem>
{
friend class boost::iterator_core_access;
typedef base64_istream_iterator_ this_t ;
typedef BOOST_DEDUCED_TYPENAME boost::iterator_facade<
base64_istream_iterator_<Elem, eof_value, buffer_size>,
Elem,
std::input_iterator_tag,
Elem
> super_t;
protected:
typedef BOOST_DEDUCED_TYPENAME std::basic_istream<Elem> istream_type;
typedef BOOST_DEDUCED_TYPENAME boost::shared_array<Elem> shared_array;
//Access the value referred to
Elem dereference() const {
return m_current_value;
}
bool equal(const this_t & rhs) const {
// note: only works for comparison against end of stream
return m_istream == rhs.m_istream;
}
bool pre_read() {
assert( m_prebuf_pos >= m_prebuf_len );
if( NULL != m_istream ) {
//calculate remain length of stream
istream_type::pos_type cur_pos = m_istream->tellg();
m_istream->seekg(-1, std::ios_base::end);
istream_type::pos_type end_pos = m_istream->tellg();
m_istream->seekg(cur_pos, std::ios_base::beg);
long remain = (long)(end_pos - cur_pos)+1;
assert(remain >= 0);
if( 0 == remain ) {
m_istream->get(); //eof
assert(! m_istream->good());
m_istream = NULL;
return false;
}
m_prebuf_len = min( remain, buffer_size );
m_istream->read( m_prebuf.get(), m_prebuf_len );
m_prebuf_pos = 0;
return true;
}
return false;
}
void increment() {
++m_prebuf_pos;
if( m_prebuf_pos >= m_prebuf_len ) {
if( !pre_read() ) {
m_current_value = eof_value;
return;
}
}
m_current_value = m_prebuf[m_prebuf_pos];
}
private:
istream_type *m_istream;
Elem m_current_value;
//pre-buffer
shared_array m_prebuf;
//current pre-buffer length
long m_prebuf_len;
//current position in pre-buffer
long m_prebuf_pos;
public:
base64_istream_iterator_(istream_type & is)
: m_istream(& is)
, m_prebuf_len(0)
, m_prebuf_pos(0)
{
m_prebuf.reset( new Elem[buffer_size] );
increment();
}
base64_istream_iterator_()
: m_istream(NULL)
, m_prebuf_len(0)
, m_prebuf_pos(0)
{}
base64_istream_iterator_(const base64_istream_iterator_<Elem, eof_value, buffer_size> & rhs)
: m_istream(rhs.m_istream)
, m_current_value(rhs.m_current_value)
, m_prebuf_len(rhs.m_prebuf_len)
, m_prebuf_pos(rhs.m_prebuf_pos)
, m_prebuf(rhs.m_prebuf)
{}
};
//...........................................................................................................
template<class Elem = char, long buffer_size = prebuf_default_buffer_size>
class istream_iterator_encode_to_base64 : public base64_istream_iterator_<Elem, 0, buffer_size>
{
friend class boost::iterator_core_access;
typedef base64_istream_iterator_<Elem, 0, buffer_size> base_;
public:
istream_iterator_encode_to_base64(BOOST_DEDUCED_TYPENAME base_::istream_type & is)
: base_(is)
{}
istream_iterator_encode_to_base64()
: base_()
{}
istream_iterator_encode_to_base64(const istream_iterator_encode_to_base64<Elem, buffer_size> & rhs)
: base_(rhs)
{}
};
template<class Elem = char, long buffer_size = prebuf_default_buffer_size>
class istream_iterator_decode_from_base64 : public base64_istream_iterator_<Elem, 65, buffer_size>
{
friend class boost::iterator_core_access;
typedef base64_istream_iterator_<Elem, 65, buffer_size> base_;
public:
istream_iterator_decode_from_base64(BOOST_DEDUCED_TYPENAME base_::istream_type & is)
: base_(is)
{}
istream_iterator_decode_from_base64()
: base_()
{}
istream_iterator_decode_from_base64(const istream_iterator_decode_from_base64<Elem, buffer_size> & rhs)
: base_(rhs)
{}
};
//...........................................................................................................
//...........................................................................................................
template<class InIt, class OutIt>
inline void __CLRCALL_OR_CDECL copy_base64_to_bin(InIt First, InIt Last, OutIt Dest)
{
for (; First != Last; ++Dest, ++First )
{
typename InIt::value_type val = *First;
if( First != Last )
*Dest = val;
else
break;
}
}
} } }
#endif
|