Final changes

This commit is contained in:
John Wellbelove 2023-10-04 10:49:45 +01:00
parent f7281dc680
commit 6bc244cf8e
11 changed files with 3125 additions and 10025 deletions

View File

@ -1,4 +1,6 @@
///\file
//*************************************************************************
///Decode from Base64 from and to pointer/length
//*************************************************************************///\file
/******************************************************************************
The MIT License(MIT)
@ -34,6 +36,7 @@ SOFTWARE.
#include "etl/binary.h"
#include "etl/algorithm.h"
#include "etl/integral_limits.h"
#include "etl/iterator.h"
#include <stdint.h>
@ -65,136 +68,156 @@ namespace etl
}
};
//*************************************************************************
/// Codec for Base64
//*************************************************************************
class base64
{
public:
//*************************************************************************
/// Encode to Base64 from and to pointer/length
//*************************************************************************
template <typename T>
ETL_CONSTEXPR14
static
typename etl::enable_if<etl::is_integral<T>::value && (etl::integral_limits<T>::bits == 8U), etl::span<const char> >::type
typename etl::enable_if<etl::is_integral<T>::value && (etl::integral_limits<T>::bits == 8U), size_t>::type
encode(const T* input, size_t input_length, char* output, size_t output_length)
{
etl::span<const char> result;
int count = 0;
if (input_length > 0U)
if (input_length == 0U)
{
// Figure out if the output buffer is large enough.
size_t required_output_length = (input_length * 8U) / 6U;
if ((input_length % 3U) != 0U)
{
while ((required_output_length % 4U) != 0)
{
++required_output_length;
}
}
ETL_ASSERT_OR_RETURN_VALUE(output_length >= required_output_length, ETL_ERROR(base64_overflow), etl::span<const T>());
const T* p_in = input;
const T* p_in_end = input + input_length;
char* p_out = output;
char* p_out_end = output + required_output_length;
int next_sextet = First_Sextet;
// Step through the input buffer, creating the output sextets.
while (p_in != p_in_end)
{
T c = *p_in;
char index = 0;
switch (next_sextet)
{
case First_Sextet:
{
index = static_cast<char>((c & b11111100) >> 2);
next_sextet = Second_Sextet;
break;
}
case Second_Sextet:
{
index = static_cast<char>((c & b00000011) << 4);
++p_in;
++count;
// Next byte valid?
if (p_in != p_in_end)
{
c = *p_in;
index = index | ((c & b11110000) >> 4);
}
next_sextet = Third_Sextet;
break;
}
case Third_Sextet:
{
index = (c & b00001111) << 2;
++p_in;
++count;
// Next byte valid?
if (p_in != p_in_end)
{
c = *p_in;
index = index | static_cast<char>((c & b11000000) >> 6);
}
next_sextet = Fourth_Sextet;
break;
}
case Fourth_Sextet:
{
index = static_cast<char>(c & b00111111);
++p_in;
++count;
next_sextet = First_Sextet;
break;
}
default:
{
// Should never get here.
break;
}
}
*p_out = get_sextet_from_index(index);
++p_out;
}
// Pad out the end of the output buffer.
while (p_out != p_out_end)
{
*p_out++ = Padding;
}
result = etl::span<const char>(output, p_out);
return 0;
}
return result;
// Figure out if the output buffer is large enough.
size_t required_output_length = (input_length * 8U) / 6U;
if ((input_length % 3U) != 0U)
{
while ((required_output_length % 4U) != 0)
{
++required_output_length;
}
}
ETL_ASSERT_OR_RETURN_VALUE(output_length >= required_output_length, ETL_ERROR(base64_overflow), etl::span<const T>());
const T* p_in = input;
const T* p_in_end = input + input_length;
char* p_out = output;
char* p_out_end = output + required_output_length;
int next_sextet = First_Sextet;
// Step through the input buffer, creating the output sextets.
while (p_in != p_in_end)
{
T c = *p_in;
char index = 0;
switch (next_sextet)
{
//**************************
case First_Sextet:
{
index = static_cast<char>((*p_in & b11111100) >> 2);
next_sextet = Second_Sextet;
break;
}
//**************************
case Second_Sextet:
{
index = static_cast<char>((c & b00000011) << 4);
++p_in;
// Next byte valid?
if (p_in != p_in_end)
{
index = index | ((*p_in & b11110000) >> 4);
}
next_sextet = Third_Sextet;
break;
}
//**************************
case Third_Sextet:
{
index = (c & b00001111) << 2;
++p_in;
// Next byte valid?
if (p_in != p_in_end)
{
index = index | static_cast<char>((*p_in & b11000000) >> 6);
}
next_sextet = Fourth_Sextet;
break;
}
//**************************
case Fourth_Sextet:
{
index = static_cast<char>(c & b00111111);
++p_in;
next_sextet = First_Sextet;
break;
}
//**************************
default:
{
// Should never get here.
assert(false);
break;
}
}
*p_out = get_sextet_from_index(index);
++p_out;
}
// Pad out the end of the output buffer.
while (p_out != p_out_end)
{
*p_out++ = padding();
}
return static_cast<size_t>(etl::distance(output, p_out));
}
//*************************************************************************
/// Encode to Base64 from and to span/span
//*************************************************************************
template <typename T, size_t Length1, size_t Length2>
ETL_CONSTEXPR14
static
typename etl::enable_if<etl::is_integral<T>::value && (etl::integral_limits<T>::bits == 8U), etl::span<const char> >::type
encode(const etl::span<const T, Length1>& input_span,
const etl::span<char, Length2>& output_span)
typename etl::enable_if<etl::is_integral<T>::value && (etl::integral_limits<T>::bits == 8U), size_t>::type
encode(const etl::span<const T, Length1>& input_span,
const etl::span<char, Length2>& output_span)
{
return encode(input_span.begin(), input_span.size(),
output_span.begin(), output_span.size());
return encode(input_span.begin(), input_span.size(),
output_span.begin(), output_span.size());
}
//*************************************************************************
/// Encode to Base64 from and to pointer/pointer
//*************************************************************************
template <typename T>
ETL_CONSTEXPR14
static
typename etl::enable_if<etl::is_integral<T>::value && (etl::integral_limits<T>::bits == 8U), size_t>::type
encode(const T* input_begin, const T* input_end, char* output_begin, char* output_end)
{
return encode(input_begin, static_cast<size_t>(etl::distance(input_begin, input_end)),
output_begin, static_cast<size_t>(etl::distance(output_begin, output_end)));
}
//*************************************************************************
/// Calculates the buffer size required to encode to Base64
//*************************************************************************
ETL_NODISCARD
ETL_CONSTEXPR14
static
size_t encode_size(size_t input_length)
@ -212,98 +235,105 @@ namespace etl
return required_output_length;
}
//*************************************************************************
/// Decode from Base64 from and to pointer/length
//*************************************************************************
template <typename T>
ETL_CONSTEXPR14
static
typename etl::enable_if<etl::is_integral<T>::value && (etl::integral_limits<T>::bits == 8U), etl::span<const T> >::type
typename etl::enable_if<etl::is_integral<T>::value && (etl::integral_limits<T>::bits == 8U), size_t>::type
decode(const char* input, size_t input_length, T* output, size_t output_length)
{
etl::span<const T> result;
if (input_length > 0)
if (input_length == 0)
{
// Figure out if the output buffer is large enough.
size_t length = etl::distance(input, etl::find(input, input + input_length, Padding)) - 1;
size_t required_output_length = length - (length / 4U);
return 0;
}
ETL_ASSERT_OR_RETURN_VALUE(output_length >= required_output_length, ETL_ERROR(base64_overflow), etl::span<const T>());
// Figure out if the output buffer is large enough.
size_t length = static_cast<size_t>(etl::distance(input, etl::find(input, input + input_length, padding())) - 1);
size_t required_output_length = length - (length / 4U);
const char* p_in = input;
const char* p_in_end = input + input_length;
ETL_ASSERT_OR_RETURN_VALUE(output_length >= required_output_length, ETL_ERROR(base64_overflow), etl::span<const T>());
T* p_out = output;
T* p_out_end = output + output_length;
const char* p_in = input;
const char* p_in_end = input + input_length;
T c = 0;
int next_sextet = First_Sextet;
T* p_out = output;
// Step through the input buffer, creating the output binary.
while (p_in != p_in_end)
T c = 0;
int next_sextet = First_Sextet;
// Step through the input buffer, creating the output binary.
while (p_in != p_in_end)
{
char sextet = *p_in++; // Get the sextet as a T.
if (sextet == padding())
{
char sextet = *p_in++; // Get the sextet as a T.
break;
}
if (sextet == Padding)
char index = get_index_from_sextet(sextet);
switch (next_sextet)
{
//**************************
case First_Sextet:
{
c = (index & b00111111) << 2;
next_sextet = Second_Sextet;
break;
}
char index = get_index_from_sextet(sextet);
switch (next_sextet)
//**************************
case Second_Sextet:
{
case First_Sextet:
{
c = (index & b00111111) << 2;
next_sextet = Second_Sextet;
break;
}
c |= (index & b00110000) >> 4;
*p_out++ = static_cast<T>(c);
c = (index & b00001111) << 4;
next_sextet = Third_Sextet;
break;
}
case Second_Sextet:
{
c |= (index & b00110000) >> 4;
*p_out++ = static_cast<T>(c);
c = (index & b00001111) << 4;
next_sextet = Third_Sextet;
break;
}
//**************************
case Third_Sextet:
{
c |= (index & b00111100) >> 2;
*p_out++ = static_cast<T>(c);
c = (index & b00000011) << 6;
next_sextet = Fourth_Sextet;
break;
}
case Third_Sextet:
{
c |= (index & b00111100) >> 2;
*p_out++ = static_cast<T>(c);
c = (index & b00000011) << 6;
next_sextet = Fourth_Sextet;
break;
}
//**************************
case Fourth_Sextet:
{
c |= (index & b00111111);
*p_out++ = static_cast<T>(c);
next_sextet = First_Sextet;
break;
}
case Fourth_Sextet:
{
c |= (index & b00111111);
*p_out++ = static_cast<T>(c);
next_sextet = First_Sextet;
break;
}
default:
{
// Should never get here.
break;
}
//**************************
default:
{
// Should never get here.
assert(false);
break;
}
}
result = etl::span<const T>(output, p_out);
}
return result;
return static_cast<size_t>(etl::distance(output, p_out));
}
//*************************************************************************
/// Decode from Base64 from and to span/span
//*************************************************************************
template <typename T, size_t Length1, size_t Length2>
ETL_CONSTEXPR14
static
typename etl::enable_if<etl::is_integral<T>::value && (etl::integral_limits<T>::bits == 8U), etl::span<const T> >::type
typename etl::enable_if<etl::is_integral<T>::value && (etl::integral_limits<T>::bits == 8U), size_t>::type
decode(const etl::span<const char, Length1>& input_span,
const etl::span<T, Length2>& output_span)
{
@ -311,26 +341,33 @@ namespace etl
output_span.begin(), output_span.size());
}
////*************************************************************************
//template <typename T, size_t Length>
//ETL_CONSTEXPR14
//static
//typename etl::enable_if<etl::is_integral<T>::value && (etl::integral_limits<T>::bits == 8U), etl::span<const T> >::type
// decode_size(const etl::span<const char, Length>& input_span)
//{
// // Figure out the minimum output buffer size.
// size_t length = etl::distance(input, etl::find(input, input + input_length, Padding)) - 1;
// size_t required_output_length = length - (length / 4U);
// return required_output_length;
//}
//*************************************************************************
/// Decode from Base64 from and to pointer/pointer
//*************************************************************************
template <typename T>
ETL_CONSTEXPR14
static
typename etl::enable_if<etl::is_integral<T>::value && (etl::integral_limits<T>::bits == 8U), size_t>::type
decode(const char* input_begin, const char* input_end, T* output_begin, T* output_end)
{
return decode(input_begin, static_cast<size_t>(etl::distance(input_begin, input_end)),
output_begin, static_cast<size_t>(etl::distance(output_begin, output_end)));
}
//*************************************************************************
/// Calculates the buffer size required to decode from Base64
//*************************************************************************
ETL_NODISCARD
ETL_CONSTEXPR14
static size_t decode_size(const char* input, size_t input_length)
{
if (input_length == 0U)
{
return 0U;
}
// Figure out the minimum output buffer size.
size_t length = etl::distance(input, etl::find(input, input + input_length, Padding)) - 1;
size_t length = static_cast<size_t>(etl::distance(input, etl::find(input, input + input_length, padding())) - 1);
size_t required_output_length = length - (length / 4U);
return required_output_length;
@ -348,38 +385,92 @@ namespace etl
Fourth_Sextet
};
//*************************************************************************
/// The Base64 padding character
static ETL_CONSTANT char Padding = '=';
//*************************************************************************
// Sextet lookup.
static ETL_CONSTANT char lookup_char[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' , '+', '/'
};
// Sextets
// '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', '+', '/'
//*************************************************************************
// Translates an index into a sextet
//*************************************************************************
ETL_CONSTEXPR14 static char get_sextet_from_index(char index)
{
return lookup_char[index];
if ((index >= 0) && (index < 26))
{
return 'A' + index;
}
else if ((index >= 26) && (index < 52))
{
index -= 26;
return 'a' + index;
}
else if ((index >= 52) && (index < 62))
{
index -= 52;
return '0' + index;
}
else if (index == 62)
{
return '+';
}
else if (index == 63)
{
return '/';
}
else
{
// Should never get here.
assert(false);
return padding();
}
}
//*************************************************************************
// Translates a sextet into an index
//*************************************************************************
ETL_CONSTEXPR14 static char get_index_from_sextet(char sextet)
{
const char* p = etl::find(lookup_char, lookup_char + 64, sextet);
if ((sextet >= 'A') && (sextet <= 'Z'))
{
return sextet - 'A';
}
else if ((sextet >= 'a') && (sextet <= 'z'))
{
return sextet - 'a' + 26;
}
else if ((sextet >= '0') && (sextet <= '9'))
{
return sextet - '0' + 52;
}
else if (sextet == '+')
{
return 62;
}
else if (sextet == '/')
{
return 63;
}
else
{
// Should never get here.
assert(false);
return 0;
}
}
return static_cast<char>(etl::distance(lookup_char, p));
//*************************************************************************
/// Gets the padding character
//*************************************************************************
ETL_NODISCARD
ETL_CONSTEXPR14
static char padding()
{
return '=';
}
};
}

View File

@ -19,6 +19,7 @@ add_executable(etl_tests
test_array_view.cpp
test_array_wrapper.cpp
test_atomic.cpp
test_base64.cpp
test_binary.cpp
test_bip_buffer_spsc_atomic.cpp
test_bit.cpp

View File

@ -0,0 +1,29 @@
/******************************************************************************
The MIT License(MIT)
Embedded Template Library.
https://github.com/ETLCPP/etl
https://www.etlcpp.com
Copyright(c) 2023 John Wellbelove
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files(the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions :
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
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 AND NONINFRINGEMENT.IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
******************************************************************************/
#include <etl/base64.h>

