Sans Pareil Technologies, Inc.

Key To Your Business

Base64Encoder



An encoder that uses the base64 scheme to encode data written to output streams. See the unit test suite for sample usage.
UnbufferedStreamBuf.h 
A base interface for unbuffered I/O streams.
/*
 * UnufferedStreamBuf.h
 *
 * $Id:  *poco/1.4/Foundation/include/Poco/UnbufferedStreamBuf.h#1 $
 *
 * Library: Foundation
 * Package: Streams
 * Module:  StreamBuf
 *
 * Definition of template BasicUnbufferedStreamBuf and class UnbufferedStreamBuf.
 *
 * Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
 * and Contributors.
 *
 * Permission is hereby granted, free of charge, to any person or organization
 * obtaining a copy of the software and accompanying documentation covered by
 * this license (the "Software") to use, reproduce, display, distribute,
 * execute, and transmit the Software, and to prepare derivative works of the
 * Software, and to permit third-parties to whom the Software is furnished to
 * do so, all subject to the following:
 *
 * The copyright notices in the Software and this entire statement, including
 * the above license grant, this restriction and the following disclaimer,
 * must be included in all copies of the Software, in whole or in part, and
 * all derivative works of the Software, unless such copies or derivative
 * works are solely in the form of machine-executable object code generated by
 * a source language processor.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
 * SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
 * FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 */


#ifndef SPT_UNBUFFEREDSTREAMBUF
#define SPT_UNBUFFEREDSTREAMBUF


#if defined( ARDUINO )
#include "../StandardCplusplus/streambuf"
#include "../StandardCplusplus/iosfwd"
#include "../StandardCplusplus/ios"
#else
#include <streambuf>
#include <iosfwd>
#include <ios>
#endif


namespace spt
{
  /// This is an implementation of an unbuffered streambuf
  /// that greatly simplifies the implementation of
  /// custom streambufs of various kinds.
  /// Derived classes only have to override the methods
  /// readFromDevice() or writeToDevice().
  template <typename ch, typename tr>
  class BasicUnbufferedStreamBuf: public std::basic_streambuf<ch, tr>
  {
  protected:
    typedef std::basic_streambuf<ch, tr> Base;
    typedef std::basic_ios<ch, tr> IOS;
    typedef ch char_type;
    typedef tr char_traits;
    typedef typename Base::int_type int_type;
    typedef typename Base::pos_type pos_type;
    typedef typename Base::off_type off_type;
    typedef typename IOS::openmode openmode;

  public:
    BasicUnbufferedStreamBuf() :
      pb( char_traits::eof() ), ispb( false )
    {
      this->setg( 0, 0, 0 );
      this->setp( 0, 0 );
    }

    ~BasicUnbufferedStreamBuf() {}

    virtual int_type overflow( int_type c )
    {
      if ( c != char_traits::eof() ) return writeToDevice( char_traits::to_char_type( c ) );
      else return c;
    }

    virtual int_type underflow()
    {
      if ( ispb ) return pb;
      else
      {
        int_type c = readFromDevice();
        if ( c != char_traits::eof() )
        {
          ispb = true;
          pb   = c;
        }

        return c;
      }
    }

    virtual int_type uflow()
    {
      if (ispb)
      {
        ispb = false;
        return pb;
      }
      else
      {
        int_type c = readFromDevice();
        if ( c != char_traits::eof() ) pb = c;
        return c;
      }
    }

    virtual int_type pbackfail( int_type c )
    {
      if ( ispb ) return char_traits::eof();
      else
      {
        ispb = true;
        pb   = c;
        return c;
      }
    }

    /// Some platforms (for example, Compaq C++) have buggy implementations of
    /// xsgetn that handle null buffers incorrectly.
    /// Anyway, it does not hurt to provide an optimized implementation
    /// of xsgetn for this streambuf implementation.
    virtual std::streamsize xsgetn( char_type* p, std::streamsize count )
    {
      std::streamsize copied = 0;

      while ( count > 0 )
      {
        int_type c = uflow();
        if ( c == char_traits::eof() ) break;
        *p++ = char_traits::to_char_type(c);
        ++copied;
        --count;
      }

      return copied;
    }

  protected:
    static int_type charToInt( char_type c )
    {
      return char_traits::to_int_type( c );
    }

  private:
    virtual int_type readFromDevice()
    {
      return char_traits::eof();
    }

    virtual int_type writeToDevice( char_type )
    {
      return char_traits::eof();
    }

    int_type pb;
    bool ispb;

    BasicUnbufferedStreamBuf( const BasicUnbufferedStreamBuf& );
    BasicUnbufferedStreamBuf& operator = ( const BasicUnbufferedStreamBuf& );
  };


