48 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
61 size_t char_len = (( input.size() / 3 ) + ( input.size() % 3 > 0 )) * 4;
62 size_t char_res = char_len;
63 if( line_length > 0 ) {
65 char_res += char_res / line_length - ( char_res % line_length == 0 );
67 encoded.reserve( char_res );
71 auto put_char = [&](
char c ){
73 assert( encoded.size() + 1 <= char_res );
74 assert( encoded.size() + 1 <= encoded.capacity() );
75 encoded.append( 1, c );
80 if( line_length > 0 && out_cnt % line_length == 0 && out_cnt < char_len ) {
81 assert( encoded.size() + 1 <= char_res );
82 assert( encoded.size() + 1 <= encoded.capacity() );
83 encoded.append( 1,
'\n' );
88 std::uint32_t temp = 0;
89 auto it = input.begin();
90 for( std::size_t i = 0; i < input.size() / 3; ++i ) {
96 temp =
static_cast<std::uint32_t
>(
static_cast<unsigned char>( *it++ )) << 16;
97 temp +=
static_cast<std::uint32_t
>(
static_cast<unsigned char>( *it++ )) << 8;
98 temp +=
static_cast<std::uint32_t
>(
static_cast<unsigned char>( *it++ ));
108 switch( input.size() % 3 ) {
111 temp =
static_cast<std::uint32_t
>(
static_cast<unsigned char>( *it++ )) << 16;
112 temp +=
static_cast<std::uint32_t
>(
static_cast<unsigned char>( *it++ )) << 8;
123 temp = (*it++) << 16;
138 assert( encoded.size() == char_res );
146 if( input.size() == 0 ) {
155 for(
auto c : input ) {
157 static_assert( (
int)
true == 1 && (
int)
false == 0,
"Boolean counting does not work." );
161 throw std::runtime_error(
"Invalid base64 length that is not a multiple of 4");
165 std::size_t padding = 0;
166 assert( char_cnt >= 4 );
178 size_t const char_res = (( char_cnt / 4 ) * 3 ) - padding;
179 decoded.reserve( char_res );
182 std::uint32_t temp = 0;
185 static_assert( 0x41 ==
'A' && 0x5A ==
'Z',
"Non-ASCII encoding detected. We expect ASCII." );
186 static_assert( 0x61 ==
'a' && 0x7A ==
'z',
"Non-ASCII encoding detected. We expect ASCII." );
187 static_assert( 0x30 ==
'0' && 0x39 ==
'9',
"Non-ASCII encoding detected. We expect ASCII." );
188 static_assert( 0x2B ==
'+' && 0x2F ==
'/',
"Non-ASCII encoding detected. We expect ASCII." );
191 auto it = input.begin();
192 while( it < input.end() ) {
195 for( std::size_t i = 0; i < 4; ++i ) {
204 if ( *it >= 0x41 && *it <= 0x5A ) {
206 }
else if( *it >= 0x61 && *it <= 0x7A ) {
208 }
else if( *it >= 0x30 && *it <= 0x39 ) {
210 }
else if( *it == 0x2B ) {
212 }
else if( *it == 0x2F ) {
215 switch( input.end() - it ) {
218 assert( decoded.size() + 2 <= char_res );
219 assert( decoded.size() + 2 <= decoded.capacity() );
220 decoded.push_back(( temp >> 16 ) & 0x000000FF );
221 decoded.push_back(( temp >> 8 ) & 0x000000FF );
226 assert( decoded.size() + 1 <= char_res );
227 assert( decoded.size() + 1 <= decoded.capacity() );
228 decoded.push_back(( temp >> 10 ) & 0x000000FF );
232 throw std::runtime_error(
"Invalid padding in base64 decoding" );
236 throw std::runtime_error(
"Invalid character in base64 decoding" );
242 assert( decoded.size() + 3 <= char_res );
243 assert( decoded.size() + 3 <= decoded.capacity() );
244 decoded.push_back(( temp >> 16 ) & 0x000000FF );
245 decoded.push_back(( temp >> 8 ) & 0x000000FF );
246 decoded.push_back(( temp ) & 0x000000FF );
250 assert( decoded.size() == char_res );
258 std::string
base64_encode( std::vector<std::uint8_t>
const& input,
size_t line_length )
270 using ContainerType = std::vector<std::uint8_t>;
271 return base64_decode_<ContainerType>( input );
276 using ContainerType = std::string;
277 return base64_decode_<ContainerType>( input );