Base64Decoder
Decoder for input streams that contain base64 encoded data.
Base64Decoder.h
Definitions of the buffer, IO stream and decoder for base64 data.
/* * Base64Decoder.h * * $Id: *poco/1.4/Foundation/include/Poco/Base64Decoder.h#2 $ * * Library: Foundation * Package: Streams * Module: Base64 * * Definition of class Base64Decoder. * * 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_BASE64DECODER #define SPT_BASE64DECODER #include "UnbufferedStreamBuf.h" #include "SPT.h" #if defined( ARDUINO ) #include "../StandardCplusplus/istream" #else #include <istream> #endif namespace spt { /// This streambuf base64-decodes all data read /// from the istream connected to it. /// /// Note: For performance reasons, the characters /// are read directly from the given istream's /// underlying streambuf, so the state /// of the istream will not reflect that of /// its streambuf. class Base64DecoderBuf: public UnbufferedStreamBuf { public: Base64DecoderBuf( std::istream& istr ); ~Base64DecoderBuf(); private: int_type readFromDevice(); int readOne(); Byte group[3]; int32_t groupLength; int32_t groupIndex; std::streambuf& buf; static Byte IN_ENCODING[256]; static bool IN_ENCODING_INIT; private: Base64DecoderBuf( const Base64DecoderBuf& ); Base64DecoderBuf& operator = ( const Base64DecoderBuf& ); }; /// The base class for Base64Decoder. /// /// This class is needed to ensure the correct initialization /// order of the stream buffer and base classes. class Base64DecoderIOS: public virtual std::ios { public: Base64DecoderIOS( std::istream& istr ); ~Base64DecoderIOS(); Base64DecoderBuf* rdbuf(); protected: Base64DecoderBuf buf; private: Base64DecoderIOS( const Base64DecoderIOS& ); Base64DecoderIOS& operator = ( const Base64DecoderIOS& ); }; /// This istream base64-decodes all data /// read from the istream connected to it. /// /// Note: For performance reasons, the characters /// are read directly from the given istream's /// underlying streambuf, so the state /// of the istream will not reflect that of /// its streambuf. class Base64Decoder: public Base64DecoderIOS, public std::istream { public: Base64Decoder( std::istream& istr ); ~Base64Decoder(); private: Base64Decoder( const Base64Decoder& ); Base64Decoder& operator = ( const Base64Decoder& ); }; } // namespace spt #endif // SPT_BASE64DECODER
Base64Decoder.cpp
Implementation of the IO streams for base64 data.
/* * Base64Decoder.cpp * * $Id: *poco/1.4/Foundation/src/Base64Decoder.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 "Base64Decoder.h" #include "Base64Encoder.h" using spt::Byte; using spt::Base64Decoder; using spt::Base64DecoderBuf; using spt::Base64DecoderIOS; using spt::Base64Encoder; Byte Base64DecoderBuf::IN_ENCODING[256]; bool Base64DecoderBuf::IN_ENCODING_INIT = false; Base64DecoderBuf::Base64DecoderBuf( std::istream& istr ) : groupLength(0), groupIndex(0), buf( *istr.rdbuf() ) { if ( !IN_ENCODING_INIT ) { for ( uint16_t i = 0; i < sizeof( IN_ENCODING ); ++i ) { IN_ENCODING[i] = 0xFF; } for ( uint16_t i = 0; i < sizeof( Base64EncoderBuf::OUT_ENCODING ); ++i ) { IN_ENCODING[Base64EncoderBuf::OUT_ENCODING[i]] = i; } IN_ENCODING[static_cast<Byte>( '=' )] = '\0'; IN_ENCODING_INIT = true; } } Base64DecoderBuf::~Base64DecoderBuf() {} Base64DecoderBuf::int_type Base64DecoderBuf::readFromDevice() { if ( groupIndex < groupLength ) return group[groupIndex++]; else { Byte buffer[4]; int c; if ( ( c = readOne() ) == -1 ) return -1; buffer[0] = static_cast<Byte>( c ); if ( IN_ENCODING[buffer[0]] == 0xFF ) return -1; if ( ( c = readOne() ) == -1 ) return -1; buffer[1] = static_cast<Byte>( c ); if ( IN_ENCODING[buffer[1]] == 0xFF ) return -1; if ( ( c = readOne() ) == -1 ) return -1; buffer[2] = static_cast<Byte>( c ); if ( IN_ENCODING[buffer[2]] == 0xFF ) return -1; if ( ( c = readOne() ) == -1 ) return -1; buffer[3] = c; if ( IN_ENCODING[buffer[3]] == 0xFF ) return -1; group[0] = ( IN_ENCODING[buffer[0]] << 2 ) | ( IN_ENCODING[buffer[1]] >> 4 ); group[1] = ( ( IN_ENCODING[buffer[1]] & 0x0F ) << 4 ) | ( IN_ENCODING[buffer[2]] >> 2 ); group[2] = ( IN_ENCODING[buffer[2]] << 6 ) | IN_ENCODING[buffer[3]]; if ( buffer[2] == '=' ) groupLength = 1; else if ( buffer[3] == '=' ) groupLength = 2; else groupLength = 3; groupIndex = 1; return group[0]; } } int Base64DecoderBuf::readOne() { int ch = buf.sbumpc(); while ( ch == ' ' || ch == '\r' || ch == '\t' || ch == '\n' ) ch = buf.sbumpc(); return ch; } Base64DecoderIOS::Base64DecoderIOS( std::istream& istr ): buf( istr ) { init( &buf ); } Base64DecoderIOS::~Base64DecoderIOS() {} Base64DecoderBuf* Base64DecoderIOS::rdbuf() { return &buf; } Base64Decoder::Base64Decoder( std::istream& istr ) : Base64DecoderIOS( istr ), std::istream( &buf ) {} Base64Decoder::~Base64Decoder() {}
Base64Test.cpp
Unit test suite for base64 encoding and decoding.
#if defined( ARDUINO ) #include "tut.hpp" #include "SPT.h" #include "Base64Encoder.h" #include "Base64Decoder.h" #else #include <tut/tut.hpp> #include <SPT.h> #include <Base64Encoder.h> #include <Base64Decoder.h> #endif using spt::Base64Encoder; using spt::Base64Decoder; namespace tut { struct Base64TestData {}; typedef test_group<Base64TestData> Base64TestGroup; typedef Base64TestGroup::object Base64Test; Base64TestGroup base64TestGroup( "Base64 test suite" ); template<> template<> void Base64Test::test<1>() { set_test_name( "encode1" ); std::ostringstream str; Base64Encoder encoder( str ); encoder << std::string( "\00\01\02\03\04\05", 6 ); encoder.close(); ensure( "Encode1", str.str() == "AAECAwQF" ); spt::printFreeRam(); } template<> template<> void Base64Test::test<2>() { set_test_name( "encode2" ); std::ostringstream str; Base64Encoder encoder( str ); encoder << std::string( "\00\01\02\03", 4 ); encoder.close(); ensure( "Encode2", str.str() == "AAECAw==" ); spt::printFreeRam(); } template<> template<> void Base64Test::test<3>() { set_test_name( "encode3" ); std::ostringstream str; Base64Encoder encoder( str ); encoder << "ABCDEF"; encoder.close(); ensure( "Encode 3", str.str() == "QUJDREVG" ); spt::printFreeRam(); } template<> template<> void Base64Test::test<4>() { set_test_name( "decode1" ); std::istringstream istr( "AAECAwQF" ); Base64Decoder decoder( istr ); ensure( "Decode 1-1", decoder.good() && decoder.get() == 0 ); ensure( "Decode 1-2", decoder.good() && decoder.get() == 1 ); ensure( "Decode 1-3", decoder.good() && decoder.get() == 2 ); ensure( "Decode 1-4", decoder.good() && decoder.get() == 3 ); ensure( "Decode 1-5", decoder.good() && decoder.get() == 4 ); ensure( "Decode 1-6", decoder.good() && decoder.get() == 5 ); ensure( "Decode 1-7", decoder.good() && decoder.get() == -1 ); spt::printFreeRam(); } template<> template<> void Base64Test::test<5>() { set_test_name( "decode2" ); std::istringstream istr( "AAECAwQ=" ); Base64Decoder decoder( istr ); ensure( "Decode 2-1", decoder.good() && decoder.get() == 0 ); ensure( "Decode 2-2", decoder.good() && decoder.get() == 1 ); ensure( "Decode 2-3", decoder.good() && decoder.get() == 2 ); ensure( "Decode 2-4", decoder.good() && decoder.get() == 3 ); ensure( "Decode 2-5", decoder.good() && decoder.get() == 4 ); ensure( "Decode 2-6", decoder.good() && decoder.get() == -1 ); spt::printFreeRam(); } template<> template<> void Base64Test::test<6>() { set_test_name( "decode3" ); std::istringstream istr( "AAECAw==" ); Base64Decoder decoder( istr ); ensure( "Decode 3-1", decoder.good() && decoder.get() == 0 ); ensure( "Decode 3-2", decoder.good() && decoder.get() == 1 ); ensure( "Decode 3-3", decoder.good() && decoder.get() == 2 ); ensure( "Decode 3-4", decoder.good() && decoder.get() == 3 ); ensure( "Decode 3-5", decoder.good() && decoder.get() == -1 ); spt::printFreeRam(); } template<> template<> void Base64Test::test<7>() { set_test_name( "decode4" ); std::istringstream istr( "QUJDREVG" ); Base64Decoder decoder( istr ); std::string s; decoder >> s; ensure( "Decode 4-1", s == "ABCDEF" ); ensure( "Decode 4-2", decoder.eof() ); spt::printFreeRam(); } template<> template<> void Base64Test::test<8>() { set_test_name( "decode5" ); std::istringstream istr( "QUJ\r\nDRE\r\nVG" ); Base64Decoder decoder( istr ); std::string s; decoder >> s; ensure( "Decode 5-1", s == "ABCDEF" ); ensure( "Decode 5-2", decoder.eof() ); spt::printFreeRam(); } template<> template<> void Base64Test::test<9>() { set_test_name( "decode6" ); std::istringstream istr( "QUJD#REVG" ); Base64Decoder decoder( istr ); std::string s; decoder >> s; ensure( "Decode 6-1", decoder.eof() ); spt::printFreeRam(); } template<> template<> void Base64Test::test<10>() { set_test_name( "encodeDecode1" ); std::stringstream str; Base64Encoder encoder( str ); encoder << "The quick brown fox "; encoder << "jumped over the lazy dog."; encoder.close(); Base64Decoder decoder( str ); std::string s; int c = decoder.get(); while ( c != -1 ) { s += char(c); c = decoder.get(); } ensure( "EncodeDecode1", s == "The quick brown fox jumped over the lazy dog." ); spt::printFreeRam(); } template<> template<> void Base64Test::test<11>() { set_test_name( "encodeDecode2" ); std::string src; for ( int i = 0; i < 255; ++i ) src += char( i ); std::stringstream str; Base64Encoder encoder(str); encoder.write( src.data(), static_cast<std::streamsize>( src.size() ) ); encoder.close(); Base64Decoder decoder( str ); std::string s; int c = decoder.get(); while ( c != -1 ) { s += char(c); c = decoder.get(); } ensure( "EncodeDecode2", s == src ); spt::printFreeRam(); } }
Adapted for use on Arduino from Poco.