  // We provide an instantiation for char
  typedef BasicUnbufferedStreamBuf<char, std::char_traits<char> > UnbufferedStreamBuf;


} // namespace spt


#endif // SPT_UNBUFFEREDSTREAMBUF
Base64Encoder.h 
Interfaces for the stream buffer, IO stream and encoder classes.
/*
 * Base64Encoder.h
 *
 * Definition of class Base64Encoder.
 *
 * Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
 * and Contributors.
 *
 * Permission is hereby granted, free of charge, to any person or organization
 * obtaining a copy of the software and accompanying documentation covered by
 * this license (the "Software") to use, reproduce, display, distribute,
 * execute, and transmit the Software, and to prepare derivative works of the
 * Software, and to permit third-parties to whom the Software is furnished to
 * do so, all subject to the following:
 *
 * The copyright notices in the Software and this entire statement, including
 * the above license grant, this restriction and the following disclaimer,
 * must be included in all copies of the Software, in whole or in part, and
 * all derivative works of the Software, unless such copies or derivative
 * works are solely in the form of machine-executable object code generated by
 * a source language processor.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
 * SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
 * FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 */


#ifndef SPT_BASE64ENCODER
#define SPT_BASE64ENCODER


#include "SPT.h"
#include "UnbufferedStreamBuf.h"
#include "UnbufferedStreamBuf.h"

#if defined( ARDUINO )
#include "../StandardCplusplus/ostream"
#else
#include <ostream>
#endif


namespace spt
{
  /// This streambuf base64-encodes all data written
  /// to it and forwards it to a connected
  /// ostream.
  ///
  /// Note: The characters are directly written
  /// to the ostream's streambuf, thus bypassing
  /// the ostream. The ostream's state is therefore
  /// not updated to match the buffer's state.
  class Base64EncoderBuf: public UnbufferedStreamBuf
  {
  public:
    Base64EncoderBuf(std::ostream& ostr);
    ~Base64EncoderBuf();

    /// Closes the stream buffer.
    int close();

    /// Specify the line length.
    ///
    /// After the given number of characters have been written,
    /// a newline character will be written.
    ///
    /// Specify 0 for an unlimited line length.
    void setLineLength( int32_t lineLength );

    /// Returns the currently set line length.
    int32_t getLineLength() const;

  private:
    int_type writeToDevice( char c );

    Byte group[3];
    int32_t groupLength;
    int32_t pos;
    int32_t lineLength;
    std::streambuf& buf;

    static const Byte OUT_ENCODING[64];
    friend class Base64DecoderBuf;

    Base64EncoderBuf( const Base64EncoderBuf& );
    Base64EncoderBuf& operator = ( const Base64EncoderBuf& );
  };


  /// The base class for Base64Encoder.
  ///
  /// This class is needed to ensure the correct initialization
  /// order of the stream buffer and base classes.
  class Base64EncoderIOS: public virtual std::ios
  {
  public:
    Base64EncoderIOS( std::ostream& ostr );
    ~Base64EncoderIOS();

    int close();
    Base64EncoderBuf* rdbuf();

  protected:
    Base64EncoderBuf buf;

  private:
    Base64EncoderIOS( const Base64EncoderIOS& );
    Base64EncoderIOS& operator = ( const Base64EncoderIOS& );
  };


  /// This ostream base64-encodes all data
  /// written to it and forwards it to
  /// a connected ostream.
  /// Always call close() when done
  /// writing data, to ensure proper
  /// completion of the encoding operation.
  ///
  /// Note: The characters are directly written
  /// to the ostream's streambuf, thus bypassing
  /// the ostream. The ostream's state is therefore
  /// not updated to match the buffer's state.
  class Base64Encoder: public Base64EncoderIOS, public std::ostream
  {
  public:
    Base64Encoder( std::ostream& ostr );
    ~Base64Encoder();

  private:
    Base64Encoder( const Base64Encoder& );
    Base64Encoder& operator = ( const Base64Encoder& );
  };


} // namespace spt


