Sans Pareil Technologies, Inc.

Key To Your Business

Base64Decoder



Decoder for input streams that contain base64 encoded data.

Base64Decoder.h

Definitions of the buffer, IO stream and decoder for base64 data.

    1: /*
    2: * Base64Decoder.h
    3: *
    4: * $Id:  *poco/1.4/Foundation/include/Poco/Base64Decoder.h#2 $
    5: *
    6: * Library: Foundation
    7: * Package: Streams
    8: * Module:  Base64
    9: *
   10: * Definition of class Base64Decoder.
   11: *
   12: * Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
   13: * and Contributors.
   14: *
   15: * Permission is hereby granted, free of charge, to any person or organization
   16: * obtaining a copy of the software and accompanying documentation covered by
   17: * this license (the "Software") to use, reproduce, display, distribute,
   18: * execute, and transmit the Software, and to prepare derivative works of the
   19: * Software, and to permit third-parties to whom the Software is furnished to
   20: * do so, all subject to the following:
   21: *
   22: * The copyright notices in the Software and this entire statement, including
   23: * the above license grant, this restriction and the following disclaimer,
   24: * must be included in all copies of the Software, in whole or in part, and
   25: * all derivative works of the Software, unless such copies or derivative
   26: * works are solely in the form of machine-executable object code generated by
   27: * a source language processor.
   28: *
   29: * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   30: * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   31: * FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
   32: * SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
   33: * FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
   34: * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
   35: * DEALINGS IN THE SOFTWARE.
   36: */
   37:
   38:
   39: #ifndef SPT_BASE64DECODER
   40: #define SPT_BASE64DECODER
   41:
   42:
   43: #include "UnbufferedStreamBuf.h"
   44: #include "SPT.h"
   45:
   46: #if defined( ARDUINO )
   47: #include "../StandardCplusplus/istream"
   48: #else
   49: #include <istream>
   50: #endif
   51:
   52:
   53: namespace spt
   54: {
   55:   /// This streambuf base64-decodes all data read
   56:   /// from the istream connected to it.
   57:   ///
   58:   /// Note: For performance reasons, the characters
   59:   /// are read directly from the given istream's
   60:   /// underlying streambuf, so the state
   61:   /// of the istream will not reflect that of
   62:   /// its streambuf.
   63:   class Base64DecoderBuf: public UnbufferedStreamBuf
   64:   {
   65:   public:
   66:     Base64DecoderBuf( std::istream& istr );
   67:     ~Base64DecoderBuf();
   68:
   69:   private:
   70:     int_type readFromDevice();
   71:     int readOne();
   72:
   73:     Byte group[3];
   74:     int32_t groupLength;
   75:     int32_t groupIndex;
   76:     std::streambuf& buf;
   77:
   78:     static Byte IN_ENCODING[256];
   79:     static bool IN_ENCODING_INIT;
   80:
   81:   private:
   82:     Base64DecoderBuf( const Base64DecoderBuf& );
   83:     Base64DecoderBuf& operator = ( const Base64DecoderBuf& );
   84:   };
   85:
   86:
   87:   /// The base class for Base64Decoder.
   88:   ///
   89:   /// This class is needed to ensure the correct initialization
   90:   /// order of the stream buffer and base classes.
   91:   class Base64DecoderIOS: public virtual std::ios
   92:   {
   93:   public:
   94:     Base64DecoderIOS( std::istream& istr );
   95:     ~Base64DecoderIOS();
   96:     Base64DecoderBuf* rdbuf();
   97:
   98:   protected:
   99:     Base64DecoderBuf buf;
  100:
  101:   private:
  102:     Base64DecoderIOS( const Base64DecoderIOS& );
  103:     Base64DecoderIOS& operator = ( const Base64DecoderIOS& );
  104:   };
  105:
  106:
  107:   /// This istream base64-decodes all data
  108:   /// read from the istream connected to it.
  109:   ///
  110:   /// Note: For performance reasons, the characters
  111:   /// are read directly from the given istream's
  112:   /// underlying streambuf, so the state
  113:   /// of the istream will not reflect that of
  114:   /// its streambuf.
  115:   class Base64Decoder: public Base64DecoderIOS, public std::istream
  116:   {
  117:   public:
  118:     Base64Decoder( std::istream& istr );
  119:     ~Base64Decoder();
  120:
  121:   private:
  122:     Base64Decoder( const Base64Decoder& );
  123:     Base64Decoder& operator = ( const Base64Decoder& );
  124:   };
  125:
  126:
  127: } // namespace spt
  128:
  129:
  130: #endif // SPT_BASE64DECODER


Base64Decoder.cpp

Implementation of the IO streams for base64 data.

    1: /*
    2: * Base64Decoder.cpp
    3: *
    4: * $Id:  *poco/1.4/Foundation/src/Base64Decoder.cpp#2 $
    5: *
    6: * Library: Foundation
    7: * Package: Streams
    8: * Module:  Base64
    9: *
   10: * Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
   11: * and Contributors.
   12: *
   13: * Permission is hereby granted, free of charge, to any person or organization
   14: * obtaining a copy of the software and accompanying documentation covered by
   15: * this license (the "Software") to use, reproduce, display, distribute,
   16: * execute, and transmit the Software, and to prepare derivative works of the
   17: * Software, and to permit third-parties to whom the Software is furnished to
   18: * do so, all subject to the following:
   19: *
   20: * The copyright notices in the Software and this entire statement, including
   21: * the above license grant, this restriction and the following disclaimer,
   22: * must be included in all copies of the Software, in whole or in part, and
   23: * all derivative works of the Software, unless such copies or derivative
   24: * works are solely in the form of machine-executable object code generated by
   25: * a source language processor.
   26: *
   27: * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   28: * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   29: * FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
   30: * SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
   31: * FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
   32: * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
   33: * DEALINGS IN THE SOFTWARE.
   34: */
   35:
   36:
   37: #include "Base64Decoder.h"
   38: #include "Base64Encoder.h"
   39:
   40:
   41: using spt::Byte;
   42: using spt::Base64Decoder;
   43: using spt::Base64DecoderBuf;
   44: using spt::Base64DecoderIOS;
   45: using spt::Base64Encoder;
   46:
   47:
   48: Byte Base64DecoderBuf::IN_ENCODING[256];
   49: bool Base64DecoderBuf::IN_ENCODING_INIT = false;
   50:
   51:
   52: Base64DecoderBuf::Base64DecoderBuf( std::istream& istr ) :
   53:   groupLength(0), groupIndex(0), buf( *istr.rdbuf() )
   54: {
   55:   if ( !IN_ENCODING_INIT )
   56:         {
   57:     for ( uint16_t i = 0; i < sizeof( IN_ENCODING ); ++i )
   58:                 {
   59:                         IN_ENCODING[i] = 0xFF;
   60:                 }
   61:
   62:     for ( uint16_t i = 0; i < sizeof( Base64EncoderBuf::OUT_ENCODING ); ++i )
   63:                 {
   64:                         IN_ENCODING[Base64EncoderBuf::OUT_ENCODING[i]] = i;
   65:                 }
   66:
   67:     IN_ENCODING[static_cast<Byte>( '=' )] = '\0';
   68:                 IN_ENCODING_INIT = true;
   69:         }
   70: }
   71:
   72:
   73: Base64DecoderBuf::~Base64DecoderBuf() {}
   74:
   75:
   76: Base64DecoderBuf::int_type Base64DecoderBuf::readFromDevice()
   77: {
   78:   if ( groupIndex <  groupLength ) return group[groupIndex++];
   79:         else
   80:         {
   81:     Byte buffer[4];
   82:
   83:                 int c;
   84:     if ( ( c = readOne() ) == -1 ) return -1;
   85:
   86:     buffer[0] = static_cast<Byte>( c );
   87:     if ( IN_ENCODING[buffer[0]] == 0xFF ) return -1;
   88:     if ( ( c = readOne() ) == -1 ) return -1;
   89:
   90:     buffer[1] = static_cast<Byte>( c );
   91:     if ( IN_ENCODING[buffer[1]] == 0xFF ) return -1;
   92:     if ( ( c = readOne() ) == -1 ) return -1;
   93:
   94:     buffer[2] = static_cast<Byte>( c );
   95:     if ( IN_ENCODING[buffer[2]] == 0xFF ) return -1;
   96:     if ( ( c = readOne() ) == -1 ) return -1;
   97:
   98:                 buffer[3] = c;
   99:     if ( IN_ENCODING[buffer[3]] == 0xFF ) return -1;
  100:                
  101:     group[0] = ( IN_ENCODING[buffer[0]] << 2 ) | ( IN_ENCODING[buffer[1]] >> 4 );
  102:     group[1] = ( ( IN_ENCODING[buffer[1]] & 0x0F ) << 4 ) | ( IN_ENCODING[buffer[2]] >> 2 );
  103:     group[2] = ( IN_ENCODING[buffer[2]] << 6 ) | IN_ENCODING[buffer[3]];
  104:
  105:     if ( buffer[2] == '=' ) groupLength = 1;
  106:     else if ( buffer[3] == '=' )  groupLength = 2;
  107:     else groupLength = 3;
  108:
  109:     groupIndex = 1;
  110:     return group[0];
  111:         }
  112: }
  113:
  114:
  115: int Base64DecoderBuf::readOne()
  116: {
  117:   int ch = buf.sbumpc();
  118:   while ( ch == ' ' || ch == '\r' || ch == '\t' || ch == '\n' ) ch = buf.sbumpc();
  119:         return ch;
  120: }
  121:
  122:
  123: Base64DecoderIOS::Base64DecoderIOS( std::istream& istr ): buf( istr )
  124: {
  125:   init( &buf );
  126: }
  127:
  128:
  129: Base64DecoderIOS::~Base64DecoderIOS() {}
  130:
  131:
  132: Base64DecoderBuf* Base64DecoderIOS::rdbuf() { return &buf; }
  133:
  134:
  135: Base64Decoder::Base64Decoder( std::istream& istr ) :
  136:   Base64DecoderIOS( istr ), std::istream( &buf ) {}
  137:
  138:
  139: Base64Decoder::~Base64Decoder() {}


Base64Test.cpp

Unit test suite for base64 encoding and decoding.

    1: #if defined( ARDUINO )
    2: #include "tut.hpp"
    3: #include "SPT.h"
    4: #include "Base64Encoder.h"
    5: #include "Base64Decoder.h"
    6: #else
    7: #include <tut/tut.hpp>
    8: #include <SPT.h>
    9: #include <Base64Encoder.h>
   10: #include <Base64Decoder.h>
   11: #endif
   12:
   13: using spt::Base64Encoder;
   14: using spt::Base64Decoder;
   15:
   16: namespace tut
   17: {
   18:   struct Base64TestData {};
   19:
   20:   typedef test_group<Base64TestData> Base64TestGroup;
   21:   typedef Base64TestGroup::object Base64Test;
   22:   Base64TestGroup base64TestGroup( "Base64 test suite" );
   23:
   24:
   25:   template<>
   26:   template<>
   27:   void Base64Test::test<1>()
   28:   {
   29:     set_test_name( "encode1" );
   30:
   31:     std::ostringstream str;
   32:     Base64Encoder encoder( str );
   33:     encoder << std::string( "\00\01\02\03\04\05", 6 );
   34:     encoder.close();
   35:     ensure( "Encode1", str.str() == "AAECAwQF" );
   36:     spt::printFreeRam();
   37:   }
   38:
   39:
   40:   template<>
   41:   template<>
   42:   void Base64Test::test<2>()
   43:   {
   44:     set_test_name( "encode2" );
   45:
   46:     std::ostringstream str;
   47:     Base64Encoder encoder( str );
   48:     encoder << std::string( "\00\01\02\03", 4 );
   49:     encoder.close();
   50:     ensure( "Encode2", str.str() == "AAECAw==" );
   51:     spt::printFreeRam();
   52:   }
   53:
   54:
   55:   template<>
   56:   template<>
   57:   void Base64Test::test<3>()
   58:   {
   59:     set_test_name( "encode3" );
   60:
   61:     std::ostringstream str;
   62:     Base64Encoder encoder( str );
   63:     encoder << "ABCDEF";
   64:     encoder.close();
   65:     ensure( "Encode 3", str.str() == "QUJDREVG" );
   66:     spt::printFreeRam();
   67:   }
   68:
   69:
   70:   template<>
   71:   template<>
   72:   void Base64Test::test<4>()
   73:   {
   74:     set_test_name( "decode1" );
   75:
   76:     std::istringstream istr( "AAECAwQF" );
   77:     Base64Decoder decoder( istr );
   78:     ensure( "Decode 1-1", decoder.good() && decoder.get() == 0 );
   79:     ensure( "Decode 1-2", decoder.good() && decoder.get() == 1 );
   80:     ensure( "Decode 1-3", decoder.good() && decoder.get() == 2 );
   81:     ensure( "Decode 1-4", decoder.good() && decoder.get() == 3 );
   82:     ensure( "Decode 1-5", decoder.good() && decoder.get() == 4 );
   83:     ensure( "Decode 1-6", decoder.good() && decoder.get() == 5 );
   84:     ensure( "Decode 1-7", decoder.good() && decoder.get() == -1 );
   85:     spt::printFreeRam();
   86:   }
   87:
   88:
   89:   template<>
   90:   template<>
   91:   void Base64Test::test<5>()
   92:   {
   93:     set_test_name( "decode2" );
   94:
   95:     std::istringstream istr( "AAECAwQ=" );
   96:     Base64Decoder decoder( istr );
   97:     ensure( "Decode 2-1", decoder.good() && decoder.get() == 0 );
   98:     ensure( "Decode 2-2", decoder.good() && decoder.get() == 1 );
   99:     ensure( "Decode 2-3", decoder.good() && decoder.get() == 2 );
  100:     ensure( "Decode 2-4", decoder.good() && decoder.get() == 3 );
  101:     ensure( "Decode 2-5", decoder.good() && decoder.get() == 4 );
  102:     ensure( "Decode 2-6", decoder.good() && decoder.get() == -1 );
  103:     spt::printFreeRam();
  104:   }
  105:
  106:
  107:   template<>
  108:   template<>
  109:   void Base64Test::test<6>()
  110:   {
  111:     set_test_name( "decode3" );
  112:
  113:     std::istringstream istr( "AAECAw==" );
  114:     Base64Decoder decoder( istr );
  115:     ensure( "Decode 3-1", decoder.good() && decoder.get() == 0 );
  116:     ensure( "Decode 3-2", decoder.good() && decoder.get() == 1 );
  117:     ensure( "Decode 3-3", decoder.good() && decoder.get() == 2 );
  118:     ensure( "Decode 3-4", decoder.good() && decoder.get() == 3 );
  119:     ensure( "Decode 3-5", decoder.good() && decoder.get() == -1 );
  120:     spt::printFreeRam();
  121:   }
  122:
  123:
  124:   template<>
  125:   template<>
  126:   void Base64Test::test<7>()
  127:   {
  128:     set_test_name( "decode4" );
  129:
  130:     std::istringstream istr( "QUJDREVG" );
  131:     Base64Decoder decoder( istr );
  132:     std::string s;
  133:     decoder >> s;
  134:     ensure( "Decode 4-1", s == "ABCDEF" );
  135:     ensure( "Decode 4-2", decoder.eof() );
  136:     spt::printFreeRam();
  137:   }
  138:
  139:
  140:   template<>
  141:   template<>
  142:   void Base64Test::test<8>()
  143:   {
  144:     set_test_name( "decode5" );
  145:
  146:     std::istringstream istr( "QUJ\r\nDRE\r\nVG" );
  147:     Base64Decoder decoder( istr );
  148:     std::string s;
  149:     decoder >> s;
  150:     ensure( "Decode 5-1", s == "ABCDEF" );
  151:     ensure( "Decode 5-2", decoder.eof() );
  152:     spt::printFreeRam();
  153:   }
  154:
  155:
  156:   template<>
  157:   template<>
  158:   void Base64Test::test<9>()
  159:   {
  160:     set_test_name( "decode6" );
  161:
  162:     std::istringstream istr( "QUJD#REVG" );
  163:     Base64Decoder decoder( istr );
  164:     std::string s;
  165:     decoder >> s;
  166:     ensure( "Decode 6-1", decoder.eof() );
  167:     spt::printFreeRam();
  168:   }
  169:
  170:
  171:   template<>
  172:   template<>
  173:   void Base64Test::test<10>()
  174:   {
  175:     set_test_name( "encodeDecode1" );
  176:
  177:     std::stringstream str;
  178:     Base64Encoder encoder( str );
  179:     encoder << "The quick brown fox ";
  180:     encoder << "jumped over the lazy dog.";
  181:     encoder.close();
  182:
  183:     Base64Decoder decoder( str );
  184:     std::string s;
  185:     int c = decoder.get();
  186:     while ( c != -1 ) { s += char(c); c = decoder.get(); }
  187:     ensure( "EncodeDecode1", s == "The quick brown fox jumped over the lazy dog." );
  188:     spt::printFreeRam();
  189:   }
  190:
  191:
  192:   template<>
  193:   template<>
  194:   void Base64Test::test<11>()
  195:   {
  196:     set_test_name( "encodeDecode2" );
  197:
  198:     std::string src;
  199:     for ( int i = 0; i < 255; ++i ) src += char( i );
  200:     std::stringstream str;
  201:     Base64Encoder encoder(str);
  202:     encoder.write( src.data(), static_cast<std::streamsize>( src.size() ) );
  203:     encoder.close();
  204:
  205:     Base64Decoder decoder( str );
  206:     std::string s;
  207:     int c = decoder.get();
  208:     while ( c != -1 ) { s += char(c); c = decoder.get(); }
  209:     ensure( "EncodeDecode2", s == src );
  210:     spt::printFreeRam();
  211:   }
  212: }