From a1e5f1c7c94d42faae0556bbca66f218e278d5b1 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Mon, 9 Oct 2023 09:55:01 +0100 Subject: [PATCH 01/12] Updates --- include/etl/base64.h | 68 +++++++++++++++++++++++++++++--------------- test/test_base64.cpp | 54 ++++++++++++++++++++++------------- version.txt | 2 +- 3 files changed, 80 insertions(+), 44 deletions(-) diff --git a/include/etl/base64.h b/include/etl/base64.h index 32217a96..220632c7 100644 --- a/include/etl/base64.h +++ b/include/etl/base64.h @@ -46,6 +46,8 @@ SOFTWARE. #include #endif +#define ETL_IS_8_BIT_INTEGRAL(Type) (etl::is_integral::value && (etl::integral_limits::bits == 8U)) + namespace etl { //*************************************************************************** @@ -87,7 +89,7 @@ namespace etl template ETL_CONSTEXPR14 static - typename etl::enable_if::value && (etl::integral_limits::bits == 8U), size_t>::type + typename etl::enable_if::type encode(const T* input, size_t input_length, char* output, size_t output_length) { if (input_length == 0U) @@ -96,7 +98,7 @@ namespace etl } // Figure out if the output buffer is large enough. - size_t required_output_length = encode_size(input_length); + size_t required_output_length = encoded_size(input_length); ETL_ASSERT_OR_RETURN_VALUE(output_length >= required_output_length, ETL_ERROR(base64_overflow), 0U); @@ -190,8 +192,8 @@ namespace etl //************************************************************************* template ETL_CONSTEXPR14 - static - typename etl::enable_if::value && (etl::integral_limits::bits == 8U), size_t>::type + static + typename etl::enable_if::type encode(const T* input_begin, const T* input_end, char* output_begin, char* output_end) { return encode(input_begin, static_cast(etl::distance(input_begin, input_end)), @@ -204,7 +206,7 @@ namespace etl template ETL_CONSTEXPR14 static - typename etl::enable_if::value && (etl::integral_limits::bits == 8U), size_t>::type + typename etl::enable_if::type encode(const etl::span& input_span, const etl::span& output_span) { @@ -218,11 +220,11 @@ namespace etl template ETL_CONSTEXPR14 static - typename etl::enable_if::value && (etl::integral_limits::bits == 8U), size_t>::type + typename etl::enable_if::type encode(const T* input_begin, size_t input_length, etl::istring& output) { - output.resize(etl::base64::encode_size(input_length)); + output.resize(etl::base64::encoded_size(input_length)); return encode(input_begin, input_length, output.data(), output.size()); @@ -234,11 +236,11 @@ namespace etl template ETL_CONSTEXPR14 static - typename etl::enable_if::value && (etl::integral_limits::bits == 8U), size_t>::type + typename etl::enable_if::type encode(const T* input_begin, const T* input_end, etl::istring& output) { - output.resize(etl::base64::encode_size(etl::distance(input_begin, input_end))); + output.resize(etl::base64::encoded_size(etl::distance(input_begin, input_end))); return encode(input_begin, static_cast(etl::distance(input_begin, input_end)), output.data(), output.size()); @@ -250,11 +252,11 @@ namespace etl template ETL_CONSTEXPR14 static - typename etl::enable_if::value && (etl::integral_limits::bits == 8U), size_t>::type + typename etl::enable_if::type encode(const etl::span& input_span, etl::istring& output) { - output.resize(etl::base64::encode_size(Length1)); + output.resize(etl::base64::encoded_size(Length1)); return encode(input_span.begin(), input_span.size(), output.data(), output.size()); @@ -266,16 +268,13 @@ namespace etl ETL_NODISCARD ETL_CONSTEXPR14 static - size_t encode_size(size_t input_length) + size_t encoded_size(size_t input_length) { size_t required_output_length = (input_length * 8U) / 6U; - if ((input_length % 3U) != 0U) + while ((required_output_length % 4U) != 0) { - while ((required_output_length % 4U) != 0) - { - ++required_output_length; - } + ++required_output_length; } return required_output_length; @@ -287,7 +286,7 @@ namespace etl template ETL_CONSTEXPR14 static - typename etl::enable_if::value && (etl::integral_limits::bits == 8U), size_t>::type + typename etl::enable_if::type decode(const char* input, size_t input_length, T* output, size_t output_length) { if (input_length == 0) @@ -296,7 +295,7 @@ namespace etl } // Figure out if the output buffer is large enough. - size_t required_output_length = etl::base64::decode_size(input, input_length); + size_t required_output_length = etl::base64::decoded_size(input, input_length); ETL_ASSERT_OR_RETURN_VALUE(output_length >= required_output_length, ETL_ERROR(base64_overflow), 0U); @@ -378,7 +377,7 @@ namespace etl template ETL_CONSTEXPR14 static - typename etl::enable_if::value && (etl::integral_limits::bits == 8U), size_t>::type + typename etl::enable_if::type decode(const char* input_begin, const char* input_end, T* output_begin, T* output_end) { return decode(input_begin, static_cast(etl::distance(input_begin, input_end)), @@ -390,8 +389,8 @@ namespace etl //************************************************************************* template ETL_CONSTEXPR14 - static - typename etl::enable_if::value && (etl::integral_limits::bits == 8U), size_t>::type + static + typename etl::enable_if::type decode(const etl::span& input_span, const etl::span& output_span) { @@ -404,7 +403,7 @@ namespace etl //************************************************************************* ETL_NODISCARD ETL_CONSTEXPR14 - static size_t decode_size(const char* input, size_t input_length) + static size_t decoded_size(const char* input, size_t input_length) { if (input_length == 0U) { @@ -418,6 +417,27 @@ namespace etl return required_output_length; } + //************************************************************************* + /// Calculates the buffer size required to decode from Base64 + //************************************************************************* + ETL_NODISCARD + ETL_CONSTEXPR14 + static size_t decoded_size(const char* input_begin, const char* input_end) + { + return decoded_size(input_begin, static_cast(etl::distance(input_begin, input_end))); + } + + //************************************************************************* + /// Calculates the buffer size required to decode from Base64 + //************************************************************************* + template + ETL_NODISCARD + ETL_CONSTEXPR14 + static size_t decoded_size(etl::span sp) + { + return decoded_size(sp.begin(), sp.size()); + } + private: //************************************************************************* @@ -520,4 +540,6 @@ namespace etl }; } +#undef ETL_IS_8_BIT_INTEGRAL + #endif diff --git a/test/test_base64.cpp b/test/test_base64.cpp index b26423e4..409a6c63 100644 --- a/test/test_base64.cpp +++ b/test/test_base64.cpp @@ -359,7 +359,7 @@ namespace std::string actual(encoded_output.data(), size); CHECK_EQUAL(expected, actual); - CHECK_EQUAL(etl::base64::encode_size(i), size); + CHECK_EQUAL(etl::base64::encoded_size(i), size); } } @@ -379,7 +379,7 @@ namespace std::string actual(encoded_output.data(), size); CHECK_EQUAL(expected, actual); - CHECK_EQUAL(etl::base64::encode_size(i), size); + CHECK_EQUAL(etl::base64::encoded_size(i), size); } } @@ -401,7 +401,7 @@ namespace std::string actual(encoded_output.data(), size); CHECK_EQUAL(expected, actual); - CHECK_EQUAL(etl::base64::encode_size(i), size); + CHECK_EQUAL(etl::base64::encoded_size(i), size); } } @@ -421,7 +421,7 @@ namespace std::string actual(encoded_output.data(), size); CHECK_EQUAL(expected, actual); - CHECK_EQUAL(etl::base64::encode_size(i), size); + CHECK_EQUAL(etl::base64::encoded_size(i), size); } } @@ -441,7 +441,7 @@ namespace std::string actual(encoded_output.data(), size); CHECK_EQUAL(expected, actual); - CHECK_EQUAL(etl::base64::encode_size(i), size); + CHECK_EQUAL(etl::base64::encoded_size(i), size); } } @@ -463,7 +463,7 @@ namespace std::string actual(encoded_output.data(), size); CHECK_EQUAL(expected, actual); - CHECK_EQUAL(etl::base64::encode_size(i), size); + CHECK_EQUAL(etl::base64::encoded_size(i), size); } } @@ -483,7 +483,7 @@ namespace std::string actual(encoded_output.data(), size); CHECK_EQUAL(expected, actual); - CHECK_EQUAL(etl::base64::encode_size(i), size); + CHECK_EQUAL(etl::base64::encoded_size(i), size); } } @@ -503,7 +503,7 @@ namespace std::string actual(encoded_output.data(), size); CHECK_EQUAL(expected, actual); - CHECK_EQUAL(etl::base64::encode_size(i), size); + CHECK_EQUAL(etl::base64::encoded_size(i), size); } } @@ -525,7 +525,7 @@ namespace std::string actual(encoded_output.data(), size); CHECK_EQUAL(expected, actual); - CHECK_EQUAL(etl::base64::encode_size(i), size); + CHECK_EQUAL(etl::base64::encoded_size(i), size); } } @@ -545,7 +545,7 @@ namespace std::string actual(encoded_output.data(), size); CHECK_EQUAL(expected, actual); - CHECK_EQUAL(etl::base64::encode_size(i), size); + CHECK_EQUAL(etl::base64::encoded_size(i), size); } } @@ -565,7 +565,7 @@ namespace std::string actual(encoded_output.data(), size); CHECK_EQUAL(expected, actual); - CHECK_EQUAL(etl::base64::encode_size(i), size); + CHECK_EQUAL(etl::base64::encoded_size(i), size); } } @@ -587,7 +587,7 @@ namespace std::string actual(encoded_output.data(), size); CHECK_EQUAL(expected, actual); - CHECK_EQUAL(etl::base64::encode_size(i), size); + CHECK_EQUAL(etl::base64::encoded_size(i), size); } } @@ -596,11 +596,11 @@ namespace template constexpr auto GetConstexprBase64(const etl::array input) noexcept { - constexpr size_t encode_size = etl::base64::encode_size(Size); - etl::array output{ 0 }; + constexpr size_t encoded_size = etl::base64::encoded_size(Size); + etl::array output{ 0 }; etl::base64::encode(input.begin(), Size, - output._buffer, encode_size); + output._buffer, encoded_size); return output; } @@ -615,7 +615,7 @@ namespace std::string actual(output.data(), output.size()); CHECK_EQUAL(expected, actual); - CHECK_EQUAL(etl::base64::encode_size(10), output.size()); + CHECK_EQUAL(etl::base64::encoded_size(10), output.size()); } #endif @@ -649,7 +649,7 @@ namespace 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, etl::base64::decoded_size(encoded[i].data(), encoded[i].size())); CHECK_EQUAL(i, decoded_size); } } @@ -664,10 +664,10 @@ namespace decoded_output.fill(0); auto decoded_size = etl::base64::decode(encoded[i].data(), encoded[i].size(), - decoded_output.data(), decoded_output.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, etl::base64::decoded_size(encoded[i].data(), encoded[i].size())); CHECK_EQUAL(i, decoded_size); } } @@ -678,7 +678,21 @@ namespace std::array decoded_output{ 0 }; CHECK_THROW((etl::base64::decode(encoded[10].data(), encoded[10].size(), - decoded_output.data(), decoded_output.size())), etl::base64_overflow); + decoded_output.data(), decoded_output.size())), etl::base64_overflow); + } + + //************************************************************************* + TEST(test_decoded_size) + { + for (size_t i = 0; i < 256; ++i) + { + size_t length = etl::base64::decoded_size(encoded[i].data(), encoded[i].size()); + + CHECK_EQUAL(length, etl::base64::decoded_size(encoded[i].data(), encoded[i].data() + encoded[i].size())); + + etl::span sp(encoded[i].data(), encoded[i].size()); + CHECK_EQUAL(length, etl::base64::decoded_size(sp)); + } } }; } diff --git a/version.txt b/version.txt index f2655965..4298195f 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -20.38.4 +20.39.0 From 2ea76c99af666045242d079d3fca0f37772aff93 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Sat, 21 Oct 2023 10:27:42 +0100 Subject: [PATCH 02/12] Static version of Base64 - RFC-6848 - No optional padding --- arduino/library-arduino.json | 2 +- arduino/library-arduino.properties | 2 +- include/etl/base64.h | 682 +++++++++++++++++------------ include/etl/iterator.h | 10 +- include/etl/private/pvoidvector.h | 4 +- include/etl/version.h | 4 +- library.json | 2 +- library.properties | 2 +- test/CMakeLists.txt | 267 +---------- test/test_base64.cpp | 460 +++++++++++-------- 10 files changed, 688 insertions(+), 747 deletions(-) diff --git a/arduino/library-arduino.json b/arduino/library-arduino.json index 822e28f8..446119aa 100644 --- a/arduino/library-arduino.json +++ b/arduino/library-arduino.json @@ -1,6 +1,6 @@ { "name": "Embedded Template Library - Arduino", - "version": "20.38.4", + "version": "20.39.0", "authors": { "name": "John Wellbelove", "email": "john.wellbelove@etlcpp.com" diff --git a/arduino/library-arduino.properties b/arduino/library-arduino.properties index 41ce4dfd..b93ae97e 100644 --- a/arduino/library-arduino.properties +++ b/arduino/library-arduino.properties @@ -1,5 +1,5 @@ name=Embedded Template Library - Arduino -version=20.38.4 +version=20.39.0 author= John Wellbelove maintainer=John Wellbelove license=MIT diff --git a/include/etl/base64.h b/include/etl/base64.h index 220632c7..d8372dcb 100644 --- a/include/etl/base64.h +++ b/include/etl/base64.h @@ -42,11 +42,8 @@ SOFTWARE. #include -#if ETL_USING_STL - #include -#endif - -#define ETL_IS_8_BIT_INTEGRAL(Type) (etl::is_integral::value && (etl::integral_limits::bits == 8U)) +#define ETL_IS_ITERATOR_TYPE_8_BIT_INTEGRAL(Type) (etl::is_integral::type>::value_type>::value && \ + (etl::integral_limits::type>::value_type>::bits == 8U)) namespace etl { @@ -77,200 +74,135 @@ namespace etl }; //************************************************************************* - /// Codec for Base64 + /// Codec for Base64 (RFC 4648) //************************************************************************* class base64 { public: //************************************************************************* - /// Encode to Base64 from and to pointer/length + /// Encode to Base64 + /// Four parameter //************************************************************************* - template + template ETL_CONSTEXPR14 - static - typename etl::enable_if::type - encode(const T* input, size_t input_length, char* output, size_t output_length) + static size_t encode(TInputIterator input_begin, TInputIterator input_end, TOutputIterator output_begin, TOutputIterator output_end) { - if (input_length == 0U) - { - return 0; - } + ETL_STATIC_ASSERT(ETL_IS_ITERATOR_TYPE_8_BIT_INTEGRAL(TInputIterator), "Input type must be an 8 bit integral"); + ETL_STATIC_ASSERT(ETL_IS_ITERATOR_TYPE_8_BIT_INTEGRAL(TOutputIterator), "Output type must be an 8 bit integral"); + + const size_t input_length = static_cast(etl::distance(input_begin, input_end)); + const size_t output_length = static_cast(etl::distance(output_begin, output_end)); // Figure out if the output buffer is large enough. - size_t required_output_length = encoded_size(input_length); - + size_t required_output_length = etl::base64::encoded_size(input_length); ETL_ASSERT_OR_RETURN_VALUE(output_length >= required_output_length, ETL_ERROR(base64_overflow), 0U); - 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((*p_in & b11111100) >> 2); - next_sextet = Second_Sextet; - break; - } - - //************************** - case Second_Sextet: - { - index = static_cast((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((*p_in & b11000000) >> 6); - } - next_sextet = Fourth_Sextet; - break; - } - - //************************** - case Fourth_Sextet: - { - index = static_cast(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(etl::distance(output, p_out)); + return process_encode(input_begin, input_length, output_begin, required_output_length); } //************************************************************************* - /// Encode to Base64 from and to pointer/pointer + /// Encode to Base64 + /// For TOutputIterator not derived from etl::iterator + /// Three parameter + /// Assumes the output container is large enough. //************************************************************************* - template + template ETL_CONSTEXPR14 - static - typename etl::enable_if::type - encode(const T* input_begin, const T* input_end, char* output_begin, char* output_end) + static typename etl::enable_if::value_type>::value, size_t>::type + encode(TInputIterator input_begin, TInputIterator input_end, TOutputIterator output_begin) { - return encode(input_begin, static_cast(etl::distance(input_begin, input_end)), - output_begin, static_cast(etl::distance(output_begin, output_end))); - } + ETL_STATIC_ASSERT(ETL_IS_ITERATOR_TYPE_8_BIT_INTEGRAL(TInputIterator), "Input type must be an 8 bit integral"); + ETL_STATIC_ASSERT(ETL_IS_ITERATOR_TYPE_8_BIT_INTEGRAL(TOutputIterator), "Output type must be an 8 bit integral"); + + const size_t input_length = static_cast(etl::distance(input_begin, input_end)); + const size_t output_length = encoded_size(input_length); + + return process_encode(input_begin, input_length, output_begin, output_length); + } //************************************************************************* - /// Encode to Base64 from and to span/span + /// Encode to Base64 + /// For TOutputIterator derived from etl::iterator + /// Three parameter + /// Assumes the output container is large enough. //************************************************************************* - template + template ETL_CONSTEXPR14 - static - typename etl::enable_if::type - encode(const etl::span& input_span, - const etl::span& output_span) + static typename etl::enable_if::value_type>::value, size_t>::type + encode(TInputIterator input_begin, TInputIterator input_end, TOutputIterator output_begin) { - return encode(input_span.begin(), input_span.size(), - output_span.begin(), output_span.size()); + ETL_STATIC_ASSERT(ETL_IS_ITERATOR_TYPE_8_BIT_INTEGRAL(TInputIterator), "Input type must be an 8 bit integral"); + + const size_t input_length = static_cast(etl::distance(input_begin, input_end)); + const size_t output_length = encoded_size(input_length); + + return process_encode(input_begin, input_length, output_begin, output_length); } //************************************************************************* - /// Encode to Base64 from pointer/length to etl::istring + /// Encode to Base64 + /// Four parameter //************************************************************************* - template + template ETL_CONSTEXPR14 - static - typename etl::enable_if::type - encode(const T* input_begin, size_t input_length, - etl::istring& output) + static size_t encode(TInputIterator input_begin, size_t input_length, TOutputIterator output_begin, size_t output_length) { - output.resize(etl::base64::encoded_size(input_length)); + ETL_STATIC_ASSERT(ETL_IS_ITERATOR_TYPE_8_BIT_INTEGRAL(TInputIterator), "Input type must be an 8 bit integral"); + ETL_STATIC_ASSERT(ETL_IS_ITERATOR_TYPE_8_BIT_INTEGRAL(TOutputIterator), "Output type must be an 8 bit integral"); - return encode(input_begin, input_length, - output.data(), output.size()); + // Figure out if the output buffer is large enough. + size_t required_output_length = etl::base64::encoded_size(input_length); + ETL_ASSERT_OR_RETURN_VALUE(output_length >= required_output_length, ETL_ERROR(base64_overflow), 0U); + + return process_encode(input_begin, input_length, output_begin, required_output_length); } //************************************************************************* - /// Encode to Base64 from pointer/pointer to etl::istring + /// Encode to Base64 + /// For TOutputIterator not derived from etl::iterator + /// Three parameter + /// Assumes the output container is large enough. //************************************************************************* - template + template ETL_CONSTEXPR14 - static - typename etl::enable_if::type - encode(const T* input_begin, const T* input_end, - etl::istring& output) + static typename etl::enable_if::value_type>::value, size_t>::type + encode(TInputIterator input_begin, size_t input_length, TOutputIterator output_begin) { - output.resize(etl::base64::encoded_size(etl::distance(input_begin, input_end))); + ETL_STATIC_ASSERT(ETL_IS_ITERATOR_TYPE_8_BIT_INTEGRAL(TInputIterator), "Input type must be an 8 bit integral"); + ETL_STATIC_ASSERT(ETL_IS_ITERATOR_TYPE_8_BIT_INTEGRAL(TOutputIterator), "Output type must be an 8 bit integral"); - return encode(input_begin, static_cast(etl::distance(input_begin, input_end)), - output.data(), output.size()); + const size_t output_length = encoded_size(input_length); + + return process_encode(input_begin, input_length, output_begin, output_length); } //************************************************************************* - /// Encode to Base64 from span to etl::istring + /// Encode to Base64 + /// For TOutputIterator derived from etl::iterator + /// Three parameter + /// Assumes the output container is large enough. //************************************************************************* - template + template ETL_CONSTEXPR14 - static - typename etl::enable_if::type - encode(const etl::span& input_span, - etl::istring& output) + static typename etl::enable_if::value_type>::value, size_t>::type + encode(TInputIterator input_begin, size_t input_length, TOutputIterator output_begin) { - output.resize(etl::base64::encoded_size(Length1)); + ETL_STATIC_ASSERT(ETL_IS_ITERATOR_TYPE_8_BIT_INTEGRAL(TInputIterator), "Input type must be an 8 bit integral"); - return encode(input_span.begin(), input_span.size(), - output.data(), output.size()); + const size_t output_length = encoded_size(input_length); + + return process_encode(input_begin, input_length, output_begin, output_length); } //************************************************************************* - /// Calculates the buffer size required to encode to Base64 + /// Calculates the minimum buffer size required to encode to Base64 //************************************************************************* ETL_NODISCARD ETL_CONSTEXPR14 - static - size_t encoded_size(size_t input_length) + static size_t encoded_size(size_t input_length) { - size_t required_output_length = (input_length * 8U) / 6U; + size_t required_output_length = (input_length * 4U) / 3U; while ((required_output_length % 4U) != 0) { @@ -281,175 +213,238 @@ namespace etl } //************************************************************************* - /// Decode from Base64 from and to pointer/length + /// Decode from Base64 + /// Four parameter //************************************************************************* - template + template ETL_CONSTEXPR14 - static - typename etl::enable_if::type - decode(const char* input, size_t input_length, T* output, size_t output_length) + static size_t decode(TInputIterator input_begin, TInputIterator input_end, TOutputIterator output_begin, TOutputIterator output_end) { - if (input_length == 0) - { - return 0; - } + ETL_STATIC_ASSERT(ETL_IS_ITERATOR_TYPE_8_BIT_INTEGRAL(TInputIterator), "Input type must be an 8 bit integral"); + ETL_STATIC_ASSERT(ETL_IS_ITERATOR_TYPE_8_BIT_INTEGRAL(TOutputIterator), "Output type must be an 8 bit integral"); + + const size_t input_length = valid_input_length(input_begin, input_end); + const size_t output_length = static_cast(etl::distance(output_begin, output_end)); // Figure out if the output buffer is large enough. - size_t required_output_length = etl::base64::decoded_size(input, input_length); - + size_t required_output_length = etl::base64::decoded_size_from_valid_input_length(input_length); ETL_ASSERT_OR_RETURN_VALUE(output_length >= required_output_length, ETL_ERROR(base64_overflow), 0U); - const char* p_in = input; - const char* p_in_end = input + input_length; - - T* p_out = output; - - 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()) - { - break; - } - - char index = get_index_from_sextet(sextet); - - switch (next_sextet) - { - //************************** - case First_Sextet: - { - c = (index & b00111111) << 2; - next_sextet = Second_Sextet; - break; - } - - //************************** - case Second_Sextet: - { - c |= (index & b00110000) >> 4; - *p_out++ = static_cast(c); - c = (index & b00001111) << 4; - next_sextet = Third_Sextet; - break; - } - - //************************** - case Third_Sextet: - { - c |= (index & b00111100) >> 2; - *p_out++ = static_cast(c); - c = (index & b00000011) << 6; - next_sextet = Fourth_Sextet; - break; - } - - //************************** - case Fourth_Sextet: - { - c |= (index & b00111111); - *p_out++ = static_cast(c); - next_sextet = First_Sextet; - break; - } - - //************************** - default: - { - // Should never get here. - assert(false); - break; - } - } - } - - return static_cast(etl::distance(output, p_out)); + return process_decode(input_begin, input_length, output_begin, required_output_length); } //************************************************************************* - /// Decode from Base64 from and to pointer/pointer + /// Decode from Base64 + /// For TOutputIterator not derived from etl::iterator + /// Three parameter + /// Assumes the output container is large enough. //************************************************************************* - template + template ETL_CONSTEXPR14 - static - typename etl::enable_if::type - decode(const char* input_begin, const char* input_end, T* output_begin, T* output_end) + static typename etl::enable_if::value_type>::value, size_t>::type + decode(TInputIterator input_begin, TInputIterator input_end, TOutputIterator output_begin) { - return decode(input_begin, static_cast(etl::distance(input_begin, input_end)), - output_begin, static_cast(etl::distance(output_begin, output_end))); + ETL_STATIC_ASSERT(ETL_IS_ITERATOR_TYPE_8_BIT_INTEGRAL(TInputIterator), "Input type must be an 8 bit integral"); + ETL_STATIC_ASSERT(ETL_IS_ITERATOR_TYPE_8_BIT_INTEGRAL(TOutputIterator), "Output type must be an 8 bit integral"); + + // Find the length of decodable characters. + const size_t input_length = valid_input_length(input_begin, input_end); + + // Find the length of the decoded output. + const size_t required_output_length = decoded_size(input_begin, input_length); + + return process_decode(input_begin, input_length, output_begin, required_output_length); } //************************************************************************* - /// Decode from Base64 from and to span/span + /// Decode from Base64 + /// For TOutputIterator derived from etl::iterator + /// Three parameter + /// Assumes the output container is large enough. //************************************************************************* - template + template ETL_CONSTEXPR14 - static - typename etl::enable_if::type - decode(const etl::span& input_span, - const etl::span& output_span) + static typename etl::enable_if::value_type>::value, size_t>::type + decode(TInputIterator input_begin, TInputIterator input_end, TOutputIterator output_begin) { - return decode(input_span.begin(), input_span.size(), - output_span.begin(), output_span.size()); + ETL_STATIC_ASSERT(ETL_IS_ITERATOR_TYPE_8_BIT_INTEGRAL(TInputIterator), "Input type must be an 8 bit integral"); + + // Find the length of decodable characters. + const size_t input_length = valid_input_length(input_begin, input_end); + + // Find the length of the decoded output. + const size_t required_output_length = decoded_size(input_begin, input_length); + + return process_decode(input_begin, input_length, output_begin, required_output_length); } //************************************************************************* - /// Calculates the buffer size required to decode from Base64 + /// Decode from Base64 + /// Four parameter //************************************************************************* + template + ETL_CONSTEXPR14 + static size_t decode(TInputIterator input_begin, size_t input_length, TOutputIterator output_begin, size_t output_length) + { + ETL_STATIC_ASSERT(ETL_IS_ITERATOR_TYPE_8_BIT_INTEGRAL(TInputIterator), "Input type must be an 8 bit integral"); + ETL_STATIC_ASSERT(ETL_IS_ITERATOR_TYPE_8_BIT_INTEGRAL(TOutputIterator), "Output type must be an 8 bit integral"); + + // Find the length of decodable characters. + input_length = valid_input_length(input_begin, input_length); + + // Figure out if the output buffer is large enough. + size_t required_output_length = etl::base64::decoded_size_from_valid_input_length(input_length); + ETL_ASSERT_OR_RETURN_VALUE(output_length >= required_output_length, ETL_ERROR(base64_overflow), 0U); + + return process_decode(input_begin, input_length, output_begin, required_output_length); + } + + //************************************************************************* + /// Decode from Base64 + /// For TOutputIterator not derived from etl::iterator + /// Three parameter + /// Assumes the output container is large enough. + //************************************************************************* + template + ETL_CONSTEXPR14 + static typename etl::enable_if::value_type>::value, size_t>::type + decode(TInputIterator input_begin, size_t input_length, TOutputIterator output_begin) + { + ETL_STATIC_ASSERT(ETL_IS_ITERATOR_TYPE_8_BIT_INTEGRAL(TInputIterator), "Input type must be an 8 bit integral"); + ETL_STATIC_ASSERT(ETL_IS_ITERATOR_TYPE_8_BIT_INTEGRAL(TOutputIterator), "Output type must be an 8 bit integral"); + + // Find the length of decodable characters. + input_length = valid_input_length(input_begin, input_length); + + // Find the length of the decoded output. + const size_t required_output_length = decoded_size(input_begin, input_length); + + return process_decode(input_begin, input_length, output_begin, required_output_length); + } + + //************************************************************************* + /// Decode from Base64 + /// For TOutputIterator derived from etl::iterator + /// Three parameter + /// Assumes the output container is large enough. + //************************************************************************* + template + ETL_CONSTEXPR14 + static typename etl::enable_if::value_type>::value, size_t>::type + decode(TInputIterator input_begin, size_t input_length, TOutputIterator output_begin) + { + ETL_STATIC_ASSERT(ETL_IS_ITERATOR_TYPE_8_BIT_INTEGRAL(TInputIterator), "Input type must be an 8 bit integral"); + + // Find the length of decodable characters. + input_length = valid_input_length(input_begin, input_length); + + // Find the length of the decoded output. + const size_t output_length = decoded_size(input_begin, input_length); + + return process_decode(input_begin, input_length, output_begin, output_length); + } + + //************************************************************************* + /// Discovers the number of valid decodable characters + //************************************************************************* + template ETL_NODISCARD ETL_CONSTEXPR14 - static size_t decoded_size(const char* input, size_t input_length) + static size_t valid_input_length(TInputIterator input_begin, size_t input_length) { if (input_length == 0U) { return 0U; } - // Figure out the minimum output buffer size. - size_t length = static_cast(etl::distance(input, etl::find(input, input + input_length, padding())) - 1); - size_t required_output_length = length - (length / 4U); + TInputIterator input_end = input_begin; - return required_output_length; + if (input_length >= 2U) + { + // Jump forward to where padding characters possibly start. + // There are never more than two padding characters. + input_length -= 2U; + etl::advance(input_end, input_length); + } + + typedef etl::iterator_traits::value_type input_type; + + if (*input_end != padding()) + { + ++input_end; + ++input_length; + + if (*input_end != padding()) + { + ++input_end; + ++input_length; + } + } + + return input_length; } //************************************************************************* - /// Calculates the buffer size required to decode from Base64 + /// Discovers the number of valid decodable characters //************************************************************************* + template ETL_NODISCARD ETL_CONSTEXPR14 - static size_t decoded_size(const char* input_begin, const char* input_end) + static size_t valid_input_length(TInputIterator input_begin, TInputIterator input_end) + { + return valid_input_length(input_begin, static_cast(etl::distance(input_begin, input_end))); + } + + //************************************************************************* + /// Calculates the minimum buffer size required to decode from Base64 + //************************************************************************* + template + ETL_NODISCARD + ETL_CONSTEXPR14 + static + size_t decoded_size(TInputIterator input_begin, size_t input_length) + { + if (input_length == 0U) + { + return 0U; + } + + input_length = valid_input_length(input_begin, input_length); + --input_length; + return input_length - (input_length / 4U); + } + + //************************************************************************* + /// Calculates the minimum buffer size required to decode from Base64 + //************************************************************************* + template + ETL_NODISCARD + ETL_CONSTEXPR14 + static + size_t decoded_size(TInputIterator input_begin, TInputIterator input_end) { return decoded_size(input_begin, static_cast(etl::distance(input_begin, input_end))); } //************************************************************************* - /// Calculates the buffer size required to decode from Base64 + /// Calculates the minimum buffer size required to decode from Base64 //************************************************************************* - template ETL_NODISCARD ETL_CONSTEXPR14 - static size_t decoded_size(etl::span sp) + static + size_t decoded_size_from_valid_input_length(size_t input_length) { - return decoded_size(sp.begin(), sp.size()); + if (input_length == 0U) + { + return 0U; + } + + --input_length; + return input_length - (input_length / 4U); } private: - //************************************************************************* - /// Sextet index id. - enum - { - First_Sextet, - Second_Sextet, - Third_Sextet, - Fourth_Sextet - }; - // Sextets // 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', // 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', @@ -463,42 +458,44 @@ namespace etl //************************************************************************* // Translates an index into a sextet //************************************************************************* - ETL_CONSTEXPR14 static char get_sextet_from_index(char index) + template + ETL_CONSTEXPR14 static T get_sextet_from_index(char index) { if ((index >= 0) && (index < 26)) { - return 'A' + index; + return static_cast('A' + index); } else if ((index >= 26) && (index < 52)) { index -= 26; - return 'a' + index; + return static_cast('a' + index); } else if ((index >= 52) && (index < 62)) { index -= 52; - return '0' + index; + return static_cast('0' + index); } else if (index == 62) { - return '+'; + return static_cast('+'); } else if (index == 63) { - return '/'; + return static_cast('/'); } else { // Should never get here. assert(false); - return padding(); + return padding(); } } //************************************************************************* // Translates a sextet into an index //************************************************************************* - ETL_CONSTEXPR14 static char get_index_from_sextet(char sextet) + template + ETL_CONSTEXPR14 static uint32_t get_index_from_sextet(T sextet) { if ((sextet >= 'A') && (sextet <= 'Z')) { @@ -512,11 +509,11 @@ namespace etl { return sextet - '0' + 52; } - else if (sextet == '+') + else if ((sextet == '+')) { return 62; } - else if (sextet == '/') + else if ((sextet == '/')) { return 63; } @@ -531,15 +528,142 @@ namespace etl //************************************************************************* /// Gets the padding character //************************************************************************* + template ETL_NODISCARD ETL_CONSTEXPR14 - static char padding() + static T padding() { - return '='; + return static_cast('='); + } + + //************************************************************************* + /// Encode to Base64 implementation + //************************************************************************* + template + ETL_CONSTEXPR14 + static + size_t process_encode(TInputIterator input, size_t input_length, + TOutputIterator output, size_t output_length) + { + if (input_length == 0U) + { + return 0; + } + + // Count the actual number of sextets written. + size_t output_count = 0; + + uint32_t octets = 0; + + // Read octet triplets and write sextet quartets + while (input_length >= 3U) + { + // Read in three octets + octets = (static_cast(static_cast(*input++)) << 16); + octets = octets | (static_cast(static_cast(*input++)) << 8); + octets = octets | static_cast(static_cast(*input++)); + + // Write out four sextets + *output++ = get_sextet_from_index((octets >> 18) & b00111111); + *output++ = get_sextet_from_index((octets >> 12) & b00111111); + *output++ = get_sextet_from_index((octets >> 6) & b00111111); + *output++ = get_sextet_from_index((octets >> 0) & b00111111); + + input_length -= 3U; + output_count += 4U; + } + + // Any input left? + if (input_length > 0) + { + // Write out any remaining sextets + if (input_length == 1U) + { + // There is one octet remaining + octets = static_cast(static_cast(*input++)); + octets <<= 4; // Adjust one octet (8 bits) for two sextets worth of data (12 bits) + output_count += 2U; + } + else if (input_length == 2U) + { + // There are two octets remaining + octets = static_cast(static_cast(*input++)); + octets <<= 8; + octets = octets | static_cast(static_cast(*input++)); + octets <<= 2; // Adjust two octets (16 bits) for three sextets worth of data (18 bits) + output_count += 3U; + } + + int shift = static_cast(input_length * 6U); + + while (shift >= 0) + { + *output++ = get_sextet_from_index((octets >> shift) & b00111111); + shift -= 6; + } + } + + // Pad out the end of the output buffer. + while (output_count != output_length) + { + *output++ = padding(); + ++output_count; + } + + return output_length; + } + + //************************************************************************* + /// Decode from Base64 implementation + //************************************************************************* + template + ETL_CONSTEXPR14 + static + size_t process_decode(TInputIterator input, size_t input_length, TOutputIterator output, size_t output_length) + { + if (input_length == 0) + { + return 0; + } + + // Read sextet quartets and write octet triplets + while (input_length >= 4U) + { + // Read in four sextets + uint32_t sextets = (get_index_from_sextet(*input++) << 18) | + (get_index_from_sextet(*input++) << 12) | + (get_index_from_sextet(*input++) << 6) | + (get_index_from_sextet(*input++)); + + // Write out three octets + *output++ = (sextets >> 16) & b11111111; + *output++ = (sextets >> 8) & b11111111; + *output++ = (sextets >> 0) & b11111111; + + input_length -= 4U; + } + + // Write out any remaining octets + if (input_length == 2U) + { + uint32_t sextets = (get_index_from_sextet(*input++) << 6) | + (get_index_from_sextet(*input++)); + *output++ = (sextets >> 4) & b11111111; + input_length -= 2U; + } + else if (input_length == 3U) + { + uint32_t sextets = (get_index_from_sextet(*input++) << 12) | + (get_index_from_sextet(*input++) << 6) | + (get_index_from_sextet(*input++)); + *output++ = (sextets >> 10) & b11111111; + *output++ = (sextets >> 2) & b11111111; + input_length -= 3U; + } + + return output_length; } }; } -#undef ETL_IS_8_BIT_INTEGRAL - #endif diff --git a/include/etl/iterator.h b/include/etl/iterator.h index ab19db39..8c23c6bd 100644 --- a/include/etl/iterator.h +++ b/include/etl/iterator.h @@ -605,14 +605,14 @@ namespace etl } //*************************************************************************** - /// This kind of %iterator doesn't really have a @a position in the + /// This kind of iterator doesn't really have a a position in the /// container (you can think of the position as being permanently at - /// the end, if you like). Assigning a value to the %iterator will + /// the end, if you like). Assigning a value to the iterator will /// always append the value to the end of the container. /// /// @param value An instance of whatever type container_type::const_reference is; /// presumably a reference-to-const T for container. - /// @return This %iterator, for chained operations. + /// @return This iterator, for chained operations. //*************************************************************************** ETL_CONSTEXPR14 back_insert_iterator& operator =(const typename TContainer::value_type& value) { @@ -644,7 +644,7 @@ namespace etl //*************************************************************************** /// Pre-increment operator. - /// Simply returns *this. (This %iterator does not @a move.) + /// Simply returns *this. (This iterator does not move.) //*************************************************************************** ETL_CONSTEXPR14 back_insert_iterator& operator ++() { @@ -653,7 +653,7 @@ namespace etl //*************************************************************************** /// Post-increment operator. - /// Simply returns *this. (This %iterator does not @a move.) + /// Simply returns *this. (This iterator does not move.) //*************************************************************************** ETL_CONSTEXPR14 back_insert_iterator operator ++(int) { diff --git a/include/etl/private/pvoidvector.h b/include/etl/private/pvoidvector.h index 6ec32092..02f45832 100644 --- a/include/etl/private/pvoidvector.h +++ b/include/etl/private/pvoidvector.h @@ -593,7 +593,7 @@ namespace etl iterator last_ = to_iterator(last); etl::copy(last_, end(), first_); - size_t n_delete = etl::distance(first, last); + size_t n_delete = static_cast(etl::distance(first, last)); // Just adjust the count. p_end -= n_delete; @@ -695,7 +695,7 @@ namespace etl //************************************************************************* void repair_buffer(void** p_buffer_) { - uintptr_t length = p_end - p_buffer; + uintptr_t length = static_cast(p_end - p_buffer); p_buffer = p_buffer_; p_end = p_buffer_ + length; diff --git a/include/etl/version.h b/include/etl/version.h index 66d517cd..34db9c98 100644 --- a/include/etl/version.h +++ b/include/etl/version.h @@ -39,8 +39,8 @@ SOFTWARE. ///\ingroup utilities #define ETL_VERSION_MAJOR 20 -#define ETL_VERSION_MINOR 38 -#define ETL_VERSION_PATCH 4 +#define ETL_VERSION_MINOR 39 +#define ETL_VERSION_PATCH 0 #define ETL_VERSION ETL_STRING(ETL_VERSION_MAJOR) "." ETL_STRING(ETL_VERSION_MINOR) "." ETL_STRING(ETL_VERSION_PATCH) #define ETL_VERSION_W ETL_WIDE_STRING(ETL_VERSION_MAJOR) L"." ETL_WIDE_STRING(ETL_VERSION_MINOR) L"." ETL_WIDE_STRING(ETL_VERSION_PATCH) diff --git a/library.json b/library.json index 9f7d179e..bcb615a9 100644 --- a/library.json +++ b/library.json @@ -1,6 +1,6 @@ { "name": "Embedded Template Library", - "version": "20.38.4", + "version": "20.39.0", "authors": { "name": "John Wellbelove", "email": "john.wellbelove@etlcpp.com" diff --git a/library.properties b/library.properties index 5d849dda..719241ac 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=Embedded Template Library -version=20.38.4 +version=20.39.0 author= John Wellbelove maintainer=John Wellbelove license=MIT diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index e8ecf183..0bd37e14 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -12,273 +12,7 @@ project(etl_unit_tests LANGUAGES CXX) add_executable(etl_tests main.cpp - murmurhash3.cpp - test_algorithm.cpp - test_alignment.cpp - test_array.cpp - 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 - test_bitset_legacy.cpp - test_bitset_new_default_element_type.cpp - test_bitset_new_explicit_single_element_type.cpp - test_bitset_new_ext_default_element_type.cpp - test_bitset_new_ext_explicit_single_element_type.cpp - test_bit_stream.cpp - test_bit_stream_reader_big_endian.cpp - test_bit_stream_reader_little_endian.cpp - test_bit_stream_writer_big_endian.cpp - test_bit_stream_writer_little_endian.cpp - test_byte.cpp - test_byte_stream.cpp - test_bloom_filter.cpp - test_bresenham_line.cpp - test_bsd_checksum.cpp - test_buffer_descriptors.cpp - test_callback_service.cpp - test_callback_timer.cpp - test_callback_timer_atomic.cpp - test_callback_timer_interrupt.cpp - test_callback_timer_locked.cpp - test_char_traits.cpp - test_checksum.cpp - test_circular_buffer.cpp - test_circular_buffer_external_buffer.cpp - test_circular_iterator.cpp - test_compare.cpp - test_constant.cpp - test_container.cpp - test_correlation.cpp - test_covariance.cpp - test_crc.cpp - test_crc16.cpp - test_crc16_a.cpp - test_crc16_arc.cpp - test_crc16_aug_ccitt.cpp - test_crc16_buypass.cpp - test_crc16_ccitt.cpp - test_crc16_cdma2000.cpp - test_crc16_dds110.cpp - test_crc16_dectr.cpp - test_crc16_dectx.cpp - test_crc16_dnp.cpp - test_crc16_en13757.cpp - test_crc16_genibus.cpp - test_crc16_kermit.cpp - test_crc16_m17.cpp - test_crc16_maxim.cpp - test_crc16_mcrf4xx.cpp - test_crc16_modbus.cpp - test_crc16_profibus.cpp - test_crc16_riello.cpp - test_crc16_t10dif.cpp - test_crc16_teledisk.cpp - test_crc16_tms37157.cpp - test_crc16_usb.cpp - test_crc16_x25.cpp - test_crc16_xmodem.cpp - test_crc32.cpp - test_crc32_bzip2.cpp - test_crc32_c.cpp - test_crc32_d.cpp - test_crc32_jamcrc.cpp - test_crc32_mpeg2.cpp - test_crc32_posix.cpp - test_crc32_q.cpp - test_crc32_xfer.cpp - test_crc64_ecma.cpp - test_crc8_ccitt.cpp - test_crc8_cdma2000.cpp - test_crc8_darc.cpp - test_crc8_dvbs2.cpp - test_crc8_ebu.cpp - test_crc8_icode.cpp - test_crc8_itu.cpp - test_crc8_maxim.cpp - test_crc8_rohc.cpp - test_crc8_wcdma.cpp - test_cyclic_value.cpp - test_debounce.cpp - test_delegate.cpp - test_delegate_cpp03.cpp - test_delegate_service.cpp - test_delegate_service_compile_time.cpp - test_deque.cpp - test_endian.cpp - test_enum_type.cpp - test_error_handler.cpp - test_etl_traits.cpp - test_exception.cpp - test_expected.cpp - test_fixed_iterator.cpp - test_fixed_sized_memory_block_allocator.cpp - test_flags.cpp - test_flat_map.cpp - test_flat_multimap.cpp - test_flat_multiset.cpp - test_flat_set.cpp - test_fnv_1.cpp - test_format_spec.cpp - test_forward_list.cpp - test_forward_list_shared_pool.cpp - test_fsm.cpp - test_function.cpp - test_functional.cpp - test_gamma.cpp - test_hash.cpp - test_hfsm.cpp - test_histogram.cpp - test_indirect_vector.cpp - test_indirect_vector_external_buffer.cpp - test_instance_count.cpp - test_integral_limits.cpp - test_intrusive_forward_list.cpp - test_intrusive_links.cpp - test_intrusive_list.cpp - test_intrusive_queue.cpp - test_intrusive_stack.cpp - test_invert.cpp - test_io_port.cpp - test_iterator.cpp - test_jenkins.cpp - test_largest.cpp - test_limiter.cpp - test_limits.cpp - test_list.cpp - test_list_shared_pool.cpp - test_make_string.cpp - test_map.cpp - test_maths.cpp - test_mean.cpp - test_mem_cast.cpp - test_mem_cast_ptr.cpp - test_memory.cpp - test_message_broker.cpp - test_message_bus.cpp - test_message_packet.cpp - test_message_router.cpp - test_message_router_registry.cpp - test_message_timer.cpp - test_message_timer_atomic.cpp - test_message_timer_interrupt.cpp - test_message_timer_locked.cpp - test_multimap.cpp - test_multiset.cpp - test_multi_array.cpp - test_multi_range.cpp - test_multi_vector.cpp - test_murmur3.cpp - test_nth_type.cpp - test_numeric.cpp - test_observer.cpp - test_optional.cpp - test_packet.cpp - test_parameter_pack.cpp - test_parameter_type.cpp - test_parity_checksum.cpp - test_pearson.cpp - test_poly_span_dynamic_extent.cpp - test_poly_span_fixed_extent.cpp - test_pool.cpp - test_pool_external_buffer.cpp - test_priority_queue.cpp - test_pseudo_moving_average.cpp - test_quantize.cpp - test_queue.cpp - test_queue_lockable.cpp - test_queue_lockable_small.cpp - test_queue_memory_model_small.cpp - test_queue_mpmc_mutex.cpp - test_queue_mpmc_mutex_small.cpp - test_queue_spsc_atomic.cpp - test_queue_spsc_atomic_small.cpp - test_queue_spsc_isr.cpp - test_queue_spsc_isr_small.cpp - test_queue_spsc_locked.cpp - test_queue_spsc_locked_small.cpp - test_random.cpp - test_reference_flat_map.cpp - test_reference_flat_multimap.cpp - test_reference_flat_multiset.cpp - test_reference_flat_set.cpp - test_rescale.cpp - test_result.cpp - test_rms.cpp - test_scaled_rounding.cpp - test_set.cpp - test_shared_message.cpp - test_singleton.cpp - test_smallest.cpp - test_span_dynamic_extent.cpp - test_span_fixed_extent.cpp - test_stack.cpp - test_standard_deviation.cpp - test_state_chart.cpp - test_state_chart_with_data_parameter.cpp - test_state_chart_with_rvalue_data_parameter.cpp - test_state_chart_compile_time.cpp - test_state_chart_compile_time_with_data_parameter.cpp - test_string_char.cpp - test_string_char_external_buffer.cpp - test_string_stream.cpp - test_string_stream_u16.cpp - test_string_stream_u32.cpp - test_string_stream_wchar_t.cpp - test_string_u16.cpp - test_string_u16_external_buffer.cpp - test_string_u32.cpp - test_string_u32_external_buffer.cpp - test_string_utilities.cpp - test_string_utilities_std.cpp - test_string_utilities_std_u16.cpp - test_string_utilities_std_u32.cpp - test_string_utilities_std_wchar_t.cpp - test_string_utilities_u16.cpp - test_string_utilities_u32.cpp - test_string_utilities_wchar_t.cpp - test_string_view.cpp - test_string_wchar_t.cpp - test_string_wchar_t_external_buffer.cpp - test_successor.cpp - test_task_scheduler.cpp - test_threshold.cpp - test_to_arithmetic.cpp - test_to_arithmetic_u16.cpp - test_to_arithmetic_u32.cpp - test_to_arithmetic_wchar_t.cpp - test_to_string.cpp - test_to_u16string.cpp - test_to_u32string.cpp - test_to_wstring.cpp - test_type_def.cpp - test_type_lookup.cpp - test_type_select.cpp - test_type_traits.cpp - test_unaligned_type.cpp - test_unaligned_type_constexpr.cpp - test_unordered_map.cpp - test_unordered_multimap.cpp - test_unordered_multiset.cpp - test_unordered_set.cpp - test_user_type.cpp - test_utility.cpp - test_variance.cpp - test_variant_legacy.cpp - test_variant_variadic.cpp - test_variant_pool.cpp - test_variant_pool_external_buffer.cpp - test_vector.cpp - test_vector_external_buffer.cpp - test_vector_non_trivial.cpp - test_vector_pointer.cpp - test_vector_pointer_external_buffer.cpp - test_visitor.cpp - test_xor_checksum.cpp - test_xor_rotate_checksum.cpp ) target_compile_definitions(etl_tests PRIVATE -DETL_DEBUG) @@ -371,6 +105,7 @@ if ((CMAKE_CXX_COMPILER_ID MATCHES "GNU") OR (CMAKE_CXX_COMPILER_ID MATCHES "Cla -Wall -Wextra -Werror + -Wsign-conversion ) if (ETL_ENABLE_SANITIZER) diff --git a/test/test_base64.cpp b/test/test_base64.cpp index 409a6c63..959a2907 100644 --- a/test/test_base64.cpp +++ b/test/test_base64.cpp @@ -38,6 +38,8 @@ SOFTWARE. #include #include +#include "etl/integral_limits.h" + namespace { std::array input_data_unsigned_char = @@ -343,198 +345,109 @@ namespace SUITE(test_base64) { - //************************************************************************* - TEST(test_encode_unsigned_char_pointer_size) - { - std::array encoded_output; + ////************************************************************************* + //TEST(test_encode_unsigned_char_pointer_size) + //{ + // std::array encoded_output; - for (size_t i = 0; i < 256; ++i) - { - encoded_output.fill(0); + // for (size_t i = 0; i < 256; ++i) + // { + // encoded_output.fill(0); - auto size = etl::base64::encode(input_data_unsigned_char.data(), i, - encoded_output.data(), encoded_output.size()); + // auto size = etl::base64::encode(input_data_unsigned_char.data(), i, + // encoded_output.data(), encoded_output.size()); - std::string expected(encoded[i]); - std::string actual(encoded_output.data(), size); + // std::string expected(encoded[i]); + // std::string actual(encoded_output.data(), size); - CHECK_EQUAL(expected, actual); - CHECK_EQUAL(etl::base64::encoded_size(i), size); - } - } + // CHECK_EQUAL(expected, actual); + // CHECK_EQUAL(etl::base64::encoded_size(i), size); + // } + //} - //************************************************************************* - TEST(test_encode_unsigned_char_pointer_pointer) - { - std::array encoded_output; + ////************************************************************************* + //TEST(test_encode_unsigned_char_pointer_size_no_output_length) + //{ + // std::array encoded_output; - for (size_t i = 0; i < 256; ++i) - { - encoded_output.fill(0); + // 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()); + // auto size = etl::base64::encode(input_data_unsigned_char.data(), i, + // encoded_output.data()); - std::string expected(encoded[i]); - std::string actual(encoded_output.data(), size); + // std::string expected(encoded[i]); + // std::string actual(encoded_output.data(), size); - CHECK_EQUAL(expected, actual); - CHECK_EQUAL(etl::base64::encoded_size(i), size); - } - } + // CHECK_EQUAL(expected, actual); + // CHECK_EQUAL(etl::base64::encoded_size(i), size); + // } + //} - //************************************************************************* - TEST(test_encode_unsigned_char_span) - { - std::array encoded_output; + ////************************************************************************* + //TEST(test_encode_unsigned_char_pointer_size_to_back_inserter) + //{ + // for (size_t i = 0; i < 256; ++i) + // { + // std::string actual; - for (size_t i = 0; i < 256; ++i) - { - encoded_output.fill(0); + // auto size = etl::base64::encode(input_data_unsigned_char.data(), i, + // etl::back_inserter(actual)); - etl::span input_span(input_data_unsigned_char.data(), i); - etl::span output_span(encoded_output.data(), encoded_output.size()); + // std::string expected(encoded[i]); + // + // CHECK_EQUAL(expected, actual); + // CHECK_EQUAL(etl::base64::encoded_size(i), size); + // } + //} - auto size = etl::base64::encode(input_span, output_span); + ////************************************************************************* + //TEST(test_encode_unsigned_char_pointer_pointer) + //{ + // std::array encoded_output; - std::string expected(encoded[i]); - std::string actual(encoded_output.data(), size); + // for (size_t i = 0; i < 256; ++i) + // { + // encoded_output.fill(0); - CHECK_EQUAL(expected, actual); - CHECK_EQUAL(etl::base64::encoded_size(i), size); - } - } + // 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()); - //************************************************************************* - TEST(test_encode_unsigned_char_pointer_size_to_etl_string) - { - etl::string<344U> encoded_output; + // std::string expected(encoded[i]); + // std::string actual(encoded_output.data(), size); - for (size_t i = 0; i < 256; ++i) - { - encoded_output.clear(); + // CHECK_EQUAL(expected, actual); + // CHECK_EQUAL(etl::base64::encoded_size(i), size); + // } + //} - auto size = etl::base64::encode(input_data_unsigned_char.data(), i, - encoded_output); + ////************************************************************************* + //TEST(test_encode_unsigned_char_pointer_pointer_no_output_end_pointer) + //{ + // std::array encoded_output; - std::string expected(encoded[i]); - std::string actual(encoded_output.data(), size); + // for (size_t i = 6; i < 256; ++i) + // { + // encoded_output.fill(0); - CHECK_EQUAL(expected, actual); - CHECK_EQUAL(etl::base64::encoded_size(i), size); - } - } + // auto size = etl::base64::encode(input_data_unsigned_char.data(), input_data_unsigned_char.data() + i, + // encoded_output.data()); - //************************************************************************* - TEST(test_encode_unsigned_char_pointer_pointer_to_etl_string) - { - etl::string<344U> encoded_output; + // std::string expected(encoded[i]); + // std::string actual(encoded_output.data(), size); - for (size_t i = 0; i < 256; ++i) - { - encoded_output.clear(); - - auto size = etl::base64::encode(input_data_unsigned_char.data(), input_data_unsigned_char.data() + i, - encoded_output); - - std::string expected(encoded[i]); - std::string actual(encoded_output.data(), size); - - CHECK_EQUAL(expected, actual); - CHECK_EQUAL(etl::base64::encoded_size(i), size); - } - } - - //************************************************************************* - TEST(test_encode_unsigned_char_span_to_etl_string) - { - etl::string<344U> encoded_output; - - for (size_t i = 0; i < 256; ++i) - { - encoded_output.clear(); - - etl::span input_span(input_data_unsigned_char.data(), i); - - auto size = etl::base64::encode(input_span, - encoded_output); - - std::string expected(encoded[i]); - std::string actual(encoded_output.data(), size); - - CHECK_EQUAL(expected, actual); - CHECK_EQUAL(etl::base64::encoded_size(i), size); - } - } - - //************************************************************************* - TEST(test_encode_int8_t_pointer_size_to_etl_string) - { - etl::string<344U> encoded_output; - - for (size_t i = 0; i < 256; ++i) - { - encoded_output.clear(); - - auto size = etl::base64::encode(input_data_int8_t.data(), i, - encoded_output); - - std::string expected(encoded[i]); - std::string actual(encoded_output.data(), size); - - CHECK_EQUAL(expected, actual); - CHECK_EQUAL(etl::base64::encoded_size(i), size); - } - } - - //************************************************************************* - TEST(test_encode_int8_t_pointer_pointer_to_etl_string) - { - etl::string<344U> encoded_output; - - for (size_t i = 0; i < 256; ++i) - { - encoded_output.clear(); - - auto size = etl::base64::encode(input_data_int8_t.data(), input_data_int8_t.data() + i, - encoded_output); - - std::string expected(encoded[i]); - std::string actual(encoded_output.data(), size); - - CHECK_EQUAL(expected, actual); - CHECK_EQUAL(etl::base64::encoded_size(i), size); - } - } - - //************************************************************************* - TEST(test_encode_int8_t_span_to_etl_string) - { - etl::string<344U> encoded_output; - - for (size_t i = 0; i < 256; ++i) - { - encoded_output.clear(); - - etl::span input_span(input_data_int8_t.data(), i); - - auto size = etl::base64::encode(input_span, - encoded_output); - - std::string expected(encoded[i]); - std::string actual(encoded_output.data(), size); - - CHECK_EQUAL(expected, actual); - CHECK_EQUAL(etl::base64::encoded_size(i), size); - } - } + // CHECK_EQUAL(expected, actual); + // CHECK_EQUAL(etl::base64::encoded_size(i), size); + // } + //} //************************************************************************* TEST(test_encode_int8_t_pointer_size) { std::array encoded_output; - for (size_t i = 0; i < 256; ++i) + for (size_t i = 11; i < 256; ++i) { encoded_output.fill(0); @@ -550,16 +463,16 @@ namespace } //************************************************************************* - TEST(test_encode_int8_t_pointer_pointer) + TEST(test_encode_int8_t_pointer_size_no_output_length) { std::array encoded_output; - for (size_t i = 0; i < 256; ++i) + for (size_t i = 6; 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()); + auto size = etl::base64::encode(input_data_int8_t.data(), i, + encoded_output.data()); std::string expected(encoded[i]); std::string actual(encoded_output.data(), size); @@ -570,7 +483,24 @@ namespace } //************************************************************************* - TEST(test_encode_int8_t_span) + TEST(test_encode_int8_t_pointer_size_to_back_inserter) + { + for (size_t i = 0; i < 256; ++i) + { + std::string actual; + + auto size = etl::base64::encode(input_data_int8_t.data(), i, + etl::back_inserter(actual)); + + std::string expected(encoded[i]); + + CHECK_EQUAL(expected, actual); + CHECK_EQUAL(etl::base64::encoded_size(i), size); + } + } + + //************************************************************************* + TEST(test_encode_int8_t_pointer_pointer) { std::array encoded_output; @@ -578,10 +508,28 @@ namespace { encoded_output.fill(0); - etl::span input_span(input_data_int8_t.data(), i); - etl::span output_span(encoded_output.data(), encoded_output.size()); + 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()); - 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::encoded_size(i), size); + } + } + + //************************************************************************* + TEST(test_encode_int8_t_pointer_pointer_no_end_pointer) + { + std::array 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()); std::string expected(encoded[i]); std::string actual(encoded_output.data(), size); @@ -600,7 +548,7 @@ namespace etl::array output{ 0 }; etl::base64::encode(input.begin(), Size, - output._buffer, encoded_size); + output._buffer, encoded_size); return output; } @@ -625,19 +573,12 @@ namespace std::array encoded_output{ 0 }; CHECK_THROW((etl::base64::encode(input_data_unsigned_char.data(), 10, - encoded_output.data(), encoded_output.size())), etl::base64_overflow); + encoded_output.data(), encoded_output.size())), + etl::base64_overflow); } //************************************************************************* - TEST(test_encode_overflow_for_etl_string) - { - etl::string<10> output; - - CHECK_THROW((etl::base64::encode(input_data_unsigned_char.data(), 10, output)), etl::base64_overflow); - } - - //************************************************************************* - TEST(test_decode_unsigned_char) + TEST(test_decode_unsigned_char_pointer_size) { std::array decoded_output; @@ -645,8 +586,8 @@ namespace { decoded_output.fill(0); - auto decoded_size = etl::base64::decode(encoded[i].data(), encoded[i].size(), - decoded_output.data(), decoded_output.size()); + 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::decoded_size(encoded[i].data(), encoded[i].size())); @@ -655,7 +596,61 @@ namespace } //************************************************************************* - TEST(test_decode_int8_t) + TEST(test_decode_unsigned_char_pointer_size_no_end_pointer) + { + std::array 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()); + + CHECK_ARRAY_EQUAL(input_data_unsigned_char.data(), decoded_output.data(), i); + CHECK_EQUAL(i, etl::base64::decoded_size(encoded[i].data(), encoded[i].size())); + CHECK_EQUAL(i, decoded_size); + } + } + + //************************************************************************* + TEST(test_decode_unsigned_char_pointer_pointer) + { + std::array 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].data() + encoded[i].size(), + decoded_output.data(), decoded_output.data() + decoded_output.size()); + + CHECK_ARRAY_EQUAL(input_data_unsigned_char.data(), decoded_output.data(), i); + CHECK_EQUAL(i, etl::base64::decoded_size(encoded[i].data(), encoded[i].size())); + CHECK_EQUAL(i, decoded_size); + } + } + + //************************************************************************* + TEST(test_decode_unsigned_char_pointer_pointer_no_end_pointer) + { + std::array 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].data() + encoded[i].size(), + decoded_output.data()); + + CHECK_ARRAY_EQUAL(input_data_unsigned_char.data(), decoded_output.data(), i); + CHECK_EQUAL(i, etl::base64::decoded_size(encoded[i].data(), encoded[i].size())); + CHECK_EQUAL(i, decoded_size); + } + } + + //************************************************************************* + TEST(test_decode_int8_t_pointer_size) { std::array decoded_output; @@ -672,6 +667,96 @@ namespace } } + //************************************************************************* + TEST(test_decode_int8_t_pointer_size_back_inserter) + { + std::vector decoded_output; + + for (size_t i = 0; i < 256; ++i) + { + decoded_output.clear(); + + auto decoded_size = etl::base64::decode(encoded[i].data(), encoded[i].size(), + etl::back_inserter(decoded_output)); + + CHECK_ARRAY_EQUAL(input_data_int8_t.data(), decoded_output.data(), i); + CHECK_EQUAL(i, etl::base64::decoded_size(encoded[i].data(), encoded[i].size())); + CHECK_EQUAL(i, decoded_size); + } + } + + //************************************************************************* + TEST(test_decode_int8_t_pointer_size_no_output_size) + { + std::array 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()); + + CHECK_ARRAY_EQUAL(input_data_int8_t.data(), decoded_output.data(), i); + CHECK_EQUAL(i, etl::base64::decoded_size(encoded[i].data(), encoded[i].size())); + CHECK_EQUAL(i, decoded_size); + } + } + + //************************************************************************* + TEST(test_decode_int8_t_pointer_pointer) + { + std::array 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].data() + encoded[i].size(), + decoded_output.data(), decoded_output.data() + decoded_output.size()); + + CHECK_ARRAY_EQUAL(input_data_int8_t.data(), decoded_output.data(), i); + CHECK_EQUAL(i, etl::base64::decoded_size(encoded[i].data(), encoded[i].size())); + CHECK_EQUAL(i, decoded_size); + } + } + + //************************************************************************* + TEST(test_decode_int8_t_pointer_pointer_back_inserter) + { + std::vector decoded_output; + + for (size_t i = 0; i < 256; ++i) + { + decoded_output.clear(); + + auto decoded_size = etl::base64::decode(encoded[i].data(), encoded[i].data() + encoded[i].size(), + etl::back_inserter(decoded_output)); + + CHECK_ARRAY_EQUAL(input_data_int8_t.data(), decoded_output.data(), i); + CHECK_EQUAL(i, etl::base64::decoded_size(encoded[i].data(), encoded[i].size())); + CHECK_EQUAL(i, decoded_size); + } + } + + //************************************************************************* + TEST(test_decode_int8_t_pointer_pointer_no_end_pointer) + { + std::array 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].data() + encoded[i].size(), + decoded_output.data()); + + CHECK_ARRAY_EQUAL(input_data_int8_t.data(), decoded_output.data(), i); + CHECK_EQUAL(i, etl::base64::decoded_size(encoded[i].data(), encoded[i].size())); + CHECK_EQUAL(i, decoded_size); + } + } + //************************************************************************* TEST(test_decode_overflow) { @@ -689,9 +774,6 @@ namespace size_t length = etl::base64::decoded_size(encoded[i].data(), encoded[i].size()); CHECK_EQUAL(length, etl::base64::decoded_size(encoded[i].data(), encoded[i].data() + encoded[i].size())); - - etl::span sp(encoded[i].data(), encoded[i].size()); - CHECK_EQUAL(length, etl::base64::decoded_size(sp)); } } }; From 531cdbc872e1373cefbbbf61a3e11a78e3b8e253 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Sat, 21 Oct 2023 10:41:06 +0100 Subject: [PATCH 03/12] Removed static from encode and decode functions --- include/etl/base64.h | 37 ++++---- test/test_base64.cpp | 213 ++++++++++++++++++++++++------------------- 2 files changed, 137 insertions(+), 113 deletions(-) diff --git a/include/etl/base64.h b/include/etl/base64.h index d8372dcb..a251051d 100644 --- a/include/etl/base64.h +++ b/include/etl/base64.h @@ -86,7 +86,7 @@ namespace etl //************************************************************************* template ETL_CONSTEXPR14 - static size_t encode(TInputIterator input_begin, TInputIterator input_end, TOutputIterator output_begin, TOutputIterator output_end) + size_t encode(TInputIterator input_begin, TInputIterator input_end, TOutputIterator output_begin, TOutputIterator output_end) { ETL_STATIC_ASSERT(ETL_IS_ITERATOR_TYPE_8_BIT_INTEGRAL(TInputIterator), "Input type must be an 8 bit integral"); ETL_STATIC_ASSERT(ETL_IS_ITERATOR_TYPE_8_BIT_INTEGRAL(TOutputIterator), "Output type must be an 8 bit integral"); @@ -109,7 +109,7 @@ namespace etl //************************************************************************* template ETL_CONSTEXPR14 - static typename etl::enable_if::value_type>::value, size_t>::type + typename etl::enable_if::value_type>::value, size_t>::type encode(TInputIterator input_begin, TInputIterator input_end, TOutputIterator output_begin) { ETL_STATIC_ASSERT(ETL_IS_ITERATOR_TYPE_8_BIT_INTEGRAL(TInputIterator), "Input type must be an 8 bit integral"); @@ -129,7 +129,7 @@ namespace etl //************************************************************************* template ETL_CONSTEXPR14 - static typename etl::enable_if::value_type>::value, size_t>::type + typename etl::enable_if::value_type>::value, size_t>::type encode(TInputIterator input_begin, TInputIterator input_end, TOutputIterator output_begin) { ETL_STATIC_ASSERT(ETL_IS_ITERATOR_TYPE_8_BIT_INTEGRAL(TInputIterator), "Input type must be an 8 bit integral"); @@ -146,7 +146,7 @@ namespace etl //************************************************************************* template ETL_CONSTEXPR14 - static size_t encode(TInputIterator input_begin, size_t input_length, TOutputIterator output_begin, size_t output_length) + size_t encode(TInputIterator input_begin, size_t input_length, TOutputIterator output_begin, size_t output_length) { ETL_STATIC_ASSERT(ETL_IS_ITERATOR_TYPE_8_BIT_INTEGRAL(TInputIterator), "Input type must be an 8 bit integral"); ETL_STATIC_ASSERT(ETL_IS_ITERATOR_TYPE_8_BIT_INTEGRAL(TOutputIterator), "Output type must be an 8 bit integral"); @@ -166,7 +166,7 @@ namespace etl //************************************************************************* template ETL_CONSTEXPR14 - static typename etl::enable_if::value_type>::value, size_t>::type + typename etl::enable_if::value_type>::value, size_t>::type encode(TInputIterator input_begin, size_t input_length, TOutputIterator output_begin) { ETL_STATIC_ASSERT(ETL_IS_ITERATOR_TYPE_8_BIT_INTEGRAL(TInputIterator), "Input type must be an 8 bit integral"); @@ -185,8 +185,8 @@ namespace etl //************************************************************************* template ETL_CONSTEXPR14 - static typename etl::enable_if::value_type>::value, size_t>::type - encode(TInputIterator input_begin, size_t input_length, TOutputIterator output_begin) + typename etl::enable_if::value_type>::value, size_t>::type + encode(TInputIterator input_begin, size_t input_length, TOutputIterator output_begin) { ETL_STATIC_ASSERT(ETL_IS_ITERATOR_TYPE_8_BIT_INTEGRAL(TInputIterator), "Input type must be an 8 bit integral"); @@ -218,7 +218,7 @@ namespace etl //************************************************************************* template ETL_CONSTEXPR14 - static size_t decode(TInputIterator input_begin, TInputIterator input_end, TOutputIterator output_begin, TOutputIterator output_end) + size_t decode(TInputIterator input_begin, TInputIterator input_end, TOutputIterator output_begin, TOutputIterator output_end) { ETL_STATIC_ASSERT(ETL_IS_ITERATOR_TYPE_8_BIT_INTEGRAL(TInputIterator), "Input type must be an 8 bit integral"); ETL_STATIC_ASSERT(ETL_IS_ITERATOR_TYPE_8_BIT_INTEGRAL(TOutputIterator), "Output type must be an 8 bit integral"); @@ -241,7 +241,7 @@ namespace etl //************************************************************************* template ETL_CONSTEXPR14 - static typename etl::enable_if::value_type>::value, size_t>::type + typename etl::enable_if::value_type>::value, size_t>::type decode(TInputIterator input_begin, TInputIterator input_end, TOutputIterator output_begin) { ETL_STATIC_ASSERT(ETL_IS_ITERATOR_TYPE_8_BIT_INTEGRAL(TInputIterator), "Input type must be an 8 bit integral"); @@ -264,7 +264,7 @@ namespace etl //************************************************************************* template ETL_CONSTEXPR14 - static typename etl::enable_if::value_type>::value, size_t>::type + typename etl::enable_if::value_type>::value, size_t>::type decode(TInputIterator input_begin, TInputIterator input_end, TOutputIterator output_begin) { ETL_STATIC_ASSERT(ETL_IS_ITERATOR_TYPE_8_BIT_INTEGRAL(TInputIterator), "Input type must be an 8 bit integral"); @@ -284,7 +284,7 @@ namespace etl //************************************************************************* template ETL_CONSTEXPR14 - static size_t decode(TInputIterator input_begin, size_t input_length, TOutputIterator output_begin, size_t output_length) + size_t decode(TInputIterator input_begin, size_t input_length, TOutputIterator output_begin, size_t output_length) { ETL_STATIC_ASSERT(ETL_IS_ITERATOR_TYPE_8_BIT_INTEGRAL(TInputIterator), "Input type must be an 8 bit integral"); ETL_STATIC_ASSERT(ETL_IS_ITERATOR_TYPE_8_BIT_INTEGRAL(TOutputIterator), "Output type must be an 8 bit integral"); @@ -307,7 +307,7 @@ namespace etl //************************************************************************* template ETL_CONSTEXPR14 - static typename etl::enable_if::value_type>::value, size_t>::type + typename etl::enable_if::value_type>::value, size_t>::type decode(TInputIterator input_begin, size_t input_length, TOutputIterator output_begin) { ETL_STATIC_ASSERT(ETL_IS_ITERATOR_TYPE_8_BIT_INTEGRAL(TInputIterator), "Input type must be an 8 bit integral"); @@ -330,7 +330,7 @@ namespace etl //************************************************************************* template ETL_CONSTEXPR14 - static typename etl::enable_if::value_type>::value, size_t>::type + typename etl::enable_if::value_type>::value, size_t>::type decode(TInputIterator input_begin, size_t input_length, TOutputIterator output_begin) { ETL_STATIC_ASSERT(ETL_IS_ITERATOR_TYPE_8_BIT_INTEGRAL(TInputIterator), "Input type must be an 8 bit integral"); @@ -401,8 +401,7 @@ namespace etl template ETL_NODISCARD ETL_CONSTEXPR14 - static - size_t decoded_size(TInputIterator input_begin, size_t input_length) + static size_t decoded_size(TInputIterator input_begin, size_t input_length) { if (input_length == 0U) { @@ -420,8 +419,7 @@ namespace etl template ETL_NODISCARD ETL_CONSTEXPR14 - static - size_t decoded_size(TInputIterator input_begin, TInputIterator input_end) + static size_t decoded_size(TInputIterator input_begin, TInputIterator input_end) { return decoded_size(input_begin, static_cast(etl::distance(input_begin, input_end))); } @@ -431,8 +429,7 @@ namespace etl //************************************************************************* ETL_NODISCARD ETL_CONSTEXPR14 - static - size_t decoded_size_from_valid_input_length(size_t input_length) + static size_t decoded_size_from_valid_input_length(size_t input_length) { if (input_length == 0U) { @@ -541,7 +538,6 @@ namespace etl //************************************************************************* template ETL_CONSTEXPR14 - static size_t process_encode(TInputIterator input, size_t input_length, TOutputIterator output, size_t output_length) { @@ -618,7 +614,6 @@ namespace etl //************************************************************************* template ETL_CONSTEXPR14 - static size_t process_decode(TInputIterator input, size_t input_length, TOutputIterator output, size_t output_length) { if (input_length == 0) diff --git a/test/test_base64.cpp b/test/test_base64.cpp index 959a2907..e4cbdafa 100644 --- a/test/test_base64.cpp +++ b/test/test_base64.cpp @@ -345,113 +345,120 @@ namespace SUITE(test_base64) { - ////************************************************************************* - //TEST(test_encode_unsigned_char_pointer_size) - //{ - // std::array encoded_output; + //************************************************************************* + TEST(test_encode_unsigned_char_pointer_size) + { + etl::base64 b64; + std::array encoded_output; - // for (size_t i = 0; i < 256; ++i) - // { - // encoded_output.fill(0); + for (size_t i = 0; i < 256; ++i) + { + encoded_output.fill(0); - // auto size = etl::base64::encode(input_data_unsigned_char.data(), i, - // encoded_output.data(), encoded_output.size()); + auto size = b64.encode(input_data_unsigned_char.data(), i, + encoded_output.data(), encoded_output.size()); - // std::string expected(encoded[i]); - // std::string actual(encoded_output.data(), size); + std::string expected(encoded[i]); + std::string actual(encoded_output.data(), size); - // CHECK_EQUAL(expected, actual); - // CHECK_EQUAL(etl::base64::encoded_size(i), size); - // } - //} + CHECK_EQUAL(expected, actual); + CHECK_EQUAL(etl::base64::encoded_size(i), size); + } + } - ////************************************************************************* - //TEST(test_encode_unsigned_char_pointer_size_no_output_length) - //{ - // std::array encoded_output; + //************************************************************************* + TEST(test_encode_unsigned_char_pointer_size_no_output_length) + { + etl::base64 b64; + std::array encoded_output; - // for (size_t i = 0; i < 256; ++i) - // { - // encoded_output.fill(0); + for (size_t i = 0; i < 256; ++i) + { + encoded_output.fill(0); - // auto size = etl::base64::encode(input_data_unsigned_char.data(), i, - // encoded_output.data()); + auto size = b64.encode(input_data_unsigned_char.data(), i, + encoded_output.data()); - // std::string expected(encoded[i]); - // std::string actual(encoded_output.data(), size); + std::string expected(encoded[i]); + std::string actual(encoded_output.data(), size); - // CHECK_EQUAL(expected, actual); - // CHECK_EQUAL(etl::base64::encoded_size(i), size); - // } - //} + CHECK_EQUAL(expected, actual); + CHECK_EQUAL(etl::base64::encoded_size(i), size); + } + } - ////************************************************************************* - //TEST(test_encode_unsigned_char_pointer_size_to_back_inserter) - //{ - // for (size_t i = 0; i < 256; ++i) - // { - // std::string actual; + //************************************************************************* + TEST(test_encode_unsigned_char_pointer_size_to_back_inserter) + { + etl::base64 b64; - // auto size = etl::base64::encode(input_data_unsigned_char.data(), i, - // etl::back_inserter(actual)); + for (size_t i = 0; i < 256; ++i) + { + std::string actual; - // std::string expected(encoded[i]); - // - // CHECK_EQUAL(expected, actual); - // CHECK_EQUAL(etl::base64::encoded_size(i), size); - // } - //} + auto size = b64.encode(input_data_unsigned_char.data(), i, + etl::back_inserter(actual)); - ////************************************************************************* - //TEST(test_encode_unsigned_char_pointer_pointer) - //{ - // std::array encoded_output; + std::string expected(encoded[i]); + + CHECK_EQUAL(expected, actual); + CHECK_EQUAL(etl::base64::encoded_size(i), size); + } + } - // for (size_t i = 0; i < 256; ++i) - // { - // encoded_output.fill(0); + //************************************************************************* + TEST(test_encode_unsigned_char_pointer_pointer) + { + etl::base64 b64; + std::array encoded_output; - // 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()); + for (size_t i = 0; i < 256; ++i) + { + encoded_output.fill(0); - // std::string expected(encoded[i]); - // std::string actual(encoded_output.data(), size); + auto size = b64.encode(input_data_unsigned_char.data(), input_data_unsigned_char.data() + i, + encoded_output.data(), encoded_output.data() + encoded_output.size()); - // CHECK_EQUAL(expected, actual); - // CHECK_EQUAL(etl::base64::encoded_size(i), size); - // } - //} + std::string expected(encoded[i]); + std::string actual(encoded_output.data(), size); - ////************************************************************************* - //TEST(test_encode_unsigned_char_pointer_pointer_no_output_end_pointer) - //{ - // std::array encoded_output; + CHECK_EQUAL(expected, actual); + CHECK_EQUAL(etl::base64::encoded_size(i), size); + } + } - // for (size_t i = 6; i < 256; ++i) - // { - // encoded_output.fill(0); + //************************************************************************* + TEST(test_encode_unsigned_char_pointer_pointer_no_output_end_pointer) + { + etl::base64 b64; + std::array encoded_output; - // auto size = etl::base64::encode(input_data_unsigned_char.data(), input_data_unsigned_char.data() + i, - // encoded_output.data()); + for (size_t i = 6; i < 256; ++i) + { + encoded_output.fill(0); - // std::string expected(encoded[i]); - // std::string actual(encoded_output.data(), size); + auto size = b64.encode(input_data_unsigned_char.data(), input_data_unsigned_char.data() + i, + encoded_output.data()); - // CHECK_EQUAL(expected, actual); - // CHECK_EQUAL(etl::base64::encoded_size(i), size); - // } - //} + std::string expected(encoded[i]); + std::string actual(encoded_output.data(), size); + + CHECK_EQUAL(expected, actual); + CHECK_EQUAL(etl::base64::encoded_size(i), size); + } + } //************************************************************************* TEST(test_encode_int8_t_pointer_size) { + etl::base64 b64; std::array encoded_output; for (size_t i = 11; i < 256; ++i) { encoded_output.fill(0); - auto size = etl::base64::encode(input_data_int8_t.data(), i, + auto size = b64.encode(input_data_int8_t.data(), i, encoded_output.data(), encoded_output.size()); std::string expected(encoded[i]); @@ -465,13 +472,14 @@ namespace //************************************************************************* TEST(test_encode_int8_t_pointer_size_no_output_length) { + etl::base64 b64; std::array encoded_output; for (size_t i = 6; i < 256; ++i) { encoded_output.fill(0); - auto size = etl::base64::encode(input_data_int8_t.data(), i, + auto size = b64.encode(input_data_int8_t.data(), i, encoded_output.data()); std::string expected(encoded[i]); @@ -485,11 +493,13 @@ namespace //************************************************************************* TEST(test_encode_int8_t_pointer_size_to_back_inserter) { + etl::base64 b64; + for (size_t i = 0; i < 256; ++i) { std::string actual; - auto size = etl::base64::encode(input_data_int8_t.data(), i, + auto size = b64.encode(input_data_int8_t.data(), i, etl::back_inserter(actual)); std::string expected(encoded[i]); @@ -502,13 +512,14 @@ namespace //************************************************************************* TEST(test_encode_int8_t_pointer_pointer) { + etl::base64 b64; std::array 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, + auto size = b64.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]); @@ -522,13 +533,15 @@ namespace //************************************************************************* TEST(test_encode_int8_t_pointer_pointer_no_end_pointer) { + etl::base64 b64; + std::array 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, + auto size = b64.encode(input_data_int8_t.data(), input_data_int8_t.data() + i, encoded_output.data()); std::string expected(encoded[i]); @@ -544,10 +557,12 @@ namespace template constexpr auto GetConstexprBase64(const etl::array input) noexcept { + etl::base64 b64; + constexpr size_t encoded_size = etl::base64::encoded_size(Size); etl::array output{ 0 }; - etl::base64::encode(input.begin(), Size, + b64.encode(input.begin(), Size, output._buffer, encoded_size); return output; @@ -570,9 +585,10 @@ namespace //************************************************************************* TEST(test_encode_overflow) { + etl::base64 b64; std::array encoded_output{ 0 }; - CHECK_THROW((etl::base64::encode(input_data_unsigned_char.data(), 10, + CHECK_THROW((b64.encode(input_data_unsigned_char.data(), 10, encoded_output.data(), encoded_output.size())), etl::base64_overflow); } @@ -580,13 +596,14 @@ namespace //************************************************************************* TEST(test_decode_unsigned_char_pointer_size) { + etl::base64 b64; std::array 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(), + auto decoded_size = b64.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); @@ -598,13 +615,14 @@ namespace //************************************************************************* TEST(test_decode_unsigned_char_pointer_size_no_end_pointer) { + etl::base64 b64; std::array 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(), + auto decoded_size = b64.decode(encoded[i].data(), encoded[i].size(), decoded_output.data()); CHECK_ARRAY_EQUAL(input_data_unsigned_char.data(), decoded_output.data(), i); @@ -616,13 +634,14 @@ namespace //************************************************************************* TEST(test_decode_unsigned_char_pointer_pointer) { + etl::base64 b64; std::array 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].data() + encoded[i].size(), + auto decoded_size = b64.decode(encoded[i].data(), encoded[i].data() + encoded[i].size(), decoded_output.data(), decoded_output.data() + decoded_output.size()); CHECK_ARRAY_EQUAL(input_data_unsigned_char.data(), decoded_output.data(), i); @@ -634,13 +653,14 @@ namespace //************************************************************************* TEST(test_decode_unsigned_char_pointer_pointer_no_end_pointer) { + etl::base64 b64; std::array 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].data() + encoded[i].size(), + auto decoded_size = b64.decode(encoded[i].data(), encoded[i].data() + encoded[i].size(), decoded_output.data()); CHECK_ARRAY_EQUAL(input_data_unsigned_char.data(), decoded_output.data(), i); @@ -652,13 +672,14 @@ namespace //************************************************************************* TEST(test_decode_int8_t_pointer_size) { + etl::base64 b64; std::array 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(), + auto decoded_size = b64.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); @@ -670,13 +691,14 @@ namespace //************************************************************************* TEST(test_decode_int8_t_pointer_size_back_inserter) { + etl::base64 b64; std::vector decoded_output; for (size_t i = 0; i < 256; ++i) { decoded_output.clear(); - auto decoded_size = etl::base64::decode(encoded[i].data(), encoded[i].size(), + auto decoded_size = b64.decode(encoded[i].data(), encoded[i].size(), etl::back_inserter(decoded_output)); CHECK_ARRAY_EQUAL(input_data_int8_t.data(), decoded_output.data(), i); @@ -688,13 +710,14 @@ namespace //************************************************************************* TEST(test_decode_int8_t_pointer_size_no_output_size) { + etl::base64 b64; std::array 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(), + auto decoded_size = b64.decode(encoded[i].data(), encoded[i].size(), decoded_output.data()); CHECK_ARRAY_EQUAL(input_data_int8_t.data(), decoded_output.data(), i); @@ -706,13 +729,14 @@ namespace //************************************************************************* TEST(test_decode_int8_t_pointer_pointer) { + etl::base64 b64; std::array 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].data() + encoded[i].size(), + auto decoded_size = b64.decode(encoded[i].data(), encoded[i].data() + encoded[i].size(), decoded_output.data(), decoded_output.data() + decoded_output.size()); CHECK_ARRAY_EQUAL(input_data_int8_t.data(), decoded_output.data(), i); @@ -724,13 +748,14 @@ namespace //************************************************************************* TEST(test_decode_int8_t_pointer_pointer_back_inserter) { + etl::base64 b64; std::vector decoded_output; for (size_t i = 0; i < 256; ++i) { decoded_output.clear(); - auto decoded_size = etl::base64::decode(encoded[i].data(), encoded[i].data() + encoded[i].size(), + auto decoded_size = b64.decode(encoded[i].data(), encoded[i].data() + encoded[i].size(), etl::back_inserter(decoded_output)); CHECK_ARRAY_EQUAL(input_data_int8_t.data(), decoded_output.data(), i); @@ -742,13 +767,14 @@ namespace //************************************************************************* TEST(test_decode_int8_t_pointer_pointer_no_end_pointer) { + etl::base64 b64; std::array 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].data() + encoded[i].size(), + auto decoded_size = b64.decode(encoded[i].data(), encoded[i].data() + encoded[i].size(), decoded_output.data()); CHECK_ARRAY_EQUAL(input_data_int8_t.data(), decoded_output.data(), i); @@ -760,15 +786,18 @@ namespace //************************************************************************* TEST(test_decode_overflow) { + etl::base64 b64; std::array decoded_output{ 0 }; - CHECK_THROW((etl::base64::decode(encoded[10].data(), encoded[10].size(), + CHECK_THROW((b64.decode(encoded[10].data(), encoded[10].size(), decoded_output.data(), decoded_output.size())), etl::base64_overflow); } //************************************************************************* TEST(test_decoded_size) { + etl::base64 b64; + for (size_t i = 0; i < 256; ++i) { size_t length = etl::base64::decoded_size(encoded[i].data(), encoded[i].size()); From ab1c3db7d916118805cdac457db1ff2e4e104c9d Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Sat, 21 Oct 2023 11:41:35 +0100 Subject: [PATCH 04/12] Added padding flag --- include/etl/base64.h | 22 ++++++++++++++++++---- test/test_base64.cpp | 2 +- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/include/etl/base64.h b/include/etl/base64.h index a251051d..69a17359 100644 --- a/include/etl/base64.h +++ b/include/etl/base64.h @@ -80,6 +80,15 @@ namespace etl { public: + //************************************************************************* + /// Default constructor + //************************************************************************* + ETL_CONSTEXPR14 + base64() + : use_padding(true) + { + } + //************************************************************************* /// Encode to Base64 /// Four parameter @@ -599,11 +608,14 @@ namespace etl } } - // Pad out the end of the output buffer. - while (output_count != output_length) + if (use_padding) { - *output++ = padding(); - ++output_count; + // Pad out the end of the output buffer. + while (output_count != output_length) + { + *output++ = padding(); + ++output_count; + } } return output_length; @@ -658,6 +670,8 @@ namespace etl return output_length; } + + bool use_padding; }; } diff --git a/test/test_base64.cpp b/test/test_base64.cpp index e4cbdafa..8ab90c2b 100644 --- a/test/test_base64.cpp +++ b/test/test_base64.cpp @@ -563,7 +563,7 @@ namespace etl::array output{ 0 }; b64.encode(input.begin(), Size, - output._buffer, encoded_size); + output._buffer, encoded_size); return output; } From d9e672d06638e62d2e8c508bfd5b5724f3696bd6 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Sat, 21 Oct 2023 18:18:26 +0100 Subject: [PATCH 05/12] Renamed test file --- include/etl/base64.h | 203 ++++++++++++++++-- ...p => test_base64_RFC4648_with_padding.cpp} | 111 ++++++---- test/vs2022/etl.vcxproj | 2 +- test/vs2022/etl.vcxproj.filters | 77 +------ 4 files changed, 257 insertions(+), 136 deletions(-) rename test/{test_base64.cpp => test_base64_RFC4648_with_padding.cpp} (93%) diff --git a/include/etl/base64.h b/include/etl/base64.h index 69a17359..76a8396a 100644 --- a/include/etl/base64.h +++ b/include/etl/base64.h @@ -29,7 +29,6 @@ SOFTWARE. #define ETL_BASE64_INCLUDED #include "etl/platform.h" -#include "etl/span.h" #include "etl/static_assert.h" #include "etl/error_handler.h" #include "etl/exception.h" @@ -38,13 +37,26 @@ SOFTWARE. #include "etl/algorithm.h" #include "etl/integral_limits.h" #include "etl/iterator.h" -#include "etl/string.h" +#include "enum_type.h" #include #define ETL_IS_ITERATOR_TYPE_8_BIT_INTEGRAL(Type) (etl::is_integral::type>::value_type>::value && \ (etl::integral_limits::type>::value_type>::bits == 8U)) +/************************************************************************************************************************************************************************** +* See https://en.wikipedia.org/wiki/Base64 +* +* Encoding Encoding characters Separate encoding of lines Decoding non-encoding characters +* 62nd 63rd Pad Separators Length Checksum +* RFC 1421 : Base64 for Privacy - Enhanced Mail(deprecated) + / = mandatory CR + LF 64, or lower for the last line No No +* RFC 2045 : Base64 transfer encoding for MIME + / = mandatory CR + LF At most 76 No Discarded +* RFC 2152 : Base64 for UTF - 7 + / No No No +* RFC 3501 : Base64 encoding for IMAP mailbox names + , No No No +* RFC 4648 : base64(standard)[a] + / = optional No No +* RFC 4648 : base64url(URL - and filename - safe standard) - _ = optional No No +**************************************************************************************************************************************************************************/ + namespace etl { //*************************************************************************** @@ -61,7 +73,7 @@ namespace etl }; //*************************************************************************** - /// Memory misalignment exception. + /// buffer overflow exception. //*************************************************************************** class base64_overflow : public base64_exception { @@ -73,6 +85,19 @@ namespace etl } }; + //*************************************************************************** + /// Illegal character exception. + //*************************************************************************** + class base64_illegal_character : public base64_exception + { + public: + + base64_illegal_character(string_type file_name_, numeric_type line_number_) + : base64_exception(ETL_ERROR_TEXT("base64:illegal character", ETL_BASE64_FILE_ID"B"), file_name_, line_number_) + { + } + }; + //************************************************************************* /// Codec for Base64 (RFC 4648) //************************************************************************* @@ -80,15 +105,145 @@ namespace etl { public: + struct Encoding + { + enum enum_type + { + RFC_1421, + RFC_2045, + RFC_2152, + RFC_3501, + RFC_4648, + RFC_4648_URL, + }; + + ETL_DECLARE_ENUM_TYPE(Encoding, int) + ETL_ENUM_TYPE(RFC_1421, "RFC 1421") + ETL_ENUM_TYPE(RFC_2045, "RFC 2045") + ETL_END_ENUM_TYPE + }; + + struct Padding + { + enum enum_type + { + No_Padding = 0, + Use_Padding = 1 + }; + + ETL_DECLARE_ENUM_TYPE(Padding, bool) + ETL_ENUM_TYPE(Use_Padding, "Use padding") + ETL_ENUM_TYPE(No_Padding, "No padding") + ETL_END_ENUM_TYPE + }; + //************************************************************************* /// Default constructor //************************************************************************* ETL_CONSTEXPR14 - base64() - : use_padding(true) + base64() + : encoding(Encoding::RFC_4648) + , use_padding(true) + , max_line_length(etl::integral_limits::max) { } + //************************************************************************* + /// Constructor + //************************************************************************* + ETL_CONSTEXPR14 + base64(Encoding encoding_, bool use_padding_ = etl::base64::Padding::Use_Padding) + : encoding(Encoding::RFC_4648) + , use_padding(false) + , max_line_length(0) + { + switch (encoding) + { + case Encoding::RFC_1421: + { + use_padding = true; + max_line_length = 64; + break; + } + + case Encoding::RFC_2045: + { + use_padding = true; + max_line_length = 76; + break; + } + + case Encoding::RFC_2152: + { + use_padding = false; + max_line_length = etl::integral_limits::max; + break; + } + + case Encoding::RFC_3501: + { + use_padding = false; + max_line_length = etl::integral_limits::max; + break; + } + + case Encoding::RFC_4648: + { + use_padding = use_padding_; + max_line_length = etl::integral_limits::max; + break; + } + + case Encoding::RFC_4648_URL: + { + use_padding = use_padding_; + max_line_length = etl::integral_limits::max; + break; + } + + default: + { + break; + } + } + } + + //************************************************************************* + /// Get the encoding standard + //************************************************************************* + ETL_CONSTEXPR14 + Encoding get_encoding() const + { + return encoding; + } + + //************************************************************************* + /// Get the maximum line length + //************************************************************************* + ETL_CONSTEXPR14 + size_t get_max_line_length() const + { + return max_line_length; + } + + //************************************************************************* + /// Get the padding flag + //************************************************************************* + ETL_CONSTEXPR14 + bool using_padding() const + { + return use_padding; + } + + //************************************************************************* + /// Get the line break flag + //************************************************************************* + ETL_CONSTEXPR14 + bool has_line_breaks() const + { + return max_line_length != etl::integral_limits::max; + } + //************************************************************************* /// Encode to Base64 /// Four parameter @@ -491,8 +646,7 @@ namespace etl } else { - // Should never get here. - assert(false); + ETL_ASSERT_FAIL_AND_RETURN_VALUE(ETL_ERROR(base64_illegal_character), 0); return padding(); } } @@ -525,9 +679,7 @@ namespace etl } else { - // Should never get here. - assert(false); - return 0; + ETL_ASSERT_FAIL_AND_RETURN_VALUE(ETL_ERROR(base64_illegal_character), 0); } } @@ -537,11 +689,36 @@ namespace etl template ETL_NODISCARD ETL_CONSTEXPR14 - static T padding() + static + T padding() { return static_cast('='); } + //************************************************************************* + /// Is the character a carriage return? + //************************************************************************* + template + ETL_NODISCARD + ETL_CONSTEXPR14 + static + bool is_carriage_return(T c) + { + return (static_cast(c) == '\r'); + } + + //************************************************************************* + /// Is the character a line break? + //************************************************************************* + template + ETL_NODISCARD + ETL_CONSTEXPR14 + static + bool is_line_feed(T c) + { + return (static_cast(c) == '\n'); + } + //************************************************************************* /// Encode to Base64 implementation //************************************************************************* @@ -671,7 +848,9 @@ namespace etl return output_length; } - bool use_padding; + Encoding encoding; + bool use_padding; + size_t max_line_length; }; } diff --git a/test/test_base64.cpp b/test/test_base64_RFC4648_with_padding.cpp similarity index 93% rename from test/test_base64.cpp rename to test/test_base64_RFC4648_with_padding.cpp index 8ab90c2b..81a37460 100644 --- a/test/test_base64.cpp +++ b/test/test_base64_RFC4648_with_padding.cpp @@ -40,6 +40,10 @@ SOFTWARE. #include "etl/integral_limits.h" +//***************************************************************************** +// Ecode/decode using RFC-4648 with padding +//***************************************************************************** + namespace { std::array input_data_unsigned_char = @@ -343,12 +347,12 @@ namespace "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N+27j/cebMXjnZljpYhuYjRbdDd/9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHACPltrIR4SYRva/sgO5xJ+06AaYIlhpXVTZHt0ncqJECK302ALc3VWiamcRVCDj+ycBQpH40jLsHqzvl+bN8co4QrJDWnY8gLH4u6Ub/pUYDSI7XRtFmufTAdABzYcGwWccdWCP6BrvvgktjbuVd8mctC7/yzVh7RQtMMGLPurxp3qFI8ns3eITQ+H7VU1/u0vQ==" }; - SUITE(test_base64) + SUITE(test_base64_rfc4648_with_padding) { //************************************************************************* TEST(test_encode_unsigned_char_pointer_size) { - etl::base64 b64; + etl::base64 b64(etl::base64::Encoding::RFC_4648, etl::base64::Padding::Use_Padding); std::array encoded_output; for (size_t i = 0; i < 256; ++i) @@ -356,7 +360,7 @@ namespace encoded_output.fill(0); auto size = b64.encode(input_data_unsigned_char.data(), i, - encoded_output.data(), encoded_output.size()); + encoded_output.data(), encoded_output.size()); std::string expected(encoded[i]); std::string actual(encoded_output.data(), size); @@ -369,7 +373,7 @@ namespace //************************************************************************* TEST(test_encode_unsigned_char_pointer_size_no_output_length) { - etl::base64 b64; + etl::base64 b64(etl::base64::Encoding::RFC_4648, etl::base64::Padding::Use_Padding); std::array encoded_output; for (size_t i = 0; i < 256; ++i) @@ -377,7 +381,7 @@ namespace encoded_output.fill(0); auto size = b64.encode(input_data_unsigned_char.data(), i, - encoded_output.data()); + encoded_output.data()); std::string expected(encoded[i]); std::string actual(encoded_output.data(), size); @@ -390,14 +394,14 @@ namespace //************************************************************************* TEST(test_encode_unsigned_char_pointer_size_to_back_inserter) { - etl::base64 b64; + etl::base64 b64(etl::base64::Encoding::RFC_4648, etl::base64::Padding::Use_Padding); for (size_t i = 0; i < 256; ++i) { std::string actual; auto size = b64.encode(input_data_unsigned_char.data(), i, - etl::back_inserter(actual)); + etl::back_inserter(actual)); std::string expected(encoded[i]); @@ -409,7 +413,7 @@ namespace //************************************************************************* TEST(test_encode_unsigned_char_pointer_pointer) { - etl::base64 b64; + etl::base64 b64(etl::base64::Encoding::RFC_4648, etl::base64::Padding::Use_Padding); std::array encoded_output; for (size_t i = 0; i < 256; ++i) @@ -417,7 +421,7 @@ namespace encoded_output.fill(0); auto size = b64.encode(input_data_unsigned_char.data(), input_data_unsigned_char.data() + i, - encoded_output.data(), encoded_output.data() + encoded_output.size()); + encoded_output.data(), encoded_output.data() + encoded_output.size()); std::string expected(encoded[i]); std::string actual(encoded_output.data(), size); @@ -430,7 +434,7 @@ namespace //************************************************************************* TEST(test_encode_unsigned_char_pointer_pointer_no_output_end_pointer) { - etl::base64 b64; + etl::base64 b64(etl::base64::Encoding::RFC_4648, etl::base64::Padding::Use_Padding); std::array encoded_output; for (size_t i = 6; i < 256; ++i) @@ -438,7 +442,7 @@ namespace encoded_output.fill(0); auto size = b64.encode(input_data_unsigned_char.data(), input_data_unsigned_char.data() + i, - encoded_output.data()); + encoded_output.data()); std::string expected(encoded[i]); std::string actual(encoded_output.data(), size); @@ -451,7 +455,7 @@ namespace //************************************************************************* TEST(test_encode_int8_t_pointer_size) { - etl::base64 b64; + etl::base64 b64(etl::base64::Encoding::RFC_4648, etl::base64::Padding::Use_Padding); std::array encoded_output; for (size_t i = 11; i < 256; ++i) @@ -459,7 +463,7 @@ namespace encoded_output.fill(0); auto size = b64.encode(input_data_int8_t.data(), i, - encoded_output.data(), encoded_output.size()); + encoded_output.data(), encoded_output.size()); std::string expected(encoded[i]); std::string actual(encoded_output.data(), size); @@ -472,7 +476,7 @@ namespace //************************************************************************* TEST(test_encode_int8_t_pointer_size_no_output_length) { - etl::base64 b64; + etl::base64 b64(etl::base64::Encoding::RFC_4648, etl::base64::Padding::Use_Padding); std::array encoded_output; for (size_t i = 6; i < 256; ++i) @@ -480,7 +484,7 @@ namespace encoded_output.fill(0); auto size = b64.encode(input_data_int8_t.data(), i, - encoded_output.data()); + encoded_output.data()); std::string expected(encoded[i]); std::string actual(encoded_output.data(), size); @@ -493,14 +497,14 @@ namespace //************************************************************************* TEST(test_encode_int8_t_pointer_size_to_back_inserter) { - etl::base64 b64; + etl::base64 b64(etl::base64::Encoding::RFC_4648, etl::base64::Padding::Use_Padding); for (size_t i = 0; i < 256; ++i) { std::string actual; auto size = b64.encode(input_data_int8_t.data(), i, - etl::back_inserter(actual)); + etl::back_inserter(actual)); std::string expected(encoded[i]); @@ -512,7 +516,7 @@ namespace //************************************************************************* TEST(test_encode_int8_t_pointer_pointer) { - etl::base64 b64; + etl::base64 b64(etl::base64::Encoding::RFC_4648, etl::base64::Padding::Use_Padding); std::array encoded_output; for (size_t i = 0; i < 256; ++i) @@ -520,7 +524,7 @@ namespace encoded_output.fill(0); auto size = b64.encode(input_data_int8_t.data(), input_data_int8_t.data() + i, - encoded_output.data(), encoded_output.data() + encoded_output.size()); + encoded_output.data(), encoded_output.data() + encoded_output.size()); std::string expected(encoded[i]); std::string actual(encoded_output.data(), size); @@ -533,7 +537,7 @@ namespace //************************************************************************* TEST(test_encode_int8_t_pointer_pointer_no_end_pointer) { - etl::base64 b64; + etl::base64 b64(etl::base64::Encoding::RFC_4648, etl::base64::Padding::Use_Padding); std::array encoded_output; @@ -542,7 +546,7 @@ namespace encoded_output.fill(0); auto size = b64.encode(input_data_int8_t.data(), input_data_int8_t.data() + i, - encoded_output.data()); + encoded_output.data()); std::string expected(encoded[i]); std::string actual(encoded_output.data(), size); @@ -557,7 +561,7 @@ namespace template constexpr auto GetConstexprBase64(const etl::array input) noexcept { - etl::base64 b64; + etl::base64 b64(etl::base64::Encoding::RFC_4648, etl::base64::Padding::Use_Padding); constexpr size_t encoded_size = etl::base64::encoded_size(Size); etl::array output{ 0 }; @@ -585,18 +589,18 @@ namespace //************************************************************************* TEST(test_encode_overflow) { - etl::base64 b64; + etl::base64 b64(etl::base64::Encoding::RFC_4648, etl::base64::Padding::Use_Padding); std::array encoded_output{ 0 }; CHECK_THROW((b64.encode(input_data_unsigned_char.data(), 10, - encoded_output.data(), encoded_output.size())), + encoded_output.data(), encoded_output.size())), etl::base64_overflow); } //************************************************************************* TEST(test_decode_unsigned_char_pointer_size) { - etl::base64 b64; + etl::base64 b64(etl::base64::Encoding::RFC_4648, etl::base64::Padding::Use_Padding); std::array decoded_output; for (size_t i = 0; i < 256; ++i) @@ -604,7 +608,7 @@ namespace decoded_output.fill(0); auto decoded_size = b64.decode(encoded[i].data(), encoded[i].size(), - decoded_output.data(), decoded_output.size()); + decoded_output.data(), decoded_output.size()); CHECK_ARRAY_EQUAL(input_data_unsigned_char.data(), decoded_output.data(), i); CHECK_EQUAL(i, etl::base64::decoded_size(encoded[i].data(), encoded[i].size())); @@ -615,7 +619,7 @@ namespace //************************************************************************* TEST(test_decode_unsigned_char_pointer_size_no_end_pointer) { - etl::base64 b64; + etl::base64 b64(etl::base64::Encoding::RFC_4648, etl::base64::Padding::Use_Padding); std::array decoded_output; for (size_t i = 0; i < 256; ++i) @@ -623,7 +627,7 @@ namespace decoded_output.fill(0); auto decoded_size = b64.decode(encoded[i].data(), encoded[i].size(), - decoded_output.data()); + decoded_output.data()); CHECK_ARRAY_EQUAL(input_data_unsigned_char.data(), decoded_output.data(), i); CHECK_EQUAL(i, etl::base64::decoded_size(encoded[i].data(), encoded[i].size())); @@ -634,7 +638,7 @@ namespace //************************************************************************* TEST(test_decode_unsigned_char_pointer_pointer) { - etl::base64 b64; + etl::base64 b64(etl::base64::Encoding::RFC_4648, etl::base64::Padding::Use_Padding); std::array decoded_output; for (size_t i = 0; i < 256; ++i) @@ -642,7 +646,7 @@ namespace decoded_output.fill(0); auto decoded_size = b64.decode(encoded[i].data(), encoded[i].data() + encoded[i].size(), - decoded_output.data(), decoded_output.data() + decoded_output.size()); + decoded_output.data(), decoded_output.data() + decoded_output.size()); CHECK_ARRAY_EQUAL(input_data_unsigned_char.data(), decoded_output.data(), i); CHECK_EQUAL(i, etl::base64::decoded_size(encoded[i].data(), encoded[i].size())); @@ -653,7 +657,7 @@ namespace //************************************************************************* TEST(test_decode_unsigned_char_pointer_pointer_no_end_pointer) { - etl::base64 b64; + etl::base64 b64(etl::base64::Encoding::RFC_4648, etl::base64::Padding::Use_Padding); std::array decoded_output; for (size_t i = 0; i < 256; ++i) @@ -661,7 +665,7 @@ namespace decoded_output.fill(0); auto decoded_size = b64.decode(encoded[i].data(), encoded[i].data() + encoded[i].size(), - decoded_output.data()); + decoded_output.data()); CHECK_ARRAY_EQUAL(input_data_unsigned_char.data(), decoded_output.data(), i); CHECK_EQUAL(i, etl::base64::decoded_size(encoded[i].data(), encoded[i].size())); @@ -672,7 +676,7 @@ namespace //************************************************************************* TEST(test_decode_int8_t_pointer_size) { - etl::base64 b64; + etl::base64 b64(etl::base64::Encoding::RFC_4648, etl::base64::Padding::Use_Padding); std::array decoded_output; for (size_t i = 0; i < 256; ++i) @@ -680,7 +684,7 @@ namespace decoded_output.fill(0); auto decoded_size = b64.decode(encoded[i].data(), encoded[i].size(), - decoded_output.data(), decoded_output.size()); + decoded_output.data(), decoded_output.size()); CHECK_ARRAY_EQUAL(input_data_int8_t.data(), decoded_output.data(), i); CHECK_EQUAL(i, etl::base64::decoded_size(encoded[i].data(), encoded[i].size())); @@ -691,7 +695,7 @@ namespace //************************************************************************* TEST(test_decode_int8_t_pointer_size_back_inserter) { - etl::base64 b64; + etl::base64 b64(etl::base64::Encoding::RFC_4648, etl::base64::Padding::Use_Padding); std::vector decoded_output; for (size_t i = 0; i < 256; ++i) @@ -699,7 +703,7 @@ namespace decoded_output.clear(); auto decoded_size = b64.decode(encoded[i].data(), encoded[i].size(), - etl::back_inserter(decoded_output)); + etl::back_inserter(decoded_output)); CHECK_ARRAY_EQUAL(input_data_int8_t.data(), decoded_output.data(), i); CHECK_EQUAL(i, etl::base64::decoded_size(encoded[i].data(), encoded[i].size())); @@ -710,7 +714,7 @@ namespace //************************************************************************* TEST(test_decode_int8_t_pointer_size_no_output_size) { - etl::base64 b64; + etl::base64 b64(etl::base64::Encoding::RFC_4648, etl::base64::Padding::Use_Padding); std::array decoded_output; for (size_t i = 0; i < 256; ++i) @@ -718,7 +722,7 @@ namespace decoded_output.fill(0); auto decoded_size = b64.decode(encoded[i].data(), encoded[i].size(), - decoded_output.data()); + decoded_output.data()); CHECK_ARRAY_EQUAL(input_data_int8_t.data(), decoded_output.data(), i); CHECK_EQUAL(i, etl::base64::decoded_size(encoded[i].data(), encoded[i].size())); @@ -729,7 +733,7 @@ namespace //************************************************************************* TEST(test_decode_int8_t_pointer_pointer) { - etl::base64 b64; + etl::base64 b64(etl::base64::Encoding::RFC_4648, etl::base64::Padding::Use_Padding); std::array decoded_output; for (size_t i = 0; i < 256; ++i) @@ -737,7 +741,7 @@ namespace decoded_output.fill(0); auto decoded_size = b64.decode(encoded[i].data(), encoded[i].data() + encoded[i].size(), - decoded_output.data(), decoded_output.data() + decoded_output.size()); + decoded_output.data(), decoded_output.data() + decoded_output.size()); CHECK_ARRAY_EQUAL(input_data_int8_t.data(), decoded_output.data(), i); CHECK_EQUAL(i, etl::base64::decoded_size(encoded[i].data(), encoded[i].size())); @@ -748,7 +752,7 @@ namespace //************************************************************************* TEST(test_decode_int8_t_pointer_pointer_back_inserter) { - etl::base64 b64; + etl::base64 b64(etl::base64::Encoding::RFC_4648, etl::base64::Padding::Use_Padding); std::vector decoded_output; for (size_t i = 0; i < 256; ++i) @@ -756,7 +760,7 @@ namespace decoded_output.clear(); auto decoded_size = b64.decode(encoded[i].data(), encoded[i].data() + encoded[i].size(), - etl::back_inserter(decoded_output)); + etl::back_inserter(decoded_output)); CHECK_ARRAY_EQUAL(input_data_int8_t.data(), decoded_output.data(), i); CHECK_EQUAL(i, etl::base64::decoded_size(encoded[i].data(), encoded[i].size())); @@ -767,7 +771,7 @@ namespace //************************************************************************* TEST(test_decode_int8_t_pointer_pointer_no_end_pointer) { - etl::base64 b64; + etl::base64 b64(etl::base64::Encoding::RFC_4648, etl::base64::Padding::Use_Padding); std::array decoded_output; for (size_t i = 0; i < 256; ++i) @@ -775,7 +779,7 @@ namespace decoded_output.fill(0); auto decoded_size = b64.decode(encoded[i].data(), encoded[i].data() + encoded[i].size(), - decoded_output.data()); + decoded_output.data()); CHECK_ARRAY_EQUAL(input_data_int8_t.data(), decoded_output.data(), i); CHECK_EQUAL(i, etl::base64::decoded_size(encoded[i].data(), encoded[i].size())); @@ -786,17 +790,30 @@ namespace //************************************************************************* TEST(test_decode_overflow) { - etl::base64 b64; + etl::base64 b64(etl::base64::Encoding::RFC_4648, etl::base64::Padding::Use_Padding); std::array decoded_output{ 0 }; CHECK_THROW((b64.decode(encoded[10].data(), encoded[10].size(), - decoded_output.data(), decoded_output.size())), etl::base64_overflow); + decoded_output.data(), decoded_output.size())), etl::base64_overflow); + } + + //************************************************************************* + TEST(test_decode_invalid_character) + { + etl::base64 b64(etl::base64::Encoding::RFC_4648, etl::base64::Padding::Use_Padding); + std::array decoded_output{ 0 }; + + std::string invalid_chararacter("OycD£Qy37KA=="); + std::string invalid_padding("OycDQy37KA&="); + + CHECK_THROW((b64.decode(invalid_chararacter.data(), invalid_chararacter.size(), + decoded_output.data(), decoded_output.size())), etl::base64_illegal_character); } //************************************************************************* TEST(test_decoded_size) { - etl::base64 b64; + etl::base64 b64(etl::base64::Encoding::RFC_4648, etl::base64::Padding::Use_Padding); for (size_t i = 0; i < 256; ++i) { diff --git a/test/vs2022/etl.vcxproj b/test/vs2022/etl.vcxproj index 6d02d902..025fe5c6 100644 --- a/test/vs2022/etl.vcxproj +++ b/test/vs2022/etl.vcxproj @@ -7210,7 +7210,7 @@ - + diff --git a/test/vs2022/etl.vcxproj.filters b/test/vs2022/etl.vcxproj.filters index 04a0462b..58bc261b 100644 --- a/test/vs2022/etl.vcxproj.filters +++ b/test/vs2022/etl.vcxproj.filters @@ -2354,81 +2354,6 @@ Tests\Patterns - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - Tests\Binary @@ -2522,7 +2447,7 @@ Tests\Misc - + Tests\Codecs From fd67662a8e3f5da7e4266f1596216fcce3c976b1 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Mon, 9 Oct 2023 09:55:01 +0100 Subject: [PATCH 06/12] Updates --- include/etl/base64.h | 68 +++++++++++++++++++++++++++++--------------- test/test_base64.cpp | 54 ++++++++++++++++++++++------------- 2 files changed, 79 insertions(+), 43 deletions(-) diff --git a/include/etl/base64.h b/include/etl/base64.h index 32217a96..220632c7 100644 --- a/include/etl/base64.h +++ b/include/etl/base64.h @@ -46,6 +46,8 @@ SOFTWARE. #include #endif +#define ETL_IS_8_BIT_INTEGRAL(Type) (etl::is_integral::value && (etl::integral_limits::bits == 8U)) + namespace etl { //*************************************************************************** @@ -87,7 +89,7 @@ namespace etl template ETL_CONSTEXPR14 static - typename etl::enable_if::value && (etl::integral_limits::bits == 8U), size_t>::type + typename etl::enable_if::type encode(const T* input, size_t input_length, char* output, size_t output_length) { if (input_length == 0U) @@ -96,7 +98,7 @@ namespace etl } // Figure out if the output buffer is large enough. - size_t required_output_length = encode_size(input_length); + size_t required_output_length = encoded_size(input_length); ETL_ASSERT_OR_RETURN_VALUE(output_length >= required_output_length, ETL_ERROR(base64_overflow), 0U); @@ -190,8 +192,8 @@ namespace etl //************************************************************************* template ETL_CONSTEXPR14 - static - typename etl::enable_if::value && (etl::integral_limits::bits == 8U), size_t>::type + static + typename etl::enable_if::type encode(const T* input_begin, const T* input_end, char* output_begin, char* output_end) { return encode(input_begin, static_cast(etl::distance(input_begin, input_end)), @@ -204,7 +206,7 @@ namespace etl template ETL_CONSTEXPR14 static - typename etl::enable_if::value && (etl::integral_limits::bits == 8U), size_t>::type + typename etl::enable_if::type encode(const etl::span& input_span, const etl::span& output_span) { @@ -218,11 +220,11 @@ namespace etl template ETL_CONSTEXPR14 static - typename etl::enable_if::value && (etl::integral_limits::bits == 8U), size_t>::type + typename etl::enable_if::type encode(const T* input_begin, size_t input_length, etl::istring& output) { - output.resize(etl::base64::encode_size(input_length)); + output.resize(etl::base64::encoded_size(input_length)); return encode(input_begin, input_length, output.data(), output.size()); @@ -234,11 +236,11 @@ namespace etl template ETL_CONSTEXPR14 static - typename etl::enable_if::value && (etl::integral_limits::bits == 8U), size_t>::type + typename etl::enable_if::type encode(const T* input_begin, const T* input_end, etl::istring& output) { - output.resize(etl::base64::encode_size(etl::distance(input_begin, input_end))); + output.resize(etl::base64::encoded_size(etl::distance(input_begin, input_end))); return encode(input_begin, static_cast(etl::distance(input_begin, input_end)), output.data(), output.size()); @@ -250,11 +252,11 @@ namespace etl template ETL_CONSTEXPR14 static - typename etl::enable_if::value && (etl::integral_limits::bits == 8U), size_t>::type + typename etl::enable_if::type encode(const etl::span& input_span, etl::istring& output) { - output.resize(etl::base64::encode_size(Length1)); + output.resize(etl::base64::encoded_size(Length1)); return encode(input_span.begin(), input_span.size(), output.data(), output.size()); @@ -266,16 +268,13 @@ namespace etl ETL_NODISCARD ETL_CONSTEXPR14 static - size_t encode_size(size_t input_length) + size_t encoded_size(size_t input_length) { size_t required_output_length = (input_length * 8U) / 6U; - if ((input_length % 3U) != 0U) + while ((required_output_length % 4U) != 0) { - while ((required_output_length % 4U) != 0) - { - ++required_output_length; - } + ++required_output_length; } return required_output_length; @@ -287,7 +286,7 @@ namespace etl template ETL_CONSTEXPR14 static - typename etl::enable_if::value && (etl::integral_limits::bits == 8U), size_t>::type + typename etl::enable_if::type decode(const char* input, size_t input_length, T* output, size_t output_length) { if (input_length == 0) @@ -296,7 +295,7 @@ namespace etl } // Figure out if the output buffer is large enough. - size_t required_output_length = etl::base64::decode_size(input, input_length); + size_t required_output_length = etl::base64::decoded_size(input, input_length); ETL_ASSERT_OR_RETURN_VALUE(output_length >= required_output_length, ETL_ERROR(base64_overflow), 0U); @@ -378,7 +377,7 @@ namespace etl template ETL_CONSTEXPR14 static - typename etl::enable_if::value && (etl::integral_limits::bits == 8U), size_t>::type + typename etl::enable_if::type decode(const char* input_begin, const char* input_end, T* output_begin, T* output_end) { return decode(input_begin, static_cast(etl::distance(input_begin, input_end)), @@ -390,8 +389,8 @@ namespace etl //************************************************************************* template ETL_CONSTEXPR14 - static - typename etl::enable_if::value && (etl::integral_limits::bits == 8U), size_t>::type + static + typename etl::enable_if::type decode(const etl::span& input_span, const etl::span& output_span) { @@ -404,7 +403,7 @@ namespace etl //************************************************************************* ETL_NODISCARD ETL_CONSTEXPR14 - static size_t decode_size(const char* input, size_t input_length) + static size_t decoded_size(const char* input, size_t input_length) { if (input_length == 0U) { @@ -418,6 +417,27 @@ namespace etl return required_output_length; } + //************************************************************************* + /// Calculates the buffer size required to decode from Base64 + //************************************************************************* + ETL_NODISCARD + ETL_CONSTEXPR14 + static size_t decoded_size(const char* input_begin, const char* input_end) + { + return decoded_size(input_begin, static_cast(etl::distance(input_begin, input_end))); + } + + //************************************************************************* + /// Calculates the buffer size required to decode from Base64 + //************************************************************************* + template + ETL_NODISCARD + ETL_CONSTEXPR14 + static size_t decoded_size(etl::span sp) + { + return decoded_size(sp.begin(), sp.size()); + } + private: //************************************************************************* @@ -520,4 +540,6 @@ namespace etl }; } +#undef ETL_IS_8_BIT_INTEGRAL + #endif diff --git a/test/test_base64.cpp b/test/test_base64.cpp index b26423e4..409a6c63 100644 --- a/test/test_base64.cpp +++ b/test/test_base64.cpp @@ -359,7 +359,7 @@ namespace std::string actual(encoded_output.data(), size); CHECK_EQUAL(expected, actual); - CHECK_EQUAL(etl::base64::encode_size(i), size); + CHECK_EQUAL(etl::base64::encoded_size(i), size); } } @@ -379,7 +379,7 @@ namespace std::string actual(encoded_output.data(), size); CHECK_EQUAL(expected, actual); - CHECK_EQUAL(etl::base64::encode_size(i), size); + CHECK_EQUAL(etl::base64::encoded_size(i), size); } } @@ -401,7 +401,7 @@ namespace std::string actual(encoded_output.data(), size); CHECK_EQUAL(expected, actual); - CHECK_EQUAL(etl::base64::encode_size(i), size); + CHECK_EQUAL(etl::base64::encoded_size(i), size); } } @@ -421,7 +421,7 @@ namespace std::string actual(encoded_output.data(), size); CHECK_EQUAL(expected, actual); - CHECK_EQUAL(etl::base64::encode_size(i), size); + CHECK_EQUAL(etl::base64::encoded_size(i), size); } } @@ -441,7 +441,7 @@ namespace std::string actual(encoded_output.data(), size); CHECK_EQUAL(expected, actual); - CHECK_EQUAL(etl::base64::encode_size(i), size); + CHECK_EQUAL(etl::base64::encoded_size(i), size); } } @@ -463,7 +463,7 @@ namespace std::string actual(encoded_output.data(), size); CHECK_EQUAL(expected, actual); - CHECK_EQUAL(etl::base64::encode_size(i), size); + CHECK_EQUAL(etl::base64::encoded_size(i), size); } } @@ -483,7 +483,7 @@ namespace std::string actual(encoded_output.data(), size); CHECK_EQUAL(expected, actual); - CHECK_EQUAL(etl::base64::encode_size(i), size); + CHECK_EQUAL(etl::base64::encoded_size(i), size); } } @@ -503,7 +503,7 @@ namespace std::string actual(encoded_output.data(), size); CHECK_EQUAL(expected, actual); - CHECK_EQUAL(etl::base64::encode_size(i), size); + CHECK_EQUAL(etl::base64::encoded_size(i), size); } } @@ -525,7 +525,7 @@ namespace std::string actual(encoded_output.data(), size); CHECK_EQUAL(expected, actual); - CHECK_EQUAL(etl::base64::encode_size(i), size); + CHECK_EQUAL(etl::base64::encoded_size(i), size); } } @@ -545,7 +545,7 @@ namespace std::string actual(encoded_output.data(), size); CHECK_EQUAL(expected, actual); - CHECK_EQUAL(etl::base64::encode_size(i), size); + CHECK_EQUAL(etl::base64::encoded_size(i), size); } } @@ -565,7 +565,7 @@ namespace std::string actual(encoded_output.data(), size); CHECK_EQUAL(expected, actual); - CHECK_EQUAL(etl::base64::encode_size(i), size); + CHECK_EQUAL(etl::base64::encoded_size(i), size); } } @@ -587,7 +587,7 @@ namespace std::string actual(encoded_output.data(), size); CHECK_EQUAL(expected, actual); - CHECK_EQUAL(etl::base64::encode_size(i), size); + CHECK_EQUAL(etl::base64::encoded_size(i), size); } } @@ -596,11 +596,11 @@ namespace template constexpr auto GetConstexprBase64(const etl::array input) noexcept { - constexpr size_t encode_size = etl::base64::encode_size(Size); - etl::array output{ 0 }; + constexpr size_t encoded_size = etl::base64::encoded_size(Size); + etl::array output{ 0 }; etl::base64::encode(input.begin(), Size, - output._buffer, encode_size); + output._buffer, encoded_size); return output; } @@ -615,7 +615,7 @@ namespace std::string actual(output.data(), output.size()); CHECK_EQUAL(expected, actual); - CHECK_EQUAL(etl::base64::encode_size(10), output.size()); + CHECK_EQUAL(etl::base64::encoded_size(10), output.size()); } #endif @@ -649,7 +649,7 @@ namespace 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, etl::base64::decoded_size(encoded[i].data(), encoded[i].size())); CHECK_EQUAL(i, decoded_size); } } @@ -664,10 +664,10 @@ namespace decoded_output.fill(0); auto decoded_size = etl::base64::decode(encoded[i].data(), encoded[i].size(), - decoded_output.data(), decoded_output.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, etl::base64::decoded_size(encoded[i].data(), encoded[i].size())); CHECK_EQUAL(i, decoded_size); } } @@ -678,7 +678,21 @@ namespace std::array decoded_output{ 0 }; CHECK_THROW((etl::base64::decode(encoded[10].data(), encoded[10].size(), - decoded_output.data(), decoded_output.size())), etl::base64_overflow); + decoded_output.data(), decoded_output.size())), etl::base64_overflow); + } + + //************************************************************************* + TEST(test_decoded_size) + { + for (size_t i = 0; i < 256; ++i) + { + size_t length = etl::base64::decoded_size(encoded[i].data(), encoded[i].size()); + + CHECK_EQUAL(length, etl::base64::decoded_size(encoded[i].data(), encoded[i].data() + encoded[i].size())); + + etl::span sp(encoded[i].data(), encoded[i].size()); + CHECK_EQUAL(length, etl::base64::decoded_size(sp)); + } } }; } From 5ad7fd2f900951432502f3c38b4d886e983fe3dc Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Sat, 21 Oct 2023 10:27:42 +0100 Subject: [PATCH 07/12] Static version of Base64 - RFC-6848 - No optional padding --- arduino/library-arduino.json | 2 +- arduino/library-arduino.properties | 2 +- include/etl/base64.h | 682 +++++++++++++++++------------ include/etl/iterator.h | 10 +- include/etl/private/pvoidvector.h | 4 +- test/CMakeLists.txt | 267 +---------- test/test_base64.cpp | 460 +++++++++++-------- 7 files changed, 684 insertions(+), 743 deletions(-) diff --git a/arduino/library-arduino.json b/arduino/library-arduino.json index 822e28f8..446119aa 100644 --- a/arduino/library-arduino.json +++ b/arduino/library-arduino.json @@ -1,6 +1,6 @@ { "name": "Embedded Template Library - Arduino", - "version": "20.38.4", + "version": "20.39.0", "authors": { "name": "John Wellbelove", "email": "john.wellbelove@etlcpp.com" diff --git a/arduino/library-arduino.properties b/arduino/library-arduino.properties index 41ce4dfd..b93ae97e 100644 --- a/arduino/library-arduino.properties +++ b/arduino/library-arduino.properties @@ -1,5 +1,5 @@ name=Embedded Template Library - Arduino -version=20.38.4 +version=20.39.0 author= John Wellbelove maintainer=John Wellbelove license=MIT diff --git a/include/etl/base64.h b/include/etl/base64.h index 220632c7..d8372dcb 100644 --- a/include/etl/base64.h +++ b/include/etl/base64.h @@ -42,11 +42,8 @@ SOFTWARE. #include -#if ETL_USING_STL - #include -#endif - -#define ETL_IS_8_BIT_INTEGRAL(Type) (etl::is_integral::value && (etl::integral_limits::bits == 8U)) +#define ETL_IS_ITERATOR_TYPE_8_BIT_INTEGRAL(Type) (etl::is_integral::type>::value_type>::value && \ + (etl::integral_limits::type>::value_type>::bits == 8U)) namespace etl { @@ -77,200 +74,135 @@ namespace etl }; //************************************************************************* - /// Codec for Base64 + /// Codec for Base64 (RFC 4648) //************************************************************************* class base64 { public: //************************************************************************* - /// Encode to Base64 from and to pointer/length + /// Encode to Base64 + /// Four parameter //************************************************************************* - template + template ETL_CONSTEXPR14 - static - typename etl::enable_if::type - encode(const T* input, size_t input_length, char* output, size_t output_length) + static size_t encode(TInputIterator input_begin, TInputIterator input_end, TOutputIterator output_begin, TOutputIterator output_end) { - if (input_length == 0U) - { - return 0; - } + ETL_STATIC_ASSERT(ETL_IS_ITERATOR_TYPE_8_BIT_INTEGRAL(TInputIterator), "Input type must be an 8 bit integral"); + ETL_STATIC_ASSERT(ETL_IS_ITERATOR_TYPE_8_BIT_INTEGRAL(TOutputIterator), "Output type must be an 8 bit integral"); + + const size_t input_length = static_cast(etl::distance(input_begin, input_end)); + const size_t output_length = static_cast(etl::distance(output_begin, output_end)); // Figure out if the output buffer is large enough. - size_t required_output_length = encoded_size(input_length); - + size_t required_output_length = etl::base64::encoded_size(input_length); ETL_ASSERT_OR_RETURN_VALUE(output_length >= required_output_length, ETL_ERROR(base64_overflow), 0U); - 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((*p_in & b11111100) >> 2); - next_sextet = Second_Sextet; - break; - } - - //************************** - case Second_Sextet: - { - index = static_cast((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((*p_in & b11000000) >> 6); - } - next_sextet = Fourth_Sextet; - break; - } - - //************************** - case Fourth_Sextet: - { - index = static_cast(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(etl::distance(output, p_out)); + return process_encode(input_begin, input_length, output_begin, required_output_length); } //************************************************************************* - /// Encode to Base64 from and to pointer/pointer + /// Encode to Base64 + /// For TOutputIterator not derived from etl::iterator + /// Three parameter + /// Assumes the output container is large enough. //************************************************************************* - template + template ETL_CONSTEXPR14 - static - typename etl::enable_if::type - encode(const T* input_begin, const T* input_end, char* output_begin, char* output_end) + static typename etl::enable_if::value_type>::value, size_t>::type + encode(TInputIterator input_begin, TInputIterator input_end, TOutputIterator output_begin) { - return encode(input_begin, static_cast(etl::distance(input_begin, input_end)), - output_begin, static_cast(etl::distance(output_begin, output_end))); - } + ETL_STATIC_ASSERT(ETL_IS_ITERATOR_TYPE_8_BIT_INTEGRAL(TInputIterator), "Input type must be an 8 bit integral"); + ETL_STATIC_ASSERT(ETL_IS_ITERATOR_TYPE_8_BIT_INTEGRAL(TOutputIterator), "Output type must be an 8 bit integral"); + + const size_t input_length = static_cast(etl::distance(input_begin, input_end)); + const size_t output_length = encoded_size(input_length); + + return process_encode(input_begin, input_length, output_begin, output_length); + } //************************************************************************* - /// Encode to Base64 from and to span/span + /// Encode to Base64 + /// For TOutputIterator derived from etl::iterator + /// Three parameter + /// Assumes the output container is large enough. //************************************************************************* - template + template ETL_CONSTEXPR14 - static - typename etl::enable_if::type - encode(const etl::span& input_span, - const etl::span& output_span) + static typename etl::enable_if::value_type>::value, size_t>::type + encode(TInputIterator input_begin, TInputIterator input_end, TOutputIterator output_begin) { - return encode(input_span.begin(), input_span.size(), - output_span.begin(), output_span.size()); + ETL_STATIC_ASSERT(ETL_IS_ITERATOR_TYPE_8_BIT_INTEGRAL(TInputIterator), "Input type must be an 8 bit integral"); + + const size_t input_length = static_cast(etl::distance(input_begin, input_end)); + const size_t output_length = encoded_size(input_length); + + return process_encode(input_begin, input_length, output_begin, output_length); } //************************************************************************* - /// Encode to Base64 from pointer/length to etl::istring + /// Encode to Base64 + /// Four parameter //************************************************************************* - template + template ETL_CONSTEXPR14 - static - typename etl::enable_if::type - encode(const T* input_begin, size_t input_length, - etl::istring& output) + static size_t encode(TInputIterator input_begin, size_t input_length, TOutputIterator output_begin, size_t output_length) { - output.resize(etl::base64::encoded_size(input_length)); + ETL_STATIC_ASSERT(ETL_IS_ITERATOR_TYPE_8_BIT_INTEGRAL(TInputIterator), "Input type must be an 8 bit integral"); + ETL_STATIC_ASSERT(ETL_IS_ITERATOR_TYPE_8_BIT_INTEGRAL(TOutputIterator), "Output type must be an 8 bit integral"); - return encode(input_begin, input_length, - output.data(), output.size()); + // Figure out if the output buffer is large enough. + size_t required_output_length = etl::base64::encoded_size(input_length); + ETL_ASSERT_OR_RETURN_VALUE(output_length >= required_output_length, ETL_ERROR(base64_overflow), 0U); + + return process_encode(input_begin, input_length, output_begin, required_output_length); } //************************************************************************* - /// Encode to Base64 from pointer/pointer to etl::istring + /// Encode to Base64 + /// For TOutputIterator not derived from etl::iterator + /// Three parameter + /// Assumes the output container is large enough. //************************************************************************* - template + template ETL_CONSTEXPR14 - static - typename etl::enable_if::type - encode(const T* input_begin, const T* input_end, - etl::istring& output) + static typename etl::enable_if::value_type>::value, size_t>::type + encode(TInputIterator input_begin, size_t input_length, TOutputIterator output_begin) { - output.resize(etl::base64::encoded_size(etl::distance(input_begin, input_end))); + ETL_STATIC_ASSERT(ETL_IS_ITERATOR_TYPE_8_BIT_INTEGRAL(TInputIterator), "Input type must be an 8 bit integral"); + ETL_STATIC_ASSERT(ETL_IS_ITERATOR_TYPE_8_BIT_INTEGRAL(TOutputIterator), "Output type must be an 8 bit integral"); - return encode(input_begin, static_cast(etl::distance(input_begin, input_end)), - output.data(), output.size()); + const size_t output_length = encoded_size(input_length); + + return process_encode(input_begin, input_length, output_begin, output_length); } //************************************************************************* - /// Encode to Base64 from span to etl::istring + /// Encode to Base64 + /// For TOutputIterator derived from etl::iterator + /// Three parameter + /// Assumes the output container is large enough. //************************************************************************* - template + template ETL_CONSTEXPR14 - static - typename etl::enable_if::type - encode(const etl::span& input_span, - etl::istring& output) + static typename etl::enable_if::value_type>::value, size_t>::type + encode(TInputIterator input_begin, size_t input_length, TOutputIterator output_begin) { - output.resize(etl::base64::encoded_size(Length1)); + ETL_STATIC_ASSERT(ETL_IS_ITERATOR_TYPE_8_BIT_INTEGRAL(TInputIterator), "Input type must be an 8 bit integral"); - return encode(input_span.begin(), input_span.size(), - output.data(), output.size()); + const size_t output_length = encoded_size(input_length); + + return process_encode(input_begin, input_length, output_begin, output_length); } //************************************************************************* - /// Calculates the buffer size required to encode to Base64 + /// Calculates the minimum buffer size required to encode to Base64 //************************************************************************* ETL_NODISCARD ETL_CONSTEXPR14 - static - size_t encoded_size(size_t input_length) + static size_t encoded_size(size_t input_length) { - size_t required_output_length = (input_length * 8U) / 6U; + size_t required_output_length = (input_length * 4U) / 3U; while ((required_output_length % 4U) != 0) { @@ -281,175 +213,238 @@ namespace etl } //************************************************************************* - /// Decode from Base64 from and to pointer/length + /// Decode from Base64 + /// Four parameter //************************************************************************* - template + template ETL_CONSTEXPR14 - static - typename etl::enable_if::type - decode(const char* input, size_t input_length, T* output, size_t output_length) + static size_t decode(TInputIterator input_begin, TInputIterator input_end, TOutputIterator output_begin, TOutputIterator output_end) { - if (input_length == 0) - { - return 0; - } + ETL_STATIC_ASSERT(ETL_IS_ITERATOR_TYPE_8_BIT_INTEGRAL(TInputIterator), "Input type must be an 8 bit integral"); + ETL_STATIC_ASSERT(ETL_IS_ITERATOR_TYPE_8_BIT_INTEGRAL(TOutputIterator), "Output type must be an 8 bit integral"); + + const size_t input_length = valid_input_length(input_begin, input_end); + const size_t output_length = static_cast(etl::distance(output_begin, output_end)); // Figure out if the output buffer is large enough. - size_t required_output_length = etl::base64::decoded_size(input, input_length); - + size_t required_output_length = etl::base64::decoded_size_from_valid_input_length(input_length); ETL_ASSERT_OR_RETURN_VALUE(output_length >= required_output_length, ETL_ERROR(base64_overflow), 0U); - const char* p_in = input; - const char* p_in_end = input + input_length; - - T* p_out = output; - - 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()) - { - break; - } - - char index = get_index_from_sextet(sextet); - - switch (next_sextet) - { - //************************** - case First_Sextet: - { - c = (index & b00111111) << 2; - next_sextet = Second_Sextet; - break; - } - - //************************** - case Second_Sextet: - { - c |= (index & b00110000) >> 4; - *p_out++ = static_cast(c); - c = (index & b00001111) << 4; - next_sextet = Third_Sextet; - break; - } - - //************************** - case Third_Sextet: - { - c |= (index & b00111100) >> 2; - *p_out++ = static_cast(c); - c = (index & b00000011) << 6; - next_sextet = Fourth_Sextet; - break; - } - - //************************** - case Fourth_Sextet: - { - c |= (index & b00111111); - *p_out++ = static_cast(c); - next_sextet = First_Sextet; - break; - } - - //************************** - default: - { - // Should never get here. - assert(false); - break; - } - } - } - - return static_cast(etl::distance(output, p_out)); + return process_decode(input_begin, input_length, output_begin, required_output_length); } //************************************************************************* - /// Decode from Base64 from and to pointer/pointer + /// Decode from Base64 + /// For TOutputIterator not derived from etl::iterator + /// Three parameter + /// Assumes the output container is large enough. //************************************************************************* - template + template ETL_CONSTEXPR14 - static - typename etl::enable_if::type - decode(const char* input_begin, const char* input_end, T* output_begin, T* output_end) + static typename etl::enable_if::value_type>::value, size_t>::type + decode(TInputIterator input_begin, TInputIterator input_end, TOutputIterator output_begin) { - return decode(input_begin, static_cast(etl::distance(input_begin, input_end)), - output_begin, static_cast(etl::distance(output_begin, output_end))); + ETL_STATIC_ASSERT(ETL_IS_ITERATOR_TYPE_8_BIT_INTEGRAL(TInputIterator), "Input type must be an 8 bit integral"); + ETL_STATIC_ASSERT(ETL_IS_ITERATOR_TYPE_8_BIT_INTEGRAL(TOutputIterator), "Output type must be an 8 bit integral"); + + // Find the length of decodable characters. + const size_t input_length = valid_input_length(input_begin, input_end); + + // Find the length of the decoded output. + const size_t required_output_length = decoded_size(input_begin, input_length); + + return process_decode(input_begin, input_length, output_begin, required_output_length); } //************************************************************************* - /// Decode from Base64 from and to span/span + /// Decode from Base64 + /// For TOutputIterator derived from etl::iterator + /// Three parameter + /// Assumes the output container is large enough. //************************************************************************* - template + template ETL_CONSTEXPR14 - static - typename etl::enable_if::type - decode(const etl::span& input_span, - const etl::span& output_span) + static typename etl::enable_if::value_type>::value, size_t>::type + decode(TInputIterator input_begin, TInputIterator input_end, TOutputIterator output_begin) { - return decode(input_span.begin(), input_span.size(), - output_span.begin(), output_span.size()); + ETL_STATIC_ASSERT(ETL_IS_ITERATOR_TYPE_8_BIT_INTEGRAL(TInputIterator), "Input type must be an 8 bit integral"); + + // Find the length of decodable characters. + const size_t input_length = valid_input_length(input_begin, input_end); + + // Find the length of the decoded output. + const size_t required_output_length = decoded_size(input_begin, input_length); + + return process_decode(input_begin, input_length, output_begin, required_output_length); } //************************************************************************* - /// Calculates the buffer size required to decode from Base64 + /// Decode from Base64 + /// Four parameter //************************************************************************* + template + ETL_CONSTEXPR14 + static size_t decode(TInputIterator input_begin, size_t input_length, TOutputIterator output_begin, size_t output_length) + { + ETL_STATIC_ASSERT(ETL_IS_ITERATOR_TYPE_8_BIT_INTEGRAL(TInputIterator), "Input type must be an 8 bit integral"); + ETL_STATIC_ASSERT(ETL_IS_ITERATOR_TYPE_8_BIT_INTEGRAL(TOutputIterator), "Output type must be an 8 bit integral"); + + // Find the length of decodable characters. + input_length = valid_input_length(input_begin, input_length); + + // Figure out if the output buffer is large enough. + size_t required_output_length = etl::base64::decoded_size_from_valid_input_length(input_length); + ETL_ASSERT_OR_RETURN_VALUE(output_length >= required_output_length, ETL_ERROR(base64_overflow), 0U); + + return process_decode(input_begin, input_length, output_begin, required_output_length); + } + + //************************************************************************* + /// Decode from Base64 + /// For TOutputIterator not derived from etl::iterator + /// Three parameter + /// Assumes the output container is large enough. + //************************************************************************* + template + ETL_CONSTEXPR14 + static typename etl::enable_if::value_type>::value, size_t>::type + decode(TInputIterator input_begin, size_t input_length, TOutputIterator output_begin) + { + ETL_STATIC_ASSERT(ETL_IS_ITERATOR_TYPE_8_BIT_INTEGRAL(TInputIterator), "Input type must be an 8 bit integral"); + ETL_STATIC_ASSERT(ETL_IS_ITERATOR_TYPE_8_BIT_INTEGRAL(TOutputIterator), "Output type must be an 8 bit integral"); + + // Find the length of decodable characters. + input_length = valid_input_length(input_begin, input_length); + + // Find the length of the decoded output. + const size_t required_output_length = decoded_size(input_begin, input_length); + + return process_decode(input_begin, input_length, output_begin, required_output_length); + } + + //************************************************************************* + /// Decode from Base64 + /// For TOutputIterator derived from etl::iterator + /// Three parameter + /// Assumes the output container is large enough. + //************************************************************************* + template + ETL_CONSTEXPR14 + static typename etl::enable_if::value_type>::value, size_t>::type + decode(TInputIterator input_begin, size_t input_length, TOutputIterator output_begin) + { + ETL_STATIC_ASSERT(ETL_IS_ITERATOR_TYPE_8_BIT_INTEGRAL(TInputIterator), "Input type must be an 8 bit integral"); + + // Find the length of decodable characters. + input_length = valid_input_length(input_begin, input_length); + + // Find the length of the decoded output. + const size_t output_length = decoded_size(input_begin, input_length); + + return process_decode(input_begin, input_length, output_begin, output_length); + } + + //************************************************************************* + /// Discovers the number of valid decodable characters + //************************************************************************* + template ETL_NODISCARD ETL_CONSTEXPR14 - static size_t decoded_size(const char* input, size_t input_length) + static size_t valid_input_length(TInputIterator input_begin, size_t input_length) { if (input_length == 0U) { return 0U; } - // Figure out the minimum output buffer size. - size_t length = static_cast(etl::distance(input, etl::find(input, input + input_length, padding())) - 1); - size_t required_output_length = length - (length / 4U); + TInputIterator input_end = input_begin; - return required_output_length; + if (input_length >= 2U) + { + // Jump forward to where padding characters possibly start. + // There are never more than two padding characters. + input_length -= 2U; + etl::advance(input_end, input_length); + } + + typedef etl::iterator_traits::value_type input_type; + + if (*input_end != padding()) + { + ++input_end; + ++input_length; + + if (*input_end != padding()) + { + ++input_end; + ++input_length; + } + } + + return input_length; } //************************************************************************* - /// Calculates the buffer size required to decode from Base64 + /// Discovers the number of valid decodable characters //************************************************************************* + template ETL_NODISCARD ETL_CONSTEXPR14 - static size_t decoded_size(const char* input_begin, const char* input_end) + static size_t valid_input_length(TInputIterator input_begin, TInputIterator input_end) + { + return valid_input_length(input_begin, static_cast(etl::distance(input_begin, input_end))); + } + + //************************************************************************* + /// Calculates the minimum buffer size required to decode from Base64 + //************************************************************************* + template + ETL_NODISCARD + ETL_CONSTEXPR14 + static + size_t decoded_size(TInputIterator input_begin, size_t input_length) + { + if (input_length == 0U) + { + return 0U; + } + + input_length = valid_input_length(input_begin, input_length); + --input_length; + return input_length - (input_length / 4U); + } + + //************************************************************************* + /// Calculates the minimum buffer size required to decode from Base64 + //************************************************************************* + template + ETL_NODISCARD + ETL_CONSTEXPR14 + static + size_t decoded_size(TInputIterator input_begin, TInputIterator input_end) { return decoded_size(input_begin, static_cast(etl::distance(input_begin, input_end))); } //************************************************************************* - /// Calculates the buffer size required to decode from Base64 + /// Calculates the minimum buffer size required to decode from Base64 //************************************************************************* - template ETL_NODISCARD ETL_CONSTEXPR14 - static size_t decoded_size(etl::span sp) + static + size_t decoded_size_from_valid_input_length(size_t input_length) { - return decoded_size(sp.begin(), sp.size()); + if (input_length == 0U) + { + return 0U; + } + + --input_length; + return input_length - (input_length / 4U); } private: - //************************************************************************* - /// Sextet index id. - enum - { - First_Sextet, - Second_Sextet, - Third_Sextet, - Fourth_Sextet - }; - // Sextets // 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', // 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', @@ -463,42 +458,44 @@ namespace etl //************************************************************************* // Translates an index into a sextet //************************************************************************* - ETL_CONSTEXPR14 static char get_sextet_from_index(char index) + template + ETL_CONSTEXPR14 static T get_sextet_from_index(char index) { if ((index >= 0) && (index < 26)) { - return 'A' + index; + return static_cast('A' + index); } else if ((index >= 26) && (index < 52)) { index -= 26; - return 'a' + index; + return static_cast('a' + index); } else if ((index >= 52) && (index < 62)) { index -= 52; - return '0' + index; + return static_cast('0' + index); } else if (index == 62) { - return '+'; + return static_cast('+'); } else if (index == 63) { - return '/'; + return static_cast('/'); } else { // Should never get here. assert(false); - return padding(); + return padding(); } } //************************************************************************* // Translates a sextet into an index //************************************************************************* - ETL_CONSTEXPR14 static char get_index_from_sextet(char sextet) + template + ETL_CONSTEXPR14 static uint32_t get_index_from_sextet(T sextet) { if ((sextet >= 'A') && (sextet <= 'Z')) { @@ -512,11 +509,11 @@ namespace etl { return sextet - '0' + 52; } - else if (sextet == '+') + else if ((sextet == '+')) { return 62; } - else if (sextet == '/') + else if ((sextet == '/')) { return 63; } @@ -531,15 +528,142 @@ namespace etl //************************************************************************* /// Gets the padding character //************************************************************************* + template ETL_NODISCARD ETL_CONSTEXPR14 - static char padding() + static T padding() { - return '='; + return static_cast('='); + } + + //************************************************************************* + /// Encode to Base64 implementation + //************************************************************************* + template + ETL_CONSTEXPR14 + static + size_t process_encode(TInputIterator input, size_t input_length, + TOutputIterator output, size_t output_length) + { + if (input_length == 0U) + { + return 0; + } + + // Count the actual number of sextets written. + size_t output_count = 0; + + uint32_t octets = 0; + + // Read octet triplets and write sextet quartets + while (input_length >= 3U) + { + // Read in three octets + octets = (static_cast(static_cast(*input++)) << 16); + octets = octets | (static_cast(static_cast(*input++)) << 8); + octets = octets | static_cast(static_cast(*input++)); + + // Write out four sextets + *output++ = get_sextet_from_index((octets >> 18) & b00111111); + *output++ = get_sextet_from_index((octets >> 12) & b00111111); + *output++ = get_sextet_from_index((octets >> 6) & b00111111); + *output++ = get_sextet_from_index((octets >> 0) & b00111111); + + input_length -= 3U; + output_count += 4U; + } + + // Any input left? + if (input_length > 0) + { + // Write out any remaining sextets + if (input_length == 1U) + { + // There is one octet remaining + octets = static_cast(static_cast(*input++)); + octets <<= 4; // Adjust one octet (8 bits) for two sextets worth of data (12 bits) + output_count += 2U; + } + else if (input_length == 2U) + { + // There are two octets remaining + octets = static_cast(static_cast(*input++)); + octets <<= 8; + octets = octets | static_cast(static_cast(*input++)); + octets <<= 2; // Adjust two octets (16 bits) for three sextets worth of data (18 bits) + output_count += 3U; + } + + int shift = static_cast(input_length * 6U); + + while (shift >= 0) + { + *output++ = get_sextet_from_index((octets >> shift) & b00111111); + shift -= 6; + } + } + + // Pad out the end of the output buffer. + while (output_count != output_length) + { + *output++ = padding(); + ++output_count; + } + + return output_length; + } + + //************************************************************************* + /// Decode from Base64 implementation + //************************************************************************* + template + ETL_CONSTEXPR14 + static + size_t process_decode(TInputIterator input, size_t input_length, TOutputIterator output, size_t output_length) + { + if (input_length == 0) + { + return 0; + } + + // Read sextet quartets and write octet triplets + while (input_length >= 4U) + { + // Read in four sextets + uint32_t sextets = (get_index_from_sextet(*input++) << 18) | + (get_index_from_sextet(*input++) << 12) | + (get_index_from_sextet(*input++) << 6) | + (get_index_from_sextet(*input++)); + + // Write out three octets + *output++ = (sextets >> 16) & b11111111; + *output++ = (sextets >> 8) & b11111111; + *output++ = (sextets >> 0) & b11111111; + + input_length -= 4U; + } + + // Write out any remaining octets + if (input_length == 2U) + { + uint32_t sextets = (get_index_from_sextet(*input++) << 6) | + (get_index_from_sextet(*input++)); + *output++ = (sextets >> 4) & b11111111; + input_length -= 2U; + } + else if (input_length == 3U) + { + uint32_t sextets = (get_index_from_sextet(*input++) << 12) | + (get_index_from_sextet(*input++) << 6) | + (get_index_from_sextet(*input++)); + *output++ = (sextets >> 10) & b11111111; + *output++ = (sextets >> 2) & b11111111; + input_length -= 3U; + } + + return output_length; } }; } -#undef ETL_IS_8_BIT_INTEGRAL - #endif diff --git a/include/etl/iterator.h b/include/etl/iterator.h index ab19db39..8c23c6bd 100644 --- a/include/etl/iterator.h +++ b/include/etl/iterator.h @@ -605,14 +605,14 @@ namespace etl } //*************************************************************************** - /// This kind of %iterator doesn't really have a @a position in the + /// This kind of iterator doesn't really have a a position in the /// container (you can think of the position as being permanently at - /// the end, if you like). Assigning a value to the %iterator will + /// the end, if you like). Assigning a value to the iterator will /// always append the value to the end of the container. /// /// @param value An instance of whatever type container_type::const_reference is; /// presumably a reference-to-const T for container. - /// @return This %iterator, for chained operations. + /// @return This iterator, for chained operations. //*************************************************************************** ETL_CONSTEXPR14 back_insert_iterator& operator =(const typename TContainer::value_type& value) { @@ -644,7 +644,7 @@ namespace etl //*************************************************************************** /// Pre-increment operator. - /// Simply returns *this. (This %iterator does not @a move.) + /// Simply returns *this. (This iterator does not move.) //*************************************************************************** ETL_CONSTEXPR14 back_insert_iterator& operator ++() { @@ -653,7 +653,7 @@ namespace etl //*************************************************************************** /// Post-increment operator. - /// Simply returns *this. (This %iterator does not @a move.) + /// Simply returns *this. (This iterator does not move.) //*************************************************************************** ETL_CONSTEXPR14 back_insert_iterator operator ++(int) { diff --git a/include/etl/private/pvoidvector.h b/include/etl/private/pvoidvector.h index 6ec32092..02f45832 100644 --- a/include/etl/private/pvoidvector.h +++ b/include/etl/private/pvoidvector.h @@ -593,7 +593,7 @@ namespace etl iterator last_ = to_iterator(last); etl::copy(last_, end(), first_); - size_t n_delete = etl::distance(first, last); + size_t n_delete = static_cast(etl::distance(first, last)); // Just adjust the count. p_end -= n_delete; @@ -695,7 +695,7 @@ namespace etl //************************************************************************* void repair_buffer(void** p_buffer_) { - uintptr_t length = p_end - p_buffer; + uintptr_t length = static_cast(p_end - p_buffer); p_buffer = p_buffer_; p_end = p_buffer_ + length; diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index e8ecf183..0bd37e14 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -12,273 +12,7 @@ project(etl_unit_tests LANGUAGES CXX) add_executable(etl_tests main.cpp - murmurhash3.cpp - test_algorithm.cpp - test_alignment.cpp - test_array.cpp - 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 - test_bitset_legacy.cpp - test_bitset_new_default_element_type.cpp - test_bitset_new_explicit_single_element_type.cpp - test_bitset_new_ext_default_element_type.cpp - test_bitset_new_ext_explicit_single_element_type.cpp - test_bit_stream.cpp - test_bit_stream_reader_big_endian.cpp - test_bit_stream_reader_little_endian.cpp - test_bit_stream_writer_big_endian.cpp - test_bit_stream_writer_little_endian.cpp - test_byte.cpp - test_byte_stream.cpp - test_bloom_filter.cpp - test_bresenham_line.cpp - test_bsd_checksum.cpp - test_buffer_descriptors.cpp - test_callback_service.cpp - test_callback_timer.cpp - test_callback_timer_atomic.cpp - test_callback_timer_interrupt.cpp - test_callback_timer_locked.cpp - test_char_traits.cpp - test_checksum.cpp - test_circular_buffer.cpp - test_circular_buffer_external_buffer.cpp - test_circular_iterator.cpp - test_compare.cpp - test_constant.cpp - test_container.cpp - test_correlation.cpp - test_covariance.cpp - test_crc.cpp - test_crc16.cpp - test_crc16_a.cpp - test_crc16_arc.cpp - test_crc16_aug_ccitt.cpp - test_crc16_buypass.cpp - test_crc16_ccitt.cpp - test_crc16_cdma2000.cpp - test_crc16_dds110.cpp - test_crc16_dectr.cpp - test_crc16_dectx.cpp - test_crc16_dnp.cpp - test_crc16_en13757.cpp - test_crc16_genibus.cpp - test_crc16_kermit.cpp - test_crc16_m17.cpp - test_crc16_maxim.cpp - test_crc16_mcrf4xx.cpp - test_crc16_modbus.cpp - test_crc16_profibus.cpp - test_crc16_riello.cpp - test_crc16_t10dif.cpp - test_crc16_teledisk.cpp - test_crc16_tms37157.cpp - test_crc16_usb.cpp - test_crc16_x25.cpp - test_crc16_xmodem.cpp - test_crc32.cpp - test_crc32_bzip2.cpp - test_crc32_c.cpp - test_crc32_d.cpp - test_crc32_jamcrc.cpp - test_crc32_mpeg2.cpp - test_crc32_posix.cpp - test_crc32_q.cpp - test_crc32_xfer.cpp - test_crc64_ecma.cpp - test_crc8_ccitt.cpp - test_crc8_cdma2000.cpp - test_crc8_darc.cpp - test_crc8_dvbs2.cpp - test_crc8_ebu.cpp - test_crc8_icode.cpp - test_crc8_itu.cpp - test_crc8_maxim.cpp - test_crc8_rohc.cpp - test_crc8_wcdma.cpp - test_cyclic_value.cpp - test_debounce.cpp - test_delegate.cpp - test_delegate_cpp03.cpp - test_delegate_service.cpp - test_delegate_service_compile_time.cpp - test_deque.cpp - test_endian.cpp - test_enum_type.cpp - test_error_handler.cpp - test_etl_traits.cpp - test_exception.cpp - test_expected.cpp - test_fixed_iterator.cpp - test_fixed_sized_memory_block_allocator.cpp - test_flags.cpp - test_flat_map.cpp - test_flat_multimap.cpp - test_flat_multiset.cpp - test_flat_set.cpp - test_fnv_1.cpp - test_format_spec.cpp - test_forward_list.cpp - test_forward_list_shared_pool.cpp - test_fsm.cpp - test_function.cpp - test_functional.cpp - test_gamma.cpp - test_hash.cpp - test_hfsm.cpp - test_histogram.cpp - test_indirect_vector.cpp - test_indirect_vector_external_buffer.cpp - test_instance_count.cpp - test_integral_limits.cpp - test_intrusive_forward_list.cpp - test_intrusive_links.cpp - test_intrusive_list.cpp - test_intrusive_queue.cpp - test_intrusive_stack.cpp - test_invert.cpp - test_io_port.cpp - test_iterator.cpp - test_jenkins.cpp - test_largest.cpp - test_limiter.cpp - test_limits.cpp - test_list.cpp - test_list_shared_pool.cpp - test_make_string.cpp - test_map.cpp - test_maths.cpp - test_mean.cpp - test_mem_cast.cpp - test_mem_cast_ptr.cpp - test_memory.cpp - test_message_broker.cpp - test_message_bus.cpp - test_message_packet.cpp - test_message_router.cpp - test_message_router_registry.cpp - test_message_timer.cpp - test_message_timer_atomic.cpp - test_message_timer_interrupt.cpp - test_message_timer_locked.cpp - test_multimap.cpp - test_multiset.cpp - test_multi_array.cpp - test_multi_range.cpp - test_multi_vector.cpp - test_murmur3.cpp - test_nth_type.cpp - test_numeric.cpp - test_observer.cpp - test_optional.cpp - test_packet.cpp - test_parameter_pack.cpp - test_parameter_type.cpp - test_parity_checksum.cpp - test_pearson.cpp - test_poly_span_dynamic_extent.cpp - test_poly_span_fixed_extent.cpp - test_pool.cpp - test_pool_external_buffer.cpp - test_priority_queue.cpp - test_pseudo_moving_average.cpp - test_quantize.cpp - test_queue.cpp - test_queue_lockable.cpp - test_queue_lockable_small.cpp - test_queue_memory_model_small.cpp - test_queue_mpmc_mutex.cpp - test_queue_mpmc_mutex_small.cpp - test_queue_spsc_atomic.cpp - test_queue_spsc_atomic_small.cpp - test_queue_spsc_isr.cpp - test_queue_spsc_isr_small.cpp - test_queue_spsc_locked.cpp - test_queue_spsc_locked_small.cpp - test_random.cpp - test_reference_flat_map.cpp - test_reference_flat_multimap.cpp - test_reference_flat_multiset.cpp - test_reference_flat_set.cpp - test_rescale.cpp - test_result.cpp - test_rms.cpp - test_scaled_rounding.cpp - test_set.cpp - test_shared_message.cpp - test_singleton.cpp - test_smallest.cpp - test_span_dynamic_extent.cpp - test_span_fixed_extent.cpp - test_stack.cpp - test_standard_deviation.cpp - test_state_chart.cpp - test_state_chart_with_data_parameter.cpp - test_state_chart_with_rvalue_data_parameter.cpp - test_state_chart_compile_time.cpp - test_state_chart_compile_time_with_data_parameter.cpp - test_string_char.cpp - test_string_char_external_buffer.cpp - test_string_stream.cpp - test_string_stream_u16.cpp - test_string_stream_u32.cpp - test_string_stream_wchar_t.cpp - test_string_u16.cpp - test_string_u16_external_buffer.cpp - test_string_u32.cpp - test_string_u32_external_buffer.cpp - test_string_utilities.cpp - test_string_utilities_std.cpp - test_string_utilities_std_u16.cpp - test_string_utilities_std_u32.cpp - test_string_utilities_std_wchar_t.cpp - test_string_utilities_u16.cpp - test_string_utilities_u32.cpp - test_string_utilities_wchar_t.cpp - test_string_view.cpp - test_string_wchar_t.cpp - test_string_wchar_t_external_buffer.cpp - test_successor.cpp - test_task_scheduler.cpp - test_threshold.cpp - test_to_arithmetic.cpp - test_to_arithmetic_u16.cpp - test_to_arithmetic_u32.cpp - test_to_arithmetic_wchar_t.cpp - test_to_string.cpp - test_to_u16string.cpp - test_to_u32string.cpp - test_to_wstring.cpp - test_type_def.cpp - test_type_lookup.cpp - test_type_select.cpp - test_type_traits.cpp - test_unaligned_type.cpp - test_unaligned_type_constexpr.cpp - test_unordered_map.cpp - test_unordered_multimap.cpp - test_unordered_multiset.cpp - test_unordered_set.cpp - test_user_type.cpp - test_utility.cpp - test_variance.cpp - test_variant_legacy.cpp - test_variant_variadic.cpp - test_variant_pool.cpp - test_variant_pool_external_buffer.cpp - test_vector.cpp - test_vector_external_buffer.cpp - test_vector_non_trivial.cpp - test_vector_pointer.cpp - test_vector_pointer_external_buffer.cpp - test_visitor.cpp - test_xor_checksum.cpp - test_xor_rotate_checksum.cpp ) target_compile_definitions(etl_tests PRIVATE -DETL_DEBUG) @@ -371,6 +105,7 @@ if ((CMAKE_CXX_COMPILER_ID MATCHES "GNU") OR (CMAKE_CXX_COMPILER_ID MATCHES "Cla -Wall -Wextra -Werror + -Wsign-conversion ) if (ETL_ENABLE_SANITIZER) diff --git a/test/test_base64.cpp b/test/test_base64.cpp index 409a6c63..959a2907 100644 --- a/test/test_base64.cpp +++ b/test/test_base64.cpp @@ -38,6 +38,8 @@ SOFTWARE. #include #include +#include "etl/integral_limits.h" + namespace { std::array input_data_unsigned_char = @@ -343,198 +345,109 @@ namespace SUITE(test_base64) { - //************************************************************************* - TEST(test_encode_unsigned_char_pointer_size) - { - std::array encoded_output; + ////************************************************************************* + //TEST(test_encode_unsigned_char_pointer_size) + //{ + // std::array encoded_output; - for (size_t i = 0; i < 256; ++i) - { - encoded_output.fill(0); + // for (size_t i = 0; i < 256; ++i) + // { + // encoded_output.fill(0); - auto size = etl::base64::encode(input_data_unsigned_char.data(), i, - encoded_output.data(), encoded_output.size()); + // auto size = etl::base64::encode(input_data_unsigned_char.data(), i, + // encoded_output.data(), encoded_output.size()); - std::string expected(encoded[i]); - std::string actual(encoded_output.data(), size); + // std::string expected(encoded[i]); + // std::string actual(encoded_output.data(), size); - CHECK_EQUAL(expected, actual); - CHECK_EQUAL(etl::base64::encoded_size(i), size); - } - } + // CHECK_EQUAL(expected, actual); + // CHECK_EQUAL(etl::base64::encoded_size(i), size); + // } + //} - //************************************************************************* - TEST(test_encode_unsigned_char_pointer_pointer) - { - std::array encoded_output; + ////************************************************************************* + //TEST(test_encode_unsigned_char_pointer_size_no_output_length) + //{ + // std::array encoded_output; - for (size_t i = 0; i < 256; ++i) - { - encoded_output.fill(0); + // 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()); + // auto size = etl::base64::encode(input_data_unsigned_char.data(), i, + // encoded_output.data()); - std::string expected(encoded[i]); - std::string actual(encoded_output.data(), size); + // std::string expected(encoded[i]); + // std::string actual(encoded_output.data(), size); - CHECK_EQUAL(expected, actual); - CHECK_EQUAL(etl::base64::encoded_size(i), size); - } - } + // CHECK_EQUAL(expected, actual); + // CHECK_EQUAL(etl::base64::encoded_size(i), size); + // } + //} - //************************************************************************* - TEST(test_encode_unsigned_char_span) - { - std::array encoded_output; + ////************************************************************************* + //TEST(test_encode_unsigned_char_pointer_size_to_back_inserter) + //{ + // for (size_t i = 0; i < 256; ++i) + // { + // std::string actual; - for (size_t i = 0; i < 256; ++i) - { - encoded_output.fill(0); + // auto size = etl::base64::encode(input_data_unsigned_char.data(), i, + // etl::back_inserter(actual)); - etl::span input_span(input_data_unsigned_char.data(), i); - etl::span output_span(encoded_output.data(), encoded_output.size()); + // std::string expected(encoded[i]); + // + // CHECK_EQUAL(expected, actual); + // CHECK_EQUAL(etl::base64::encoded_size(i), size); + // } + //} - auto size = etl::base64::encode(input_span, output_span); + ////************************************************************************* + //TEST(test_encode_unsigned_char_pointer_pointer) + //{ + // std::array encoded_output; - std::string expected(encoded[i]); - std::string actual(encoded_output.data(), size); + // for (size_t i = 0; i < 256; ++i) + // { + // encoded_output.fill(0); - CHECK_EQUAL(expected, actual); - CHECK_EQUAL(etl::base64::encoded_size(i), size); - } - } + // 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()); - //************************************************************************* - TEST(test_encode_unsigned_char_pointer_size_to_etl_string) - { - etl::string<344U> encoded_output; + // std::string expected(encoded[i]); + // std::string actual(encoded_output.data(), size); - for (size_t i = 0; i < 256; ++i) - { - encoded_output.clear(); + // CHECK_EQUAL(expected, actual); + // CHECK_EQUAL(etl::base64::encoded_size(i), size); + // } + //} - auto size = etl::base64::encode(input_data_unsigned_char.data(), i, - encoded_output); + ////************************************************************************* + //TEST(test_encode_unsigned_char_pointer_pointer_no_output_end_pointer) + //{ + // std::array encoded_output; - std::string expected(encoded[i]); - std::string actual(encoded_output.data(), size); + // for (size_t i = 6; i < 256; ++i) + // { + // encoded_output.fill(0); - CHECK_EQUAL(expected, actual); - CHECK_EQUAL(etl::base64::encoded_size(i), size); - } - } + // auto size = etl::base64::encode(input_data_unsigned_char.data(), input_data_unsigned_char.data() + i, + // encoded_output.data()); - //************************************************************************* - TEST(test_encode_unsigned_char_pointer_pointer_to_etl_string) - { - etl::string<344U> encoded_output; + // std::string expected(encoded[i]); + // std::string actual(encoded_output.data(), size); - for (size_t i = 0; i < 256; ++i) - { - encoded_output.clear(); - - auto size = etl::base64::encode(input_data_unsigned_char.data(), input_data_unsigned_char.data() + i, - encoded_output); - - std::string expected(encoded[i]); - std::string actual(encoded_output.data(), size); - - CHECK_EQUAL(expected, actual); - CHECK_EQUAL(etl::base64::encoded_size(i), size); - } - } - - //************************************************************************* - TEST(test_encode_unsigned_char_span_to_etl_string) - { - etl::string<344U> encoded_output; - - for (size_t i = 0; i < 256; ++i) - { - encoded_output.clear(); - - etl::span input_span(input_data_unsigned_char.data(), i); - - auto size = etl::base64::encode(input_span, - encoded_output); - - std::string expected(encoded[i]); - std::string actual(encoded_output.data(), size); - - CHECK_EQUAL(expected, actual); - CHECK_EQUAL(etl::base64::encoded_size(i), size); - } - } - - //************************************************************************* - TEST(test_encode_int8_t_pointer_size_to_etl_string) - { - etl::string<344U> encoded_output; - - for (size_t i = 0; i < 256; ++i) - { - encoded_output.clear(); - - auto size = etl::base64::encode(input_data_int8_t.data(), i, - encoded_output); - - std::string expected(encoded[i]); - std::string actual(encoded_output.data(), size); - - CHECK_EQUAL(expected, actual); - CHECK_EQUAL(etl::base64::encoded_size(i), size); - } - } - - //************************************************************************* - TEST(test_encode_int8_t_pointer_pointer_to_etl_string) - { - etl::string<344U> encoded_output; - - for (size_t i = 0; i < 256; ++i) - { - encoded_output.clear(); - - auto size = etl::base64::encode(input_data_int8_t.data(), input_data_int8_t.data() + i, - encoded_output); - - std::string expected(encoded[i]); - std::string actual(encoded_output.data(), size); - - CHECK_EQUAL(expected, actual); - CHECK_EQUAL(etl::base64::encoded_size(i), size); - } - } - - //************************************************************************* - TEST(test_encode_int8_t_span_to_etl_string) - { - etl::string<344U> encoded_output; - - for (size_t i = 0; i < 256; ++i) - { - encoded_output.clear(); - - etl::span input_span(input_data_int8_t.data(), i); - - auto size = etl::base64::encode(input_span, - encoded_output); - - std::string expected(encoded[i]); - std::string actual(encoded_output.data(), size); - - CHECK_EQUAL(expected, actual); - CHECK_EQUAL(etl::base64::encoded_size(i), size); - } - } + // CHECK_EQUAL(expected, actual); + // CHECK_EQUAL(etl::base64::encoded_size(i), size); + // } + //} //************************************************************************* TEST(test_encode_int8_t_pointer_size) { std::array encoded_output; - for (size_t i = 0; i < 256; ++i) + for (size_t i = 11; i < 256; ++i) { encoded_output.fill(0); @@ -550,16 +463,16 @@ namespace } //************************************************************************* - TEST(test_encode_int8_t_pointer_pointer) + TEST(test_encode_int8_t_pointer_size_no_output_length) { std::array encoded_output; - for (size_t i = 0; i < 256; ++i) + for (size_t i = 6; 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()); + auto size = etl::base64::encode(input_data_int8_t.data(), i, + encoded_output.data()); std::string expected(encoded[i]); std::string actual(encoded_output.data(), size); @@ -570,7 +483,24 @@ namespace } //************************************************************************* - TEST(test_encode_int8_t_span) + TEST(test_encode_int8_t_pointer_size_to_back_inserter) + { + for (size_t i = 0; i < 256; ++i) + { + std::string actual; + + auto size = etl::base64::encode(input_data_int8_t.data(), i, + etl::back_inserter(actual)); + + std::string expected(encoded[i]); + + CHECK_EQUAL(expected, actual); + CHECK_EQUAL(etl::base64::encoded_size(i), size); + } + } + + //************************************************************************* + TEST(test_encode_int8_t_pointer_pointer) { std::array encoded_output; @@ -578,10 +508,28 @@ namespace { encoded_output.fill(0); - etl::span input_span(input_data_int8_t.data(), i); - etl::span output_span(encoded_output.data(), encoded_output.size()); + 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()); - 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::encoded_size(i), size); + } + } + + //************************************************************************* + TEST(test_encode_int8_t_pointer_pointer_no_end_pointer) + { + std::array 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()); std::string expected(encoded[i]); std::string actual(encoded_output.data(), size); @@ -600,7 +548,7 @@ namespace etl::array output{ 0 }; etl::base64::encode(input.begin(), Size, - output._buffer, encoded_size); + output._buffer, encoded_size); return output; } @@ -625,19 +573,12 @@ namespace std::array encoded_output{ 0 }; CHECK_THROW((etl::base64::encode(input_data_unsigned_char.data(), 10, - encoded_output.data(), encoded_output.size())), etl::base64_overflow); + encoded_output.data(), encoded_output.size())), + etl::base64_overflow); } //************************************************************************* - TEST(test_encode_overflow_for_etl_string) - { - etl::string<10> output; - - CHECK_THROW((etl::base64::encode(input_data_unsigned_char.data(), 10, output)), etl::base64_overflow); - } - - //************************************************************************* - TEST(test_decode_unsigned_char) + TEST(test_decode_unsigned_char_pointer_size) { std::array decoded_output; @@ -645,8 +586,8 @@ namespace { decoded_output.fill(0); - auto decoded_size = etl::base64::decode(encoded[i].data(), encoded[i].size(), - decoded_output.data(), decoded_output.size()); + 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::decoded_size(encoded[i].data(), encoded[i].size())); @@ -655,7 +596,61 @@ namespace } //************************************************************************* - TEST(test_decode_int8_t) + TEST(test_decode_unsigned_char_pointer_size_no_end_pointer) + { + std::array 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()); + + CHECK_ARRAY_EQUAL(input_data_unsigned_char.data(), decoded_output.data(), i); + CHECK_EQUAL(i, etl::base64::decoded_size(encoded[i].data(), encoded[i].size())); + CHECK_EQUAL(i, decoded_size); + } + } + + //************************************************************************* + TEST(test_decode_unsigned_char_pointer_pointer) + { + std::array 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].data() + encoded[i].size(), + decoded_output.data(), decoded_output.data() + decoded_output.size()); + + CHECK_ARRAY_EQUAL(input_data_unsigned_char.data(), decoded_output.data(), i); + CHECK_EQUAL(i, etl::base64::decoded_size(encoded[i].data(), encoded[i].size())); + CHECK_EQUAL(i, decoded_size); + } + } + + //************************************************************************* + TEST(test_decode_unsigned_char_pointer_pointer_no_end_pointer) + { + std::array 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].data() + encoded[i].size(), + decoded_output.data()); + + CHECK_ARRAY_EQUAL(input_data_unsigned_char.data(), decoded_output.data(), i); + CHECK_EQUAL(i, etl::base64::decoded_size(encoded[i].data(), encoded[i].size())); + CHECK_EQUAL(i, decoded_size); + } + } + + //************************************************************************* + TEST(test_decode_int8_t_pointer_size) { std::array decoded_output; @@ -672,6 +667,96 @@ namespace } } + //************************************************************************* + TEST(test_decode_int8_t_pointer_size_back_inserter) + { + std::vector decoded_output; + + for (size_t i = 0; i < 256; ++i) + { + decoded_output.clear(); + + auto decoded_size = etl::base64::decode(encoded[i].data(), encoded[i].size(), + etl::back_inserter(decoded_output)); + + CHECK_ARRAY_EQUAL(input_data_int8_t.data(), decoded_output.data(), i); + CHECK_EQUAL(i, etl::base64::decoded_size(encoded[i].data(), encoded[i].size())); + CHECK_EQUAL(i, decoded_size); + } + } + + //************************************************************************* + TEST(test_decode_int8_t_pointer_size_no_output_size) + { + std::array 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()); + + CHECK_ARRAY_EQUAL(input_data_int8_t.data(), decoded_output.data(), i); + CHECK_EQUAL(i, etl::base64::decoded_size(encoded[i].data(), encoded[i].size())); + CHECK_EQUAL(i, decoded_size); + } + } + + //************************************************************************* + TEST(test_decode_int8_t_pointer_pointer) + { + std::array 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].data() + encoded[i].size(), + decoded_output.data(), decoded_output.data() + decoded_output.size()); + + CHECK_ARRAY_EQUAL(input_data_int8_t.data(), decoded_output.data(), i); + CHECK_EQUAL(i, etl::base64::decoded_size(encoded[i].data(), encoded[i].size())); + CHECK_EQUAL(i, decoded_size); + } + } + + //************************************************************************* + TEST(test_decode_int8_t_pointer_pointer_back_inserter) + { + std::vector decoded_output; + + for (size_t i = 0; i < 256; ++i) + { + decoded_output.clear(); + + auto decoded_size = etl::base64::decode(encoded[i].data(), encoded[i].data() + encoded[i].size(), + etl::back_inserter(decoded_output)); + + CHECK_ARRAY_EQUAL(input_data_int8_t.data(), decoded_output.data(), i); + CHECK_EQUAL(i, etl::base64::decoded_size(encoded[i].data(), encoded[i].size())); + CHECK_EQUAL(i, decoded_size); + } + } + + //************************************************************************* + TEST(test_decode_int8_t_pointer_pointer_no_end_pointer) + { + std::array 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].data() + encoded[i].size(), + decoded_output.data()); + + CHECK_ARRAY_EQUAL(input_data_int8_t.data(), decoded_output.data(), i); + CHECK_EQUAL(i, etl::base64::decoded_size(encoded[i].data(), encoded[i].size())); + CHECK_EQUAL(i, decoded_size); + } + } + //************************************************************************* TEST(test_decode_overflow) { @@ -689,9 +774,6 @@ namespace size_t length = etl::base64::decoded_size(encoded[i].data(), encoded[i].size()); CHECK_EQUAL(length, etl::base64::decoded_size(encoded[i].data(), encoded[i].data() + encoded[i].size())); - - etl::span sp(encoded[i].data(), encoded[i].size()); - CHECK_EQUAL(length, etl::base64::decoded_size(sp)); } } }; From 702b0ef3a2afb30a9a3cebff00b7628b71ae6741 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Sat, 21 Oct 2023 10:41:06 +0100 Subject: [PATCH 08/12] Removed static from encode and decode functions --- include/etl/base64.h | 37 ++++---- test/test_base64.cpp | 213 ++++++++++++++++++++++++------------------- 2 files changed, 137 insertions(+), 113 deletions(-) diff --git a/include/etl/base64.h b/include/etl/base64.h index d8372dcb..a251051d 100644 --- a/include/etl/base64.h +++ b/include/etl/base64.h @@ -86,7 +86,7 @@ namespace etl //************************************************************************* template ETL_CONSTEXPR14 - static size_t encode(TInputIterator input_begin, TInputIterator input_end, TOutputIterator output_begin, TOutputIterator output_end) + size_t encode(TInputIterator input_begin, TInputIterator input_end, TOutputIterator output_begin, TOutputIterator output_end) { ETL_STATIC_ASSERT(ETL_IS_ITERATOR_TYPE_8_BIT_INTEGRAL(TInputIterator), "Input type must be an 8 bit integral"); ETL_STATIC_ASSERT(ETL_IS_ITERATOR_TYPE_8_BIT_INTEGRAL(TOutputIterator), "Output type must be an 8 bit integral"); @@ -109,7 +109,7 @@ namespace etl //************************************************************************* template ETL_CONSTEXPR14 - static typename etl::enable_if::value_type>::value, size_t>::type + typename etl::enable_if::value_type>::value, size_t>::type encode(TInputIterator input_begin, TInputIterator input_end, TOutputIterator output_begin) { ETL_STATIC_ASSERT(ETL_IS_ITERATOR_TYPE_8_BIT_INTEGRAL(TInputIterator), "Input type must be an 8 bit integral"); @@ -129,7 +129,7 @@ namespace etl //************************************************************************* template ETL_CONSTEXPR14 - static typename etl::enable_if::value_type>::value, size_t>::type + typename etl::enable_if::value_type>::value, size_t>::type encode(TInputIterator input_begin, TInputIterator input_end, TOutputIterator output_begin) { ETL_STATIC_ASSERT(ETL_IS_ITERATOR_TYPE_8_BIT_INTEGRAL(TInputIterator), "Input type must be an 8 bit integral"); @@ -146,7 +146,7 @@ namespace etl //************************************************************************* template ETL_CONSTEXPR14 - static size_t encode(TInputIterator input_begin, size_t input_length, TOutputIterator output_begin, size_t output_length) + size_t encode(TInputIterator input_begin, size_t input_length, TOutputIterator output_begin, size_t output_length) { ETL_STATIC_ASSERT(ETL_IS_ITERATOR_TYPE_8_BIT_INTEGRAL(TInputIterator), "Input type must be an 8 bit integral"); ETL_STATIC_ASSERT(ETL_IS_ITERATOR_TYPE_8_BIT_INTEGRAL(TOutputIterator), "Output type must be an 8 bit integral"); @@ -166,7 +166,7 @@ namespace etl //************************************************************************* template ETL_CONSTEXPR14 - static typename etl::enable_if::value_type>::value, size_t>::type + typename etl::enable_if::value_type>::value, size_t>::type encode(TInputIterator input_begin, size_t input_length, TOutputIterator output_begin) { ETL_STATIC_ASSERT(ETL_IS_ITERATOR_TYPE_8_BIT_INTEGRAL(TInputIterator), "Input type must be an 8 bit integral"); @@ -185,8 +185,8 @@ namespace etl //************************************************************************* template ETL_CONSTEXPR14 - static typename etl::enable_if::value_type>::value, size_t>::type - encode(TInputIterator input_begin, size_t input_length, TOutputIterator output_begin) + typename etl::enable_if::value_type>::value, size_t>::type + encode(TInputIterator input_begin, size_t input_length, TOutputIterator output_begin) { ETL_STATIC_ASSERT(ETL_IS_ITERATOR_TYPE_8_BIT_INTEGRAL(TInputIterator), "Input type must be an 8 bit integral"); @@ -218,7 +218,7 @@ namespace etl //************************************************************************* template ETL_CONSTEXPR14 - static size_t decode(TInputIterator input_begin, TInputIterator input_end, TOutputIterator output_begin, TOutputIterator output_end) + size_t decode(TInputIterator input_begin, TInputIterator input_end, TOutputIterator output_begin, TOutputIterator output_end) { ETL_STATIC_ASSERT(ETL_IS_ITERATOR_TYPE_8_BIT_INTEGRAL(TInputIterator), "Input type must be an 8 bit integral"); ETL_STATIC_ASSERT(ETL_IS_ITERATOR_TYPE_8_BIT_INTEGRAL(TOutputIterator), "Output type must be an 8 bit integral"); @@ -241,7 +241,7 @@ namespace etl //************************************************************************* template ETL_CONSTEXPR14 - static typename etl::enable_if::value_type>::value, size_t>::type + typename etl::enable_if::value_type>::value, size_t>::type decode(TInputIterator input_begin, TInputIterator input_end, TOutputIterator output_begin) { ETL_STATIC_ASSERT(ETL_IS_ITERATOR_TYPE_8_BIT_INTEGRAL(TInputIterator), "Input type must be an 8 bit integral"); @@ -264,7 +264,7 @@ namespace etl //************************************************************************* template ETL_CONSTEXPR14 - static typename etl::enable_if::value_type>::value, size_t>::type + typename etl::enable_if::value_type>::value, size_t>::type decode(TInputIterator input_begin, TInputIterator input_end, TOutputIterator output_begin) { ETL_STATIC_ASSERT(ETL_IS_ITERATOR_TYPE_8_BIT_INTEGRAL(TInputIterator), "Input type must be an 8 bit integral"); @@ -284,7 +284,7 @@ namespace etl //************************************************************************* template ETL_CONSTEXPR14 - static size_t decode(TInputIterator input_begin, size_t input_length, TOutputIterator output_begin, size_t output_length) + size_t decode(TInputIterator input_begin, size_t input_length, TOutputIterator output_begin, size_t output_length) { ETL_STATIC_ASSERT(ETL_IS_ITERATOR_TYPE_8_BIT_INTEGRAL(TInputIterator), "Input type must be an 8 bit integral"); ETL_STATIC_ASSERT(ETL_IS_ITERATOR_TYPE_8_BIT_INTEGRAL(TOutputIterator), "Output type must be an 8 bit integral"); @@ -307,7 +307,7 @@ namespace etl //************************************************************************* template ETL_CONSTEXPR14 - static typename etl::enable_if::value_type>::value, size_t>::type + typename etl::enable_if::value_type>::value, size_t>::type decode(TInputIterator input_begin, size_t input_length, TOutputIterator output_begin) { ETL_STATIC_ASSERT(ETL_IS_ITERATOR_TYPE_8_BIT_INTEGRAL(TInputIterator), "Input type must be an 8 bit integral"); @@ -330,7 +330,7 @@ namespace etl //************************************************************************* template ETL_CONSTEXPR14 - static typename etl::enable_if::value_type>::value, size_t>::type + typename etl::enable_if::value_type>::value, size_t>::type decode(TInputIterator input_begin, size_t input_length, TOutputIterator output_begin) { ETL_STATIC_ASSERT(ETL_IS_ITERATOR_TYPE_8_BIT_INTEGRAL(TInputIterator), "Input type must be an 8 bit integral"); @@ -401,8 +401,7 @@ namespace etl template ETL_NODISCARD ETL_CONSTEXPR14 - static - size_t decoded_size(TInputIterator input_begin, size_t input_length) + static size_t decoded_size(TInputIterator input_begin, size_t input_length) { if (input_length == 0U) { @@ -420,8 +419,7 @@ namespace etl template ETL_NODISCARD ETL_CONSTEXPR14 - static - size_t decoded_size(TInputIterator input_begin, TInputIterator input_end) + static size_t decoded_size(TInputIterator input_begin, TInputIterator input_end) { return decoded_size(input_begin, static_cast(etl::distance(input_begin, input_end))); } @@ -431,8 +429,7 @@ namespace etl //************************************************************************* ETL_NODISCARD ETL_CONSTEXPR14 - static - size_t decoded_size_from_valid_input_length(size_t input_length) + static size_t decoded_size_from_valid_input_length(size_t input_length) { if (input_length == 0U) { @@ -541,7 +538,6 @@ namespace etl //************************************************************************* template ETL_CONSTEXPR14 - static size_t process_encode(TInputIterator input, size_t input_length, TOutputIterator output, size_t output_length) { @@ -618,7 +614,6 @@ namespace etl //************************************************************************* template ETL_CONSTEXPR14 - static size_t process_decode(TInputIterator input, size_t input_length, TOutputIterator output, size_t output_length) { if (input_length == 0) diff --git a/test/test_base64.cpp b/test/test_base64.cpp index 959a2907..e4cbdafa 100644 --- a/test/test_base64.cpp +++ b/test/test_base64.cpp @@ -345,113 +345,120 @@ namespace SUITE(test_base64) { - ////************************************************************************* - //TEST(test_encode_unsigned_char_pointer_size) - //{ - // std::array encoded_output; + //************************************************************************* + TEST(test_encode_unsigned_char_pointer_size) + { + etl::base64 b64; + std::array encoded_output; - // for (size_t i = 0; i < 256; ++i) - // { - // encoded_output.fill(0); + for (size_t i = 0; i < 256; ++i) + { + encoded_output.fill(0); - // auto size = etl::base64::encode(input_data_unsigned_char.data(), i, - // encoded_output.data(), encoded_output.size()); + auto size = b64.encode(input_data_unsigned_char.data(), i, + encoded_output.data(), encoded_output.size()); - // std::string expected(encoded[i]); - // std::string actual(encoded_output.data(), size); + std::string expected(encoded[i]); + std::string actual(encoded_output.data(), size); - // CHECK_EQUAL(expected, actual); - // CHECK_EQUAL(etl::base64::encoded_size(i), size); - // } - //} + CHECK_EQUAL(expected, actual); + CHECK_EQUAL(etl::base64::encoded_size(i), size); + } + } - ////************************************************************************* - //TEST(test_encode_unsigned_char_pointer_size_no_output_length) - //{ - // std::array encoded_output; + //************************************************************************* + TEST(test_encode_unsigned_char_pointer_size_no_output_length) + { + etl::base64 b64; + std::array encoded_output; - // for (size_t i = 0; i < 256; ++i) - // { - // encoded_output.fill(0); + for (size_t i = 0; i < 256; ++i) + { + encoded_output.fill(0); - // auto size = etl::base64::encode(input_data_unsigned_char.data(), i, - // encoded_output.data()); + auto size = b64.encode(input_data_unsigned_char.data(), i, + encoded_output.data()); - // std::string expected(encoded[i]); - // std::string actual(encoded_output.data(), size); + std::string expected(encoded[i]); + std::string actual(encoded_output.data(), size); - // CHECK_EQUAL(expected, actual); - // CHECK_EQUAL(etl::base64::encoded_size(i), size); - // } - //} + CHECK_EQUAL(expected, actual); + CHECK_EQUAL(etl::base64::encoded_size(i), size); + } + } - ////************************************************************************* - //TEST(test_encode_unsigned_char_pointer_size_to_back_inserter) - //{ - // for (size_t i = 0; i < 256; ++i) - // { - // std::string actual; + //************************************************************************* + TEST(test_encode_unsigned_char_pointer_size_to_back_inserter) + { + etl::base64 b64; - // auto size = etl::base64::encode(input_data_unsigned_char.data(), i, - // etl::back_inserter(actual)); + for (size_t i = 0; i < 256; ++i) + { + std::string actual; - // std::string expected(encoded[i]); - // - // CHECK_EQUAL(expected, actual); - // CHECK_EQUAL(etl::base64::encoded_size(i), size); - // } - //} + auto size = b64.encode(input_data_unsigned_char.data(), i, + etl::back_inserter(actual)); - ////************************************************************************* - //TEST(test_encode_unsigned_char_pointer_pointer) - //{ - // std::array encoded_output; + std::string expected(encoded[i]); + + CHECK_EQUAL(expected, actual); + CHECK_EQUAL(etl::base64::encoded_size(i), size); + } + } - // for (size_t i = 0; i < 256; ++i) - // { - // encoded_output.fill(0); + //************************************************************************* + TEST(test_encode_unsigned_char_pointer_pointer) + { + etl::base64 b64; + std::array encoded_output; - // 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()); + for (size_t i = 0; i < 256; ++i) + { + encoded_output.fill(0); - // std::string expected(encoded[i]); - // std::string actual(encoded_output.data(), size); + auto size = b64.encode(input_data_unsigned_char.data(), input_data_unsigned_char.data() + i, + encoded_output.data(), encoded_output.data() + encoded_output.size()); - // CHECK_EQUAL(expected, actual); - // CHECK_EQUAL(etl::base64::encoded_size(i), size); - // } - //} + std::string expected(encoded[i]); + std::string actual(encoded_output.data(), size); - ////************************************************************************* - //TEST(test_encode_unsigned_char_pointer_pointer_no_output_end_pointer) - //{ - // std::array encoded_output; + CHECK_EQUAL(expected, actual); + CHECK_EQUAL(etl::base64::encoded_size(i), size); + } + } - // for (size_t i = 6; i < 256; ++i) - // { - // encoded_output.fill(0); + //************************************************************************* + TEST(test_encode_unsigned_char_pointer_pointer_no_output_end_pointer) + { + etl::base64 b64; + std::array encoded_output; - // auto size = etl::base64::encode(input_data_unsigned_char.data(), input_data_unsigned_char.data() + i, - // encoded_output.data()); + for (size_t i = 6; i < 256; ++i) + { + encoded_output.fill(0); - // std::string expected(encoded[i]); - // std::string actual(encoded_output.data(), size); + auto size = b64.encode(input_data_unsigned_char.data(), input_data_unsigned_char.data() + i, + encoded_output.data()); - // CHECK_EQUAL(expected, actual); - // CHECK_EQUAL(etl::base64::encoded_size(i), size); - // } - //} + std::string expected(encoded[i]); + std::string actual(encoded_output.data(), size); + + CHECK_EQUAL(expected, actual); + CHECK_EQUAL(etl::base64::encoded_size(i), size); + } + } //************************************************************************* TEST(test_encode_int8_t_pointer_size) { + etl::base64 b64; std::array encoded_output; for (size_t i = 11; i < 256; ++i) { encoded_output.fill(0); - auto size = etl::base64::encode(input_data_int8_t.data(), i, + auto size = b64.encode(input_data_int8_t.data(), i, encoded_output.data(), encoded_output.size()); std::string expected(encoded[i]); @@ -465,13 +472,14 @@ namespace //************************************************************************* TEST(test_encode_int8_t_pointer_size_no_output_length) { + etl::base64 b64; std::array encoded_output; for (size_t i = 6; i < 256; ++i) { encoded_output.fill(0); - auto size = etl::base64::encode(input_data_int8_t.data(), i, + auto size = b64.encode(input_data_int8_t.data(), i, encoded_output.data()); std::string expected(encoded[i]); @@ -485,11 +493,13 @@ namespace //************************************************************************* TEST(test_encode_int8_t_pointer_size_to_back_inserter) { + etl::base64 b64; + for (size_t i = 0; i < 256; ++i) { std::string actual; - auto size = etl::base64::encode(input_data_int8_t.data(), i, + auto size = b64.encode(input_data_int8_t.data(), i, etl::back_inserter(actual)); std::string expected(encoded[i]); @@ -502,13 +512,14 @@ namespace //************************************************************************* TEST(test_encode_int8_t_pointer_pointer) { + etl::base64 b64; std::array 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, + auto size = b64.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]); @@ -522,13 +533,15 @@ namespace //************************************************************************* TEST(test_encode_int8_t_pointer_pointer_no_end_pointer) { + etl::base64 b64; + std::array 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, + auto size = b64.encode(input_data_int8_t.data(), input_data_int8_t.data() + i, encoded_output.data()); std::string expected(encoded[i]); @@ -544,10 +557,12 @@ namespace template constexpr auto GetConstexprBase64(const etl::array input) noexcept { + etl::base64 b64; + constexpr size_t encoded_size = etl::base64::encoded_size(Size); etl::array output{ 0 }; - etl::base64::encode(input.begin(), Size, + b64.encode(input.begin(), Size, output._buffer, encoded_size); return output; @@ -570,9 +585,10 @@ namespace //************************************************************************* TEST(test_encode_overflow) { + etl::base64 b64; std::array encoded_output{ 0 }; - CHECK_THROW((etl::base64::encode(input_data_unsigned_char.data(), 10, + CHECK_THROW((b64.encode(input_data_unsigned_char.data(), 10, encoded_output.data(), encoded_output.size())), etl::base64_overflow); } @@ -580,13 +596,14 @@ namespace //************************************************************************* TEST(test_decode_unsigned_char_pointer_size) { + etl::base64 b64; std::array 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(), + auto decoded_size = b64.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); @@ -598,13 +615,14 @@ namespace //************************************************************************* TEST(test_decode_unsigned_char_pointer_size_no_end_pointer) { + etl::base64 b64; std::array 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(), + auto decoded_size = b64.decode(encoded[i].data(), encoded[i].size(), decoded_output.data()); CHECK_ARRAY_EQUAL(input_data_unsigned_char.data(), decoded_output.data(), i); @@ -616,13 +634,14 @@ namespace //************************************************************************* TEST(test_decode_unsigned_char_pointer_pointer) { + etl::base64 b64; std::array 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].data() + encoded[i].size(), + auto decoded_size = b64.decode(encoded[i].data(), encoded[i].data() + encoded[i].size(), decoded_output.data(), decoded_output.data() + decoded_output.size()); CHECK_ARRAY_EQUAL(input_data_unsigned_char.data(), decoded_output.data(), i); @@ -634,13 +653,14 @@ namespace //************************************************************************* TEST(test_decode_unsigned_char_pointer_pointer_no_end_pointer) { + etl::base64 b64; std::array 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].data() + encoded[i].size(), + auto decoded_size = b64.decode(encoded[i].data(), encoded[i].data() + encoded[i].size(), decoded_output.data()); CHECK_ARRAY_EQUAL(input_data_unsigned_char.data(), decoded_output.data(), i); @@ -652,13 +672,14 @@ namespace //************************************************************************* TEST(test_decode_int8_t_pointer_size) { + etl::base64 b64; std::array 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(), + auto decoded_size = b64.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); @@ -670,13 +691,14 @@ namespace //************************************************************************* TEST(test_decode_int8_t_pointer_size_back_inserter) { + etl::base64 b64; std::vector decoded_output; for (size_t i = 0; i < 256; ++i) { decoded_output.clear(); - auto decoded_size = etl::base64::decode(encoded[i].data(), encoded[i].size(), + auto decoded_size = b64.decode(encoded[i].data(), encoded[i].size(), etl::back_inserter(decoded_output)); CHECK_ARRAY_EQUAL(input_data_int8_t.data(), decoded_output.data(), i); @@ -688,13 +710,14 @@ namespace //************************************************************************* TEST(test_decode_int8_t_pointer_size_no_output_size) { + etl::base64 b64; std::array 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(), + auto decoded_size = b64.decode(encoded[i].data(), encoded[i].size(), decoded_output.data()); CHECK_ARRAY_EQUAL(input_data_int8_t.data(), decoded_output.data(), i); @@ -706,13 +729,14 @@ namespace //************************************************************************* TEST(test_decode_int8_t_pointer_pointer) { + etl::base64 b64; std::array 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].data() + encoded[i].size(), + auto decoded_size = b64.decode(encoded[i].data(), encoded[i].data() + encoded[i].size(), decoded_output.data(), decoded_output.data() + decoded_output.size()); CHECK_ARRAY_EQUAL(input_data_int8_t.data(), decoded_output.data(), i); @@ -724,13 +748,14 @@ namespace //************************************************************************* TEST(test_decode_int8_t_pointer_pointer_back_inserter) { + etl::base64 b64; std::vector decoded_output; for (size_t i = 0; i < 256; ++i) { decoded_output.clear(); - auto decoded_size = etl::base64::decode(encoded[i].data(), encoded[i].data() + encoded[i].size(), + auto decoded_size = b64.decode(encoded[i].data(), encoded[i].data() + encoded[i].size(), etl::back_inserter(decoded_output)); CHECK_ARRAY_EQUAL(input_data_int8_t.data(), decoded_output.data(), i); @@ -742,13 +767,14 @@ namespace //************************************************************************* TEST(test_decode_int8_t_pointer_pointer_no_end_pointer) { + etl::base64 b64; std::array 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].data() + encoded[i].size(), + auto decoded_size = b64.decode(encoded[i].data(), encoded[i].data() + encoded[i].size(), decoded_output.data()); CHECK_ARRAY_EQUAL(input_data_int8_t.data(), decoded_output.data(), i); @@ -760,15 +786,18 @@ namespace //************************************************************************* TEST(test_decode_overflow) { + etl::base64 b64; std::array decoded_output{ 0 }; - CHECK_THROW((etl::base64::decode(encoded[10].data(), encoded[10].size(), + CHECK_THROW((b64.decode(encoded[10].data(), encoded[10].size(), decoded_output.data(), decoded_output.size())), etl::base64_overflow); } //************************************************************************* TEST(test_decoded_size) { + etl::base64 b64; + for (size_t i = 0; i < 256; ++i) { size_t length = etl::base64::decoded_size(encoded[i].data(), encoded[i].size()); From 5dad4402c63e284de0c68f1ebdfb47c4bc7a92c1 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Sat, 21 Oct 2023 11:41:35 +0100 Subject: [PATCH 09/12] Added padding flag --- include/etl/base64.h | 22 ++++++++++++++++++---- test/test_base64.cpp | 2 +- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/include/etl/base64.h b/include/etl/base64.h index a251051d..69a17359 100644 --- a/include/etl/base64.h +++ b/include/etl/base64.h @@ -80,6 +80,15 @@ namespace etl { public: + //************************************************************************* + /// Default constructor + //************************************************************************* + ETL_CONSTEXPR14 + base64() + : use_padding(true) + { + } + //************************************************************************* /// Encode to Base64 /// Four parameter @@ -599,11 +608,14 @@ namespace etl } } - // Pad out the end of the output buffer. - while (output_count != output_length) + if (use_padding) { - *output++ = padding(); - ++output_count; + // Pad out the end of the output buffer. + while (output_count != output_length) + { + *output++ = padding(); + ++output_count; + } } return output_length; @@ -658,6 +670,8 @@ namespace etl return output_length; } + + bool use_padding; }; } diff --git a/test/test_base64.cpp b/test/test_base64.cpp index e4cbdafa..8ab90c2b 100644 --- a/test/test_base64.cpp +++ b/test/test_base64.cpp @@ -563,7 +563,7 @@ namespace etl::array output{ 0 }; b64.encode(input.begin(), Size, - output._buffer, encoded_size); + output._buffer, encoded_size); return output; } From a92b28fdea870a60e83c45a31b1cba3e5a26de75 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Sat, 21 Oct 2023 18:18:26 +0100 Subject: [PATCH 10/12] Renamed test file --- include/etl/base64.h | 203 ++++++++++++++++-- ...p => test_base64_RFC4648_with_padding.cpp} | 111 ++++++---- test/vs2022/etl.vcxproj | 2 +- test/vs2022/etl.vcxproj.filters | 77 +------ 4 files changed, 257 insertions(+), 136 deletions(-) rename test/{test_base64.cpp => test_base64_RFC4648_with_padding.cpp} (93%) diff --git a/include/etl/base64.h b/include/etl/base64.h index 69a17359..76a8396a 100644 --- a/include/etl/base64.h +++ b/include/etl/base64.h @@ -29,7 +29,6 @@ SOFTWARE. #define ETL_BASE64_INCLUDED #include "etl/platform.h" -#include "etl/span.h" #include "etl/static_assert.h" #include "etl/error_handler.h" #include "etl/exception.h" @@ -38,13 +37,26 @@ SOFTWARE. #include "etl/algorithm.h" #include "etl/integral_limits.h" #include "etl/iterator.h" -#include "etl/string.h" +#include "enum_type.h" #include #define ETL_IS_ITERATOR_TYPE_8_BIT_INTEGRAL(Type) (etl::is_integral::type>::value_type>::value && \ (etl::integral_limits::type>::value_type>::bits == 8U)) +/************************************************************************************************************************************************************************** +* See https://en.wikipedia.org/wiki/Base64 +* +* Encoding Encoding characters Separate encoding of lines Decoding non-encoding characters +* 62nd 63rd Pad Separators Length Checksum +* RFC 1421 : Base64 for Privacy - Enhanced Mail(deprecated) + / = mandatory CR + LF 64, or lower for the last line No No +* RFC 2045 : Base64 transfer encoding for MIME + / = mandatory CR + LF At most 76 No Discarded +* RFC 2152 : Base64 for UTF - 7 + / No No No +* RFC 3501 : Base64 encoding for IMAP mailbox names + , No No No +* RFC 4648 : base64(standard)[a] + / = optional No No +* RFC 4648 : base64url(URL - and filename - safe standard) - _ = optional No No +**************************************************************************************************************************************************************************/ + namespace etl { //*************************************************************************** @@ -61,7 +73,7 @@ namespace etl }; //*************************************************************************** - /// Memory misalignment exception. + /// buffer overflow exception. //*************************************************************************** class base64_overflow : public base64_exception { @@ -73,6 +85,19 @@ namespace etl } }; + //*************************************************************************** + /// Illegal character exception. + //*************************************************************************** + class base64_illegal_character : public base64_exception + { + public: + + base64_illegal_character(string_type file_name_, numeric_type line_number_) + : base64_exception(ETL_ERROR_TEXT("base64:illegal character", ETL_BASE64_FILE_ID"B"), file_name_, line_number_) + { + } + }; + //************************************************************************* /// Codec for Base64 (RFC 4648) //************************************************************************* @@ -80,15 +105,145 @@ namespace etl { public: + struct Encoding + { + enum enum_type + { + RFC_1421, + RFC_2045, + RFC_2152, + RFC_3501, + RFC_4648, + RFC_4648_URL, + }; + + ETL_DECLARE_ENUM_TYPE(Encoding, int) + ETL_ENUM_TYPE(RFC_1421, "RFC 1421") + ETL_ENUM_TYPE(RFC_2045, "RFC 2045") + ETL_END_ENUM_TYPE + }; + + struct Padding + { + enum enum_type + { + No_Padding = 0, + Use_Padding = 1 + }; + + ETL_DECLARE_ENUM_TYPE(Padding, bool) + ETL_ENUM_TYPE(Use_Padding, "Use padding") + ETL_ENUM_TYPE(No_Padding, "No padding") + ETL_END_ENUM_TYPE + }; + //************************************************************************* /// Default constructor //************************************************************************* ETL_CONSTEXPR14 - base64() - : use_padding(true) + base64() + : encoding(Encoding::RFC_4648) + , use_padding(true) + , max_line_length(etl::integral_limits::max) { } + //************************************************************************* + /// Constructor + //************************************************************************* + ETL_CONSTEXPR14 + base64(Encoding encoding_, bool use_padding_ = etl::base64::Padding::Use_Padding) + : encoding(Encoding::RFC_4648) + , use_padding(false) + , max_line_length(0) + { + switch (encoding) + { + case Encoding::RFC_1421: + { + use_padding = true; + max_line_length = 64; + break; + } + + case Encoding::RFC_2045: + { + use_padding = true; + max_line_length = 76; + break; + } + + case Encoding::RFC_2152: + { + use_padding = false; + max_line_length = etl::integral_limits::max; + break; + } + + case Encoding::RFC_3501: + { + use_padding = false; + max_line_length = etl::integral_limits::max; + break; + } + + case Encoding::RFC_4648: + { + use_padding = use_padding_; + max_line_length = etl::integral_limits::max; + break; + } + + case Encoding::RFC_4648_URL: + { + use_padding = use_padding_; + max_line_length = etl::integral_limits::max; + break; + } + + default: + { + break; + } + } + } + + //************************************************************************* + /// Get the encoding standard + //************************************************************************* + ETL_CONSTEXPR14 + Encoding get_encoding() const + { + return encoding; + } + + //************************************************************************* + /// Get the maximum line length + //************************************************************************* + ETL_CONSTEXPR14 + size_t get_max_line_length() const + { + return max_line_length; + } + + //************************************************************************* + /// Get the padding flag + //************************************************************************* + ETL_CONSTEXPR14 + bool using_padding() const + { + return use_padding; + } + + //************************************************************************* + /// Get the line break flag + //************************************************************************* + ETL_CONSTEXPR14 + bool has_line_breaks() const + { + return max_line_length != etl::integral_limits::max; + } + //************************************************************************* /// Encode to Base64 /// Four parameter @@ -491,8 +646,7 @@ namespace etl } else { - // Should never get here. - assert(false); + ETL_ASSERT_FAIL_AND_RETURN_VALUE(ETL_ERROR(base64_illegal_character), 0); return padding(); } } @@ -525,9 +679,7 @@ namespace etl } else { - // Should never get here. - assert(false); - return 0; + ETL_ASSERT_FAIL_AND_RETURN_VALUE(ETL_ERROR(base64_illegal_character), 0); } } @@ -537,11 +689,36 @@ namespace etl template ETL_NODISCARD ETL_CONSTEXPR14 - static T padding() + static + T padding() { return static_cast('='); } + //************************************************************************* + /// Is the character a carriage return? + //************************************************************************* + template + ETL_NODISCARD + ETL_CONSTEXPR14 + static + bool is_carriage_return(T c) + { + return (static_cast(c) == '\r'); + } + + //************************************************************************* + /// Is the character a line break? + //************************************************************************* + template + ETL_NODISCARD + ETL_CONSTEXPR14 + static + bool is_line_feed(T c) + { + return (static_cast(c) == '\n'); + } + //************************************************************************* /// Encode to Base64 implementation //************************************************************************* @@ -671,7 +848,9 @@ namespace etl return output_length; } - bool use_padding; + Encoding encoding; + bool use_padding; + size_t max_line_length; }; } diff --git a/test/test_base64.cpp b/test/test_base64_RFC4648_with_padding.cpp similarity index 93% rename from test/test_base64.cpp rename to test/test_base64_RFC4648_with_padding.cpp index 8ab90c2b..81a37460 100644 --- a/test/test_base64.cpp +++ b/test/test_base64_RFC4648_with_padding.cpp @@ -40,6 +40,10 @@ SOFTWARE. #include "etl/integral_limits.h" +//***************************************************************************** +// Ecode/decode using RFC-4648 with padding +//***************************************************************************** + namespace { std::array input_data_unsigned_char = @@ -343,12 +347,12 @@ namespace "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N+27j/cebMXjnZljpYhuYjRbdDd/9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHACPltrIR4SYRva/sgO5xJ+06AaYIlhpXVTZHt0ncqJECK302ALc3VWiamcRVCDj+ycBQpH40jLsHqzvl+bN8co4QrJDWnY8gLH4u6Ub/pUYDSI7XRtFmufTAdABzYcGwWccdWCP6BrvvgktjbuVd8mctC7/yzVh7RQtMMGLPurxp3qFI8ns3eITQ+H7VU1/u0vQ==" }; - SUITE(test_base64) + SUITE(test_base64_rfc4648_with_padding) { //************************************************************************* TEST(test_encode_unsigned_char_pointer_size) { - etl::base64 b64; + etl::base64 b64(etl::base64::Encoding::RFC_4648, etl::base64::Padding::Use_Padding); std::array encoded_output; for (size_t i = 0; i < 256; ++i) @@ -356,7 +360,7 @@ namespace encoded_output.fill(0); auto size = b64.encode(input_data_unsigned_char.data(), i, - encoded_output.data(), encoded_output.size()); + encoded_output.data(), encoded_output.size()); std::string expected(encoded[i]); std::string actual(encoded_output.data(), size); @@ -369,7 +373,7 @@ namespace //************************************************************************* TEST(test_encode_unsigned_char_pointer_size_no_output_length) { - etl::base64 b64; + etl::base64 b64(etl::base64::Encoding::RFC_4648, etl::base64::Padding::Use_Padding); std::array encoded_output; for (size_t i = 0; i < 256; ++i) @@ -377,7 +381,7 @@ namespace encoded_output.fill(0); auto size = b64.encode(input_data_unsigned_char.data(), i, - encoded_output.data()); + encoded_output.data()); std::string expected(encoded[i]); std::string actual(encoded_output.data(), size); @@ -390,14 +394,14 @@ namespace //************************************************************************* TEST(test_encode_unsigned_char_pointer_size_to_back_inserter) { - etl::base64 b64; + etl::base64 b64(etl::base64::Encoding::RFC_4648, etl::base64::Padding::Use_Padding); for (size_t i = 0; i < 256; ++i) { std::string actual; auto size = b64.encode(input_data_unsigned_char.data(), i, - etl::back_inserter(actual)); + etl::back_inserter(actual)); std::string expected(encoded[i]); @@ -409,7 +413,7 @@ namespace //************************************************************************* TEST(test_encode_unsigned_char_pointer_pointer) { - etl::base64 b64; + etl::base64 b64(etl::base64::Encoding::RFC_4648, etl::base64::Padding::Use_Padding); std::array encoded_output; for (size_t i = 0; i < 256; ++i) @@ -417,7 +421,7 @@ namespace encoded_output.fill(0); auto size = b64.encode(input_data_unsigned_char.data(), input_data_unsigned_char.data() + i, - encoded_output.data(), encoded_output.data() + encoded_output.size()); + encoded_output.data(), encoded_output.data() + encoded_output.size()); std::string expected(encoded[i]); std::string actual(encoded_output.data(), size); @@ -430,7 +434,7 @@ namespace //************************************************************************* TEST(test_encode_unsigned_char_pointer_pointer_no_output_end_pointer) { - etl::base64 b64; + etl::base64 b64(etl::base64::Encoding::RFC_4648, etl::base64::Padding::Use_Padding); std::array encoded_output; for (size_t i = 6; i < 256; ++i) @@ -438,7 +442,7 @@ namespace encoded_output.fill(0); auto size = b64.encode(input_data_unsigned_char.data(), input_data_unsigned_char.data() + i, - encoded_output.data()); + encoded_output.data()); std::string expected(encoded[i]); std::string actual(encoded_output.data(), size); @@ -451,7 +455,7 @@ namespace //************************************************************************* TEST(test_encode_int8_t_pointer_size) { - etl::base64 b64; + etl::base64 b64(etl::base64::Encoding::RFC_4648, etl::base64::Padding::Use_Padding); std::array encoded_output; for (size_t i = 11; i < 256; ++i) @@ -459,7 +463,7 @@ namespace encoded_output.fill(0); auto size = b64.encode(input_data_int8_t.data(), i, - encoded_output.data(), encoded_output.size()); + encoded_output.data(), encoded_output.size()); std::string expected(encoded[i]); std::string actual(encoded_output.data(), size); @@ -472,7 +476,7 @@ namespace //************************************************************************* TEST(test_encode_int8_t_pointer_size_no_output_length) { - etl::base64 b64; + etl::base64 b64(etl::base64::Encoding::RFC_4648, etl::base64::Padding::Use_Padding); std::array encoded_output; for (size_t i = 6; i < 256; ++i) @@ -480,7 +484,7 @@ namespace encoded_output.fill(0); auto size = b64.encode(input_data_int8_t.data(), i, - encoded_output.data()); + encoded_output.data()); std::string expected(encoded[i]); std::string actual(encoded_output.data(), size); @@ -493,14 +497,14 @@ namespace //************************************************************************* TEST(test_encode_int8_t_pointer_size_to_back_inserter) { - etl::base64 b64; + etl::base64 b64(etl::base64::Encoding::RFC_4648, etl::base64::Padding::Use_Padding); for (size_t i = 0; i < 256; ++i) { std::string actual; auto size = b64.encode(input_data_int8_t.data(), i, - etl::back_inserter(actual)); + etl::back_inserter(actual)); std::string expected(encoded[i]); @@ -512,7 +516,7 @@ namespace //************************************************************************* TEST(test_encode_int8_t_pointer_pointer) { - etl::base64 b64; + etl::base64 b64(etl::base64::Encoding::RFC_4648, etl::base64::Padding::Use_Padding); std::array encoded_output; for (size_t i = 0; i < 256; ++i) @@ -520,7 +524,7 @@ namespace encoded_output.fill(0); auto size = b64.encode(input_data_int8_t.data(), input_data_int8_t.data() + i, - encoded_output.data(), encoded_output.data() + encoded_output.size()); + encoded_output.data(), encoded_output.data() + encoded_output.size()); std::string expected(encoded[i]); std::string actual(encoded_output.data(), size); @@ -533,7 +537,7 @@ namespace //************************************************************************* TEST(test_encode_int8_t_pointer_pointer_no_end_pointer) { - etl::base64 b64; + etl::base64 b64(etl::base64::Encoding::RFC_4648, etl::base64::Padding::Use_Padding); std::array encoded_output; @@ -542,7 +546,7 @@ namespace encoded_output.fill(0); auto size = b64.encode(input_data_int8_t.data(), input_data_int8_t.data() + i, - encoded_output.data()); + encoded_output.data()); std::string expected(encoded[i]); std::string actual(encoded_output.data(), size); @@ -557,7 +561,7 @@ namespace template constexpr auto GetConstexprBase64(const etl::array input) noexcept { - etl::base64 b64; + etl::base64 b64(etl::base64::Encoding::RFC_4648, etl::base64::Padding::Use_Padding); constexpr size_t encoded_size = etl::base64::encoded_size(Size); etl::array output{ 0 }; @@ -585,18 +589,18 @@ namespace //************************************************************************* TEST(test_encode_overflow) { - etl::base64 b64; + etl::base64 b64(etl::base64::Encoding::RFC_4648, etl::base64::Padding::Use_Padding); std::array encoded_output{ 0 }; CHECK_THROW((b64.encode(input_data_unsigned_char.data(), 10, - encoded_output.data(), encoded_output.size())), + encoded_output.data(), encoded_output.size())), etl::base64_overflow); } //************************************************************************* TEST(test_decode_unsigned_char_pointer_size) { - etl::base64 b64; + etl::base64 b64(etl::base64::Encoding::RFC_4648, etl::base64::Padding::Use_Padding); std::array decoded_output; for (size_t i = 0; i < 256; ++i) @@ -604,7 +608,7 @@ namespace decoded_output.fill(0); auto decoded_size = b64.decode(encoded[i].data(), encoded[i].size(), - decoded_output.data(), decoded_output.size()); + decoded_output.data(), decoded_output.size()); CHECK_ARRAY_EQUAL(input_data_unsigned_char.data(), decoded_output.data(), i); CHECK_EQUAL(i, etl::base64::decoded_size(encoded[i].data(), encoded[i].size())); @@ -615,7 +619,7 @@ namespace //************************************************************************* TEST(test_decode_unsigned_char_pointer_size_no_end_pointer) { - etl::base64 b64; + etl::base64 b64(etl::base64::Encoding::RFC_4648, etl::base64::Padding::Use_Padding); std::array decoded_output; for (size_t i = 0; i < 256; ++i) @@ -623,7 +627,7 @@ namespace decoded_output.fill(0); auto decoded_size = b64.decode(encoded[i].data(), encoded[i].size(), - decoded_output.data()); + decoded_output.data()); CHECK_ARRAY_EQUAL(input_data_unsigned_char.data(), decoded_output.data(), i); CHECK_EQUAL(i, etl::base64::decoded_size(encoded[i].data(), encoded[i].size())); @@ -634,7 +638,7 @@ namespace //************************************************************************* TEST(test_decode_unsigned_char_pointer_pointer) { - etl::base64 b64; + etl::base64 b64(etl::base64::Encoding::RFC_4648, etl::base64::Padding::Use_Padding); std::array decoded_output; for (size_t i = 0; i < 256; ++i) @@ -642,7 +646,7 @@ namespace decoded_output.fill(0); auto decoded_size = b64.decode(encoded[i].data(), encoded[i].data() + encoded[i].size(), - decoded_output.data(), decoded_output.data() + decoded_output.size()); + decoded_output.data(), decoded_output.data() + decoded_output.size()); CHECK_ARRAY_EQUAL(input_data_unsigned_char.data(), decoded_output.data(), i); CHECK_EQUAL(i, etl::base64::decoded_size(encoded[i].data(), encoded[i].size())); @@ -653,7 +657,7 @@ namespace //************************************************************************* TEST(test_decode_unsigned_char_pointer_pointer_no_end_pointer) { - etl::base64 b64; + etl::base64 b64(etl::base64::Encoding::RFC_4648, etl::base64::Padding::Use_Padding); std::array decoded_output; for (size_t i = 0; i < 256; ++i) @@ -661,7 +665,7 @@ namespace decoded_output.fill(0); auto decoded_size = b64.decode(encoded[i].data(), encoded[i].data() + encoded[i].size(), - decoded_output.data()); + decoded_output.data()); CHECK_ARRAY_EQUAL(input_data_unsigned_char.data(), decoded_output.data(), i); CHECK_EQUAL(i, etl::base64::decoded_size(encoded[i].data(), encoded[i].size())); @@ -672,7 +676,7 @@ namespace //************************************************************************* TEST(test_decode_int8_t_pointer_size) { - etl::base64 b64; + etl::base64 b64(etl::base64::Encoding::RFC_4648, etl::base64::Padding::Use_Padding); std::array decoded_output; for (size_t i = 0; i < 256; ++i) @@ -680,7 +684,7 @@ namespace decoded_output.fill(0); auto decoded_size = b64.decode(encoded[i].data(), encoded[i].size(), - decoded_output.data(), decoded_output.size()); + decoded_output.data(), decoded_output.size()); CHECK_ARRAY_EQUAL(input_data_int8_t.data(), decoded_output.data(), i); CHECK_EQUAL(i, etl::base64::decoded_size(encoded[i].data(), encoded[i].size())); @@ -691,7 +695,7 @@ namespace //************************************************************************* TEST(test_decode_int8_t_pointer_size_back_inserter) { - etl::base64 b64; + etl::base64 b64(etl::base64::Encoding::RFC_4648, etl::base64::Padding::Use_Padding); std::vector decoded_output; for (size_t i = 0; i < 256; ++i) @@ -699,7 +703,7 @@ namespace decoded_output.clear(); auto decoded_size = b64.decode(encoded[i].data(), encoded[i].size(), - etl::back_inserter(decoded_output)); + etl::back_inserter(decoded_output)); CHECK_ARRAY_EQUAL(input_data_int8_t.data(), decoded_output.data(), i); CHECK_EQUAL(i, etl::base64::decoded_size(encoded[i].data(), encoded[i].size())); @@ -710,7 +714,7 @@ namespace //************************************************************************* TEST(test_decode_int8_t_pointer_size_no_output_size) { - etl::base64 b64; + etl::base64 b64(etl::base64::Encoding::RFC_4648, etl::base64::Padding::Use_Padding); std::array decoded_output; for (size_t i = 0; i < 256; ++i) @@ -718,7 +722,7 @@ namespace decoded_output.fill(0); auto decoded_size = b64.decode(encoded[i].data(), encoded[i].size(), - decoded_output.data()); + decoded_output.data()); CHECK_ARRAY_EQUAL(input_data_int8_t.data(), decoded_output.data(), i); CHECK_EQUAL(i, etl::base64::decoded_size(encoded[i].data(), encoded[i].size())); @@ -729,7 +733,7 @@ namespace //************************************************************************* TEST(test_decode_int8_t_pointer_pointer) { - etl::base64 b64; + etl::base64 b64(etl::base64::Encoding::RFC_4648, etl::base64::Padding::Use_Padding); std::array decoded_output; for (size_t i = 0; i < 256; ++i) @@ -737,7 +741,7 @@ namespace decoded_output.fill(0); auto decoded_size = b64.decode(encoded[i].data(), encoded[i].data() + encoded[i].size(), - decoded_output.data(), decoded_output.data() + decoded_output.size()); + decoded_output.data(), decoded_output.data() + decoded_output.size()); CHECK_ARRAY_EQUAL(input_data_int8_t.data(), decoded_output.data(), i); CHECK_EQUAL(i, etl::base64::decoded_size(encoded[i].data(), encoded[i].size())); @@ -748,7 +752,7 @@ namespace //************************************************************************* TEST(test_decode_int8_t_pointer_pointer_back_inserter) { - etl::base64 b64; + etl::base64 b64(etl::base64::Encoding::RFC_4648, etl::base64::Padding::Use_Padding); std::vector decoded_output; for (size_t i = 0; i < 256; ++i) @@ -756,7 +760,7 @@ namespace decoded_output.clear(); auto decoded_size = b64.decode(encoded[i].data(), encoded[i].data() + encoded[i].size(), - etl::back_inserter(decoded_output)); + etl::back_inserter(decoded_output)); CHECK_ARRAY_EQUAL(input_data_int8_t.data(), decoded_output.data(), i); CHECK_EQUAL(i, etl::base64::decoded_size(encoded[i].data(), encoded[i].size())); @@ -767,7 +771,7 @@ namespace //************************************************************************* TEST(test_decode_int8_t_pointer_pointer_no_end_pointer) { - etl::base64 b64; + etl::base64 b64(etl::base64::Encoding::RFC_4648, etl::base64::Padding::Use_Padding); std::array decoded_output; for (size_t i = 0; i < 256; ++i) @@ -775,7 +779,7 @@ namespace decoded_output.fill(0); auto decoded_size = b64.decode(encoded[i].data(), encoded[i].data() + encoded[i].size(), - decoded_output.data()); + decoded_output.data()); CHECK_ARRAY_EQUAL(input_data_int8_t.data(), decoded_output.data(), i); CHECK_EQUAL(i, etl::base64::decoded_size(encoded[i].data(), encoded[i].size())); @@ -786,17 +790,30 @@ namespace //************************************************************************* TEST(test_decode_overflow) { - etl::base64 b64; + etl::base64 b64(etl::base64::Encoding::RFC_4648, etl::base64::Padding::Use_Padding); std::array decoded_output{ 0 }; CHECK_THROW((b64.decode(encoded[10].data(), encoded[10].size(), - decoded_output.data(), decoded_output.size())), etl::base64_overflow); + decoded_output.data(), decoded_output.size())), etl::base64_overflow); + } + + //************************************************************************* + TEST(test_decode_invalid_character) + { + etl::base64 b64(etl::base64::Encoding::RFC_4648, etl::base64::Padding::Use_Padding); + std::array decoded_output{ 0 }; + + std::string invalid_chararacter("OycD£Qy37KA=="); + std::string invalid_padding("OycDQy37KA&="); + + CHECK_THROW((b64.decode(invalid_chararacter.data(), invalid_chararacter.size(), + decoded_output.data(), decoded_output.size())), etl::base64_illegal_character); } //************************************************************************* TEST(test_decoded_size) { - etl::base64 b64; + etl::base64 b64(etl::base64::Encoding::RFC_4648, etl::base64::Padding::Use_Padding); for (size_t i = 0; i < 256; ++i) { diff --git a/test/vs2022/etl.vcxproj b/test/vs2022/etl.vcxproj index 6d02d902..025fe5c6 100644 --- a/test/vs2022/etl.vcxproj +++ b/test/vs2022/etl.vcxproj @@ -7210,7 +7210,7 @@ - + diff --git a/test/vs2022/etl.vcxproj.filters b/test/vs2022/etl.vcxproj.filters index 04a0462b..58bc261b 100644 --- a/test/vs2022/etl.vcxproj.filters +++ b/test/vs2022/etl.vcxproj.filters @@ -2354,81 +2354,6 @@ Tests\Patterns - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - - - Tests\Sanity Checks\Source - Tests\Binary @@ -2522,7 +2447,7 @@ Tests\Misc - + Tests\Codecs From b99fa790c29d4beccd4f42349acc598a62ab0811 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Sat, 21 Oct 2023 20:29:08 +0100 Subject: [PATCH 11/12] Refactor to support multiple RFCs --- include/etl/base64.h | 208 ++++++++++++---------- test/test_base64_RFC4648_with_padding.cpp | 100 +++++------ 2 files changed, 161 insertions(+), 147 deletions(-) diff --git a/include/etl/base64.h b/include/etl/base64.h index 76a8396a..c34847c1 100644 --- a/include/etl/base64.h +++ b/include/etl/base64.h @@ -101,7 +101,7 @@ namespace etl //************************************************************************* /// Codec for Base64 (RFC 4648) //************************************************************************* - class base64 + class ibase64 { public: @@ -118,8 +118,12 @@ namespace etl }; ETL_DECLARE_ENUM_TYPE(Encoding, int) - ETL_ENUM_TYPE(RFC_1421, "RFC 1421") - ETL_ENUM_TYPE(RFC_2045, "RFC 2045") + ETL_ENUM_TYPE(RFC_1421, "RFC_1421") + ETL_ENUM_TYPE(RFC_2045, "RFC_2045") + ETL_ENUM_TYPE(RFC_2152, "RFC_2152") + ETL_ENUM_TYPE(RFC_3501, "RFC_3501") + ETL_ENUM_TYPE(RFC_4648, "RFC_4648") + ETL_ENUM_TYPE(RFC_4648_URL, "RFC_4648_URL") ETL_END_ENUM_TYPE }; @@ -132,82 +136,11 @@ namespace etl }; ETL_DECLARE_ENUM_TYPE(Padding, bool) - ETL_ENUM_TYPE(Use_Padding, "Use padding") - ETL_ENUM_TYPE(No_Padding, "No padding") + ETL_ENUM_TYPE(Use_Padding, "Use_Padding") + ETL_ENUM_TYPE(No_Padding, "No_Padding") ETL_END_ENUM_TYPE }; - //************************************************************************* - /// Default constructor - //************************************************************************* - ETL_CONSTEXPR14 - base64() - : encoding(Encoding::RFC_4648) - , use_padding(true) - , max_line_length(etl::integral_limits::max) - { - } - - //************************************************************************* - /// Constructor - //************************************************************************* - ETL_CONSTEXPR14 - base64(Encoding encoding_, bool use_padding_ = etl::base64::Padding::Use_Padding) - : encoding(Encoding::RFC_4648) - , use_padding(false) - , max_line_length(0) - { - switch (encoding) - { - case Encoding::RFC_1421: - { - use_padding = true; - max_line_length = 64; - break; - } - - case Encoding::RFC_2045: - { - use_padding = true; - max_line_length = 76; - break; - } - - case Encoding::RFC_2152: - { - use_padding = false; - max_line_length = etl::integral_limits::max; - break; - } - - case Encoding::RFC_3501: - { - use_padding = false; - max_line_length = etl::integral_limits::max; - break; - } - - case Encoding::RFC_4648: - { - use_padding = use_padding_; - max_line_length = etl::integral_limits::max; - break; - } - - case Encoding::RFC_4648_URL: - { - use_padding = use_padding_; - max_line_length = etl::integral_limits::max; - break; - } - - default: - { - break; - } - } - } - //************************************************************************* /// Get the encoding standard //************************************************************************* @@ -259,7 +192,7 @@ namespace etl const size_t output_length = static_cast(etl::distance(output_begin, output_end)); // Figure out if the output buffer is large enough. - size_t required_output_length = etl::base64::encoded_size(input_length); + size_t required_output_length = encoded_size(input_length); ETL_ASSERT_OR_RETURN_VALUE(output_length >= required_output_length, ETL_ERROR(base64_overflow), 0U); return process_encode(input_begin, input_length, output_begin, required_output_length); @@ -316,7 +249,7 @@ namespace etl ETL_STATIC_ASSERT(ETL_IS_ITERATOR_TYPE_8_BIT_INTEGRAL(TOutputIterator), "Output type must be an 8 bit integral"); // Figure out if the output buffer is large enough. - size_t required_output_length = etl::base64::encoded_size(input_length); + size_t required_output_length = encoded_size(input_length); ETL_ASSERT_OR_RETURN_VALUE(output_length >= required_output_length, ETL_ERROR(base64_overflow), 0U); return process_encode(input_begin, input_length, output_begin, required_output_length); @@ -391,7 +324,7 @@ namespace etl const size_t output_length = static_cast(etl::distance(output_begin, output_end)); // Figure out if the output buffer is large enough. - size_t required_output_length = etl::base64::decoded_size_from_valid_input_length(input_length); + size_t required_output_length = decoded_size_from_valid_input_length(input_length); ETL_ASSERT_OR_RETURN_VALUE(output_length >= required_output_length, ETL_ERROR(base64_overflow), 0U); return process_decode(input_begin, input_length, output_begin, required_output_length); @@ -457,7 +390,7 @@ namespace etl input_length = valid_input_length(input_begin, input_length); // Figure out if the output buffer is large enough. - size_t required_output_length = etl::base64::decoded_size_from_valid_input_length(input_length); + size_t required_output_length = decoded_size_from_valid_input_length(input_length); ETL_ASSERT_OR_RETURN_VALUE(output_length >= required_output_length, ETL_ERROR(base64_overflow), 0U); return process_decode(input_begin, input_length, output_begin, required_output_length); @@ -604,23 +537,29 @@ namespace etl return input_length - (input_length / 4U); } - private: + protected: - // 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', '+', '/' + //************************************************************************* + /// Constructor + //************************************************************************* + ETL_CONSTEXPR14 + ibase64(Encoding encoding_, const char* lookup_, bool use_padding_, bool discard_illegal_characters_, size_t max_line_length_) + : encoding(encoding_) + , lookup(lookup_) + , use_padding(use_padding_) + , discard_illegal_characters(discard_illegal_characters_) + , max_line_length(max_line_length_) + { + } + + private: //************************************************************************* // Translates an index into a sextet //************************************************************************* template - ETL_CONSTEXPR14 static T get_sextet_from_index(char index) + ETL_CONSTEXPR14 + T get_sextet_from_index(char index) { if ((index >= 0) && (index < 26)) { @@ -638,11 +577,11 @@ namespace etl } else if (index == 62) { - return static_cast('+'); + return static_cast(lookup[62]); } else if (index == 63) { - return static_cast('/'); + return static_cast(lookup[63]); } else { @@ -655,7 +594,8 @@ namespace etl // Translates a sextet into an index //************************************************************************* template - ETL_CONSTEXPR14 static uint32_t get_index_from_sextet(T sextet) + ETL_CONSTEXPR14 + uint32_t get_index_from_sextet(T sextet) { if ((sextet >= 'A') && (sextet <= 'Z')) { @@ -848,9 +788,83 @@ namespace etl return output_length; } - Encoding encoding; - bool use_padding; - size_t max_line_length; + Encoding encoding; + const char* lookup; + bool use_padding; + bool discard_illegal_characters; + size_t max_line_length; + }; + + //************************************************************************* + /// Base64 RFC-1421 + //************************************************************************* + class base64_rfc1421 : public ibase64 + { + public: + + ETL_CONSTEXPR14 + base64_rfc1421() + : ibase64(etl::ibase64::Encoding::RFC_1421, + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/", + etl::ibase64::Padding::Use_Padding, + false, + 64U) + { + } + }; + + //************************************************************************* + /// Base64 RFC-2045 + //************************************************************************* + class base64_rfc2045 : public ibase64 + { + public: + + ETL_CONSTEXPR14 + base64_rfc2045(size_t max_line_length) + : ibase64(etl::ibase64::Encoding::RFC_2045, + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/", + etl::ibase64::Padding::Use_Padding, + true, + max_line_length) + { + } + }; + + //************************************************************************* + /// Base64 RFC-4648 + //************************************************************************* + class base64_rfc4648 : public ibase64 + { + public: + + ETL_CONSTEXPR14 + base64_rfc4648(etl::ibase64::Padding use_padding) + : ibase64(etl::ibase64::Encoding::RFC_4648, + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/", + use_padding, + false, + etl::integral_limits::max) + { + } + }; + + //************************************************************************* + /// Base64 RFC-4648 URL + //************************************************************************* + class base64_rfc4648_url : public ibase64 + { + public: + + ETL_CONSTEXPR14 + base64_rfc4648_url(etl::ibase64::Padding use_padding) + : ibase64(etl::ibase64::Encoding::RFC_4648_URL, + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_", + use_padding, + false, + etl::integral_limits::max) + { + } }; } diff --git a/test/test_base64_RFC4648_with_padding.cpp b/test/test_base64_RFC4648_with_padding.cpp index 81a37460..a6a323da 100644 --- a/test/test_base64_RFC4648_with_padding.cpp +++ b/test/test_base64_RFC4648_with_padding.cpp @@ -352,7 +352,7 @@ namespace //************************************************************************* TEST(test_encode_unsigned_char_pointer_size) { - etl::base64 b64(etl::base64::Encoding::RFC_4648, etl::base64::Padding::Use_Padding); + etl::base64_rfc4648 b64(etl::ibase64::Padding::Use_Padding); std::array encoded_output; for (size_t i = 0; i < 256; ++i) @@ -366,14 +366,14 @@ namespace std::string actual(encoded_output.data(), size); CHECK_EQUAL(expected, actual); - CHECK_EQUAL(etl::base64::encoded_size(i), size); + CHECK_EQUAL(etl::base64_rfc4648::encoded_size(i), size); } } //************************************************************************* TEST(test_encode_unsigned_char_pointer_size_no_output_length) { - etl::base64 b64(etl::base64::Encoding::RFC_4648, etl::base64::Padding::Use_Padding); + etl::base64_rfc4648 b64(etl::ibase64::Padding::Use_Padding); std::array encoded_output; for (size_t i = 0; i < 256; ++i) @@ -387,14 +387,14 @@ namespace std::string actual(encoded_output.data(), size); CHECK_EQUAL(expected, actual); - CHECK_EQUAL(etl::base64::encoded_size(i), size); + CHECK_EQUAL(etl::base64_rfc4648::encoded_size(i), size); } } //************************************************************************* TEST(test_encode_unsigned_char_pointer_size_to_back_inserter) { - etl::base64 b64(etl::base64::Encoding::RFC_4648, etl::base64::Padding::Use_Padding); + etl::base64_rfc4648 b64(etl::ibase64::Padding::Use_Padding); for (size_t i = 0; i < 256; ++i) { @@ -406,14 +406,14 @@ namespace std::string expected(encoded[i]); CHECK_EQUAL(expected, actual); - CHECK_EQUAL(etl::base64::encoded_size(i), size); + CHECK_EQUAL(etl::base64_rfc4648::encoded_size(i), size); } } //************************************************************************* TEST(test_encode_unsigned_char_pointer_pointer) { - etl::base64 b64(etl::base64::Encoding::RFC_4648, etl::base64::Padding::Use_Padding); + etl::base64_rfc4648 b64(etl::ibase64::Padding::Use_Padding); std::array encoded_output; for (size_t i = 0; i < 256; ++i) @@ -427,14 +427,14 @@ namespace std::string actual(encoded_output.data(), size); CHECK_EQUAL(expected, actual); - CHECK_EQUAL(etl::base64::encoded_size(i), size); + CHECK_EQUAL(etl::base64_rfc4648::encoded_size(i), size); } } //************************************************************************* TEST(test_encode_unsigned_char_pointer_pointer_no_output_end_pointer) { - etl::base64 b64(etl::base64::Encoding::RFC_4648, etl::base64::Padding::Use_Padding); + etl::base64_rfc4648 b64(etl::ibase64::Padding::Use_Padding); std::array encoded_output; for (size_t i = 6; i < 256; ++i) @@ -448,14 +448,14 @@ namespace std::string actual(encoded_output.data(), size); CHECK_EQUAL(expected, actual); - CHECK_EQUAL(etl::base64::encoded_size(i), size); + CHECK_EQUAL(etl::base64_rfc4648::encoded_size(i), size); } } //************************************************************************* TEST(test_encode_int8_t_pointer_size) { - etl::base64 b64(etl::base64::Encoding::RFC_4648, etl::base64::Padding::Use_Padding); + etl::base64_rfc4648 b64(etl::ibase64::Padding::Use_Padding); std::array encoded_output; for (size_t i = 11; i < 256; ++i) @@ -469,14 +469,14 @@ namespace std::string actual(encoded_output.data(), size); CHECK_EQUAL(expected, actual); - CHECK_EQUAL(etl::base64::encoded_size(i), size); + CHECK_EQUAL(etl::base64_rfc4648::encoded_size(i), size); } } //************************************************************************* TEST(test_encode_int8_t_pointer_size_no_output_length) { - etl::base64 b64(etl::base64::Encoding::RFC_4648, etl::base64::Padding::Use_Padding); + etl::base64_rfc4648 b64(etl::ibase64::Padding::Use_Padding); std::array encoded_output; for (size_t i = 6; i < 256; ++i) @@ -490,14 +490,14 @@ namespace std::string actual(encoded_output.data(), size); CHECK_EQUAL(expected, actual); - CHECK_EQUAL(etl::base64::encoded_size(i), size); + CHECK_EQUAL(etl::base64_rfc4648::encoded_size(i), size); } } //************************************************************************* TEST(test_encode_int8_t_pointer_size_to_back_inserter) { - etl::base64 b64(etl::base64::Encoding::RFC_4648, etl::base64::Padding::Use_Padding); + etl::base64_rfc4648 b64(etl::ibase64::Padding::Use_Padding); for (size_t i = 0; i < 256; ++i) { @@ -509,14 +509,14 @@ namespace std::string expected(encoded[i]); CHECK_EQUAL(expected, actual); - CHECK_EQUAL(etl::base64::encoded_size(i), size); + CHECK_EQUAL(etl::base64_rfc4648::encoded_size(i), size); } } //************************************************************************* TEST(test_encode_int8_t_pointer_pointer) { - etl::base64 b64(etl::base64::Encoding::RFC_4648, etl::base64::Padding::Use_Padding); + etl::base64_rfc4648 b64(etl::ibase64::Padding::Use_Padding); std::array encoded_output; for (size_t i = 0; i < 256; ++i) @@ -530,14 +530,14 @@ namespace std::string actual(encoded_output.data(), size); CHECK_EQUAL(expected, actual); - CHECK_EQUAL(etl::base64::encoded_size(i), size); + CHECK_EQUAL(etl::base64_rfc4648::encoded_size(i), size); } } //************************************************************************* TEST(test_encode_int8_t_pointer_pointer_no_end_pointer) { - etl::base64 b64(etl::base64::Encoding::RFC_4648, etl::base64::Padding::Use_Padding); + etl::base64_rfc4648 b64(etl::ibase64::Padding::Use_Padding); std::array encoded_output; @@ -552,7 +552,7 @@ namespace std::string actual(encoded_output.data(), size); CHECK_EQUAL(expected, actual); - CHECK_EQUAL(etl::base64::encoded_size(i), size); + CHECK_EQUAL(etl::base64_rfc4648::encoded_size(i), size); } } @@ -561,10 +561,10 @@ namespace template constexpr auto GetConstexprBase64(const etl::array input) noexcept { - etl::base64 b64(etl::base64::Encoding::RFC_4648, etl::base64::Padding::Use_Padding); + etl::base64_rfc4648 b64(etl::ibase64::Padding::Use_Padding); - constexpr size_t encoded_size = etl::base64::encoded_size(Size); - etl::array output{ 0 }; + constexpr size_t encoded_size = etl::base64_rfc4648::encoded_size(Size); + etl::array output{ 0 }; b64.encode(input.begin(), Size, output._buffer, encoded_size); @@ -582,14 +582,14 @@ namespace std::string actual(output.data(), output.size()); CHECK_EQUAL(expected, actual); - CHECK_EQUAL(etl::base64::encoded_size(10), output.size()); + CHECK_EQUAL(etl::base64_rfc4648::encoded_size(10), output.size()); } #endif //************************************************************************* TEST(test_encode_overflow) { - etl::base64 b64(etl::base64::Encoding::RFC_4648, etl::base64::Padding::Use_Padding); + etl::base64_rfc4648 b64(etl::ibase64::Padding::Use_Padding); std::array encoded_output{ 0 }; CHECK_THROW((b64.encode(input_data_unsigned_char.data(), 10, @@ -600,7 +600,7 @@ namespace //************************************************************************* TEST(test_decode_unsigned_char_pointer_size) { - etl::base64 b64(etl::base64::Encoding::RFC_4648, etl::base64::Padding::Use_Padding); + etl::base64_rfc4648 b64(etl::ibase64::Padding::Use_Padding); std::array decoded_output; for (size_t i = 0; i < 256; ++i) @@ -611,7 +611,7 @@ namespace decoded_output.data(), decoded_output.size()); CHECK_ARRAY_EQUAL(input_data_unsigned_char.data(), decoded_output.data(), i); - CHECK_EQUAL(i, etl::base64::decoded_size(encoded[i].data(), encoded[i].size())); + CHECK_EQUAL(i, etl::base64_rfc4648::decoded_size(encoded[i].data(), encoded[i].size())); CHECK_EQUAL(i, decoded_size); } } @@ -619,7 +619,7 @@ namespace //************************************************************************* TEST(test_decode_unsigned_char_pointer_size_no_end_pointer) { - etl::base64 b64(etl::base64::Encoding::RFC_4648, etl::base64::Padding::Use_Padding); + etl::base64_rfc4648 b64(etl::ibase64::Padding::Use_Padding); std::array decoded_output; for (size_t i = 0; i < 256; ++i) @@ -630,7 +630,7 @@ namespace decoded_output.data()); CHECK_ARRAY_EQUAL(input_data_unsigned_char.data(), decoded_output.data(), i); - CHECK_EQUAL(i, etl::base64::decoded_size(encoded[i].data(), encoded[i].size())); + CHECK_EQUAL(i, etl::base64_rfc4648::decoded_size(encoded[i].data(), encoded[i].size())); CHECK_EQUAL(i, decoded_size); } } @@ -638,7 +638,7 @@ namespace //************************************************************************* TEST(test_decode_unsigned_char_pointer_pointer) { - etl::base64 b64(etl::base64::Encoding::RFC_4648, etl::base64::Padding::Use_Padding); + etl::base64_rfc4648 b64(etl::ibase64::Padding::Use_Padding); std::array decoded_output; for (size_t i = 0; i < 256; ++i) @@ -649,7 +649,7 @@ namespace decoded_output.data(), decoded_output.data() + decoded_output.size()); CHECK_ARRAY_EQUAL(input_data_unsigned_char.data(), decoded_output.data(), i); - CHECK_EQUAL(i, etl::base64::decoded_size(encoded[i].data(), encoded[i].size())); + CHECK_EQUAL(i, etl::base64_rfc4648::decoded_size(encoded[i].data(), encoded[i].size())); CHECK_EQUAL(i, decoded_size); } } @@ -657,7 +657,7 @@ namespace //************************************************************************* TEST(test_decode_unsigned_char_pointer_pointer_no_end_pointer) { - etl::base64 b64(etl::base64::Encoding::RFC_4648, etl::base64::Padding::Use_Padding); + etl::base64_rfc4648 b64(etl::ibase64::Padding::Use_Padding); std::array decoded_output; for (size_t i = 0; i < 256; ++i) @@ -668,7 +668,7 @@ namespace decoded_output.data()); CHECK_ARRAY_EQUAL(input_data_unsigned_char.data(), decoded_output.data(), i); - CHECK_EQUAL(i, etl::base64::decoded_size(encoded[i].data(), encoded[i].size())); + CHECK_EQUAL(i, etl::base64_rfc4648::decoded_size(encoded[i].data(), encoded[i].size())); CHECK_EQUAL(i, decoded_size); } } @@ -676,7 +676,7 @@ namespace //************************************************************************* TEST(test_decode_int8_t_pointer_size) { - etl::base64 b64(etl::base64::Encoding::RFC_4648, etl::base64::Padding::Use_Padding); + etl::base64_rfc4648 b64(etl::ibase64::Padding::Use_Padding); std::array decoded_output; for (size_t i = 0; i < 256; ++i) @@ -687,7 +687,7 @@ namespace decoded_output.data(), decoded_output.size()); CHECK_ARRAY_EQUAL(input_data_int8_t.data(), decoded_output.data(), i); - CHECK_EQUAL(i, etl::base64::decoded_size(encoded[i].data(), encoded[i].size())); + CHECK_EQUAL(i, etl::base64_rfc4648::decoded_size(encoded[i].data(), encoded[i].size())); CHECK_EQUAL(i, decoded_size); } } @@ -695,7 +695,7 @@ namespace //************************************************************************* TEST(test_decode_int8_t_pointer_size_back_inserter) { - etl::base64 b64(etl::base64::Encoding::RFC_4648, etl::base64::Padding::Use_Padding); + etl::base64_rfc4648 b64(etl::ibase64::Padding::Use_Padding); std::vector decoded_output; for (size_t i = 0; i < 256; ++i) @@ -706,7 +706,7 @@ namespace etl::back_inserter(decoded_output)); CHECK_ARRAY_EQUAL(input_data_int8_t.data(), decoded_output.data(), i); - CHECK_EQUAL(i, etl::base64::decoded_size(encoded[i].data(), encoded[i].size())); + CHECK_EQUAL(i, etl::base64_rfc4648::decoded_size(encoded[i].data(), encoded[i].size())); CHECK_EQUAL(i, decoded_size); } } @@ -714,7 +714,7 @@ namespace //************************************************************************* TEST(test_decode_int8_t_pointer_size_no_output_size) { - etl::base64 b64(etl::base64::Encoding::RFC_4648, etl::base64::Padding::Use_Padding); + etl::base64_rfc4648 b64(etl::ibase64::Padding::Use_Padding); std::array decoded_output; for (size_t i = 0; i < 256; ++i) @@ -725,7 +725,7 @@ namespace decoded_output.data()); CHECK_ARRAY_EQUAL(input_data_int8_t.data(), decoded_output.data(), i); - CHECK_EQUAL(i, etl::base64::decoded_size(encoded[i].data(), encoded[i].size())); + CHECK_EQUAL(i, etl::base64_rfc4648::decoded_size(encoded[i].data(), encoded[i].size())); CHECK_EQUAL(i, decoded_size); } } @@ -733,7 +733,7 @@ namespace //************************************************************************* TEST(test_decode_int8_t_pointer_pointer) { - etl::base64 b64(etl::base64::Encoding::RFC_4648, etl::base64::Padding::Use_Padding); + etl::base64_rfc4648 b64(etl::ibase64::Padding::Use_Padding); std::array decoded_output; for (size_t i = 0; i < 256; ++i) @@ -744,7 +744,7 @@ namespace decoded_output.data(), decoded_output.data() + decoded_output.size()); CHECK_ARRAY_EQUAL(input_data_int8_t.data(), decoded_output.data(), i); - CHECK_EQUAL(i, etl::base64::decoded_size(encoded[i].data(), encoded[i].size())); + CHECK_EQUAL(i, etl::base64_rfc4648::decoded_size(encoded[i].data(), encoded[i].size())); CHECK_EQUAL(i, decoded_size); } } @@ -752,7 +752,7 @@ namespace //************************************************************************* TEST(test_decode_int8_t_pointer_pointer_back_inserter) { - etl::base64 b64(etl::base64::Encoding::RFC_4648, etl::base64::Padding::Use_Padding); + etl::base64_rfc4648 b64(etl::ibase64::Padding::Use_Padding); std::vector decoded_output; for (size_t i = 0; i < 256; ++i) @@ -763,7 +763,7 @@ namespace etl::back_inserter(decoded_output)); CHECK_ARRAY_EQUAL(input_data_int8_t.data(), decoded_output.data(), i); - CHECK_EQUAL(i, etl::base64::decoded_size(encoded[i].data(), encoded[i].size())); + CHECK_EQUAL(i, etl::base64_rfc4648::decoded_size(encoded[i].data(), encoded[i].size())); CHECK_EQUAL(i, decoded_size); } } @@ -771,7 +771,7 @@ namespace //************************************************************************* TEST(test_decode_int8_t_pointer_pointer_no_end_pointer) { - etl::base64 b64(etl::base64::Encoding::RFC_4648, etl::base64::Padding::Use_Padding); + etl::base64_rfc4648 b64(etl::ibase64::Padding::Use_Padding); std::array decoded_output; for (size_t i = 0; i < 256; ++i) @@ -782,7 +782,7 @@ namespace decoded_output.data()); CHECK_ARRAY_EQUAL(input_data_int8_t.data(), decoded_output.data(), i); - CHECK_EQUAL(i, etl::base64::decoded_size(encoded[i].data(), encoded[i].size())); + CHECK_EQUAL(i, etl::base64_rfc4648::decoded_size(encoded[i].data(), encoded[i].size())); CHECK_EQUAL(i, decoded_size); } } @@ -790,7 +790,7 @@ namespace //************************************************************************* TEST(test_decode_overflow) { - etl::base64 b64(etl::base64::Encoding::RFC_4648, etl::base64::Padding::Use_Padding); + etl::base64_rfc4648 b64(etl::ibase64::Padding::Use_Padding); std::array decoded_output{ 0 }; CHECK_THROW((b64.decode(encoded[10].data(), encoded[10].size(), @@ -800,7 +800,7 @@ namespace //************************************************************************* TEST(test_decode_invalid_character) { - etl::base64 b64(etl::base64::Encoding::RFC_4648, etl::base64::Padding::Use_Padding); + etl::base64_rfc4648 b64(etl::ibase64::Padding::Use_Padding); std::array decoded_output{ 0 }; std::string invalid_chararacter("OycD£Qy37KA=="); @@ -813,13 +813,13 @@ namespace //************************************************************************* TEST(test_decoded_size) { - etl::base64 b64(etl::base64::Encoding::RFC_4648, etl::base64::Padding::Use_Padding); + etl::base64_rfc4648 b64(etl::ibase64::Padding::Use_Padding); for (size_t i = 0; i < 256; ++i) { - size_t length = etl::base64::decoded_size(encoded[i].data(), encoded[i].size()); + size_t length = etl::base64_rfc4648::decoded_size(encoded[i].data(), encoded[i].size()); - CHECK_EQUAL(length, etl::base64::decoded_size(encoded[i].data(), encoded[i].data() + encoded[i].size())); + CHECK_EQUAL(length, etl::base64_rfc4648::decoded_size(encoded[i].data(), encoded[i].data() + encoded[i].size())); } } }; From b4ea535fc57cd6902693e420291ab88729299935 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Mon, 23 Oct 2023 19:33:37 +0100 Subject: [PATCH 12/12] Refactored back_inserter support --- include/etl/base64.h | 566 ++++++----- test/CMakeLists.txt | 3 +- test/test_base64_RFC4648_URL_with_padding.cpp | 915 ++++++++++++++++++ test/test_base64_RFC4648_with_padding.cpp | 96 +- test/vs2022/etl.vcxproj | 1 + 5 files changed, 1286 insertions(+), 295 deletions(-) create mode 100644 test/test_base64_RFC4648_URL_with_padding.cpp diff --git a/include/etl/base64.h b/include/etl/base64.h index d9a99354..cd4740ef 100644 --- a/include/etl/base64.h +++ b/include/etl/base64.h @@ -41,6 +41,13 @@ SOFTWARE. #include +#if ETL_USING_STL + #include +#endif + +#define ETL_IS_8_BIT_INTEGRAL(Type) (etl::is_integral::type>::value && \ + (etl::integral_limits::type>::bits == 8U)) + #define ETL_IS_ITERATOR_TYPE_8_BIT_INTEGRAL(Type) (etl::is_integral::type>::value_type>::value && \ (etl::integral_limits::type>::value_type>::bits == 8U)) @@ -136,8 +143,22 @@ namespace etl }; ETL_DECLARE_ENUM_TYPE(Padding, bool) - ETL_ENUM_TYPE(Use_Padding, "Use_Padding") ETL_ENUM_TYPE(No_Padding, "No_Padding") + ETL_ENUM_TYPE(Use_Padding, "Use_Padding") + ETL_END_ENUM_TYPE + }; + + struct Non_Coding_Characters + { + enum enum_type + { + Ignore = 0, + Reject = 1 + }; + + ETL_DECLARE_ENUM_TYPE(Non_Coding_Characters, bool) + ETL_ENUM_TYPE(Ignore, "Ignore") + ETL_ENUM_TYPE(Reject, "Reject") ETL_END_ENUM_TYPE }; @@ -200,14 +221,13 @@ namespace etl //************************************************************************* /// Encode to Base64 - /// For TOutputIterator not derived from etl::iterator + /// For TOutputIterator value type not equal to void /// Three parameter /// Assumes the output container is large enough. //************************************************************************* template ETL_CONSTEXPR14 - typename etl::enable_if::value_type>::value, size_t>::type - encode(TInputIterator input_begin, TInputIterator input_end, TOutputIterator output_begin) + size_t encode(TInputIterator input_begin, TInputIterator input_end, TOutputIterator output_begin) { ETL_STATIC_ASSERT(ETL_IS_ITERATOR_TYPE_8_BIT_INTEGRAL(TInputIterator), "Input type must be an 8 bit integral"); ETL_STATIC_ASSERT(ETL_IS_ITERATOR_TYPE_8_BIT_INTEGRAL(TOutputIterator), "Output type must be an 8 bit integral"); @@ -220,16 +240,16 @@ namespace etl //************************************************************************* /// Encode to Base64 - /// For TOutputIterator derived from etl::iterator + /// For etl::back_insert_iterator /// Three parameter /// Assumes the output container is large enough. //************************************************************************* - template + template ETL_CONSTEXPR14 - typename etl::enable_if::value_type>::value, size_t>::type - encode(TInputIterator input_begin, TInputIterator input_end, TOutputIterator output_begin) + size_t encode(TInputIterator input_begin, TInputIterator input_end, etl::back_insert_iterator output_begin) { - ETL_STATIC_ASSERT(ETL_IS_ITERATOR_TYPE_8_BIT_INTEGRAL(TInputIterator), "Input type must be an 8 bit integral"); + ETL_STATIC_ASSERT(ETL_IS_ITERATOR_TYPE_8_BIT_INTEGRAL(TInputIterator), "Input type must be an 8 bit integral"); + ETL_STATIC_ASSERT(ETL_IS_8_BIT_INTEGRAL(typename TContainer::value_type), "Output type must be an 8 bit integral"); const size_t input_length = static_cast(etl::distance(input_begin, input_end)); const size_t output_length = encoded_size(input_length); @@ -237,6 +257,27 @@ namespace etl return process_encode(input_begin, input_length, output_begin, output_length); } +#if ETL_USING_STL + //************************************************************************* + /// Encode to Base64 + /// For std::back_insert_iterator + /// Three parameter + /// Assumes the output container is large enough. + //************************************************************************* + template + ETL_CONSTEXPR14 + size_t encode(TInputIterator input_begin, TInputIterator input_end, std::back_insert_iterator output_begin) + { + ETL_STATIC_ASSERT(ETL_IS_ITERATOR_TYPE_8_BIT_INTEGRAL(TInputIterator), "Input type must be an 8 bit integral"); + ETL_STATIC_ASSERT(ETL_IS_8_BIT_INTEGRAL(typename TContainer::value_type), "Output type must be an 8 bit integral"); + + const size_t input_length = static_cast(etl::distance(input_begin, input_end)); + const size_t output_length = encoded_size(input_length); + + return process_encode(input_begin, input_length, output_begin, output_length); + } +#endif + //************************************************************************* /// Encode to Base64 /// Four parameter @@ -257,14 +298,13 @@ namespace etl //************************************************************************* /// Encode to Base64 - /// For TOutputIterator not derived from etl::iterator + /// For TOutputIterator value_type not equal to void /// Three parameter /// Assumes the output container is large enough. //************************************************************************* template ETL_CONSTEXPR14 - typename etl::enable_if::value_type>::value, size_t>::type - encode(TInputIterator input_begin, size_t input_length, TOutputIterator output_begin) + size_t encode(TInputIterator input_begin, size_t input_length, TOutputIterator output_begin) { ETL_STATIC_ASSERT(ETL_IS_ITERATOR_TYPE_8_BIT_INTEGRAL(TInputIterator), "Input type must be an 8 bit integral"); ETL_STATIC_ASSERT(ETL_IS_ITERATOR_TYPE_8_BIT_INTEGRAL(TOutputIterator), "Output type must be an 8 bit integral"); @@ -276,28 +316,49 @@ namespace etl //************************************************************************* /// Encode to Base64 - /// For TOutputIterator derived from etl::iterator + /// For etl::back_insert_iterator /// Three parameter /// Assumes the output container is large enough. //************************************************************************* - template + template ETL_CONSTEXPR14 - typename etl::enable_if::value_type>::value, size_t>::type - encode(TInputIterator input_begin, size_t input_length, TOutputIterator output_begin) + size_t encode(TInputIterator input_begin, size_t input_length, etl::back_insert_iterator output_begin) { - ETL_STATIC_ASSERT(ETL_IS_ITERATOR_TYPE_8_BIT_INTEGRAL(TInputIterator), "Input type must be an 8 bit integral"); + ETL_STATIC_ASSERT(ETL_IS_ITERATOR_TYPE_8_BIT_INTEGRAL(TInputIterator), "Input type must be an 8 bit integral"); + ETL_STATIC_ASSERT(ETL_IS_8_BIT_INTEGRAL(typename TContainer::value_type), "Output type must be an 8 bit integral"); const size_t output_length = encoded_size(input_length); return process_encode(input_begin, input_length, output_begin, output_length); } +#if ETL_USING_STL + //************************************************************************* + /// Encode to Base64 + /// For std::back_insert_iterator + /// Three parameter + /// Assumes the output container is large enough. + //************************************************************************* + template + ETL_CONSTEXPR14 + size_t encode(TInputIterator input_begin, size_t input_length, std::back_insert_iterator output_begin) + { + ETL_STATIC_ASSERT(ETL_IS_ITERATOR_TYPE_8_BIT_INTEGRAL(TInputIterator), "Input type must be an 8 bit integral"); + ETL_STATIC_ASSERT(ETL_IS_8_BIT_INTEGRAL(typename TContainer::value_type), "Output type must be an 8 bit integral"); + + const size_t output_length = encoded_size(input_length); + + return process_encode(input_begin, input_length, output_begin, output_length); + } +#endif + //************************************************************************* /// Calculates the minimum buffer size required to encode to Base64 //************************************************************************* ETL_NODISCARD + static ETL_CONSTEXPR14 - static size_t encoded_size(size_t input_length) + size_t encoded_size(size_t input_length) { size_t required_output_length = (input_length * 4U) / 3U; @@ -332,14 +393,12 @@ namespace etl //************************************************************************* /// Decode from Base64 - /// For TOutputIterator not derived from etl::iterator /// Three parameter /// Assumes the output container is large enough. //************************************************************************* template ETL_CONSTEXPR14 - typename etl::enable_if::value_type>::value, size_t>::type - decode(TInputIterator input_begin, TInputIterator input_end, TOutputIterator output_begin) + size_t decode(TInputIterator input_begin, TInputIterator input_end, TOutputIterator output_begin) { ETL_STATIC_ASSERT(ETL_IS_ITERATOR_TYPE_8_BIT_INTEGRAL(TInputIterator), "Input type must be an 8 bit integral"); ETL_STATIC_ASSERT(ETL_IS_ITERATOR_TYPE_8_BIT_INTEGRAL(TOutputIterator), "Output type must be an 8 bit integral"); @@ -355,16 +414,16 @@ namespace etl //************************************************************************* /// Decode from Base64 - /// For TOutputIterator derived from etl::iterator + /// For etl::back_insert_iterator /// Three parameter /// Assumes the output container is large enough. //************************************************************************* - template + template ETL_CONSTEXPR14 - typename etl::enable_if::value_type>::value, size_t>::type - decode(TInputIterator input_begin, TInputIterator input_end, TOutputIterator output_begin) + size_t decode(TInputIterator input_begin, TInputIterator input_end, etl::back_insert_iterator output_begin) { - ETL_STATIC_ASSERT(ETL_IS_ITERATOR_TYPE_8_BIT_INTEGRAL(TInputIterator), "Input type must be an 8 bit integral"); + ETL_STATIC_ASSERT(ETL_IS_ITERATOR_TYPE_8_BIT_INTEGRAL(TInputIterator), "Input type must be an 8 bit integral"); + ETL_STATIC_ASSERT(ETL_IS_8_BIT_INTEGRAL(typename TContainer::value_type), "Output type must be an 8 bit integral"); // Find the length of decodable characters. const size_t input_length = valid_input_length(input_begin, input_end); @@ -375,6 +434,30 @@ namespace etl return process_decode(input_begin, input_length, output_begin, required_output_length); } +#if ETL_USING_STL + //************************************************************************* + /// Decode from Base64 + /// For std::back_insert_iterator + /// Three parameter + /// Assumes the output container is large enough. + //************************************************************************* + template + ETL_CONSTEXPR14 + size_t decode(TInputIterator input_begin, TInputIterator input_end, std::back_insert_iterator output_begin) + { + ETL_STATIC_ASSERT(ETL_IS_ITERATOR_TYPE_8_BIT_INTEGRAL(TInputIterator), "Input type must be an 8 bit integral"); + ETL_STATIC_ASSERT(ETL_IS_8_BIT_INTEGRAL(typename TContainer::value_type), "Output type must be an 8 bit integral"); + + // Find the length of decodable characters. + const size_t input_length = valid_input_length(input_begin, input_end); + + // Find the length of the decoded output. + const size_t required_output_length = decoded_size(input_begin, input_length); + + return process_decode(input_begin, input_length, output_begin, required_output_length); + } +#endif + //************************************************************************* /// Decode from Base64 /// Four parameter @@ -398,14 +481,12 @@ namespace etl //************************************************************************* /// Decode from Base64 - /// For TOutputIterator not derived from etl::iterator /// Three parameter /// Assumes the output container is large enough. //************************************************************************* template ETL_CONSTEXPR14 - typename etl::enable_if::value_type>::value, size_t>::type - decode(TInputIterator input_begin, size_t input_length, TOutputIterator output_begin) + size_t decode(TInputIterator input_begin, size_t input_length, TOutputIterator output_begin) { ETL_STATIC_ASSERT(ETL_IS_ITERATOR_TYPE_8_BIT_INTEGRAL(TInputIterator), "Input type must be an 8 bit integral"); ETL_STATIC_ASSERT(ETL_IS_ITERATOR_TYPE_8_BIT_INTEGRAL(TOutputIterator), "Output type must be an 8 bit integral"); @@ -421,16 +502,16 @@ namespace etl //************************************************************************* /// Decode from Base64 - /// For TOutputIterator derived from etl::iterator + /// For etl::back_insert_iterator /// Three parameter /// Assumes the output container is large enough. //************************************************************************* - template + template ETL_CONSTEXPR14 - typename etl::enable_if::value_type>::value, size_t>::type - decode(TInputIterator input_begin, size_t input_length, TOutputIterator output_begin) + size_t decode(TInputIterator input_begin, size_t input_length, etl::back_insert_iterator output_begin) { - ETL_STATIC_ASSERT(ETL_IS_ITERATOR_TYPE_8_BIT_INTEGRAL(TInputIterator), "Input type must be an 8 bit integral"); + ETL_STATIC_ASSERT(ETL_IS_ITERATOR_TYPE_8_BIT_INTEGRAL(TInputIterator), "Input type must be an 8 bit integral"); + ETL_STATIC_ASSERT(ETL_IS_8_BIT_INTEGRAL(typename TContainer::value_type), "Output type must be an 8 bit integral"); // Find the length of decodable characters. input_length = valid_input_length(input_begin, input_length); @@ -441,13 +522,38 @@ namespace etl return process_decode(input_begin, input_length, output_begin, output_length); } +#if ETL_USING_STL + //************************************************************************* + /// Decode from Base64 + /// For std::back_insert_iterator + /// Three parameter + /// Assumes the output container is large enough. + //************************************************************************* + template + ETL_CONSTEXPR14 + size_t decode(TInputIterator input_begin, size_t input_length, std::back_insert_iterator output_begin) + { + ETL_STATIC_ASSERT(ETL_IS_ITERATOR_TYPE_8_BIT_INTEGRAL(TInputIterator), "Input type must be an 8 bit integral"); + ETL_STATIC_ASSERT(ETL_IS_8_BIT_INTEGRAL(typename TContainer::value_type), "Output type must be an 8 bit integral"); + + // Find the length of decodable characters. + input_length = valid_input_length(input_begin, input_length); + + // Find the length of the decoded output. + const size_t output_length = decoded_size(input_begin, input_length); + + return process_decode(input_begin, input_length, output_begin, output_length); + } +#endif + //************************************************************************* /// Discovers the number of valid decodable characters //************************************************************************* template ETL_NODISCARD + static ETL_CONSTEXPR14 - static size_t valid_input_length(TInputIterator input_begin, size_t input_length) + size_t valid_input_length(TInputIterator input_begin, size_t input_length) { if (input_length == 0U) { @@ -464,7 +570,7 @@ namespace etl etl::advance(input_end, input_length); } - typedef etl::iterator_traits::value_type input_type; + typedef typename etl::iterator_traits::value_type input_type; if (*input_end != padding()) { @@ -486,8 +592,9 @@ namespace etl //************************************************************************* template ETL_NODISCARD + static ETL_CONSTEXPR14 - static size_t valid_input_length(TInputIterator input_begin, TInputIterator input_end) + size_t valid_input_length(TInputIterator input_begin, TInputIterator input_end) { return valid_input_length(input_begin, static_cast(etl::distance(input_begin, input_end))); } @@ -497,8 +604,9 @@ namespace etl //************************************************************************* template ETL_NODISCARD + static ETL_CONSTEXPR14 - static size_t decoded_size(TInputIterator input_begin, size_t input_length) + size_t decoded_size(TInputIterator input_begin, size_t input_length) { if (input_length == 0U) { @@ -515,8 +623,9 @@ namespace etl //************************************************************************* template ETL_NODISCARD + static ETL_CONSTEXPR14 - static size_t decoded_size(TInputIterator input_begin, TInputIterator input_end) + size_t decoded_size(TInputIterator input_begin, TInputIterator input_end) { return decoded_size(input_begin, static_cast(etl::distance(input_begin, input_end))); } @@ -525,8 +634,9 @@ namespace etl /// Calculates the minimum buffer size required to decode from Base64 //************************************************************************* ETL_NODISCARD + static ETL_CONSTEXPR14 - static size_t decoded_size_from_valid_input_length(size_t input_length) + size_t decoded_size_from_valid_input_length(size_t input_length) { if (input_length == 0U) { @@ -543,15 +653,45 @@ namespace etl /// Constructor //************************************************************************* ETL_CONSTEXPR14 - ibase64(Encoding encoding_, const char* lookup_, bool use_padding_, bool discard_illegal_characters_, size_t max_line_length_) + ibase64(Encoding encoding_, const char* p_lookup_, bool use_padding_, bool discard_illegal_characters_, size_t max_line_length_) : encoding(encoding_) - , lookup(lookup_) + , p_lookup(p_lookup_) , use_padding(use_padding_) , discard_illegal_characters(discard_illegal_characters_) , max_line_length(max_line_length_) { } + //************************************************************************* + // Character set for RFC-1421, RFC-2045, RFC-2152 and RFC-4648 + //************************************************************************* + static + ETL_CONSTEXPR14 + const char* character_set_1() + { + return "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + } + + //************************************************************************* + // Character set for RFC-4648-URL + //************************************************************************* + static + ETL_CONSTEXPR14 + const char* character_set_2() + { + return "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"; + } + + //************************************************************************* + // Character set for RFC-3501-URL + //************************************************************************* + static + ETL_CONSTEXPR14 + const char* character_set_3() + { + return "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+,"; + } + private: //************************************************************************* @@ -559,35 +699,9 @@ namespace etl //************************************************************************* template ETL_CONSTEXPR14 - T get_sextet_from_index(char index) + T get_sextet_from_index(int index) { - if ((index >= 0) && (index < 26)) - { - return static_cast('A' + index); - } - else if ((index >= 26) && (index < 52)) - { - index -= 26; - return static_cast('a' + index); - } - else if ((index >= 52) && (index < 62)) - { - index -= 52; - return static_cast('0' + index); - } - else if (index == 62) - { - return static_cast(lookup[62]); - } - else if (index == 63) - { - return static_cast(lookup[63]); - } - else - { - ETL_ASSERT_FAIL_AND_RETURN_VALUE(ETL_ERROR(base64_illegal_character), 0); - return padding(); - } + return static_cast(p_lookup[index]); } //************************************************************************* @@ -597,25 +711,12 @@ namespace etl ETL_CONSTEXPR14 uint32_t get_index_from_sextet(T sextet) { - if ((sextet >= 'A') && (sextet <= 'Z')) + const char* p_lookup_end = p_lookup + 64; + const char* p_sextet = etl::find(p_lookup, p_lookup_end, static_cast(sextet)); + + if (p_sextet != p_lookup_end) { - 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; + return static_cast(etl::distance(p_lookup, p_sextet)); } else { @@ -628,8 +729,8 @@ namespace etl //************************************************************************* template ETL_NODISCARD + static ETL_CONSTEXPR14 - static T padding() { return static_cast('='); @@ -640,8 +741,8 @@ namespace etl //************************************************************************* template ETL_NODISCARD + static ETL_CONSTEXPR14 - static bool is_carriage_return(T c) { return (static_cast(c) == '\r'); @@ -652,8 +753,8 @@ namespace etl //************************************************************************* template ETL_NODISCARD - ETL_CONSTEXPR14 static + ETL_CONSTEXPR14 bool is_line_feed(T c) { return (static_cast(c) == '\n'); @@ -754,10 +855,10 @@ namespace etl while (input_length >= 4U) { // Read in four sextets - uint32_t sextets = (get_index_from_sextet(*input++) << 18) | - (get_index_from_sextet(*input++) << 12) | - (get_index_from_sextet(*input++) << 6) | - (get_index_from_sextet(*input++)); + uint32_t sextets = (get_index_from_sextet(*input++) << 18); + sextets = sextets | (get_index_from_sextet(*input++) << 12); + sextets = sextets | (get_index_from_sextet(*input++) << 6); + sextets = sextets | (get_index_from_sextet(*input++)); // Write out three octets *output++ = (sextets >> 16) & b11111111; @@ -770,16 +871,16 @@ namespace etl // Write out any remaining octets if (input_length == 2U) { - uint32_t sextets = (get_index_from_sextet(*input++) << 6) | - (get_index_from_sextet(*input++)); + uint32_t sextets = (get_index_from_sextet(*input++) << 6); + sextets = sextets | (get_index_from_sextet(*input++)); *output++ = (sextets >> 4) & b11111111; input_length -= 2U; } else if (input_length == 3U) { - uint32_t sextets = (get_index_from_sextet(*input++) << 12) | - (get_index_from_sextet(*input++) << 6) | - (get_index_from_sextet(*input++)); + uint32_t sextets = (get_index_from_sextet(*input++) << 12); + sextets = sextets | (get_index_from_sextet(*input++) << 6); + sextets = sextets | (get_index_from_sextet(*input++)); *output++ = (sextets >> 10) & b11111111; *output++ = (sextets >> 2) & b11111111; input_length -= 3U; @@ -789,49 +890,88 @@ namespace etl } Encoding encoding; - const char* lookup; + const char* p_lookup; bool use_padding; bool discard_illegal_characters; size_t max_line_length; }; + namespace private_base64 + { + template + struct character_set; + + template <> + struct character_set<1> + { + static + ETL_CONSTEXPR14 + const char* set() + { + return "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + } + }; + + template <> + struct character_set<2> + { + static + ETL_CONSTEXPR14 + const char* set() + { + return "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"; + } + }; + + template <> + struct character_set<3> + { + static + ETL_CONSTEXPR14 + const char* set() + { + return "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+,"; + } + }; + } + //************************************************************************* /// Base64 RFC-1421 //************************************************************************* - class base64_rfc1421 : public ibase64 - { - public: + //class base64_rfc1421 : public ibase64 + //{ + //public: - ETL_CONSTEXPR14 - base64_rfc1421() - : ibase64(etl::ibase64::Encoding::RFC_1421, - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/", - etl::ibase64::Padding::Use_Padding, - false, - 64U) - { - } - }; + // ETL_CONSTEXPR14 + // base64_rfc1421() + // : ibase64(etl::ibase64::Encoding::RFC_1421, + // "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/", + // etl::ibase64::Padding::Use_Padding, + // false, + // 64U) + // { + // } + //}; //************************************************************************* /// Base64 RFC-2045 //************************************************************************* - class base64_rfc2045 : public ibase64 - { - public: + //class base64_rfc2045 : public ibase64 + //{ + //public: - ETL_CONSTEXPR14 - base64_rfc2045(size_t max_line_length) - : ibase64(etl::ibase64::Encoding::RFC_2045, - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/", - etl::ibase64::Padding::Use_Padding, - true, - max_line_length) - { - } - }; + // ETL_CONSTEXPR14 + // base64_rfc2045(size_t max_line_length) + // : ibase64(etl::ibase64::Encoding::RFC_2045, + // "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/", + // etl::ibase64::Padding::Use_Padding, + // true, + // max_line_length) + // { + // } + //}; - //************************************************************************* + //************************************************************************* /// Base64 RFC-4648 //************************************************************************* class base64_rfc4648 : public ibase64 @@ -841,9 +981,9 @@ namespace etl ETL_CONSTEXPR14 base64_rfc4648(etl::ibase64::Padding use_padding) : ibase64(etl::ibase64::Encoding::RFC_4648, - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/", + etl::private_base64::character_set<1>::set(), use_padding, - false, + etl::ibase64::Non_Coding_Characters::Reject, etl::integral_limits::max) { } @@ -857,172 +997,18 @@ namespace etl public: ETL_CONSTEXPR14 - base64_rfc4648_url(etl::ibase64::Padding use_padding) + base64_rfc4648_url(etl::ibase64::Padding use_padding) : ibase64(etl::ibase64::Encoding::RFC_4648_URL, - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_", + etl::private_base64::character_set<2>::set(), use_padding, - false, + etl::ibase64::Non_Coding_Characters::Reject, etl::integral_limits::max) { } - - //************************************************************************* - /// Is the character a carriage return? - //************************************************************************* - template - ETL_NODISCARD - ETL_CONSTEXPR14 - static - bool is_carriage_return(T c) - { - return (static_cast(c) == '\r'); - } - - //************************************************************************* - /// Is the character a line break? - //************************************************************************* - template - ETL_NODISCARD - ETL_CONSTEXPR14 - static - bool is_line_feed(T c) - { - return (static_cast(c) == '\n'); - } - - //************************************************************************* - /// Encode to Base64 implementation - //************************************************************************* - template - ETL_CONSTEXPR14 - size_t process_encode(TInputIterator input, size_t input_length, - TOutputIterator output, size_t output_length) - { - if (input_length == 0U) - { - return 0; - } - - // Count the actual number of sextets written. - size_t output_count = 0; - - uint32_t octets = 0; - - // Read octet triplets and write sextet quartets - while (input_length >= 3U) - { - // Read in three octets - octets = (static_cast(static_cast(*input++)) << 16); - octets = octets | (static_cast(static_cast(*input++)) << 8); - octets = octets | static_cast(static_cast(*input++)); - - // Write out four sextets - *output++ = get_sextet_from_index((octets >> 18) & b00111111); - *output++ = get_sextet_from_index((octets >> 12) & b00111111); - *output++ = get_sextet_from_index((octets >> 6) & b00111111); - *output++ = get_sextet_from_index((octets >> 0) & b00111111); - - input_length -= 3U; - output_count += 4U; - } - - // Any input left? - if (input_length > 0) - { - // Write out any remaining sextets - if (input_length == 1U) - { - // There is one octet remaining - octets = static_cast(static_cast(*input++)); - octets <<= 4; // Adjust one octet (8 bits) for two sextets worth of data (12 bits) - output_count += 2U; - } - else if (input_length == 2U) - { - // There are two octets remaining - octets = static_cast(static_cast(*input++)); - octets <<= 8; - octets = octets | static_cast(static_cast(*input++)); - octets <<= 2; // Adjust two octets (16 bits) for three sextets worth of data (18 bits) - output_count += 3U; - } - - int shift = static_cast(input_length * 6U); - - while (shift >= 0) - { - *output++ = get_sextet_from_index((octets >> shift) & b00111111); - shift -= 6; - } - } - - if (use_padding) - { - // Pad out the end of the output buffer. - while (output_count != output_length) - { - *output++ = padding(); - ++output_count; - } - } - - return output_length; - } - - //************************************************************************* - /// Decode from Base64 implementation - //************************************************************************* - template - ETL_CONSTEXPR14 - size_t process_decode(TInputIterator input, size_t input_length, TOutputIterator output, size_t output_length) - { - if (input_length == 0) - { - return 0; - } - - // Read sextet quartets and write octet triplets - while (input_length >= 4U) - { - // Read in four sextets - uint32_t sextets = (get_index_from_sextet(*input++) << 18) | - (get_index_from_sextet(*input++) << 12) | - (get_index_from_sextet(*input++) << 6) | - (get_index_from_sextet(*input++)); - - // Write out three octets - *output++ = (sextets >> 16) & b11111111; - *output++ = (sextets >> 8) & b11111111; - *output++ = (sextets >> 0) & b11111111; - - input_length -= 4U; - } - - // Write out any remaining octets - if (input_length == 2U) - { - uint32_t sextets = (get_index_from_sextet(*input++) << 6) | - (get_index_from_sextet(*input++)); - *output++ = (sextets >> 4) & b11111111; - input_length -= 2U; - } - else if (input_length == 3U) - { - uint32_t sextets = (get_index_from_sextet(*input++) << 12) | - (get_index_from_sextet(*input++) << 6) | - (get_index_from_sextet(*input++)); - *output++ = (sextets >> 10) & b11111111; - *output++ = (sextets >> 2) & b11111111; - input_length -= 3U; - } - - return output_length; - } - - Encoding encoding; - bool use_padding; - size_t max_line_length; }; } +#undef ETL_IS_TYPE_8_BIT_INTEGRAL +#undef ETL_IS_ITERATOR_TYPE_8_BIT_INTEGRAL + #endif diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 0bd37e14..20b9bd60 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -12,7 +12,8 @@ project(etl_unit_tests LANGUAGES CXX) add_executable(etl_tests main.cpp - test_base64.cpp + test_base64_RFC4648_with_padding.cpp + test_base64_RFC4648_URL_with_padding.cpp ) target_compile_definitions(etl_tests PRIVATE -DETL_DEBUG) diff --git a/test/test_base64_RFC4648_URL_with_padding.cpp b/test/test_base64_RFC4648_URL_with_padding.cpp new file mode 100644 index 00000000..f8ab0dde --- /dev/null +++ b/test/test_base64_RFC4648_URL_with_padding.cpp @@ -0,0 +1,915 @@ +/****************************************************************************** +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 "unit_test_framework.h" + +#include "etl/base64.h" + +#include "etl/string.h" +#include "etl/vector.h" + +#include +#include +#include +#include + +#if ETL_USING_STL + #include +#endif + +#include "etl/integral_limits.h" + +//***************************************************************************** +// Ecode/decode using RFC-4648-URL with padding +//***************************************************************************** + +namespace +{ + std::array 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, + 0xC0, 0xCF, 0x2A, 0xD1, 0x86, 0x56, 0xD5, 0x71, 0x37, 0xEB, 0x80, 0x32, 0xDF, 0xE4, 0xDF, 0xB6, + 0xEE, 0x3F, 0xDC, 0x79, 0xB3, 0x17, 0x8E, 0x76, 0x65, 0x8E, 0x96, 0x21, 0xB9, 0x88, 0xD1, 0x6D, + 0xD0, 0xDD, 0xFF, 0xDA, 0xA8, 0x7A, 0x4D, 0xF5, 0x71, 0x77, 0xFD, 0x2E, 0xF2, 0xE4, 0x40, 0x72, + 0x8C, 0x83, 0x00, 0x6F, 0x13, 0x72, 0x53, 0xE4, 0x6B, 0x70, 0x0E, 0x37, 0xCA, 0x25, 0xCD, 0x68, + 0x62, 0xC0, 0xAB, 0x14, 0xC7, 0x59, 0x83, 0xD2, 0x82, 0x8C, 0x93, 0x6D, 0x13, 0x21, 0xC0, 0x08, + 0xF9, 0x6D, 0xAC, 0x84, 0x78, 0x49, 0x84, 0x6F, 0x6B, 0xFB, 0x20, 0x3B, 0x9C, 0x49, 0xFB, 0x4E, + 0x80, 0x69, 0x82, 0x25, 0x86, 0x95, 0xD5, 0x4D, 0x91, 0xED, 0xD2, 0x77, 0x2A, 0x24, 0x40, 0x8A, + 0xDF, 0x4D, 0x80, 0x2D, 0xCD, 0xD5, 0x5A, 0x26, 0xA6, 0x71, 0x15, 0x42, 0x0E, 0x3F, 0xB2, 0x70, + 0x14, 0x29, 0x1F, 0x8D, 0x23, 0x2E, 0xC1, 0xEA, 0xCE, 0xF9, 0x7E, 0x6C, 0xDF, 0x1C, 0xA3, 0x84, + 0x2B, 0x24, 0x35, 0xA7, 0x63, 0xC8, 0x0B, 0x1F, 0x8B, 0xBA, 0x51, 0xBF, 0xE9, 0x51, 0x80, 0xD2, + 0x23, 0xB5, 0xD1, 0xB4, 0x59, 0xAE, 0x7D, 0x30, 0x1D, 0x00, 0x1C, 0xD8, 0x70, 0x6C, 0x16, 0x71, + 0xC7, 0x56, 0x08, 0xFE, 0x81, 0xAE, 0xFB, 0xE0, 0x92, 0xD8, 0xDB, 0xB9, 0x57, 0x7C, 0x99, 0xCB, + 0x42, 0xEF, 0xFC, 0xB3, 0x56, 0x1E, 0xD1, 0x42, 0xD3, 0x0C, 0x18, 0xB3, 0xEE, 0xAF, 0x1A, 0x77, + 0xA8, 0x52, 0x3C, 0x9E, 0xCD, 0xDE, 0x21, 0x34, 0x3E, 0x1F, 0xB5, 0x54, 0xD7, 0xFB, 0xB4, 0xBD + }; + + std::array 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 encoded = + { + "", + "Ow==", + "Oyc=", + "OycD", + "OycDQw==", + "OycDQy0=", + "OycDQy37", + "OycDQy37KA==", + "OycDQy37KCo=", + "OycDQy37KCph", + "OycDQy37KCphrg==", + "OycDQy37KCphrrw=", + "OycDQy37KCphrrxJ", + "OycDQy37KCphrrxJcQ==", + "OycDQy37KCphrrxJcTI=", + "OycDQy37KCphrrxJcTIB", + "OycDQy37KCphrrxJcTIBFQ==", + "OycDQy37KCphrrxJcTIBFWk=", + "OycDQy37KCphrrxJcTIBFWlc", + "OycDQy37KCphrrxJcTIBFWlcXg==", + "OycDQy37KCphrrxJcTIBFWlcXvU=", + "OycDQy37KCphrrxJcTIBFWlcXvXV", + "OycDQy37KCphrrxJcTIBFWlcXvXVmw==", + "OycDQy37KCphrrxJcTIBFWlcXvXVm94=", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96l", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lVw==", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8k=", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nB", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfQ==", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYA=", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDe", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTA==", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIE=", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHA", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzw==", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyo=", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrR", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhg==", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlY=", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbV", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcQ==", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTc=", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfr", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgA==", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDI=", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5A==", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N8=", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-2", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27g==", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j8=", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_c", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_ceQ==", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebM=", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMX", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjg==", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnY=", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZl", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljg==", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpY=", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYh", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuQ==", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYg=", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjR", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbQ==", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdA=", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_w==", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9o=", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qo", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoeg==", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek0=", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cQ==", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXc=", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9Lg==", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvI=", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLk", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQA==", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHI=", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKM", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgw==", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwA=", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBv", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvEw==", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3I=", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5A==", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5Gs=", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5Gtw", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDg==", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjc=", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfK", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJQ==", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc0=", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1o", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYg==", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsA=", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCr", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFA==", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMc=", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZ", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZgw==", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9I=", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KC", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjA==", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJM=", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNt", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEw==", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyE=", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHA", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHACA==", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHACPk=", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHACPlt", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHACPltrA==", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHACPltrIQ=", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHACPltrIR4", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHACPltrIR4SQ==", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHACPltrIR4SYQ=", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHACPltrIR4SYRv", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHACPltrIR4SYRvaw==", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHACPltrIR4SYRva_s=", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHACPltrIR4SYRva_sg", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHACPltrIR4SYRva_sgOw==", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHACPltrIR4SYRva_sgO5w=", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHACPltrIR4SYRva_sgO5xJ", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHACPltrIR4SYRva_sgO5xJ-w==", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHACPltrIR4SYRva_sgO5xJ-04=", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHACPltrIR4SYRva_sgO5xJ-06A", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHACPltrIR4SYRva_sgO5xJ-06AaQ==", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHACPltrIR4SYRva_sgO5xJ-06AaYI=", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHACPltrIR4SYRva_sgO5xJ-06AaYIl", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHACPltrIR4SYRva_sgO5xJ-06AaYIlhg==", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHACPltrIR4SYRva_sgO5xJ-06AaYIlhpU=", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHACPltrIR4SYRva_sgO5xJ-06AaYIlhpXV", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHACPltrIR4SYRva_sgO5xJ-06AaYIlhpXVTQ==", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHACPltrIR4SYRva_sgO5xJ-06AaYIlhpXVTZE=", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHACPltrIR4SYRva_sgO5xJ-06AaYIlhpXVTZHt", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHACPltrIR4SYRva_sgO5xJ-06AaYIlhpXVTZHt0g==", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHACPltrIR4SYRva_sgO5xJ-06AaYIlhpXVTZHt0nc=", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHACPltrIR4SYRva_sgO5xJ-06AaYIlhpXVTZHt0ncq", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHACPltrIR4SYRva_sgO5xJ-06AaYIlhpXVTZHt0ncqJA==", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHACPltrIR4SYRva_sgO5xJ-06AaYIlhpXVTZHt0ncqJEA=", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHACPltrIR4SYRva_sgO5xJ-06AaYIlhpXVTZHt0ncqJECK", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHACPltrIR4SYRva_sgO5xJ-06AaYIlhpXVTZHt0ncqJECK3w==", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHACPltrIR4SYRva_sgO5xJ-06AaYIlhpXVTZHt0ncqJECK300=", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHACPltrIR4SYRva_sgO5xJ-06AaYIlhpXVTZHt0ncqJECK302A", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHACPltrIR4SYRva_sgO5xJ-06AaYIlhpXVTZHt0ncqJECK302ALQ==", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHACPltrIR4SYRva_sgO5xJ-06AaYIlhpXVTZHt0ncqJECK302ALc0=", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHACPltrIR4SYRva_sgO5xJ-06AaYIlhpXVTZHt0ncqJECK302ALc3V", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHACPltrIR4SYRva_sgO5xJ-06AaYIlhpXVTZHt0ncqJECK302ALc3VWg==", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHACPltrIR4SYRva_sgO5xJ-06AaYIlhpXVTZHt0ncqJECK302ALc3VWiY=", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHACPltrIR4SYRva_sgO5xJ-06AaYIlhpXVTZHt0ncqJECK302ALc3VWiam", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHACPltrIR4SYRva_sgO5xJ-06AaYIlhpXVTZHt0ncqJECK302ALc3VWiamcQ==", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHACPltrIR4SYRva_sgO5xJ-06AaYIlhpXVTZHt0ncqJECK302ALc3VWiamcRU=", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHACPltrIR4SYRva_sgO5xJ-06AaYIlhpXVTZHt0ncqJECK302ALc3VWiamcRVC", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHACPltrIR4SYRva_sgO5xJ-06AaYIlhpXVTZHt0ncqJECK302ALc3VWiamcRVCDg==", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHACPltrIR4SYRva_sgO5xJ-06AaYIlhpXVTZHt0ncqJECK302ALc3VWiamcRVCDj8=", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHACPltrIR4SYRva_sgO5xJ-06AaYIlhpXVTZHt0ncqJECK302ALc3VWiamcRVCDj-y", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHACPltrIR4SYRva_sgO5xJ-06AaYIlhpXVTZHt0ncqJECK302ALc3VWiamcRVCDj-ycA==", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHACPltrIR4SYRva_sgO5xJ-06AaYIlhpXVTZHt0ncqJECK302ALc3VWiamcRVCDj-ycBQ=", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHACPltrIR4SYRva_sgO5xJ-06AaYIlhpXVTZHt0ncqJECK302ALc3VWiamcRVCDj-ycBQp", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHACPltrIR4SYRva_sgO5xJ-06AaYIlhpXVTZHt0ncqJECK302ALc3VWiamcRVCDj-ycBQpHw==", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHACPltrIR4SYRva_sgO5xJ-06AaYIlhpXVTZHt0ncqJECK302ALc3VWiamcRVCDj-ycBQpH40=", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHACPltrIR4SYRva_sgO5xJ-06AaYIlhpXVTZHt0ncqJECK302ALc3VWiamcRVCDj-ycBQpH40j", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHACPltrIR4SYRva_sgO5xJ-06AaYIlhpXVTZHt0ncqJECK302ALc3VWiamcRVCDj-ycBQpH40jLg==", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHACPltrIR4SYRva_sgO5xJ-06AaYIlhpXVTZHt0ncqJECK302ALc3VWiamcRVCDj-ycBQpH40jLsE=", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHACPltrIR4SYRva_sgO5xJ-06AaYIlhpXVTZHt0ncqJECK302ALc3VWiamcRVCDj-ycBQpH40jLsHq", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHACPltrIR4SYRva_sgO5xJ-06AaYIlhpXVTZHt0ncqJECK302ALc3VWiamcRVCDj-ycBQpH40jLsHqzg==", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHACPltrIR4SYRva_sgO5xJ-06AaYIlhpXVTZHt0ncqJECK302ALc3VWiamcRVCDj-ycBQpH40jLsHqzvk=", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHACPltrIR4SYRva_sgO5xJ-06AaYIlhpXVTZHt0ncqJECK302ALc3VWiamcRVCDj-ycBQpH40jLsHqzvl-", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHACPltrIR4SYRva_sgO5xJ-06AaYIlhpXVTZHt0ncqJECK302ALc3VWiamcRVCDj-ycBQpH40jLsHqzvl-bA==", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHACPltrIR4SYRva_sgO5xJ-06AaYIlhpXVTZHt0ncqJECK302ALc3VWiamcRVCDj-ycBQpH40jLsHqzvl-bN8=", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHACPltrIR4SYRva_sgO5xJ-06AaYIlhpXVTZHt0ncqJECK302ALc3VWiamcRVCDj-ycBQpH40jLsHqzvl-bN8c", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHACPltrIR4SYRva_sgO5xJ-06AaYIlhpXVTZHt0ncqJECK302ALc3VWiamcRVCDj-ycBQpH40jLsHqzvl-bN8cow==", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHACPltrIR4SYRva_sgO5xJ-06AaYIlhpXVTZHt0ncqJECK302ALc3VWiamcRVCDj-ycBQpH40jLsHqzvl-bN8co4Q=", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHACPltrIR4SYRva_sgO5xJ-06AaYIlhpXVTZHt0ncqJECK302ALc3VWiamcRVCDj-ycBQpH40jLsHqzvl-bN8co4Qr", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHACPltrIR4SYRva_sgO5xJ-06AaYIlhpXVTZHt0ncqJECK302ALc3VWiamcRVCDj-ycBQpH40jLsHqzvl-bN8co4QrJA==", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHACPltrIR4SYRva_sgO5xJ-06AaYIlhpXVTZHt0ncqJECK302ALc3VWiamcRVCDj-ycBQpH40jLsHqzvl-bN8co4QrJDU=", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHACPltrIR4SYRva_sgO5xJ-06AaYIlhpXVTZHt0ncqJECK302ALc3VWiamcRVCDj-ycBQpH40jLsHqzvl-bN8co4QrJDWn", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHACPltrIR4SYRva_sgO5xJ-06AaYIlhpXVTZHt0ncqJECK302ALc3VWiamcRVCDj-ycBQpH40jLsHqzvl-bN8co4QrJDWnYw==", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHACPltrIR4SYRva_sgO5xJ-06AaYIlhpXVTZHt0ncqJECK302ALc3VWiamcRVCDj-ycBQpH40jLsHqzvl-bN8co4QrJDWnY8g=", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHACPltrIR4SYRva_sgO5xJ-06AaYIlhpXVTZHt0ncqJECK302ALc3VWiamcRVCDj-ycBQpH40jLsHqzvl-bN8co4QrJDWnY8gL", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHACPltrIR4SYRva_sgO5xJ-06AaYIlhpXVTZHt0ncqJECK302ALc3VWiamcRVCDj-ycBQpH40jLsHqzvl-bN8co4QrJDWnY8gLHw==", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHACPltrIR4SYRva_sgO5xJ-06AaYIlhpXVTZHt0ncqJECK302ALc3VWiamcRVCDj-ycBQpH40jLsHqzvl-bN8co4QrJDWnY8gLH4s=", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHACPltrIR4SYRva_sgO5xJ-06AaYIlhpXVTZHt0ncqJECK302ALc3VWiamcRVCDj-ycBQpH40jLsHqzvl-bN8co4QrJDWnY8gLH4u6", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHACPltrIR4SYRva_sgO5xJ-06AaYIlhpXVTZHt0ncqJECK302ALc3VWiamcRVCDj-ycBQpH40jLsHqzvl-bN8co4QrJDWnY8gLH4u6UQ==", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHACPltrIR4SYRva_sgO5xJ-06AaYIlhpXVTZHt0ncqJECK302ALc3VWiamcRVCDj-ycBQpH40jLsHqzvl-bN8co4QrJDWnY8gLH4u6Ub8=", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHACPltrIR4SYRva_sgO5xJ-06AaYIlhpXVTZHt0ncqJECK302ALc3VWiamcRVCDj-ycBQpH40jLsHqzvl-bN8co4QrJDWnY8gLH4u6Ub_p", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHACPltrIR4SYRva_sgO5xJ-06AaYIlhpXVTZHt0ncqJECK302ALc3VWiamcRVCDj-ycBQpH40jLsHqzvl-bN8co4QrJDWnY8gLH4u6Ub_pUQ==", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHACPltrIR4SYRva_sgO5xJ-06AaYIlhpXVTZHt0ncqJECK302ALc3VWiamcRVCDj-ycBQpH40jLsHqzvl-bN8co4QrJDWnY8gLH4u6Ub_pUYA=", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHACPltrIR4SYRva_sgO5xJ-06AaYIlhpXVTZHt0ncqJECK302ALc3VWiamcRVCDj-ycBQpH40jLsHqzvl-bN8co4QrJDWnY8gLH4u6Ub_pUYDS", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHACPltrIR4SYRva_sgO5xJ-06AaYIlhpXVTZHt0ncqJECK302ALc3VWiamcRVCDj-ycBQpH40jLsHqzvl-bN8co4QrJDWnY8gLH4u6Ub_pUYDSIw==", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHACPltrIR4SYRva_sgO5xJ-06AaYIlhpXVTZHt0ncqJECK302ALc3VWiamcRVCDj-ycBQpH40jLsHqzvl-bN8co4QrJDWnY8gLH4u6Ub_pUYDSI7U=", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHACPltrIR4SYRva_sgO5xJ-06AaYIlhpXVTZHt0ncqJECK302ALc3VWiamcRVCDj-ycBQpH40jLsHqzvl-bN8co4QrJDWnY8gLH4u6Ub_pUYDSI7XR", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHACPltrIR4SYRva_sgO5xJ-06AaYIlhpXVTZHt0ncqJECK302ALc3VWiamcRVCDj-ycBQpH40jLsHqzvl-bN8co4QrJDWnY8gLH4u6Ub_pUYDSI7XRtA==", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHACPltrIR4SYRva_sgO5xJ-06AaYIlhpXVTZHt0ncqJECK302ALc3VWiamcRVCDj-ycBQpH40jLsHqzvl-bN8co4QrJDWnY8gLH4u6Ub_pUYDSI7XRtFk=", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHACPltrIR4SYRva_sgO5xJ-06AaYIlhpXVTZHt0ncqJECK302ALc3VWiamcRVCDj-ycBQpH40jLsHqzvl-bN8co4QrJDWnY8gLH4u6Ub_pUYDSI7XRtFmu", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHACPltrIR4SYRva_sgO5xJ-06AaYIlhpXVTZHt0ncqJECK302ALc3VWiamcRVCDj-ycBQpH40jLsHqzvl-bN8co4QrJDWnY8gLH4u6Ub_pUYDSI7XRtFmufQ==", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHACPltrIR4SYRva_sgO5xJ-06AaYIlhpXVTZHt0ncqJECK302ALc3VWiamcRVCDj-ycBQpH40jLsHqzvl-bN8co4QrJDWnY8gLH4u6Ub_pUYDSI7XRtFmufTA=", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHACPltrIR4SYRva_sgO5xJ-06AaYIlhpXVTZHt0ncqJECK302ALc3VWiamcRVCDj-ycBQpH40jLsHqzvl-bN8co4QrJDWnY8gLH4u6Ub_pUYDSI7XRtFmufTAd", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHACPltrIR4SYRva_sgO5xJ-06AaYIlhpXVTZHt0ncqJECK302ALc3VWiamcRVCDj-ycBQpH40jLsHqzvl-bN8co4QrJDWnY8gLH4u6Ub_pUYDSI7XRtFmufTAdAA==", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHACPltrIR4SYRva_sgO5xJ-06AaYIlhpXVTZHt0ncqJECK302ALc3VWiamcRVCDj-ycBQpH40jLsHqzvl-bN8co4QrJDWnY8gLH4u6Ub_pUYDSI7XRtFmufTAdABw=", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHACPltrIR4SYRva_sgO5xJ-06AaYIlhpXVTZHt0ncqJECK302ALc3VWiamcRVCDj-ycBQpH40jLsHqzvl-bN8co4QrJDWnY8gLH4u6Ub_pUYDSI7XRtFmufTAdABzY", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHACPltrIR4SYRva_sgO5xJ-06AaYIlhpXVTZHt0ncqJECK302ALc3VWiamcRVCDj-ycBQpH40jLsHqzvl-bN8co4QrJDWnY8gLH4u6Ub_pUYDSI7XRtFmufTAdABzYcA==", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHACPltrIR4SYRva_sgO5xJ-06AaYIlhpXVTZHt0ncqJECK302ALc3VWiamcRVCDj-ycBQpH40jLsHqzvl-bN8co4QrJDWnY8gLH4u6Ub_pUYDSI7XRtFmufTAdABzYcGw=", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHACPltrIR4SYRva_sgO5xJ-06AaYIlhpXVTZHt0ncqJECK302ALc3VWiamcRVCDj-ycBQpH40jLsHqzvl-bN8co4QrJDWnY8gLH4u6Ub_pUYDSI7XRtFmufTAdABzYcGwW", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHACPltrIR4SYRva_sgO5xJ-06AaYIlhpXVTZHt0ncqJECK302ALc3VWiamcRVCDj-ycBQpH40jLsHqzvl-bN8co4QrJDWnY8gLH4u6Ub_pUYDSI7XRtFmufTAdABzYcGwWcQ==", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHACPltrIR4SYRva_sgO5xJ-06AaYIlhpXVTZHt0ncqJECK302ALc3VWiamcRVCDj-ycBQpH40jLsHqzvl-bN8co4QrJDWnY8gLH4u6Ub_pUYDSI7XRtFmufTAdABzYcGwWccc=", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHACPltrIR4SYRva_sgO5xJ-06AaYIlhpXVTZHt0ncqJECK302ALc3VWiamcRVCDj-ycBQpH40jLsHqzvl-bN8co4QrJDWnY8gLH4u6Ub_pUYDSI7XRtFmufTAdABzYcGwWccdW", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHACPltrIR4SYRva_sgO5xJ-06AaYIlhpXVTZHt0ncqJECK302ALc3VWiamcRVCDj-ycBQpH40jLsHqzvl-bN8co4QrJDWnY8gLH4u6Ub_pUYDSI7XRtFmufTAdABzYcGwWccdWCA==", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHACPltrIR4SYRva_sgO5xJ-06AaYIlhpXVTZHt0ncqJECK302ALc3VWiamcRVCDj-ycBQpH40jLsHqzvl-bN8co4QrJDWnY8gLH4u6Ub_pUYDSI7XRtFmufTAdABzYcGwWccdWCP4=", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHACPltrIR4SYRva_sgO5xJ-06AaYIlhpXVTZHt0ncqJECK302ALc3VWiamcRVCDj-ycBQpH40jLsHqzvl-bN8co4QrJDWnY8gLH4u6Ub_pUYDSI7XRtFmufTAdABzYcGwWccdWCP6B", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHACPltrIR4SYRva_sgO5xJ-06AaYIlhpXVTZHt0ncqJECK302ALc3VWiamcRVCDj-ycBQpH40jLsHqzvl-bN8co4QrJDWnY8gLH4u6Ub_pUYDSI7XRtFmufTAdABzYcGwWccdWCP6Brg==", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHACPltrIR4SYRva_sgO5xJ-06AaYIlhpXVTZHt0ncqJECK302ALc3VWiamcRVCDj-ycBQpH40jLsHqzvl-bN8co4QrJDWnY8gLH4u6Ub_pUYDSI7XRtFmufTAdABzYcGwWccdWCP6Brvs=", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHACPltrIR4SYRva_sgO5xJ-06AaYIlhpXVTZHt0ncqJECK302ALc3VWiamcRVCDj-ycBQpH40jLsHqzvl-bN8co4QrJDWnY8gLH4u6Ub_pUYDSI7XRtFmufTAdABzYcGwWccdWCP6Brvvg", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHACPltrIR4SYRva_sgO5xJ-06AaYIlhpXVTZHt0ncqJECK302ALc3VWiamcRVCDj-ycBQpH40jLsHqzvl-bN8co4QrJDWnY8gLH4u6Ub_pUYDSI7XRtFmufTAdABzYcGwWccdWCP6Brvvgkg==", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHACPltrIR4SYRva_sgO5xJ-06AaYIlhpXVTZHt0ncqJECK302ALc3VWiamcRVCDj-ycBQpH40jLsHqzvl-bN8co4QrJDWnY8gLH4u6Ub_pUYDSI7XRtFmufTAdABzYcGwWccdWCP6Brvvgktg=", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHACPltrIR4SYRva_sgO5xJ-06AaYIlhpXVTZHt0ncqJECK302ALc3VWiamcRVCDj-ycBQpH40jLsHqzvl-bN8co4QrJDWnY8gLH4u6Ub_pUYDSI7XRtFmufTAdABzYcGwWccdWCP6Brvvgktjb", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHACPltrIR4SYRva_sgO5xJ-06AaYIlhpXVTZHt0ncqJECK302ALc3VWiamcRVCDj-ycBQpH40jLsHqzvl-bN8co4QrJDWnY8gLH4u6Ub_pUYDSI7XRtFmufTAdABzYcGwWccdWCP6BrvvgktjbuQ==", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHACPltrIR4SYRva_sgO5xJ-06AaYIlhpXVTZHt0ncqJECK302ALc3VWiamcRVCDj-ycBQpH40jLsHqzvl-bN8co4QrJDWnY8gLH4u6Ub_pUYDSI7XRtFmufTAdABzYcGwWccdWCP6BrvvgktjbuVc=", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHACPltrIR4SYRva_sgO5xJ-06AaYIlhpXVTZHt0ncqJECK302ALc3VWiamcRVCDj-ycBQpH40jLsHqzvl-bN8co4QrJDWnY8gLH4u6Ub_pUYDSI7XRtFmufTAdABzYcGwWccdWCP6BrvvgktjbuVd8", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHACPltrIR4SYRva_sgO5xJ-06AaYIlhpXVTZHt0ncqJECK302ALc3VWiamcRVCDj-ycBQpH40jLsHqzvl-bN8co4QrJDWnY8gLH4u6Ub_pUYDSI7XRtFmufTAdABzYcGwWccdWCP6BrvvgktjbuVd8mQ==", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHACPltrIR4SYRva_sgO5xJ-06AaYIlhpXVTZHt0ncqJECK302ALc3VWiamcRVCDj-ycBQpH40jLsHqzvl-bN8co4QrJDWnY8gLH4u6Ub_pUYDSI7XRtFmufTAdABzYcGwWccdWCP6BrvvgktjbuVd8mcs=", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHACPltrIR4SYRva_sgO5xJ-06AaYIlhpXVTZHt0ncqJECK302ALc3VWiamcRVCDj-ycBQpH40jLsHqzvl-bN8co4QrJDWnY8gLH4u6Ub_pUYDSI7XRtFmufTAdABzYcGwWccdWCP6BrvvgktjbuVd8mctC", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHACPltrIR4SYRva_sgO5xJ-06AaYIlhpXVTZHt0ncqJECK302ALc3VWiamcRVCDj-ycBQpH40jLsHqzvl-bN8co4QrJDWnY8gLH4u6Ub_pUYDSI7XRtFmufTAdABzYcGwWccdWCP6BrvvgktjbuVd8mctC7w==", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHACPltrIR4SYRva_sgO5xJ-06AaYIlhpXVTZHt0ncqJECK302ALc3VWiamcRVCDj-ycBQpH40jLsHqzvl-bN8co4QrJDWnY8gLH4u6Ub_pUYDSI7XRtFmufTAdABzYcGwWccdWCP6BrvvgktjbuVd8mctC7_w=", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHACPltrIR4SYRva_sgO5xJ-06AaYIlhpXVTZHt0ncqJECK302ALc3VWiamcRVCDj-ycBQpH40jLsHqzvl-bN8co4QrJDWnY8gLH4u6Ub_pUYDSI7XRtFmufTAdABzYcGwWccdWCP6BrvvgktjbuVd8mctC7_yz", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHACPltrIR4SYRva_sgO5xJ-06AaYIlhpXVTZHt0ncqJECK302ALc3VWiamcRVCDj-ycBQpH40jLsHqzvl-bN8co4QrJDWnY8gLH4u6Ub_pUYDSI7XRtFmufTAdABzYcGwWccdWCP6BrvvgktjbuVd8mctC7_yzVg==", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHACPltrIR4SYRva_sgO5xJ-06AaYIlhpXVTZHt0ncqJECK302ALc3VWiamcRVCDj-ycBQpH40jLsHqzvl-bN8co4QrJDWnY8gLH4u6Ub_pUYDSI7XRtFmufTAdABzYcGwWccdWCP6BrvvgktjbuVd8mctC7_yzVh4=", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHACPltrIR4SYRva_sgO5xJ-06AaYIlhpXVTZHt0ncqJECK302ALc3VWiamcRVCDj-ycBQpH40jLsHqzvl-bN8co4QrJDWnY8gLH4u6Ub_pUYDSI7XRtFmufTAdABzYcGwWccdWCP6BrvvgktjbuVd8mctC7_yzVh7R", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHACPltrIR4SYRva_sgO5xJ-06AaYIlhpXVTZHt0ncqJECK302ALc3VWiamcRVCDj-ycBQpH40jLsHqzvl-bN8co4QrJDWnY8gLH4u6Ub_pUYDSI7XRtFmufTAdABzYcGwWccdWCP6BrvvgktjbuVd8mctC7_yzVh7RQg==", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHACPltrIR4SYRva_sgO5xJ-06AaYIlhpXVTZHt0ncqJECK302ALc3VWiamcRVCDj-ycBQpH40jLsHqzvl-bN8co4QrJDWnY8gLH4u6Ub_pUYDSI7XRtFmufTAdABzYcGwWccdWCP6BrvvgktjbuVd8mctC7_yzVh7RQtM=", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHACPltrIR4SYRva_sgO5xJ-06AaYIlhpXVTZHt0ncqJECK302ALc3VWiamcRVCDj-ycBQpH40jLsHqzvl-bN8co4QrJDWnY8gLH4u6Ub_pUYDSI7XRtFmufTAdABzYcGwWccdWCP6BrvvgktjbuVd8mctC7_yzVh7RQtMM", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHACPltrIR4SYRva_sgO5xJ-06AaYIlhpXVTZHt0ncqJECK302ALc3VWiamcRVCDj-ycBQpH40jLsHqzvl-bN8co4QrJDWnY8gLH4u6Ub_pUYDSI7XRtFmufTAdABzYcGwWccdWCP6BrvvgktjbuVd8mctC7_yzVh7RQtMMGA==", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHACPltrIR4SYRva_sgO5xJ-06AaYIlhpXVTZHt0ncqJECK302ALc3VWiamcRVCDj-ycBQpH40jLsHqzvl-bN8co4QrJDWnY8gLH4u6Ub_pUYDSI7XRtFmufTAdABzYcGwWccdWCP6BrvvgktjbuVd8mctC7_yzVh7RQtMMGLM=", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHACPltrIR4SYRva_sgO5xJ-06AaYIlhpXVTZHt0ncqJECK302ALc3VWiamcRVCDj-ycBQpH40jLsHqzvl-bN8co4QrJDWnY8gLH4u6Ub_pUYDSI7XRtFmufTAdABzYcGwWccdWCP6BrvvgktjbuVd8mctC7_yzVh7RQtMMGLPu", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHACPltrIR4SYRva_sgO5xJ-06AaYIlhpXVTZHt0ncqJECK302ALc3VWiamcRVCDj-ycBQpH40jLsHqzvl-bN8co4QrJDWnY8gLH4u6Ub_pUYDSI7XRtFmufTAdABzYcGwWccdWCP6BrvvgktjbuVd8mctC7_yzVh7RQtMMGLPurw==", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHACPltrIR4SYRva_sgO5xJ-06AaYIlhpXVTZHt0ncqJECK302ALc3VWiamcRVCDj-ycBQpH40jLsHqzvl-bN8co4QrJDWnY8gLH4u6Ub_pUYDSI7XRtFmufTAdABzYcGwWccdWCP6BrvvgktjbuVd8mctC7_yzVh7RQtMMGLPurxo=", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHACPltrIR4SYRva_sgO5xJ-06AaYIlhpXVTZHt0ncqJECK302ALc3VWiamcRVCDj-ycBQpH40jLsHqzvl-bN8co4QrJDWnY8gLH4u6Ub_pUYDSI7XRtFmufTAdABzYcGwWccdWCP6BrvvgktjbuVd8mctC7_yzVh7RQtMMGLPurxp3", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHACPltrIR4SYRva_sgO5xJ-06AaYIlhpXVTZHt0ncqJECK302ALc3VWiamcRVCDj-ycBQpH40jLsHqzvl-bN8co4QrJDWnY8gLH4u6Ub_pUYDSI7XRtFmufTAdABzYcGwWccdWCP6BrvvgktjbuVd8mctC7_yzVh7RQtMMGLPurxp3qA==", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHACPltrIR4SYRva_sgO5xJ-06AaYIlhpXVTZHt0ncqJECK302ALc3VWiamcRVCDj-ycBQpH40jLsHqzvl-bN8co4QrJDWnY8gLH4u6Ub_pUYDSI7XRtFmufTAdABzYcGwWccdWCP6BrvvgktjbuVd8mctC7_yzVh7RQtMMGLPurxp3qFI=", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHACPltrIR4SYRva_sgO5xJ-06AaYIlhpXVTZHt0ncqJECK302ALc3VWiamcRVCDj-ycBQpH40jLsHqzvl-bN8co4QrJDWnY8gLH4u6Ub_pUYDSI7XRtFmufTAdABzYcGwWccdWCP6BrvvgktjbuVd8mctC7_yzVh7RQtMMGLPurxp3qFI8", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHACPltrIR4SYRva_sgO5xJ-06AaYIlhpXVTZHt0ncqJECK302ALc3VWiamcRVCDj-ycBQpH40jLsHqzvl-bN8co4QrJDWnY8gLH4u6Ub_pUYDSI7XRtFmufTAdABzYcGwWccdWCP6BrvvgktjbuVd8mctC7_yzVh7RQtMMGLPurxp3qFI8ng==", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHACPltrIR4SYRva_sgO5xJ-06AaYIlhpXVTZHt0ncqJECK302ALc3VWiamcRVCDj-ycBQpH40jLsHqzvl-bN8co4QrJDWnY8gLH4u6Ub_pUYDSI7XRtFmufTAdABzYcGwWccdWCP6BrvvgktjbuVd8mctC7_yzVh7RQtMMGLPurxp3qFI8ns0=", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHACPltrIR4SYRva_sgO5xJ-06AaYIlhpXVTZHt0ncqJECK302ALc3VWiamcRVCDj-ycBQpH40jLsHqzvl-bN8co4QrJDWnY8gLH4u6Ub_pUYDSI7XRtFmufTAdABzYcGwWccdWCP6BrvvgktjbuVd8mctC7_yzVh7RQtMMGLPurxp3qFI8ns3e", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHACPltrIR4SYRva_sgO5xJ-06AaYIlhpXVTZHt0ncqJECK302ALc3VWiamcRVCDj-ycBQpH40jLsHqzvl-bN8co4QrJDWnY8gLH4u6Ub_pUYDSI7XRtFmufTAdABzYcGwWccdWCP6BrvvgktjbuVd8mctC7_yzVh7RQtMMGLPurxp3qFI8ns3eIQ==", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHACPltrIR4SYRva_sgO5xJ-06AaYIlhpXVTZHt0ncqJECK302ALc3VWiamcRVCDj-ycBQpH40jLsHqzvl-bN8co4QrJDWnY8gLH4u6Ub_pUYDSI7XRtFmufTAdABzYcGwWccdWCP6BrvvgktjbuVd8mctC7_yzVh7RQtMMGLPurxp3qFI8ns3eITQ=", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHACPltrIR4SYRva_sgO5xJ-06AaYIlhpXVTZHt0ncqJECK302ALc3VWiamcRVCDj-ycBQpH40jLsHqzvl-bN8co4QrJDWnY8gLH4u6Ub_pUYDSI7XRtFmufTAdABzYcGwWccdWCP6BrvvgktjbuVd8mctC7_yzVh7RQtMMGLPurxp3qFI8ns3eITQ-", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHACPltrIR4SYRva_sgO5xJ-06AaYIlhpXVTZHt0ncqJECK302ALc3VWiamcRVCDj-ycBQpH40jLsHqzvl-bN8co4QrJDWnY8gLH4u6Ub_pUYDSI7XRtFmufTAdABzYcGwWccdWCP6BrvvgktjbuVd8mctC7_yzVh7RQtMMGLPurxp3qFI8ns3eITQ-Hw==", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHACPltrIR4SYRva_sgO5xJ-06AaYIlhpXVTZHt0ncqJECK302ALc3VWiamcRVCDj-ycBQpH40jLsHqzvl-bN8co4QrJDWnY8gLH4u6Ub_pUYDSI7XRtFmufTAdABzYcGwWccdWCP6BrvvgktjbuVd8mctC7_yzVh7RQtMMGLPurxp3qFI8ns3eITQ-H7U=", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHACPltrIR4SYRva_sgO5xJ-06AaYIlhpXVTZHt0ncqJECK302ALc3VWiamcRVCDj-ycBQpH40jLsHqzvl-bN8co4QrJDWnY8gLH4u6Ub_pUYDSI7XRtFmufTAdABzYcGwWccdWCP6BrvvgktjbuVd8mctC7_yzVh7RQtMMGLPurxp3qFI8ns3eITQ-H7VU", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHACPltrIR4SYRva_sgO5xJ-06AaYIlhpXVTZHt0ncqJECK302ALc3VWiamcRVCDj-ycBQpH40jLsHqzvl-bN8co4QrJDWnY8gLH4u6Ub_pUYDSI7XRtFmufTAdABzYcGwWccdWCP6BrvvgktjbuVd8mctC7_yzVh7RQtMMGLPurxp3qFI8ns3eITQ-H7VU1w==", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHACPltrIR4SYRva_sgO5xJ-06AaYIlhpXVTZHt0ncqJECK302ALc3VWiamcRVCDj-ycBQpH40jLsHqzvl-bN8co4QrJDWnY8gLH4u6Ub_pUYDSI7XRtFmufTAdABzYcGwWccdWCP6BrvvgktjbuVd8mctC7_yzVh7RQtMMGLPurxp3qFI8ns3eITQ-H7VU1_s=", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHACPltrIR4SYRva_sgO5xJ-06AaYIlhpXVTZHt0ncqJECK302ALc3VWiamcRVCDj-ycBQpH40jLsHqzvl-bN8co4QrJDWnY8gLH4u6Ub_pUYDSI7XRtFmufTAdABzYcGwWccdWCP6BrvvgktjbuVd8mctC7_yzVh7RQtMMGLPurxp3qFI8ns3eITQ-H7VU1_u0", + "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHACPltrIR4SYRva_sgO5xJ-06AaYIlhpXVTZHt0ncqJECK302ALc3VWiamcRVCDj-ycBQpH40jLsHqzvl-bN8co4QrJDWnY8gLH4u6Ub_pUYDSI7XRtFmufTAdABzYcGwWccdWCP6BrvvgktjbuVd8mctC7_yzVh7RQtMMGLPurxp3qFI8ns3eITQ-H7VU1_u0vQ==" + }; + + SUITE(test_base64_rfc4648_url_url_with_padding) + { + //************************************************************************* + TEST(test_encode_unsigned_char_pointer_size) + { + etl::base64_rfc4648_url b64(etl::ibase64::Padding::Use_Padding); + std::array encoded_output; + + for (size_t i = 0; i < 256; ++i) + { + encoded_output.fill(0); + + auto size = b64.encode(input_data_unsigned_char.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_rfc4648_url::encoded_size(i), size); + } + } + + //************************************************************************* + TEST(test_encode_unsigned_char_pointer_size_no_output_length) + { + etl::base64_rfc4648_url b64(etl::ibase64::Padding::Use_Padding); + std::array encoded_output; + + for (size_t i = 0; i < 256; ++i) + { + encoded_output.fill(0); + + auto size = b64.encode(input_data_unsigned_char.data(), i, + encoded_output.data()); + + std::string expected(encoded[i]); + std::string actual(encoded_output.data(), size); + + CHECK_EQUAL(expected, actual); + CHECK_EQUAL(etl::base64_rfc4648_url::encoded_size(i), size); + } + } + + //************************************************************************* + TEST(test_encode_unsigned_char_pointer_size_to_etl_back_inserter) + { + etl::base64_rfc4648_url b64(etl::ibase64::Padding::Use_Padding); + + for (size_t i = 0; i < 256; ++i) + { + std::string actual; + + auto size = b64.encode(input_data_unsigned_char.data(), i, + etl::back_inserter(actual)); + + std::string expected(encoded[i]); + + CHECK_EQUAL(expected, actual); + CHECK_EQUAL(etl::base64_rfc4648_url::encoded_size(i), size); + } + } + +#if ETL_USING_STL + //************************************************************************* + TEST(test_encode_unsigned_char_pointer_size_to_std_back_inserter) + { + etl::base64_rfc4648_url b64(etl::ibase64::Padding::Use_Padding); + + for (size_t i = 0; i < 256; ++i) + { + std::string actual; + + auto size = b64.encode(input_data_unsigned_char.data(), i, + std::back_inserter(actual)); + + std::string expected(encoded[i]); + + CHECK_EQUAL(expected, actual); + CHECK_EQUAL(etl::base64_rfc4648_url::encoded_size(i), size); + } + } +#endif + + //************************************************************************* + TEST(test_encode_unsigned_char_pointer_pointer) + { + etl::base64_rfc4648_url b64(etl::ibase64::Padding::Use_Padding); + std::array encoded_output; + + for (size_t i = 0; i < 256; ++i) + { + encoded_output.fill(0); + + auto size = b64.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_rfc4648_url::encoded_size(i), size); + } + } + + //************************************************************************* + TEST(test_encode_unsigned_char_pointer_pointer_no_output_end_pointer) + { + etl::base64_rfc4648_url b64(etl::ibase64::Padding::Use_Padding); + std::array encoded_output; + + for (size_t i = 6; i < 256; ++i) + { + encoded_output.fill(0); + + auto size = b64.encode(input_data_unsigned_char.data(), input_data_unsigned_char.data() + i, + encoded_output.data()); + + std::string expected(encoded[i]); + std::string actual(encoded_output.data(), size); + + CHECK_EQUAL(expected, actual); + CHECK_EQUAL(etl::base64_rfc4648_url::encoded_size(i), size); + } + } + + //************************************************************************* + TEST(test_encode_int8_t_pointer_size) + { + etl::base64_rfc4648_url b64(etl::ibase64::Padding::Use_Padding); + std::array encoded_output; + + for (size_t i = 11; i < 256; ++i) + { + encoded_output.fill(0); + + auto size = b64.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_rfc4648_url::encoded_size(i), size); + } + } + + //************************************************************************* + TEST(test_encode_int8_t_pointer_size_no_output_length) + { + etl::base64_rfc4648_url b64(etl::ibase64::Padding::Use_Padding); + std::array encoded_output; + + for (size_t i = 6; i < 256; ++i) + { + encoded_output.fill(0); + + auto size = b64.encode(input_data_int8_t.data(), i, + encoded_output.data()); + + std::string expected(encoded[i]); + std::string actual(encoded_output.data(), size); + + CHECK_EQUAL(expected, actual); + CHECK_EQUAL(etl::base64_rfc4648_url::encoded_size(i), size); + } + } + + //************************************************************************* + TEST(test_encode_int8_t_pointer_size_to_etl_back_inserter) + { + etl::base64_rfc4648_url b64(etl::ibase64::Padding::Use_Padding); + + for (size_t i = 0; i < 256; ++i) + { + std::string actual; + + auto size = b64.encode(input_data_int8_t.data(), i, + etl::back_inserter(actual)); + + std::string expected(encoded[i]); + + CHECK_EQUAL(expected, actual); + CHECK_EQUAL(etl::base64_rfc4648_url::encoded_size(i), size); + } + } + +#if ETL_USING_STL + //************************************************************************* + TEST(test_encode_int8_t_pointer_size_to_std_back_inserter) + { + etl::base64_rfc4648_url b64(etl::ibase64::Padding::Use_Padding); + + for (size_t i = 0; i < 256; ++i) + { + std::string actual; + + auto size = b64.encode(input_data_int8_t.data(), i, + std::back_inserter(actual)); + + std::string expected(encoded[i]); + + CHECK_EQUAL(expected, actual); + CHECK_EQUAL(etl::base64_rfc4648_url::encoded_size(i), size); + } + } +#endif + + //************************************************************************* + TEST(test_encode_int8_t_pointer_pointer) + { + etl::base64_rfc4648_url b64(etl::ibase64::Padding::Use_Padding); + std::array encoded_output; + + for (size_t i = 0; i < 256; ++i) + { + encoded_output.fill(0); + + auto size = b64.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_rfc4648_url::encoded_size(i), size); + } + } + + //************************************************************************* + TEST(test_encode_int8_t_pointer_pointer_no_end_pointer) + { + etl::base64_rfc4648_url b64(etl::ibase64::Padding::Use_Padding); + + std::array encoded_output; + + for (size_t i = 0; i < 256; ++i) + { + encoded_output.fill(0); + + auto size = b64.encode(input_data_int8_t.data(), input_data_int8_t.data() + i, + encoded_output.data()); + + std::string expected(encoded[i]); + std::string actual(encoded_output.data(), size); + + CHECK_EQUAL(expected, actual); + CHECK_EQUAL(etl::base64_rfc4648_url::encoded_size(i), size); + } + } + + //************************************************************************* +#if ETL_USING_CPP14 + template + constexpr auto GetConstexprBase64(const etl::array input) noexcept + { + etl::base64_rfc4648_url b64(etl::ibase64::Padding::Use_Padding); + + constexpr size_t encoded_size = etl::base64_rfc4648_url::encoded_size(Size); + etl::array output{ 0 }; + + b64.encode(input.begin(), Size, + output._buffer, encoded_size); + + return output; + } + + TEST(test_encode_int8_t_constexpr) + { + constexpr etl::array 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_rfc4648_url::encoded_size(10), output.size()); + } +#endif + + //************************************************************************* + TEST(test_encode_overflow) + { + etl::base64_rfc4648_url b64(etl::ibase64::Padding::Use_Padding); + std::array encoded_output{ 0 }; + + CHECK_THROW((b64.encode(input_data_unsigned_char.data(), 10, + encoded_output.data(), encoded_output.size())), + etl::base64_overflow); + } + + //************************************************************************* + TEST(test_decode_unsigned_char_pointer_size) + { + etl::base64_rfc4648_url b64(etl::ibase64::Padding::Use_Padding); + std::array decoded_output; + + for (size_t i = 0; i < 256; ++i) + { + decoded_output.fill(0); + + auto decoded_size = b64.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_rfc4648_url::decoded_size(encoded[i].data(), encoded[i].size())); + CHECK_EQUAL(i, decoded_size); + } + } + + //************************************************************************* + TEST(test_decode_unsigned_char_pointer_size_no_end_pointer) + { + etl::base64_rfc4648_url b64(etl::ibase64::Padding::Use_Padding); + std::array decoded_output; + + for (size_t i = 0; i < 256; ++i) + { + decoded_output.fill(0); + + auto decoded_size = b64.decode(encoded[i].data(), encoded[i].size(), + decoded_output.data()); + + CHECK_ARRAY_EQUAL(input_data_unsigned_char.data(), decoded_output.data(), i); + CHECK_EQUAL(i, etl::base64_rfc4648_url::decoded_size(encoded[i].data(), encoded[i].size())); + CHECK_EQUAL(i, decoded_size); + } + } + + //************************************************************************* + TEST(test_decode_unsigned_char_pointer_pointer) + { + etl::base64_rfc4648_url b64(etl::ibase64::Padding::Use_Padding); + std::array decoded_output; + + for (size_t i = 0; i < 256; ++i) + { + decoded_output.fill(0); + + auto decoded_size = b64.decode(encoded[i].data(), encoded[i].data() + encoded[i].size(), + decoded_output.data(), decoded_output.data() + decoded_output.size()); + + CHECK_ARRAY_EQUAL(input_data_unsigned_char.data(), decoded_output.data(), i); + CHECK_EQUAL(i, etl::base64_rfc4648_url::decoded_size(encoded[i].data(), encoded[i].size())); + CHECK_EQUAL(i, decoded_size); + } + } + + //************************************************************************* + TEST(test_decode_unsigned_char_pointer_pointer_no_end_pointer) + { + etl::base64_rfc4648_url b64(etl::ibase64::Padding::Use_Padding); + std::array decoded_output; + + for (size_t i = 0; i < 256; ++i) + { + decoded_output.fill(0); + + auto decoded_size = b64.decode(encoded[i].data(), encoded[i].data() + encoded[i].size(), + decoded_output.data()); + + CHECK_ARRAY_EQUAL(input_data_unsigned_char.data(), decoded_output.data(), i); + CHECK_EQUAL(i, etl::base64_rfc4648_url::decoded_size(encoded[i].data(), encoded[i].size())); + CHECK_EQUAL(i, decoded_size); + } + } + + //************************************************************************* + TEST(test_decode_int8_t_pointer_size) + { + etl::base64_rfc4648_url b64(etl::ibase64::Padding::Use_Padding); + std::array decoded_output; + + for (size_t i = 0; i < 256; ++i) + { + decoded_output.fill(0); + + auto decoded_size = b64.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_rfc4648_url::decoded_size(encoded[i].data(), encoded[i].size())); + CHECK_EQUAL(i, decoded_size); + } + } + + //************************************************************************* + TEST(test_decode_int8_t_pointer_size_etl_back_inserter) + { + etl::base64_rfc4648_url b64(etl::ibase64::Padding::Use_Padding); + std::vector decoded_output; + + for (size_t i = 0; i < 256; ++i) + { + decoded_output.clear(); + + auto decoded_size = b64.decode(encoded[i].data(), encoded[i].size(), + etl::back_inserter(decoded_output)); + + CHECK_ARRAY_EQUAL(input_data_int8_t.data(), decoded_output.data(), i); + CHECK_EQUAL(i, etl::base64_rfc4648_url::decoded_size(encoded[i].data(), encoded[i].size())); + CHECK_EQUAL(i, decoded_size); + } + } + +#if ETL_USING_STL + //************************************************************************* + TEST(test_decode_int8_t_pointer_size_std_back_inserter) + { + etl::base64_rfc4648_url b64(etl::ibase64::Padding::Use_Padding); + std::vector decoded_output; + + for (size_t i = 0; i < 256; ++i) + { + decoded_output.clear(); + + auto decoded_size = b64.decode(encoded[i].data(), encoded[i].size(), + std::back_inserter(decoded_output)); + + CHECK_ARRAY_EQUAL(input_data_int8_t.data(), decoded_output.data(), i); + CHECK_EQUAL(i, etl::base64_rfc4648_url::decoded_size(encoded[i].data(), encoded[i].size())); + CHECK_EQUAL(i, decoded_size); + } + } +#endif + + //************************************************************************* + TEST(test_decode_int8_t_pointer_size_no_output_size) + { + etl::base64_rfc4648_url b64(etl::ibase64::Padding::Use_Padding); + std::array decoded_output; + + for (size_t i = 0; i < 256; ++i) + { + decoded_output.fill(0); + + auto decoded_size = b64.decode(encoded[i].data(), encoded[i].size(), + decoded_output.data()); + + CHECK_ARRAY_EQUAL(input_data_int8_t.data(), decoded_output.data(), i); + CHECK_EQUAL(i, etl::base64_rfc4648_url::decoded_size(encoded[i].data(), encoded[i].size())); + CHECK_EQUAL(i, decoded_size); + } + } + + //************************************************************************* + TEST(test_decode_int8_t_pointer_pointer) + { + etl::base64_rfc4648_url b64(etl::ibase64::Padding::Use_Padding); + std::array decoded_output; + + for (size_t i = 0; i < 256; ++i) + { + decoded_output.fill(0); + + auto decoded_size = b64.decode(encoded[i].data(), encoded[i].data() + encoded[i].size(), + decoded_output.data(), decoded_output.data() + decoded_output.size()); + + CHECK_ARRAY_EQUAL(input_data_int8_t.data(), decoded_output.data(), i); + CHECK_EQUAL(i, etl::base64_rfc4648_url::decoded_size(encoded[i].data(), encoded[i].size())); + CHECK_EQUAL(i, decoded_size); + } + } + + //************************************************************************* + TEST(test_decode_int8_t_pointer_pointer_etl_back_inserter) + { + etl::base64_rfc4648_url b64(etl::ibase64::Padding::Use_Padding); + std::vector decoded_output; + + for (size_t i = 0; i < 256; ++i) + { + decoded_output.clear(); + + auto decoded_size = b64.decode(encoded[i].data(), encoded[i].data() + encoded[i].size(), + etl::back_inserter(decoded_output)); + + CHECK_ARRAY_EQUAL(input_data_int8_t.data(), decoded_output.data(), i); + CHECK_EQUAL(i, etl::base64_rfc4648_url::decoded_size(encoded[i].data(), encoded[i].size())); + CHECK_EQUAL(i, decoded_size); + } + } + +#if ETL_USING_STL + //************************************************************************* + TEST(test_decode_int8_t_pointer_pointer_std_back_inserter) + { + etl::base64_rfc4648_url b64(etl::ibase64::Padding::Use_Padding); + std::vector decoded_output; + + for (size_t i = 0; i < 256; ++i) + { + decoded_output.clear(); + + auto decoded_size = b64.decode(encoded[i].data(), encoded[i].data() + encoded[i].size(), + std::back_inserter(decoded_output)); + + CHECK_ARRAY_EQUAL(input_data_int8_t.data(), decoded_output.data(), i); + CHECK_EQUAL(i, etl::base64_rfc4648_url::decoded_size(encoded[i].data(), encoded[i].size())); + CHECK_EQUAL(i, decoded_size); + } + } +#endif + + //************************************************************************* + TEST(test_decode_int8_t_pointer_pointer_no_end_pointer) + { + etl::base64_rfc4648_url b64(etl::ibase64::Padding::Use_Padding); + std::array decoded_output; + + for (size_t i = 0; i < 256; ++i) + { + decoded_output.fill(0); + + auto decoded_size = b64.decode(encoded[i].data(), encoded[i].data() + encoded[i].size(), + decoded_output.data()); + + CHECK_ARRAY_EQUAL(input_data_int8_t.data(), decoded_output.data(), i); + CHECK_EQUAL(i, etl::base64_rfc4648_url::decoded_size(encoded[i].data(), encoded[i].size())); + CHECK_EQUAL(i, decoded_size); + } + } + + //************************************************************************* + TEST(test_decode_overflow) + { + etl::base64_rfc4648_url b64(etl::ibase64::Padding::Use_Padding); + std::array decoded_output{ 0 }; + + CHECK_THROW((b64.decode(encoded[10].data(), encoded[10].size(), + decoded_output.data(), decoded_output.size())), etl::base64_overflow); + } + + //************************************************************************* + TEST(test_decode_invalid_character) + { + etl::base64_rfc4648_url b64(etl::ibase64::Padding::Use_Padding); + std::array decoded_output{ 0 }; + + std::string invalid_chararacter("OycD�Qy37KA=="); + std::string invalid_padding("OycDQy37KA&="); + + CHECK_THROW((b64.decode(invalid_chararacter.data(), invalid_chararacter.size(), + decoded_output.data(), decoded_output.size())), etl::base64_illegal_character); + } + + //************************************************************************* + TEST(test_decoded_size) + { + etl::base64_rfc4648_url b64(etl::ibase64::Padding::Use_Padding); + + for (size_t i = 0; i < 256; ++i) + { + size_t length = etl::base64_rfc4648_url::decoded_size(encoded[i].data(), encoded[i].size()); + + CHECK_EQUAL(length, etl::base64_rfc4648_url::decoded_size(encoded[i].data(), encoded[i].data() + encoded[i].size())); + } + } + }; +} + diff --git a/test/test_base64_RFC4648_with_padding.cpp b/test/test_base64_RFC4648_with_padding.cpp index 2da1debb..f8186486 100644 --- a/test/test_base64_RFC4648_with_padding.cpp +++ b/test/test_base64_RFC4648_with_padding.cpp @@ -38,6 +38,10 @@ SOFTWARE. #include #include +#if ETL_USING_STL + #include +#endif + #include "etl/integral_limits.h" //***************************************************************************** @@ -392,7 +396,7 @@ namespace } //************************************************************************* - TEST(test_encode_unsigned_char_pointer_size_to_back_inserter) + TEST(test_encode_unsigned_char_pointer_size_to_etl_back_inserter) { etl::base64_rfc4648 b64(etl::ibase64::Padding::Use_Padding); @@ -410,6 +414,27 @@ namespace } } +#if ETL_USING_STL + //************************************************************************* + TEST(test_encode_unsigned_char_pointer_size_to_std_back_inserter) + { + etl::base64_rfc4648 b64(etl::ibase64::Padding::Use_Padding); + + for (size_t i = 0; i < 256; ++i) + { + std::string actual; + + auto size = b64.encode(input_data_unsigned_char.data(), i, + std::back_inserter(actual)); + + std::string expected(encoded[i]); + + CHECK_EQUAL(expected, actual); + CHECK_EQUAL(etl::base64_rfc4648::encoded_size(i), size); + } + } +#endif + //************************************************************************* TEST(test_encode_unsigned_char_pointer_pointer) { @@ -495,7 +520,7 @@ namespace } //************************************************************************* - TEST(test_encode_int8_t_pointer_size_to_back_inserter) + TEST(test_encode_int8_t_pointer_size_to_etl_back_inserter) { etl::base64_rfc4648 b64(etl::ibase64::Padding::Use_Padding); @@ -512,6 +537,27 @@ namespace CHECK_EQUAL(etl::base64_rfc4648::encoded_size(i), size); } } + +#if ETL_USING_STL + //************************************************************************* + TEST(test_encode_int8_t_pointer_size_to_std_back_inserter) + { + etl::base64_rfc4648 b64(etl::ibase64::Padding::Use_Padding); + + for (size_t i = 0; i < 256; ++i) + { + std::string actual; + + auto size = b64.encode(input_data_int8_t.data(), i, + std::back_inserter(actual)); + + std::string expected(encoded[i]); + + CHECK_EQUAL(expected, actual); + CHECK_EQUAL(etl::base64_rfc4648::encoded_size(i), size); + } + } +#endif //************************************************************************* TEST(test_encode_int8_t_pointer_pointer) @@ -693,7 +739,7 @@ namespace } //************************************************************************* - TEST(test_decode_int8_t_pointer_size_back_inserter) + TEST(test_decode_int8_t_pointer_size_etl_back_inserter) { etl::base64_rfc4648 b64(etl::ibase64::Padding::Use_Padding); std::vector decoded_output; @@ -711,6 +757,27 @@ namespace } } +#if ETL_USING_STL + //************************************************************************* + TEST(test_decode_int8_t_pointer_size_std_back_inserter) + { + etl::base64_rfc4648 b64(etl::ibase64::Padding::Use_Padding); + std::vector decoded_output; + + for (size_t i = 0; i < 256; ++i) + { + decoded_output.clear(); + + auto decoded_size = b64.decode(encoded[i].data(), encoded[i].size(), + std::back_inserter(decoded_output)); + + CHECK_ARRAY_EQUAL(input_data_int8_t.data(), decoded_output.data(), i); + CHECK_EQUAL(i, etl::base64_rfc4648::decoded_size(encoded[i].data(), encoded[i].size())); + CHECK_EQUAL(i, decoded_size); + } + } +#endif + //************************************************************************* TEST(test_decode_int8_t_pointer_size_no_output_size) { @@ -750,7 +817,7 @@ namespace } //************************************************************************* - TEST(test_decode_int8_t_pointer_pointer_back_inserter) + TEST(test_decode_int8_t_pointer_pointer_etl_back_inserter) { etl::base64_rfc4648 b64(etl::ibase64::Padding::Use_Padding); std::vector decoded_output; @@ -768,6 +835,27 @@ namespace } } +#if ETL_USING_STL + //************************************************************************* + TEST(test_decode_int8_t_pointer_pointer_std_back_inserter) + { + etl::base64_rfc4648 b64(etl::ibase64::Padding::Use_Padding); + std::vector decoded_output; + + for (size_t i = 0; i < 256; ++i) + { + decoded_output.clear(); + + auto decoded_size = b64.decode(encoded[i].data(), encoded[i].data() + encoded[i].size(), + std::back_inserter(decoded_output)); + + CHECK_ARRAY_EQUAL(input_data_int8_t.data(), decoded_output.data(), i); + CHECK_EQUAL(i, etl::base64_rfc4648::decoded_size(encoded[i].data(), encoded[i].size())); + CHECK_EQUAL(i, decoded_size); + } + } +#endif + //************************************************************************* TEST(test_decode_int8_t_pointer_pointer_no_end_pointer) { diff --git a/test/vs2022/etl.vcxproj b/test/vs2022/etl.vcxproj index 025fe5c6..b020e89f 100644 --- a/test/vs2022/etl.vcxproj +++ b/test/vs2022/etl.vcxproj @@ -7210,6 +7210,7 @@ +