#endif // SPT_BASE64ENCODER
Base64Encoder.cpp 
Implementation of the base 64 stream encoder.
/*
 * Base64Encoder.cpp
 *
 * $Id:  *poco/1.4/Foundation/src/Base64Encoder.cpp#2 $
 *
 * Library: Foundation
 * Package: Streams
 * Module:  Base64
 *
 * Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
 * and Contributors.
 *
 * Permission is hereby granted, free of charge, to any person or organization
 * obtaining a copy of the software and accompanying documentation covered by
 * this license (the "Software") to use, reproduce, display, distribute,
 * execute, and transmit the Software, and to prepare derivative works of the
 * Software, and to permit third-parties to whom the Software is furnished to
 * do so, all subject to the following:
 *
 * The copyright notices in the Software and this entire statement, including
 * the above license grant, this restriction and the following disclaimer,
 * must be included in all copies of the Software, in whole or in part, and
 * all derivative works of the Software, unless such copies or derivative
 * works are solely in the form of machine-executable object code generated by
 * a source language processor.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
 * SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
 * FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 */


#include "Base64Encoder.h"


using spt::Byte;
using spt::Base64Encoder;
using spt::Base64EncoderBuf;
using spt::Base64EncoderIOS;


const Byte Base64EncoderBuf::OUT_ENCODING[64] =
{
    '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', '+', '/'
};


Base64EncoderBuf::Base64EncoderBuf(std::ostream& ostr) :
  groupLength(0), pos(0),
  lineLength(72), buf( *ostr.rdbuf() ) {}


Base64EncoderBuf::~Base64EncoderBuf()
{
#if !defined( ARDUINO )
    try
    {
#endif
    close();
#if !defined( ARDUINO )
  }
  catch (...) {}
#endif
}


void Base64EncoderBuf::setLineLength( int32_t ll ) { lineLength = ll; }


int32_t Base64EncoderBuf::getLineLength() const { return lineLength; }


Base64EncoderBuf::int_type Base64EncoderBuf::writeToDevice( char c )
{
    static const int eof = std::char_traits<char>::eof();
  group[groupLength++] = static_cast<Byte>( c );

  if ( groupLength == 3 )
    {
    Byte idx;
    idx = group[0] >> 2;
    if ( buf.sputc(OUT_ENCODING[idx]) == eof ) return eof;

    idx = ( ( group[0] & 0x03 ) << 4 ) | ( group[1] >> 4 );
    if ( buf.sputc( OUT_ENCODING[idx] ) == eof ) return eof;

    idx = ( ( group[1] & 0x0F ) << 2 ) | ( group[2] >> 6 );
    if ( buf.sputc( OUT_ENCODING[idx] ) == eof ) return eof;

    idx = group[2] & 0x3F;
    if ( buf.sputc( OUT_ENCODING[idx] ) == eof ) return eof;

    pos += 4;
    if ( lineLength > 0 && pos >= lineLength )
        {
      if ( buf.sputc( '\r' ) == eof ) return eof;
      if ( buf.sputc( '\n' ) == eof) return eof;
      pos = 0;
        }

    groupLength = 0;
    }

  return charToInt( c );
}


int Base64EncoderBuf::close()
{
    static const int eof = std::char_traits<char>::eof();

  if ( sync() == eof ) return eof;
  if ( groupLength == 1 )
    {
    group[1] = 0;
    Byte idx;
    idx = group[0] >> 2;
    if ( buf.sputc( OUT_ENCODING[idx] ) == eof ) return eof;

    idx = ( ( group[0] & 0x03 ) << 4 ) | ( group[1] >> 4 );
    if ( buf.sputc( OUT_ENCODING[idx] ) == eof ) return eof;

    if ( buf.sputc( '=' ) == eof ) return eof;
    if ( buf.sputc( '=' ) == eof ) return eof;
    }
  else if ( groupLength == 2 )
    {
    group[2] = 0;
    Byte idx;
    idx = group[0] >> 2;
    if ( buf.sputc( OUT_ENCODING[idx] ) == eof ) return eof;

    idx = ( (group[0] & 0x03) << 4 ) | ( group[1] >> 4 );
    if ( buf.sputc( OUT_ENCODING[idx] ) == eof ) return eof;

    idx = ( ( group[1] & 0x0F ) << 2 ) | ( group[2] >> 6 );
    if ( buf.sputc( OUT_ENCODING[idx] ) == eof ) return eof;

    if ( buf.sputc( '=' ) == eof ) return eof;
    }

  groupLength = 0;
  return buf.pubsync();
}


Base64EncoderIOS::Base64EncoderIOS( std::ostream& ostr ): buf( ostr )
{
  init( &buf );
}


Base64EncoderIOS::~Base64EncoderIOS() {}


int Base64EncoderIOS::close() { return buf.close(); }


Base64EncoderBuf* Base64EncoderIOS::rdbuf() { return &buf; }


Base64Encoder::Base64Encoder( std::ostream& ostr ) :
    Base64EncoderIOS( ostr ), std::ostream( &buf ) {}


Base64Encoder::~Base64Encoder() {}
Adapted for use on Arduino from Poco.