#pragma once #include "AftrConfig.h" #include #include #include #ifdef AFTR_CONFIG_USE_BOOST #include #include #include #include #include #include #endif namespace Aftr { namespace AftrUtil { /** Converts in passed data to standard 72 column base 64 lettering. */ std::string encodeBinaryToBase64( const std::vector& data ); template< typename Iter > std::string encodeBinaryToBase64( Iter begin, Iter end ) { using namespace boost::archive::iterators; auto length = std::distance( begin, end ); using It = base64_from_binary>; auto tmp = std::string( It( begin ), It( end ) ); return tmp.append( (3 - length % 3) % 3, '=' ); return tmp; } template< typename Iter, typename IterOut > int encodeBinaryToBase64( Iter begin, Iter end, IterOut dst, bool addNullTerminatorToDst = false ) { using namespace boost::archive::iterators; auto length = std::distance( begin, end ); //the required size of dst buffer is (8/6)(inputsize)+numPads+optional null terminator using It = base64_from_binary>; auto dstEnd = std::copy( It(begin), It(end), dst ); //Now we have to append the '=' padding char, up to 3 of them int numPads = (3 - length % 3) % 3; std::fill_n( dstEnd, numPads, '=' ); if( addNullTerminatorToDst ) std::fill_n( dstEnd + numPads, 1, '\0' ); //add terminating null on this string. auto numBytes = std::distance( dst, dstEnd ); if( addNullTerminatorToDst ) return static_cast(numBytes) + numPads + 1; return static_cast(numBytes) + numPads; } int getDstBufferSizeRequired_toEncodeBinaryToBase64( int numBinaryBytes, bool addNullTerminatorToDst = false ); /** Any extra padding at the end "==" or "=" will be ignored when converting to binary. */ std::vector< unsigned char > encodeBase64ToBinary( const std::string& base64Str ); /** Converts in passed ascii string to binary data. Since each character is 8 bits but must reside in the range [0-9A-Za-z+/]+[=]*, (which is 0-63), we only need 6 bits to encode the value. Therefore going to binary from base64 ascii will reduce size by 25%. This version does not allocate */ template< typename Iter > int encodeBase64ToBinary( const std::string& base64Str, Iter begin, Iter end ) { using namespace boost::archive::iterators; std::string baseStr = base64Str; boost::trim( baseStr ); //remove any leading or trailing whitespace using it_binary_t = transform_width< binary_from_base64 >, 8, 6 >; // Decode std::string::difference_type paddChars = std::count( baseStr.begin(), baseStr.end(), '=' ); std::replace( baseStr.begin(), baseStr.end(), '=', 'A' ); // replace '=' by base64 encoding of '\0' auto endIt = std::copy( it_binary_t( base64Str.begin() ), it_binary_t( base64Str.end() - paddChars ), begin ); return static_cast(std::distance( begin, endIt )); } } }