View File

@ -46,6 +46,7 @@ target_sources(t98 PRIVATE etl_profile.h
../array_view.h.t.cpp
../array_wrapper.h.t.cpp
../atomic.h.t.cpp
../base64.h.t.cpp
../basic_format_spec.h.t.cpp
../basic_string.h.t.cpp
../basic_string_stream.h.t.cpp

View File

@ -46,6 +46,7 @@ target_sources(t11 PRIVATE etl_profile.h
../array_view.h.t.cpp
../array_wrapper.h.t.cpp
../atomic.h.t.cpp
../base64.h.t.cpp
../basic_format_spec.h.t.cpp
../basic_string.h.t.cpp
../basic_string_stream.h.t.cpp

View File

@ -46,6 +46,7 @@ target_sources(t14 PRIVATE etl_profile.h
../array_view.h.t.cpp
../array_wrapper.h.t.cpp
../atomic.h.t.cpp
../base64.h.t.cpp
../basic_format_spec.h.t.cpp
../basic_string.h.t.cpp
../basic_string_stream.h.t.cpp

View File

@ -46,6 +46,7 @@ target_sources(t17 PRIVATE etl_profile.h
../array_view.h.t.cpp
../array_wrapper.h.t.cpp
../atomic.h.t.cpp
../base64.h.t.cpp
../basic_format_spec.h.t.cpp
../basic_string.h.t.cpp
../basic_string_stream.h.t.cpp

View File

@ -46,6 +46,7 @@ target_sources(t20 PRIVATE etl_profile.h
../array_view.h.t.cpp
../array_wrapper.h.t.cpp
../atomic.h.t.cpp
../base64.h.t.cpp
../basic_format_spec.h.t.cpp
../basic_string.h.t.cpp
../basic_string_stream.h.t.cpp

View File

@ -32,10 +32,12 @@ SOFTWARE.
#include <string>
#include <array>
#include <vector>
#include <algorithm>
namespace
{
std::array<unsigned char, 256> input_data =
std::array<unsigned char, 256> input_data_unsigned_char =
{
0x3B, 0x27, 0x03, 0x43, 0x2D, 0xFB, 0x28, 0x2A, 0x61, 0xAE, 0xBC, 0x49, 0x71, 0x32, 0x01, 0x15,
0x69, 0x5C, 0x5E, 0xF5, 0xD5, 0x9B, 0xDE, 0xA5, 0x57, 0xC9, 0xC1, 0x7D, 0x80, 0xDE, 0x4C, 0x81,
@ -55,6 +57,26 @@ namespace
0xA8, 0x52, 0x3C, 0x9E, 0xCD, 0xDE, 0x21, 0x34, 0x3E, 0x1F, 0xB5, 0x54, 0xD7, 0xFB, 0xB4, 0xBD
};
std::array<int8_t, 256> input_data_int8_t =
{
int8_t(0x3B), int8_t(0x27), int8_t(0x03), int8_t(0x43), int8_t(0x2D), int8_t(0xFB), int8_t(0x28), int8_t(0x2A), int8_t(0x61), int8_t(0xAE), int8_t(0xBC), int8_t(0x49), int8_t(0x71), int8_t(0x32), int8_t(0x01), int8_t(0x15),
int8_t(0x69), int8_t(0x5C), int8_t(0x5E), int8_t(0xF5), int8_t(0xD5), int8_t(0x9B), int8_t(0xDE), int8_t(0xA5), int8_t(0x57), int8_t(0xC9), int8_t(0xC1), int8_t(0x7D), int8_t(0x80), int8_t(0xDE), int8_t(0x4C), int8_t(0x81),
int8_t(0xC0), int8_t(0xCF), int8_t(0x2A), int8_t(0xD1), int8_t(0x86), int8_t(0x56), int8_t(0xD5), int8_t(0x71), int8_t(0x37), int8_t(0xEB), int8_t(0x80), int8_t(0x32), int8_t(0xDF), int8_t(0xE4), int8_t(0xDF), int8_t(0xB6),
int8_t(0xEE), int8_t(0x3F), int8_t(0xDC), int8_t(0x79), int8_t(0xB3), int8_t(0x17), int8_t(0x8E), int8_t(0x76), int8_t(0x65), int8_t(0x8E), int8_t(0x96), int8_t(0x21), int8_t(0xB9), int8_t(0x88), int8_t(0xD1), int8_t(0x6D),
int8_t(0xD0), int8_t(0xDD), int8_t(0xFF), int8_t(0xDA), int8_t(0xA8), int8_t(0x7A), int8_t(0x4D), int8_t(0xF5), int8_t(0x71), int8_t(0x77), int8_t(0xFD), int8_t(0x2E), int8_t(0xF2), int8_t(0xE4), int8_t(0x40), int8_t(0x72),
int8_t(0x8C), int8_t(0x83), int8_t(0x00), int8_t(0x6F), int8_t(0x13), int8_t(0x72), int8_t(0x53), int8_t(0xE4), int8_t(0x6B), int8_t(0x70), int8_t(0x0E), int8_t(0x37), int8_t(0xCA), int8_t(0x25), int8_t(0xCD), int8_t(0x68),
int8_t(0x62), int8_t(0xC0), int8_t(0xAB), int8_t(0x14), int8_t(0xC7), int8_t(0x59), int8_t(0x83), int8_t(0xD2), int8_t(0x82), int8_t(0x8C), int8_t(0x93), int8_t(0x6D), int8_t(0x13), int8_t(0x21), int8_t(0xC0), int8_t(0x08),
int8_t(0xF9), int8_t(0x6D), int8_t(0xAC), int8_t(0x84), int8_t(0x78), int8_t(0x49), int8_t(0x84), int8_t(0x6F), int8_t(0x6B), int8_t(0xFB), int8_t(0x20), int8_t(0x3B), int8_t(0x9C), int8_t(0x49), int8_t(0xFB), int8_t(0x4E),
int8_t(0x80), int8_t(0x69), int8_t(0x82), int8_t(0x25), int8_t(0x86), int8_t(0x95), int8_t(0xD5), int8_t(0x4D), int8_t(0x91), int8_t(0xED), int8_t(0xD2), int8_t(0x77), int8_t(0x2A), int8_t(0x24), int8_t(0x40), int8_t(0x8A),
int8_t(0xDF), int8_t(0x4D), int8_t(0x80), int8_t(0x2D), int8_t(0xCD), int8_t(0xD5), int8_t(0x5A), int8_t(0x26), int8_t(0xA6), int8_t(0x71), int8_t(0x15), int8_t(0x42), int8_t(0x0E), int8_t(0x3F), int8_t(0xB2), int8_t(0x70),
int8_t(0x14), int8_t(0x29), int8_t(0x1F), int8_t(0x8D), int8_t(0x23), int8_t(0x2E), int8_t(0xC1), int8_t(0xEA), int8_t(0xCE), int8_t(0xF9), int8_t(0x7E), int8_t(0x6C), int8_t(0xDF), int8_t(0x1C), int8_t(0xA3), int8_t(0x84),
int8_t(0x2B), int8_t(0x24), int8_t(0x35), int8_t(0xA7), int8_t(0x63), int8_t(0xC8), int8_t(0x0B), int8_t(0x1F), int8_t(0x8B), int8_t(0xBA), int8_t(0x51), int8_t(0xBF), int8_t(0xE9), int8_t(0x51), int8_t(0x80), int8_t(0xD2),
int8_t(0x23), int8_t(0xB5), int8_t(0xD1), int8_t(0xB4), int8_t(0x59), int8_t(0xAE), int8_t(0x7D), int8_t(0x30), int8_t(0x1D), int8_t(0x00), int8_t(0x1C), int8_t(0xD8), int8_t(0x70), int8_t(0x6C), int8_t(0x16), int8_t(0x71),
int8_t(0xC7), int8_t(0x56), int8_t(0x08), int8_t(0xFE), int8_t(0x81), int8_t(0xAE), int8_t(0xFB), int8_t(0xE0), int8_t(0x92), int8_t(0xD8), int8_t(0xDB), int8_t(0xB9), int8_t(0x57), int8_t(0x7C), int8_t(0x99), int8_t(0xCB),
int8_t(0x42), int8_t(0xEF), int8_t(0xFC), int8_t(0xB3), int8_t(0x56), int8_t(0x1E), int8_t(0xD1), int8_t(0x42), int8_t(0xD3), int8_t(0x0C), int8_t(0x18), int8_t(0xB3), int8_t(0xEE), int8_t(0xAF), int8_t(0x1A), int8_t(0x77),
int8_t(0xA8), int8_t(0x52), int8_t(0x3C), int8_t(0x9E), int8_t(0xCD), int8_t(0xDE), int8_t(0x21), int8_t(0x34), int8_t(0x3E), int8_t(0x1F), int8_t(0xB5), int8_t(0x54), int8_t(0xD7), int8_t(0xFB), int8_t(0xB4), int8_t(0xBD)
};
std::array<std::string, 257> encoded =
{
"",
@ -318,27 +340,210 @@ namespace
SUITE(test_base64)
{
TEST(test_encode)
//*************************************************************************
TEST(test_encode_unsigned_char_pointer_size)
{
constexpr int length = 200;
std::array<char, 344U> encoded_output;
constexpr size_t require_encoded_length = etl::base64::encode_size(length);
for (size_t i = 0; i < 256; ++i)
{
encoded_output.fill(0);
std::array<char, require_encoded_length> encoded_output;
auto size = etl::base64::encode(input_data_unsigned_char.data(), i,
encoded_output.data(), encoded_output.size());
auto result = etl::base64::encode(input_data.data(), length, encoded_output.data(), encoded_output.size());
std::string expected(encoded[i]);
std::string actual(encoded_output.data(), size);
std::string expected(encoded[length]);
std::string actual(result.begin(), result.end());
bool equal = actual == expected;
CHECK_EQUAL(require_encoded_length, result.size());
CHECK_EQUAL(expected, actual);
CHECK_EQUAL(etl::base64::encode_size(i), size);
}
}
TEST(test_decode)
//*************************************************************************
TEST(test_encode_unsigned_char_pointer_pointer)
{
std::array<char, 344U> encoded_output;
for (size_t i = 0; i < 256; ++i)
{
encoded_output.fill(0);
auto size = etl::base64::encode(input_data_unsigned_char.data(), input_data_unsigned_char.data() + i,
encoded_output.data(), encoded_output.data() + encoded_output.size());
std::string expected(encoded[i]);
std::string actual(encoded_output.data(), size);
CHECK_EQUAL(expected, actual);
CHECK_EQUAL(etl::base64::encode_size(i), size);
}
}
//*************************************************************************
TEST(test_encode_unsigned_char_span)
{
std::array<char, 344U> encoded_output;
for (size_t i = 0; i < 256; ++i)
{
encoded_output.fill(0);
etl::span<const unsigned char> input_span(input_data_unsigned_char.data(), i);
etl::span<char> output_span(encoded_output.data(), encoded_output.size());
auto size = etl::base64::encode(input_span, output_span);
std::string expected(encoded[i]);
std::string actual(encoded_output.data(), size);
CHECK_EQUAL(expected, actual);
CHECK_EQUAL(etl::base64::encode_size(i), size);
}
}
//*************************************************************************
TEST(test_encode_int8_t_pointer_size)
{
std::array<char, 344U> encoded_output;
for (size_t i = 0; i < 256; ++i)
{
encoded_output.fill(0);
auto size = etl::base64::encode(input_data_int8_t.data(), i,
encoded_output.data(), encoded_output.size());
std::string expected(encoded[i]);
std::string actual(encoded_output.data(), size);
CHECK_EQUAL(expected, actual);
CHECK_EQUAL(etl::base64::encode_size(i), size);
}
}
//*************************************************************************
TEST(test_encode_int8_t_pointer_pointer)
{
std::array<char, 344U> encoded_output;
for (size_t i = 0; i < 256; ++i)
{
encoded_output.fill(0);
auto size = etl::base64::encode(input_data_int8_t.data(), input_data_int8_t.data() + i,
encoded_output.data(), encoded_output.data() + encoded_output.size());
std::string expected(encoded[i]);
std::string actual(encoded_output.data(), size);
CHECK_EQUAL(expected, actual);
CHECK_EQUAL(etl::base64::encode_size(i), size);
}
}
//*************************************************************************
TEST(test_encode_int8_t_span)
{
std::array<char, 344U> encoded_output;
for (size_t i = 0; i < 256; ++i)
{
encoded_output.fill(0);
etl::span<const int8_t> input_span(input_data_int8_t.data(), i);
etl::span<char> output_span(encoded_output.data(), encoded_output.size());
auto size = etl::base64::encode(input_span, output_span);
std::string expected(encoded[i]);
std::string actual(encoded_output.data(), size);
CHECK_EQUAL(expected, actual);
CHECK_EQUAL(etl::base64::encode_size(i), size);
}
}
//*************************************************************************
#if ETL_USING_CPP14
template <size_t Size>
constexpr auto GetConstexprBase64(const etl::array<int8_t, Size> input) noexcept
{
constexpr size_t encode_size = etl::base64::encode_size(Size);
etl::array<char, etl::base64::encode_size(Size)> output{ 0 };
etl::base64::encode(input.begin(), Size,
output._buffer, encode_size);
return output;
}
TEST(test_encode_int8_t_constexpr)
{
constexpr etl::array<int8_t, 10> input = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
constexpr auto output{ GetConstexprBase64(input) };
std::string expected("AAECAwQFBgcICQ==");
std::string actual(output.data(), output.size());
CHECK_EQUAL(expected, actual);
CHECK_EQUAL(etl::base64::encode_size(10), output.size());
}
#endif
//*************************************************************************
TEST(test_encode_overflow)
{
std::array<char, 1> encoded_output;
CHECK_THROW((etl::base64::encode(input_data_unsigned_char.data(), 10,
encoded_output.data(), encoded_output.size())), etl::base64_overflow);
}
//*************************************************************************
TEST(test_decode_unsigned_char)
{
std::array<unsigned char, 256> decoded_output;
for (size_t i = 0; i < 256; ++i)
{
decoded_output.fill(0);
auto decoded_size = etl::base64::decode(encoded[i].data(), encoded[i].size(),
decoded_output.data(), decoded_output.size());
CHECK_ARRAY_EQUAL(input_data_unsigned_char.data(), decoded_output.data(), i);
CHECK_EQUAL(i, etl::base64::decode_size(encoded[i].data(), encoded[i].size()));
CHECK_EQUAL(i, decoded_size);
}
}
//*************************************************************************
TEST(test_decode_int8_t)
{
std::array<int8_t, 256> decoded_output;
for (size_t i = 0; i < 256; ++i)
{
decoded_output.fill(0);
auto decoded_size = etl::base64::decode(encoded[i].data(), encoded[i].size(),
decoded_output.data(), decoded_output.size());
CHECK_ARRAY_EQUAL(input_data_int8_t.data(), decoded_output.data(), i);
CHECK_EQUAL(i, etl::base64::decode_size(encoded[i].data(), encoded[i].size()));
CHECK_EQUAL(i, decoded_size);
}
}
//*************************************************************************
TEST(test_decode_overflow)
{
std::array<unsigned char, 1> decoded_output;
CHECK_THROW((etl::base64::decode(encoded[10].data(), encoded[10].size(),
decoded_output.data(), decoded_output.size())), etl::base64_overflow);
}
};
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff