diff --git a/include/etl/base64.h b/include/etl/base64.h index 3328bcf4..21b2641b 100644 --- a/include/etl/base64.h +++ b/include/etl/base64.h @@ -1,13 +1,11 @@ -//************************************************************************* -///Decode from Base64 from and to pointer/length -//*************************************************************************///\file +///\file /****************************************************************************** The MIT License(MIT) Embedded Template Library. https://github.com/ETLCPP/etl https://www.etlcpp.com -Copyright(c) 2023 John Wellbelove +Copyright(c) 2024 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 @@ -30,27 +28,14 @@ SOFTWARE. #include "etl/platform.h" #include "etl/static_assert.h" -#include "etl/error_handler.h" #include "etl/exception.h" +#include "etl/error_handler.h" #include "etl/type_traits.h" -#include "etl/binary.h" -#include "etl/algorithm.h" +#include "etl/enum_type.h" #include "etl/integral_limits.h" -#include "etl/iterator.h" -#include "enum_type.h" #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)) - /************************************************************************************************************************************************************************** * See https://en.wikipedia.org/wiki/Base64 * @@ -95,12 +80,12 @@ namespace etl //*************************************************************************** /// Illegal character exception. //*************************************************************************** - class base64_invalid_character : public base64_exception + class base64_invalid_data : public base64_exception { public: - base64_invalid_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_) + base64_invalid_data(string_type file_name_, numeric_type line_number_) + : base64_exception(ETL_ERROR_TEXT("base64:invalid data", ETL_BASE64_FILE_ID"B"), file_name_, line_number_) { } }; @@ -118,10 +103,10 @@ namespace etl } }; - //************************************************************************* - /// Codec for Base64 (RFC 4648) - //************************************************************************* - class ibase64 + //*************************************************************************** + /// Common Base64 definitions + //*************************************************************************** + class base64 { public: @@ -129,21 +114,25 @@ namespace etl { enum enum_type { - RFC_1421, - RFC_2045, + //RFC_1421, // Not implemented + //RFC_2045, // Not implemented RFC_2152, RFC_3501, RFC_4648, + RFC_4648_PADDING, RFC_4648_URL, + RFC_4648_URL_PADDING, }; ETL_DECLARE_ENUM_TYPE(Encoding, int) - 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_ENUM_TYPE(RFC_1421, "RFC_1421") // Not implemented + //ETL_ENUM_TYPE(RFC_2045, "RFC_2045") // Not implemented + 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_PADDING, "RFC_4648_PADDING") + ETL_ENUM_TYPE(RFC_4648_URL, "RFC_4648_URL") + ETL_ENUM_TYPE(RFC_4648_URL_PADDING, "RFC_4648_URL_PADDING") ETL_END_ENUM_TYPE }; @@ -175,384 +164,20 @@ namespace etl ETL_END_ENUM_TYPE }; - //************************************************************************* - /// Get the encoding standard - //************************************************************************* - ETL_CONSTEXPR14 - Encoding get_encoding() const + enum { - 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 bool(use_padding) == etl::ibase64::Padding::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 - //************************************************************************* - template - ETL_CONSTEXPR14 - 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"); - - 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, use_padding); - 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 - /// For TOutputIterator value type not equal to void - /// Three parameter - /// Assumes the output container is large enough. - //************************************************************************* - template - ETL_CONSTEXPR14 - 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"); - - const size_t input_length = static_cast(etl::distance(input_begin, input_end)); - const size_t output_length = encoded_size(input_length, use_padding); - - return process_encode(input_begin, input_length, output_begin, output_length); - } - - //************************************************************************* - /// Encode to Base64 - /// For etl::back_insert_iterator - /// Three parameter - /// Assumes the output container is large enough. - //************************************************************************* - template - ETL_CONSTEXPR14 - 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_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, use_padding); - - 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, use_padding); - - return process_encode(input_begin, input_length, output_begin, output_length); - } -#endif - - //************************************************************************* - /// Encode to Base64 - /// Four parameter - //************************************************************************* - template - ETL_CONSTEXPR14 - 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"); - - // Figure out if the output buffer is large enough. - size_t required_output_length = encoded_size(input_length, use_padding); - 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 - /// For TOutputIterator value_type not equal to void - /// Three parameter - /// Assumes the output container is large enough. - //************************************************************************* - template - ETL_CONSTEXPR14 - 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"); - - const size_t output_length = encoded_size(input_length, use_padding); - - return process_encode(input_begin, input_length, output_begin, output_length); - } - - //************************************************************************* - /// Encode to Base64 - /// For etl::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, 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_8_BIT_INTEGRAL(typename TContainer::value_type), "Output type must be an 8 bit integral"); - - const size_t output_length = encoded_size(input_length, use_padding); - - 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, use_padding); - - return process_encode(input_begin, input_length, output_begin, output_length); - } -#endif - - //************************************************************************* - /// Decode from Base64 - /// Four parameter - //************************************************************************* - template - ETL_CONSTEXPR14 - 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"); - - const size_t input_length = valid_decode_input_length(input_begin, input_end, use_padding); - 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 = 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 - /// Three parameter - /// Assumes the output container is large enough. - //************************************************************************* - template - ETL_CONSTEXPR14 - 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"); - - // Find the length of decodable characters. - const size_t input_length = valid_decode_input_length(input_begin, input_end, use_padding); - - // Find the length of the decoded output. - const size_t required_output_length = decoded_size_impl(input_begin, input_length, use_padding); - - return process_decode(input_begin, input_length, output_begin, required_output_length); - } - - //************************************************************************* - /// Decode from Base64 - /// For etl::back_insert_iterator - /// Three parameter - /// Assumes the output container is large enough. - //************************************************************************* - template - ETL_CONSTEXPR14 - 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_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_decode_input_length(input_begin, input_end, use_padding); - - // Find the length of the decoded output. - const size_t required_output_length = decoded_size_impl(input_begin, input_length, use_padding); - - 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_decode_input_length(input_begin, input_end, use_padding); - - // Find the length of the decoded output. - const size_t required_output_length = decoded_size_impl(input_begin, input_length, use_padding); - - return process_decode(input_begin, input_length, output_begin, required_output_length); - } -#endif - - //************************************************************************* - /// Decode from Base64 - /// Four parameter - //************************************************************************* - template - ETL_CONSTEXPR14 - 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_decode_input_length(input_begin, input_length, use_padding); - - // Figure out if the output buffer is large enough. - 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); - } - - //************************************************************************* - /// Decode from Base64 - /// Three parameter - /// Assumes the output container is large enough. - //************************************************************************* - template - ETL_CONSTEXPR14 - 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"); - - // Find the length of decodable characters. - input_length = valid_decode_input_length(input_begin, input_length, use_padding); - - // Find the length of the decoded output. - const size_t required_output_length = decoded_size_impl(input_begin, input_length, use_padding); - - return process_decode(input_begin, input_length, output_begin, required_output_length); - } - - //************************************************************************* - /// Decode from Base64 - /// For etl::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, 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_8_BIT_INTEGRAL(typename TContainer::value_type), "Output type must be an 8 bit integral"); - - // Find the length of decodable characters. - input_length = valid_decode_input_length(input_begin, input_length, use_padding); - - // Find the length of the decoded output. - const size_t output_length = decoded_size_impl(input_begin, input_length, use_padding); - - 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_decode_input_length(input_begin, input_length, use_padding); - - // Find the length of the decoded output. - const size_t output_length = decoded_size_impl(input_begin, input_length, use_padding); - - return process_decode(input_begin, input_length, output_begin, output_length); - } -#endif + Invalid_Data = etl::integral_limits::max, + Min_Encode_Buffer_Size = 4, + Min_Decode_Buffer_Size = 3 + }; protected: - //************************************************************************* - /// Constructor - //************************************************************************* ETL_CONSTEXPR14 - ibase64(Encoding encoding_, const char* p_lookup_, bool use_padding_, bool discard_illegal_characters_, size_t max_line_length_) - : encoding(encoding_) - , p_lookup(p_lookup_) + base64(const char* encoder_table_, + bool use_padding_) + : encoder_table(encoder_table_) , use_padding(use_padding_) - , discard_illegal_characters(discard_illegal_characters_) - , max_line_length(max_line_length_) { } @@ -586,527 +211,8 @@ namespace etl return "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+,"; } - //************************************************************************* - /// Calculates the minimum buffer size required to encode to Base64 - //************************************************************************* - ETL_NODISCARD - static - ETL_CONSTEXPR14 - size_t encoded_size(size_t input_length, bool use_padding) - { - size_t required_output_length; - - if (input_length == 0U) - { - return 0U; - } - - if (use_padding) - { - required_output_length = (input_length * 4U) / 3U; - - while ((required_output_length % 4U) != 0) - { - ++required_output_length; - } - } - else - { - required_output_length = input_length + (((input_length - 1U) / 3U) + 1U); - } - - return required_output_length; - } - - //************************************************************************* - /// Discovers the number of valid decodable characters - //************************************************************************* - template - ETL_NODISCARD - static - ETL_CONSTEXPR14 - size_t valid_decode_input_length(TInputIterator input_begin, size_t input_length, bool use_padding) - { - if (input_length == 0U) - { - return 0U; - } - - if (use_padding) - { - TInputIterator input_end = input_begin; - - 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 typename etl::iterator_traits::value_type input_type; - - if (*input_end != padding()) - { - ++input_length; - ++input_end; - - if (*input_end != padding()) - { - ++input_length; - } - } - } - - // Not all input lengths are valid. - ETL_ASSERT_OR_RETURN_VALUE((((input_length - 1U) % 4U) != 0U), ETL_ERROR(etl::base64_invalid_decode_input_length), 0U); - - return input_length; - } - - //************************************************************************* - /// Discovers the number of valid decodable characters - //************************************************************************* - template - ETL_NODISCARD - static - ETL_CONSTEXPR14 - size_t valid_decode_input_length(TInputIterator input_begin, TInputIterator input_end, bool use_padding) - { - return valid_decode_input_length(input_begin, static_cast(etl::distance(input_begin, input_end)), use_padding); - } - - //************************************************************************* - /// Calculates the minimum buffer size required to decode from Base64 - //************************************************************************* - ETL_NODISCARD - static - ETL_CONSTEXPR14 - size_t decoded_size_from_valid_input_length(size_t input_length) - { - if (input_length == 0U) - { - return 0U; - } - - --input_length; - return input_length - (input_length / 4U); - } - - //************************************************************************* - /// Calculates the minimum buffer size required to decode from Base64 - //************************************************************************* - template - ETL_NODISCARD - static - ETL_CONSTEXPR14 - size_t decoded_size_impl(TInputIterator input, size_t input_length, bool use_padding) - { - if (input_length == 0U) - { - return 0U; - } - - input_length = valid_decode_input_length(input, input_length, use_padding); - --input_length; - return input_length - (input_length / 4U); - } - - //************************************************************************* - /// Calculates the minimum buffer size required to decode from Base64 - //************************************************************************* - template - ETL_NODISCARD - static - ETL_CONSTEXPR14 - size_t decoded_size_impl(TInputIterator input_begin, TInputIterator input_end, bool use_padding) - { - return decoded_size_impl(static_cast(etl::distance(input_begin, input_end)), use_padding); - } - - private: - - //************************************************************************* - // Translates an index into a sextet - //************************************************************************* - template - ETL_CONSTEXPR14 - T get_sextet_from_index(int index) - { - return static_cast(p_lookup[index]); - } - - //************************************************************************* - // Translates a sextet into an index - //************************************************************************* - template - ETL_CONSTEXPR14 - uint32_t get_index_from_sextet(T sextet) - { - 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 static_cast(etl::distance(p_lookup, p_sextet)); - } - else - { - ETL_ASSERT_FAIL_AND_RETURN_VALUE(ETL_ERROR(base64_invalid_character), 0); - } - } - - //************************************************************************* - /// Gets the padding character - //************************************************************************* - template - ETL_NODISCARD - static - ETL_CONSTEXPR14 - T padding() - { - return static_cast('='); - } - - //************************************************************************* - /// Is the character a carriage return? - //************************************************************************* - template - ETL_NODISCARD - static - ETL_CONSTEXPR14 - bool is_carriage_return(T c) - { - return (static_cast(c) == '\r'); - } - - //************************************************************************* - /// Is the character a line break? - //************************************************************************* - template - ETL_NODISCARD - static - ETL_CONSTEXPR14 - 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); - 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; - *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); - 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); - 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; - } - - return output_length; - } - - Encoding encoding; - const char* p_lookup; - Padding 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: - - // 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 - //************************************************************************* - template - class base64_rfc4648 : public ibase64 - { - public: - - ETL_CONSTEXPR14 - base64_rfc4648() - : ibase64(etl::ibase64::Encoding::RFC_4648, - etl::private_base64::character_set<1>::set(), - Use_Padding, - etl::ibase64::Non_Coding_Characters::Reject, - etl::integral_limits::max) - { - } - - ETL_NODISCARD - static - ETL_CONSTEXPR14 - size_t encoded_size(size_t input_length) - { - return ibase64::encoded_size(input_length, Use_Padding); - } - - //************************************************************************* - /// Calculates the minimum buffer size required to decode from Base64 - //************************************************************************* - template - ETL_NODISCARD - static - ETL_CONSTEXPR14 - size_t decoded_size(TInputIterator input_begin, size_t input_length) - { - return etl::ibase64::decoded_size_impl(input_begin, input_length, Use_Padding); - } - - //************************************************************************* - /// Calculates the minimum buffer size required to decode from Base64 - //************************************************************************* - template - ETL_NODISCARD - static - ETL_CONSTEXPR14 - size_t decoded_size(TInputIterator input_begin, TInputIterator input_end) - { - return etl::ibase64::decoded_size_impl(input_begin, input_end, Use_Padding); - } - }; - - //************************************************************************* - /// Base64 RFC-4648 URL - //************************************************************************* - template - class base64_rfc4648_url : public ibase64 - { - public: - - ETL_CONSTEXPR14 - base64_rfc4648_url() - : ibase64(etl::ibase64::Encoding::RFC_4648_URL, - etl::private_base64::character_set<2>::set(), - Use_Padding, - etl::ibase64::Non_Coding_Characters::Reject, - etl::integral_limits::max) - { - } - - ETL_NODISCARD - static - ETL_CONSTEXPR14 - size_t encoded_size(size_t input_length) - { - return ibase64::encoded_size(input_length, Use_Padding); - } - - //************************************************************************* - /// Calculates the minimum buffer size required to decode from Base64 - //************************************************************************* - template - ETL_NODISCARD - static - ETL_CONSTEXPR14 - size_t decoded_size(TInputIterator input_begin, size_t input_length) - { - return etl::ibase64::decoded_size_impl(input_begin, input_length, Use_Padding); - } - - //************************************************************************* - /// Calculates the minimum buffer size required to decode from Base64 - //************************************************************************* - template - ETL_NODISCARD - static - ETL_CONSTEXPR14 - size_t decoded_size(TInputIterator input_begin, TInputIterator input_end) - { - return etl::ibase64::decoded_size_impl(input_begin, input_end, Use_Padding); - } + const char* encoder_table; + const bool use_padding; }; } - -#undef ETL_IS_TYPE_8_BIT_INTEGRAL -#undef ETL_IS_ITERATOR_TYPE_8_BIT_INTEGRAL - #endif diff --git a/include/etl/base64_decoder.h b/include/etl/base64_decoder.h new file mode 100644 index 00000000..6ceca45c --- /dev/null +++ b/include/etl/base64_decoder.h @@ -0,0 +1,922 @@ +//************************************************************************* +///Decode from Base64 from and to pointer/length +//*************************************************************************///\file + +/****************************************************************************** +The MIT License(MIT) +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com +Copyright(c) 2024 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. +******************************************************************************/ + +#ifndef ETL_BASE64_DECODER_INCLUDED +#define ETL_BASE64_DECODER_INCLUDED + +#include "etl/platform.h" +#include "etl/static_assert.h" +#include "etl/error_handler.h" +#include "etl/type_traits.h" +#include "etl/binary.h" +#include "etl/algorithm.h" +#include "etl/integral_limits.h" +#include "etl/iterator.h" +#include "etl/enum_type.h" +#include "etl/delegate.h" +#include "etl/span.h" + +#include "etl/base64.h" + +#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)) + +namespace etl +{ + //************************************************************************* + /// Base64 Decoder + //************************************************************************* + class ibase64_decoder : public base64 + { + public: + + typedef etl::span span_type; + typedef etl::delegate callback_type; + + //************************************************************************* + /// Decode to Base64 + //************************************************************************* + template + ETL_CONSTEXPR14 + bool decode(T value) + { + ETL_STATIC_ASSERT(ETL_IS_8_BIT_INTEGRAL(T), "Input type must be an 8 bit integral"); + + push_to_input_buffer(value); + + if (input_buffer_is_full()) + { + if (decode_block()) + { + if (callback.is_valid()) + { + if (output_buffer_is_full()) + { + callback(span()); + reset_output_buffer(); + } + } + } + + reset_input_buffer(); + } + + return !error(); + } + + //************************************************************************* + /// Decode from Base64 + //************************************************************************* + template + ETL_CONSTEXPR14 + bool decode(TInputIterator input_begin, TInputIterator input_end) + { + ETL_STATIC_ASSERT(ETL_IS_ITERATOR_TYPE_8_BIT_INTEGRAL(TInputIterator), "Input type must be an 8 bit integral"); + + while (input_begin != input_end) + { + if (!decode(*input_begin++)) + { + return false; + } + } + + return true; + } + + //************************************************************************* + /// Decode from Base64 + //************************************************************************* + template + ETL_CONSTEXPR14 + bool decode(TInputIterator input_begin, size_t input_length) + { + ETL_STATIC_ASSERT(ETL_IS_ITERATOR_TYPE_8_BIT_INTEGRAL(TInputIterator), "Input type must be an 8 bit integral"); + + while (input_length-- != 0) + { + if (!decode(*input_begin++)) + { + return false; + } + } + + return true; + } + + //************************************************************************* + /// Decode from Base64 + //************************************************************************* + template + ETL_CONSTEXPR14 + bool decode_final(TInputIterator input_begin, TInputIterator input_end) + { + return decode(input_begin, input_end) && flush(); + } + + //************************************************************************* + /// Decode from Base64 + //************************************************************************* + template + ETL_CONSTEXPR14 + bool decode_final(TInputIterator input_begin, size_t input_length) + { + return decode(input_begin, input_length) && flush(); + } + + //************************************************************************* + /// Flush any remaining data to the output. + //************************************************************************* + ETL_CONSTEXPR14 + bool flush() + { + // Encode any remaining input data. + bool success = decode_block(); + + reset_input_buffer(); + + if (success) + { + if (callback.is_valid()) + { + // Send any remaining data. + if (size() != 0) + { + callback(span()); + } + + // Indicate this was the final block. + callback(span_type()); + + reset_output_buffer(); + } + } + + padding_received = false; + + return success; + } + + //************************************************************************* + /// Reset the encoder. + //************************************************************************* + ETL_CONSTEXPR14 + void restart() + { + reset_input_buffer(); + reset_output_buffer(); + overflow_detected = false; + invalid_data_detected = false; + padding_received = false; + } + + //************************************************************************* + /// Returns the beginning of the output buffer. + //************************************************************************* + ETL_NODISCARD + ETL_CONSTEXPR14 + const unsigned char* begin() const + { + return p_output_buffer; + } + + //************************************************************************* + /// This only returns a useful value if a callback has not been set or called. + //************************************************************************* + ETL_NODISCARD + ETL_CONSTEXPR14 + const unsigned char* end() const + { + return p_output_buffer + output_buffer_length; + } + + //************************************************************************* + /// Returns the beginning of the output buffer. + //************************************************************************* + ETL_NODISCARD + ETL_CONSTEXPR14 + const unsigned char* cbegin() const + { + return p_output_buffer; + } + + //************************************************************************* + /// This only returns a useful value if a callback has not been set or called. + //************************************************************************* + ETL_NODISCARD + ETL_CONSTEXPR14 + const unsigned char* cend() const + { + return p_output_buffer + output_buffer_length; + } + + //************************************************************************* + /// Returns the size of the output buffer. + /// This only returns a useful value if a callback has not been set or called. + //************************************************************************* + ETL_NODISCARD + ETL_CONSTEXPR14 + size_t size() const + { + return output_buffer_length; + } + + //************************************************************************* + /// Returns the maximum size of the output buffer. + //************************************************************************* + ETL_NODISCARD + ETL_CONSTEXPR14 + size_t buffer_size() const + { + return output_buffer_max_size; + } + + //************************************************************************* + /// Get a span of the output data. + /// This only returns a useful span if a callback has not been set or called. + //************************************************************************* + ETL_NODISCARD + ETL_CONSTEXPR14 + span_type span() const + { + return span_type(begin(), end()); + } + + //************************************************************************* + /// Returns true if the output buffer has overflowed + //************************************************************************* + ETL_NODISCARD + ETL_CONSTEXPR14 + bool overflow() const + { + return overflow_detected; + } + + //************************************************************************* + /// Returns true if an invalid character was detected. + //************************************************************************* + ETL_NODISCARD + ETL_CONSTEXPR14 + bool invalid_data() const + { + return invalid_data_detected; + } + + //************************************************************************* + /// Returns true if an error was detected. + //************************************************************************* + ETL_NODISCARD + ETL_CONSTEXPR14 + bool error() const + { + return overflow() || invalid_data(); + } + + protected: + + //************************************************************************* + /// Constructor + //************************************************************************* + ETL_CONSTEXPR14 + ibase64_decoder(const char* encoder_table_, + bool use_padding_, + unsigned char* p_output_buffer_, + size_t ouput_buffer_max_size_, + callback_type callback_) + : base64(encoder_table_, use_padding_) + , input_buffer() + , input_buffer_length(0) + , p_output_buffer(p_output_buffer_) + , output_buffer_length(0) + , output_buffer_max_size(ouput_buffer_max_size_) + , callback(callback_) + , overflow_detected(false) + , invalid_data_detected(false) + , padding_received(false) + { + } + + //************************************************************************* + /// Calculates the minimum buffer size required to decode from Base64 + //************************************************************************* + ETL_NODISCARD + static + ETL_CONSTEXPR14 + size_t decoded_size_from_valid_input_length(size_t input_length) + { + return input_length - (input_length / 4U); + } + + private: + + //************************************************************************* + // Translates a sextet into an index + //************************************************************************* + template + ETL_CONSTEXPR14 + uint32_t get_index_from_sextet(T sextet) + { + const char* encoder_table_end = encoder_table + 64; + const char* p_sextet = etl::find(encoder_table, encoder_table_end, static_cast(sextet)); + + if (p_sextet != encoder_table_end) + { + return static_cast(etl::distance(encoder_table, p_sextet)); + } + else + { + invalid_data_detected = true; + return 0; + } + } + + //************************************************************************* + /// Gets the padding character + //************************************************************************* + template + ETL_NODISCARD + static + ETL_CONSTEXPR14 + T padding() + { + return static_cast('='); + } + + //************************************************************************* + /// Decode one block of data. + //************************************************************************* + ETL_CONSTEXPR14 + bool decode_block() + { + switch (input_buffer_length) + { + // Only triggered on call to flush(). + case 2: + { + uint32_t sextets = (get_index_from_sextet(input_buffer[0]) << 6); + sextets = sextets | (get_index_from_sextet(input_buffer[1])); + push_to_output_buffer((sextets >> 4) & 0xFF); + break; + } + + // Only triggered on call to flush(). + case 3: + { + uint32_t sextets = (get_index_from_sextet(input_buffer[0]) << 12); + sextets = sextets | (get_index_from_sextet(input_buffer[1]) << 6); + sextets = sextets | (get_index_from_sextet(input_buffer[2])); + push_to_output_buffer((sextets >> 10) & 0xFF); + push_to_output_buffer((sextets >> 2) & 0xFF); + break; + } + + // Only triggered on call to decode(). + case 4: + { + // Read in four sextets + uint32_t sextets = (get_index_from_sextet(input_buffer[0]) << 18); + sextets = sextets | (get_index_from_sextet(input_buffer[1]) << 12); + sextets = sextets | (get_index_from_sextet(input_buffer[2]) << 6); + sextets = sextets | (get_index_from_sextet(input_buffer[3])); + + // Write out three octets + push_to_output_buffer((sextets >> 16) & 0xFF); + push_to_output_buffer((sextets >> 8) & 0xFF); + push_to_output_buffer((sextets >> 0) & 0xFF); + break; + } + + default: + { + break; + } + } + + ETL_ASSERT(!invalid_data_detected, ETL_ERROR(etl::base64_invalid_data)); + ETL_ASSERT(!overflow_detected, ETL_ERROR(etl::base64_overflow)); + + return (!invalid_data_detected && !overflow_detected); + } + + //************************************************************************* + // Push to the output buffer. + //************************************************************************* + ETL_CONSTEXPR14 + void push_to_output_buffer(unsigned char c) + { + if (output_buffer_length < output_buffer_max_size) + { + p_output_buffer[output_buffer_length++] = c; + } + else + { + overflow_detected = true; + } + } + + //************************************************************************* + // + //************************************************************************* + ETL_CONSTEXPR14 + bool output_buffer_is_full() const + { + return output_buffer_length == output_buffer_max_size; + } + + //************************************************************************* + // + //************************************************************************* + ETL_CONSTEXPR14 + bool output_buffer_is_empty() const + { + return output_buffer_length == 0; + } + + //************************************************************************* + // + //************************************************************************* + ETL_CONSTEXPR14 + void reset_output_buffer() + { + output_buffer_length = 0; + } + + //************************************************************************* + // Push to the input buffer. + //************************************************************************* + template + ETL_CONSTEXPR14 + void push_to_input_buffer(T value) + { + if (value == padding()) + { + padding_received = true; + } + else + { + if (padding_received) + { + ETL_ASSERT_FAIL(ETL_ERROR(etl::base64_invalid_data)); + invalid_data_detected = true; + } + else + { + input_buffer[input_buffer_length++] = static_cast(value); + } + } + } + + //************************************************************************* + // + //************************************************************************* + ETL_CONSTEXPR14 + bool input_buffer_is_full() const + { + return input_buffer_length == 4U; + } + + //************************************************************************* + // + //************************************************************************* + ETL_CONSTEXPR14 + void reset_input_buffer() + { + input_buffer_length = 0; + } + + char input_buffer[4]; + size_t input_buffer_length; + + unsigned char* p_output_buffer; + size_t output_buffer_length; + const size_t output_buffer_max_size; + + callback_type callback; + + bool overflow_detected; + bool invalid_data_detected; + bool padding_received; + }; + + //************************************************************************* + /// Base64 RFC-2152 Decoder + //************************************************************************* + template + class base64_rfc2152_decoder : public ibase64_decoder + { + public: + + static ETL_CONSTANT etl::base64::Encoding Encoding = etl::base64::Encoding::RFC_2152; + static ETL_CONSTANT size_t Buffer_Size = Buffer_Size_; + + ETL_STATIC_ASSERT((Buffer_Size >= etl::base64::Min_Decode_Buffer_Size), "Buffer size must be greater than etl::base64::Min_Decode_Buffer_Size"); + + //************************************************************************* + /// Base64 RFC-2152 constructor. + //************************************************************************* + ETL_CONSTEXPR14 + base64_rfc2152_decoder() + : ibase64_decoder(etl::base64::character_set_1(), + etl::base64::Padding::No_Padding, + output_buffer, + Buffer_Size, + callback_type()) + , output_buffer{} + { + } + + //************************************************************************* + /// Base64 RFC-2152 constructor. + //************************************************************************* + ETL_CONSTEXPR14 + base64_rfc2152_decoder(callback_type callback_) + : ibase64_decoder(etl::base64::character_set_1(), + etl::base64::Padding::No_Padding, + output_buffer, + Buffer_Size, + callback_) + , output_buffer{} + { + } + + //************************************************************************* + /// Calculate the required output encode buffer size. + //************************************************************************* + ETL_NODISCARD + static + ETL_CONSTEXPR14 + size_t safe_output_buffer_size(size_t input_length) + { + return ibase64_decoder::decoded_size_from_valid_input_length(input_length); + } + + private: + + /// The internal output buffer. + unsigned char output_buffer[Buffer_Size]; + }; + + template + ETL_CONSTANT etl::base64::Encoding base64_rfc2152_decoder::Encoding; + + template + ETL_CONSTANT size_t base64_rfc2152_decoder::Buffer_Size; + + //************************************************************************* +/// Base64 RFC-3501 Decoder +//************************************************************************* + template + class base64_rfc3501_decoder : public ibase64_decoder + { + public: + + static ETL_CONSTANT etl::base64::Encoding Encoding = etl::base64::Encoding::RFC_3501; + static ETL_CONSTANT size_t Buffer_Size = Buffer_Size_; + + ETL_STATIC_ASSERT((Buffer_Size >= etl::base64::Min_Decode_Buffer_Size), "Buffer size must be greater than etl::base64::Min_Decode_Buffer_Size"); + + //************************************************************************* + /// Base64 RFC-3501 constructor. + //************************************************************************* + ETL_CONSTEXPR14 + base64_rfc3501_decoder() + : ibase64_decoder(etl::base64::character_set_3(), + etl::base64::Padding::No_Padding, + output_buffer, + Buffer_Size, + callback_type()) + , output_buffer{} + { + } + + //************************************************************************* + /// Base64 RFC-3501 constructor. + //************************************************************************* + ETL_CONSTEXPR14 + base64_rfc3501_decoder(callback_type callback_) + : ibase64_decoder(etl::base64::character_set_3(), + etl::base64::Padding::No_Padding, + output_buffer, + Buffer_Size, + callback_) + , output_buffer{} + { + } + + //************************************************************************* + /// Calculate the required output encode buffer size. + //************************************************************************* + ETL_NODISCARD + static + ETL_CONSTEXPR14 + size_t safe_output_buffer_size(size_t input_length) + { + return ibase64_decoder::decoded_size_from_valid_input_length(input_length); + } + + private: + + /// The internal output buffer. + unsigned char output_buffer[Buffer_Size]; + }; + + template + ETL_CONSTANT etl::base64::Encoding base64_rfc3501_decoder::Encoding; + + template + ETL_CONSTANT size_t base64_rfc3501_decoder::Buffer_Size; + + //************************************************************************* + /// Base64 RFC-4648 Decoder + //************************************************************************* + template + class base64_rfc4648_decoder : public ibase64_decoder + { + public: + + static ETL_CONSTANT etl::base64::Encoding Encoding = etl::base64::Encoding::RFC_4648; + static ETL_CONSTANT size_t Buffer_Size = Buffer_Size_; + + ETL_STATIC_ASSERT((Buffer_Size >= etl::base64::Min_Decode_Buffer_Size), "Buffer size must be greater than etl::base64::Min_Decode_Buffer_Size"); + + //************************************************************************* + /// Base64 RFC-4648 constructor. + //************************************************************************* + ETL_CONSTEXPR14 + base64_rfc4648_decoder() + : ibase64_decoder(etl::base64::character_set_1(), + etl::base64::Padding::No_Padding, + output_buffer, + Buffer_Size, + callback_type()) + , output_buffer{} + { + } + + //************************************************************************* + /// Base64 RFC-4648 constructor. + //************************************************************************* + ETL_CONSTEXPR14 + base64_rfc4648_decoder(callback_type callback_) + : ibase64_decoder(etl::base64::character_set_1(), + etl::base64::Padding::No_Padding, + output_buffer, + Buffer_Size, + callback_) + , output_buffer{} + { + } + + //************************************************************************* + /// Calculate the required output encode buffer size. + //************************************************************************* + ETL_NODISCARD + static + ETL_CONSTEXPR14 + size_t safe_output_buffer_size(size_t input_length) + { + return ibase64_decoder::decoded_size_from_valid_input_length(input_length); + } + + private: + + /// The internal output buffer. + unsigned char output_buffer[Buffer_Size]; + }; + + template + ETL_CONSTANT etl::base64::Encoding base64_rfc4648_decoder::Encoding; + + template + ETL_CONSTANT size_t base64_rfc4648_decoder::Buffer_Size; + + //************************************************************************* + /// Base64 RFC-4648-Padding Decoder + //************************************************************************* + template + class base64_rfc4648_padding_decoder : public ibase64_decoder + { + public: + + static ETL_CONSTANT etl::base64::Encoding Encoding = etl::base64::Encoding::RFC_4648_PADDING; + static ETL_CONSTANT size_t Buffer_Size = Buffer_Size_; + + ETL_STATIC_ASSERT((Buffer_Size >= etl::base64::Min_Decode_Buffer_Size), "Buffer size must be greater than etl::base64::Min_Decode_Buffer_Size"); + + //************************************************************************* + /// Base64 RFC-4648-Padding constructor. + //************************************************************************* + ETL_CONSTEXPR14 + base64_rfc4648_padding_decoder() + : ibase64_decoder(etl::base64::character_set_1(), + etl::base64::Padding::Use_Padding, + output_buffer, + Buffer_Size, + callback_type()) + , output_buffer{} + { + } + + //************************************************************************* + /// Base64 RFC-4648-Padding constructor. + //************************************************************************* + ETL_CONSTEXPR14 + base64_rfc4648_padding_decoder(callback_type callback_) + : ibase64_decoder(etl::base64::character_set_1(), + etl::base64::Padding::Use_Padding, + output_buffer, + Buffer_Size, + callback_) + , output_buffer{} + { + } + + //************************************************************************* + /// Calculate the required output encode buffer size. + //************************************************************************* + ETL_NODISCARD + static + ETL_CONSTEXPR14 + size_t safe_output_buffer_size(size_t input_length) + { + return ibase64_decoder::decoded_size_from_valid_input_length(input_length); + } + + private: + + /// The internal output buffer. + unsigned char output_buffer[Buffer_Size]; + }; + + template + ETL_CONSTANT etl::base64::Encoding base64_rfc4648_padding_decoder::Encoding; + + template + ETL_CONSTANT size_t base64_rfc4648_padding_decoder::Buffer_Size; + + //************************************************************************* + /// Base64 RFC-4648-URL Decoder + //************************************************************************* + template + class base64_rfc4648_url_decoder : public ibase64_decoder + { + public: + + static ETL_CONSTANT etl::base64::Encoding Encoding = etl::base64::Encoding::RFC_4648_URL; + static ETL_CONSTANT size_t Buffer_Size = Buffer_Size_; + + ETL_STATIC_ASSERT((Buffer_Size >= etl::base64::Min_Decode_Buffer_Size), "Buffer size must be greater than etl::base64::Min_Decode_Buffer_Size"); + + //************************************************************************* + /// Base64 RFC-4648-Padding constructor. + //************************************************************************* + ETL_CONSTEXPR14 + base64_rfc4648_url_decoder() + : ibase64_decoder(etl::base64::character_set_2(), + etl::base64::Padding::No_Padding, + output_buffer, + Buffer_Size, + callback_type()) + , output_buffer{} + { + } + + //************************************************************************* + /// Base64 RFC-4648-Padding constructor. + //************************************************************************* + ETL_CONSTEXPR14 + base64_rfc4648_url_decoder(callback_type callback_) + : ibase64_decoder(etl::base64::character_set_2(), + etl::base64::Padding::No_Padding, + output_buffer, + Buffer_Size, + callback_) + , output_buffer{} + { + } + + //************************************************************************* + /// Calculate the required output encode buffer size. + //************************************************************************* + ETL_NODISCARD + static + ETL_CONSTEXPR14 + size_t safe_output_buffer_size(size_t input_length) + { + return ibase64_decoder::decoded_size_from_valid_input_length(input_length); + } + + private: + + /// The internal output buffer. + unsigned char output_buffer[Buffer_Size]; + }; + + template + ETL_CONSTANT etl::base64::Encoding base64_rfc4648_url_decoder::Encoding; + + template + ETL_CONSTANT size_t base64_rfc4648_url_decoder::Buffer_Size; + + //************************************************************************* + /// Base64 RFC-4648-URL-Padding Decoder + //************************************************************************* + template + class base64_rfc4648_url_padding_decoder : public ibase64_decoder + { + public: + + static ETL_CONSTANT etl::base64::Encoding Encoding = etl::base64::Encoding::RFC_4648_URL_PADDING; + static ETL_CONSTANT size_t Buffer_Size = Buffer_Size_; + + ETL_STATIC_ASSERT((Buffer_Size >= etl::base64::Min_Decode_Buffer_Size), "Buffer size must be greater than etl::base64::Min_Decode_Buffer_Size"); + + //************************************************************************* + /// Base64 RFC-4648-Padding constructor. + //************************************************************************* + ETL_CONSTEXPR14 + base64_rfc4648_url_padding_decoder() + : ibase64_decoder(etl::base64::character_set_2(), + etl::base64::Padding::Use_Padding, + output_buffer, + Buffer_Size, + callback_type()) + , output_buffer{} + { + } + + //************************************************************************* + /// Base64 RFC-4648-Padding constructor. + //************************************************************************* + ETL_CONSTEXPR14 + base64_rfc4648_url_padding_decoder(callback_type callback_) + : ibase64_decoder(etl::base64::character_set_2(), + etl::base64::Padding::Use_Padding, + output_buffer, + Buffer_Size, + callback_) + , output_buffer{} + { + } + + //************************************************************************* + /// Calculate the required output encode buffer size. + //************************************************************************* + ETL_NODISCARD + static + ETL_CONSTEXPR14 + size_t safe_output_buffer_size(size_t input_length) + { + return ibase64_decoder::decoded_size_from_valid_input_length(input_length); + } + + private: + + /// The internal output buffer. + unsigned char output_buffer[Buffer_Size]; + }; + + template + ETL_CONSTANT etl::base64::Encoding base64_rfc4648_url_padding_decoder::Encoding; + + template + ETL_CONSTANT size_t base64_rfc4648_url_padding_decoder::Buffer_Size; +} + +#undef ETL_IS_TYPE_8_BIT_INTEGRAL +#undef ETL_IS_ITERATOR_TYPE_8_BIT_INTEGRAL + +#endif diff --git a/include/etl/base64_encoder.h b/include/etl/base64_encoder.h new file mode 100644 index 00000000..dbee7110 --- /dev/null +++ b/include/etl/base64_encoder.h @@ -0,0 +1,897 @@ +//************************************************************************* +///Decode from Base64 from and to pointer/length +//*************************************************************************///\file + +/****************************************************************************** +The MIT License(MIT) +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com +Copyright(c) 2024 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. +******************************************************************************/ + +#ifndef ETL_BASE64_ENCODER_INCLUDED +#define ETL_BASE64_ENCODER_INCLUDED + +#include "etl/platform.h" +#include "etl/static_assert.h" +#include "etl/error_handler.h" +#include "etl/type_traits.h" +#include "etl/binary.h" +#include "etl/algorithm.h" +#include "etl/integral_limits.h" +#include "etl/iterator.h" +#include "etl/enum_type.h" +#include "etl/delegate.h" +#include "etl/span.h" + +#include "etl/base64.h" + +#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)) + +namespace etl +{ + //************************************************************************* + /// Base64 Encoder + //************************************************************************* + class ibase64_encoder : public base64 + { + public: + + typedef etl::span span_type; + typedef etl::delegate callback_type; + + //************************************************************************* + /// Encode to Base64 + //************************************************************************* + template + ETL_CONSTEXPR14 + bool encode(T value) + { + ETL_STATIC_ASSERT(ETL_IS_8_BIT_INTEGRAL(T), "Input type must be an 8 bit integral"); + + push_to_input_buffer(value); + + if (input_buffer_is_full()) + { + encode_block(); + reset_input_buffer(); + + if (callback.is_valid()) + { + if (output_buffer_is_full()) + { + callback(span()); + reset_output_buffer(); + } + } + } + + return !error(); + } + + //************************************************************************* + /// Encode to Base64 + //************************************************************************* + template + ETL_CONSTEXPR14 + bool encode(TInputIterator input_begin, size_t input_length) + { + ETL_STATIC_ASSERT(ETL_IS_ITERATOR_TYPE_8_BIT_INTEGRAL(TInputIterator), "Input type must be an 8 bit integral"); + + while (input_length-- != 0) + { + if (!encode(*input_begin++)) + { + return false; + } + } + + return true; + } + + //************************************************************************* + /// Encode to Base64 + //************************************************************************* + template + ETL_CONSTEXPR14 + bool encode(TInputIterator input_begin, TInputIterator input_end) + { + ETL_STATIC_ASSERT(ETL_IS_ITERATOR_TYPE_8_BIT_INTEGRAL(TInputIterator), "Input type must be an 8 bit integral"); + + while (input_begin != input_end) + { + if (!encode(*input_begin++)) + { + return false; + } + } + + return true; + } + + //************************************************************************* + /// Encode to Base64 + //************************************************************************* + template + ETL_CONSTEXPR14 + bool encode_final(TInputIterator input_begin, size_t input_length) + { + return encode(input_begin, input_length) && flush(); + } + + //************************************************************************* + /// Encode to Base64 + //************************************************************************* + template + ETL_CONSTEXPR14 + bool encode_final(TInputIterator input_begin, TInputIterator input_end) + { + return encode(input_begin, input_end) && flush(); + } + + //************************************************************************* + /// Flush any remaining data to the output. + //************************************************************************* + ETL_CONSTEXPR14 + bool flush() + { + // Encode any remaining input data. + bool success = encode_block(); + + reset_input_buffer(); + + if (success) + { + if (callback.is_valid()) + { + // Send any remaining data. + if (size() != 0) + { + callback(span()); + } + + // Indicate this was the final block. + callback(span_type()); + + reset_output_buffer(); + } + } + + return success; + } + + //************************************************************************* + /// Reset the encoder. + //************************************************************************* + ETL_CONSTEXPR14 + void restart() + { + reset_input_buffer(); + reset_output_buffer(); + } + + //************************************************************************* + /// Returns the beginning of the output buffer. + //************************************************************************* + ETL_NODISCARD + ETL_CONSTEXPR14 + const char* begin() const + { + return p_output_buffer; + } + + //************************************************************************* + /// This only returns a useful value if a callback has not been set or called. + //************************************************************************* + ETL_NODISCARD + ETL_CONSTEXPR14 + const char* end() const + { + return p_output_buffer + output_buffer_length; + } + + //************************************************************************* + /// Returns the beginning of the output buffer. + //************************************************************************* + ETL_NODISCARD + ETL_CONSTEXPR14 + const char* cbegin() const + { + return p_output_buffer; + } + + //************************************************************************* + /// This only returns a useful value if a callback has not been set or called. + //************************************************************************* + ETL_NODISCARD + ETL_CONSTEXPR14 + const char* cend() const + { + return p_output_buffer + output_buffer_length; + } + + //************************************************************************* + /// Returns the size of the output buffer. + /// This only returns a useful value if a callback has not been set or called. + //************************************************************************* + ETL_NODISCARD + ETL_CONSTEXPR14 + size_t size() const + { + return output_buffer_length; + } + + //************************************************************************* + /// Returns the maximum size of the output buffer. + //************************************************************************* + ETL_NODISCARD + ETL_CONSTEXPR14 + size_t max_size() const + { + return output_buffer_max_size; + } + + //************************************************************************* + /// Get a span of the output data. + /// This only returns a useful span if a callback has not been set or called. + //************************************************************************* + ETL_NODISCARD + ETL_CONSTEXPR14 + span_type span() const + { + return span_type(begin(), end()); + } + + //************************************************************************* + /// Returns true if the output buffer has overflowed + //************************************************************************* + ETL_NODISCARD + ETL_CONSTEXPR14 + bool overflow() const + { + return overflowed; + } + + //************************************************************************* + /// Returns true if an error was detected. + //************************************************************************* + ETL_NODISCARD + ETL_CONSTEXPR14 + bool error() const + { + return overflow(); + } + + protected: + + //************************************************************************* + /// Constructor + //************************************************************************* + ETL_CONSTEXPR14 + ibase64_encoder(const char* encoder_table_, + bool use_padding_, + char* p_output_buffer_, + size_t ouput_buffer_max_size_, + callback_type callback_) + : base64(encoder_table_, use_padding_) + , input_buffer() + , input_buffer_length(0) + , p_output_buffer(p_output_buffer_) + , output_buffer_length(0) + , output_buffer_max_size(ouput_buffer_max_size_) + , callback(callback_) + , overflowed(false) + { + } + + //************************************************************************* + /// Encode one block of data. + //************************************************************************* + ETL_CONSTEXPR14 + bool encode_block() + { + switch (input_buffer_length) + { + // Only triggered on call to flush(). + case 1: + { + uint32_t octets = input_buffer[0]; + octets = octets << 4; // Adjust one octet (8 bits) for two sextets worth of data (12 bits) + + // Write out two sextets + optional padding. + push_to_output_buffer(encoder_table[(octets >> 6) & 0x3F]); + push_to_output_buffer(encoder_table[(octets >> 0) & 0x3F]); + + if (use_padding) + { + push_to_output_buffer('='); + push_to_output_buffer('='); + } + break; + } + + // Only triggered on call to flush(). + case 2: + { + uint32_t octets = (input_buffer[0] << 8) | input_buffer[1]; + octets <<= 2; // Adjust two octets (16 bits) for three sextets worth of data (18 bits) + + // Write out three sextets + optional padding. + push_to_output_buffer(encoder_table[(octets >> 12) & 0x3F]); + push_to_output_buffer(encoder_table[(octets >> 6) & 0x3F]); + push_to_output_buffer(encoder_table[(octets >> 0) & 0x3F]); + + if (use_padding) + { + push_to_output_buffer('='); + } + break; + } + + // Only triggered on call to encode(). + case 3: + { + uint32_t octets = (input_buffer[0] << 16) | (input_buffer[1] << 8) | input_buffer[2]; + + // Write out four sextets + push_to_output_buffer(encoder_table[(octets >> 18) & 0x3F]); + push_to_output_buffer(encoder_table[(octets >> 12) & 0x3F]); + push_to_output_buffer(encoder_table[(octets >> 6) & 0x3F]); + push_to_output_buffer(encoder_table[(octets >> 0) & 0x3F]); + break; + } + + default: + { + break; + } + } + + ETL_ASSERT(!overflowed, ETL_ERROR(etl::base64_overflow)); + + return !overflowed; + } + + //************************************************************************* + /// Calculates the minimum buffer size required to encode to Base64 + //************************************************************************* + ETL_NODISCARD + static + ETL_CONSTEXPR14 + size_t encoded_size(size_t input_length, bool use_padding) + { + size_t required_output_length = 0; + + if (input_length == 0U) + { + return 0U; + } + + if (use_padding) + { + required_output_length = (input_length * 4U) / 3U; + + while ((required_output_length % 4U) != 0) + { + ++required_output_length; + } + } + else + { + required_output_length = input_length + (((input_length - 1U) / 3U) + 1U); + } + + while (required_output_length % 4) + { + ++required_output_length; + } + + return required_output_length; + } + + private: + + //************************************************************************* + // Push to the output buffer. + //************************************************************************* + ETL_CONSTEXPR14 + void push_to_output_buffer(char c) + { + if (output_buffer_length < output_buffer_max_size) + { + p_output_buffer[output_buffer_length++] = c; + } + else + { + overflowed = true; + } + } + + //************************************************************************* + // + //************************************************************************* + ETL_CONSTEXPR14 + bool output_buffer_is_full() const + { + return output_buffer_length == output_buffer_max_size; + } + + //************************************************************************* + // + //************************************************************************* + ETL_CONSTEXPR14 + bool output_buffer_is_empty() const + { + return output_buffer_length == 0; + } + + //************************************************************************* + // + //************************************************************************* + ETL_CONSTEXPR14 + void reset_output_buffer() + { + output_buffer_length = 0; + } + + //************************************************************************* + // Push to the input buffer. + //************************************************************************* + template + ETL_CONSTEXPR14 + void push_to_input_buffer(T value) + { + input_buffer[input_buffer_length++] = static_cast(value); + } + + //************************************************************************* + // + //************************************************************************* + ETL_CONSTEXPR14 + bool input_buffer_is_full() const + { + return input_buffer_length == 3U; + } + + //************************************************************************* + // + //************************************************************************* + ETL_CONSTEXPR14 + void reset_input_buffer() + { + input_buffer_length = 0; + } + + uint8_t input_buffer[3]; + size_t input_buffer_length; + + char* p_output_buffer; + size_t output_buffer_length; + const size_t output_buffer_max_size; + + callback_type callback; + + bool overflowed; + }; + + //************************************************************************* + /// Base64 RFC-2152 Encoder + //************************************************************************* + template + class base64_rfc2152_encoder : public ibase64_encoder + { + public: + + static ETL_CONSTANT etl::base64::Encoding Encoding = etl::base64::Encoding::RFC_2152; + static ETL_CONSTANT size_t Buffer_Size = Buffer_Size_; + + ETL_STATIC_ASSERT((Buffer_Size >= etl::base64::Min_Encode_Buffer_Size), "Buffer size must be greater than etl::base64::Min_Encode_Buffer_Size"); + ETL_STATIC_ASSERT(((Buffer_Size % etl::base64::Min_Encode_Buffer_Size) == 0), "Buffer size must be a multiple of etl::base64::Min_Encode_Buffer_Size"); + + //************************************************************************* + /// Base64 RFC-2152 constructor. + //************************************************************************* + ETL_CONSTEXPR14 + base64_rfc2152_encoder() + : ibase64_encoder(etl::base64::character_set_1(), + etl::base64::Padding::No_Padding, + output_buffer, + Buffer_Size, + callback_type()) + , output_buffer{} + { + } + + //************************************************************************* + /// Base64 RFC-2152 constructor. + //************************************************************************* + ETL_CONSTEXPR14 + base64_rfc2152_encoder(callback_type callback_) + : ibase64_encoder(etl::base64::character_set_1(), + etl::base64::Padding::No_Padding, + output_buffer, + Buffer_Size, + callback_) + , output_buffer{} + { + } + + //************************************************************************* + /// Calculate the required output encode buffer size. + //************************************************************************* + ETL_NODISCARD + static + ETL_CONSTEXPR14 + size_t safe_output_buffer_size(size_t input_length) + { + return ibase64_encoder::encoded_size(input_length, etl::base64::Padding::No_Padding); + } + + private: + + /// The internal output buffer. + char output_buffer[Buffer_Size]; + }; + + template + ETL_CONSTANT etl::base64::Encoding base64_rfc2152_encoder::Encoding; + + template + ETL_CONSTANT size_t base64_rfc2152_encoder::Buffer_Size; + + //************************************************************************* + /// Base64 RFC-3501 Encoder + //************************************************************************* + template + class base64_rfc3501_encoder : public ibase64_encoder + { + public: + + static ETL_CONSTANT etl::base64::Encoding Encoding = etl::base64::Encoding::RFC_3501; + static ETL_CONSTANT size_t Buffer_Size = Buffer_Size_; + + ETL_STATIC_ASSERT((Buffer_Size >= etl::base64::Min_Encode_Buffer_Size), "Buffer size must be greater than etl::base64::Min_Encode_Buffer_Size"); + ETL_STATIC_ASSERT(((Buffer_Size% etl::base64::Min_Encode_Buffer_Size) == 0), "Buffer size must be a multiple of etl::base64::Min_Encode_Buffer_Size"); + + //************************************************************************* + /// Base64 RFC-3501 constructor. + //************************************************************************* + ETL_CONSTEXPR14 + base64_rfc3501_encoder() + : ibase64_encoder(etl::base64::character_set_3(), + etl::base64::Padding::No_Padding, + output_buffer, + Buffer_Size, + callback_type()) + , output_buffer{} + { + } + + //************************************************************************* + /// Base64 RFC-3501 constructor. + //************************************************************************* + ETL_CONSTEXPR14 + base64_rfc3501_encoder(callback_type callback_) + : ibase64_encoder(etl::base64::character_set_3(), + etl::base64::Padding::No_Padding, + output_buffer, + Buffer_Size, + callback_) + , output_buffer{} + { + } + + //************************************************************************* + /// Calculate the required output encode buffer size. + //************************************************************************* + ETL_NODISCARD + static + ETL_CONSTEXPR14 + size_t safe_output_buffer_size(size_t input_length) + { + return ibase64_encoder::encoded_size(input_length, etl::base64::Padding::No_Padding); + } + + private: + + /// The internal output buffer. + char output_buffer[Buffer_Size]; + }; + + template + ETL_CONSTANT etl::base64::Encoding base64_rfc3501_encoder::Encoding; + + template + ETL_CONSTANT size_t base64_rfc3501_encoder::Buffer_Size; + + //************************************************************************* + /// Base64 RFC-4648 Encoder + //************************************************************************* + template + class base64_rfc4648_encoder : public ibase64_encoder + { + public: + + static ETL_CONSTANT etl::base64::Encoding Encoding = etl::base64::Encoding::RFC_4648; + static ETL_CONSTANT size_t Buffer_Size = Buffer_Size_; + + ETL_STATIC_ASSERT((Buffer_Size >= etl::base64::Min_Encode_Buffer_Size), "Buffer size must be greater than etl::base64::Min_Encode_Buffer_Size"); + ETL_STATIC_ASSERT(((Buffer_Size% etl::base64::Min_Encode_Buffer_Size) == 0), "Buffer size must be a multiple of etl::base64::Min_Encode_Buffer_Size"); + + //************************************************************************* + /// Base64 RFC-4648 constructor. + //************************************************************************* + ETL_CONSTEXPR14 + base64_rfc4648_encoder() + : ibase64_encoder(etl::base64::character_set_1(), + etl::base64::Padding::No_Padding, + output_buffer, + Buffer_Size, + callback_type()) + , output_buffer{} + { + } + + //************************************************************************* + /// Base64 RFC-4648 constructor. + //************************************************************************* + ETL_CONSTEXPR14 + base64_rfc4648_encoder(callback_type callback_) + : ibase64_encoder(etl::base64::character_set_1(), + etl::base64::Padding::No_Padding, + output_buffer, + Buffer_Size, + callback_) + , output_buffer{} + { + } + + //************************************************************************* + /// Calculate the required output encode buffer size. + //************************************************************************* + ETL_NODISCARD + static + ETL_CONSTEXPR14 + size_t safe_output_buffer_size(size_t input_length) + { + return ibase64_encoder::encoded_size(input_length, etl::base64::Padding::No_Padding); + } + + private: + + /// The internal output buffer. + char output_buffer[Buffer_Size]; + }; + + template + ETL_CONSTANT etl::base64::Encoding base64_rfc4648_encoder::Encoding; + + template + ETL_CONSTANT size_t base64_rfc4648_encoder::Buffer_Size; + + //************************************************************************* +/// Base64 RFC-4648-Padding Encoder +//************************************************************************* + template + class base64_rfc4648_padding_encoder : public ibase64_encoder + { + public: + + static ETL_CONSTANT etl::base64::Encoding Encoding = etl::base64::Encoding::RFC_4648_PADDING; + static ETL_CONSTANT size_t Buffer_Size = Buffer_Size_; + + ETL_STATIC_ASSERT((Buffer_Size >= etl::base64::Min_Encode_Buffer_Size), "Buffer size must be greater than etl::base64::Min_Encode_Buffer_Size"); + ETL_STATIC_ASSERT(((Buffer_Size% etl::base64::Min_Encode_Buffer_Size) == 0), "Buffer size must be a multiple of etl::base64::Min_Encode_Buffer_Size"); + + //************************************************************************* + /// Base64 RFC-4648-Padding constructor. + //************************************************************************* + ETL_CONSTEXPR14 + base64_rfc4648_padding_encoder() + : ibase64_encoder(etl::base64::character_set_1(), + etl::base64::Padding::Use_Padding, + output_buffer, + Buffer_Size, + callback_type()) + , output_buffer{} + { + } + + //************************************************************************* + /// Base64 RFC-4648-Padding constructor. + //************************************************************************* + ETL_CONSTEXPR14 + base64_rfc4648_padding_encoder(callback_type callback_) + : ibase64_encoder(etl::base64::character_set_1(), + etl::base64::Padding::Use_Padding, + output_buffer, + Buffer_Size, + callback_) + , output_buffer{} + { + } + + //************************************************************************* + /// Calculate the required output encode buffer size. + //************************************************************************* + ETL_NODISCARD + static + ETL_CONSTEXPR14 + size_t safe_output_buffer_size(size_t input_length) + { + return ibase64_encoder::encoded_size(input_length, etl::base64::Padding::Use_Padding); + } + + private: + + /// The internal output buffer. + char output_buffer[Buffer_Size]; + }; + + template + ETL_CONSTANT etl::base64::Encoding base64_rfc4648_padding_encoder::Encoding; + + template + ETL_CONSTANT size_t base64_rfc4648_padding_encoder::Buffer_Size; + + //************************************************************************* + /// Base64 RFC-4648-URL Encoder + //************************************************************************* + template + class base64_rfc4648_url_encoder : public ibase64_encoder + { + public: + + static ETL_CONSTANT etl::base64::Encoding Encoding = etl::base64::Encoding::RFC_4648_URL; + static ETL_CONSTANT size_t Buffer_Size = Buffer_Size_; + + ETL_STATIC_ASSERT((Buffer_Size >= etl::base64::Min_Encode_Buffer_Size), "Buffer size must be greater than etl::base64::Min_Encode_Buffer_Size"); + ETL_STATIC_ASSERT(((Buffer_Size % etl::base64::Min_Encode_Buffer_Size) == 0), "Buffer size must be a multiple of etl::base64::Min_Encode_Buffer_Size"); + + //************************************************************************* + /// Base64 RFC-4648-URL constructor. + //************************************************************************* + ETL_CONSTEXPR14 + base64_rfc4648_url_encoder() + : ibase64_encoder(etl::base64::character_set_2(), + etl::base64::Padding::No_Padding, + output_buffer, + Buffer_Size, + callback_type()) + , output_buffer{} + { + } + + //************************************************************************* + /// Base64 RFC-4648-URL constructor. + //************************************************************************* + ETL_CONSTEXPR14 + base64_rfc4648_url_encoder(callback_type callback_) + : ibase64_encoder(etl::base64::character_set_2(), + etl::base64::Padding::No_Padding, + output_buffer, + Buffer_Size, + callback_) + , output_buffer{} + { + } + + //************************************************************************* + /// Calculate the required output encode buffer size. + //************************************************************************* + ETL_NODISCARD + static + ETL_CONSTEXPR14 + size_t safe_output_buffer_size(size_t input_length) + { + return ibase64_encoder::encoded_size(input_length, etl::base64::Padding::No_Padding); + } + + private: + + /// The internal output buffer. + char output_buffer[Buffer_Size]; + }; + + template + ETL_CONSTANT etl::base64::Encoding base64_rfc4648_url_encoder::Encoding; + + template + ETL_CONSTANT size_t base64_rfc4648_url_encoder::Buffer_Size; + + //************************************************************************* + /// Base64 RFC-4648-URL_Padding Encoder + //************************************************************************* + template + class base64_rfc4648_url_padding_encoder : public ibase64_encoder + { + public: + + static ETL_CONSTANT etl::base64::Encoding Encoding = etl::base64::Encoding::RFC_4648_URL; + static ETL_CONSTANT size_t Buffer_Size = Buffer_Size_; + + ETL_STATIC_ASSERT((Buffer_Size >= etl::base64::Min_Encode_Buffer_Size), "Buffer size must be greater than etl::base64::Min_Encode_Buffer_Size"); + ETL_STATIC_ASSERT(((Buffer_Size% etl::base64::Min_Encode_Buffer_Size) == 0), "Buffer size must be a multiple of etl::base64::Min_Encode_Buffer_Size"); + + //************************************************************************* + /// Base64 RFC-4648-URL constructor. + //************************************************************************* + ETL_CONSTEXPR14 + base64_rfc4648_url_padding_encoder() + : ibase64_encoder(etl::base64::character_set_2(), + etl::base64::Padding::Use_Padding, + output_buffer, + Buffer_Size, + callback_type()) + , output_buffer{} + { + } + + //************************************************************************* + /// Base64 RFC-4648-URL constructor. + //************************************************************************* + ETL_CONSTEXPR14 + base64_rfc4648_url_padding_encoder(callback_type callback_) + : ibase64_encoder(etl::base64::character_set_2(), + etl::base64::Padding::Use_Padding, + output_buffer, + Buffer_Size, + callback_) + , output_buffer{} + { + } + + //************************************************************************* + /// Calculate the required output encode buffer size. + //************************************************************************* + ETL_NODISCARD + static + ETL_CONSTEXPR14 + size_t safe_output_buffer_size(size_t input_length) + { + return ibase64_encoder::encoded_size(input_length, etl::base64::Padding::Use_Padding); + } + + private: + + /// The internal output buffer. + char output_buffer[Buffer_Size]; + }; + + template + ETL_CONSTANT etl::base64::Encoding base64_rfc4648_url_padding_encoder::Encoding; + + template + ETL_CONSTANT size_t base64_rfc4648_url_padding_encoder::Buffer_Size; +} + +#undef ETL_IS_TYPE_8_BIT_INTEGRAL +#undef ETL_IS_ITERATOR_TYPE_8_BIT_INTEGRAL + +#endif diff --git a/include/etl/private/delegate_cpp11.h b/include/etl/private/delegate_cpp11.h index b0c2b350..f904926a 100644 --- a/include/etl/private/delegate_cpp11.h +++ b/include/etl/private/delegate_cpp11.h @@ -309,6 +309,7 @@ namespace etl /// 'void' return. //************************************************************************* template + ETL_CONSTEXPR14 typename etl::enable_if_t::value, bool> call_if(TParams... args) const { @@ -328,6 +329,7 @@ namespace etl /// Non 'void' return. //************************************************************************* template + ETL_CONSTEXPR14 typename etl::enable_if_t::value, etl::optional> call_if(TParams... args) const { diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index b564f1f6..cad0feae 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -12,8 +12,6 @@ project(etl_unit_tests LANGUAGES CXX) add_executable(etl_tests main.cpp - test_base64_RFC4648_with_padding.cpp - test_base64_RFC4648_URL_with_padding.cpp murmurhash3.cpp test_algorithm.cpp test_alignment.cpp @@ -21,7 +19,18 @@ add_executable(etl_tests test_array_view.cpp test_array_wrapper.cpp test_atomic.cpp - test_base64.cpp + test_base64_RFC2152_decoder.cpp + test_base64_RFC2152_encoder.cpp + test_base64_RFC3501_decoder.cpp + test_base64_RFC3501_encoder.cpp + test_base64_RFC4648_decoder_with_no_padding.cpp + test_base64_RFC4648_decoder_with_padding.cpp + test_base64_RFC4648_encoder_with_no_padding.cpp + test_base64_RFC4648_encoder_with_padding.cpp + test_base64_RFC4648_URL_decoder_with_no_padding.cpp + test_base64_RFC4648_URL_decoder_with_padding.cpp + test_base64_RFC4648_URL_encoder_with_no_padding.cpp + test_base64_RFC4648_URL_encoder_with_padding.cpp test_binary.cpp test_bip_buffer_spsc_atomic.cpp test_bit.cpp @@ -56,7 +65,7 @@ add_executable(etl_tests test_container.cpp test_correlation.cpp test_covariance.cpp - test_crc.cpp + test_crc1.cpp test_crc16.cpp test_crc16_a.cpp test_crc16_arc.cpp diff --git a/test/etl_profile.h b/test/etl_profile.h index c0101762..38ec2abe 100644 --- a/test/etl_profile.h +++ b/test/etl_profile.h @@ -39,7 +39,7 @@ SOFTWARE. #define ETL_IDEQUE_REPAIR_ENABLE #define ETL_ICIRCULAR_BUFFER_REPAIR_ENABLE #define ETL_IN_UNIT_TEST -//#define ETL_DEBUG_COUNT +#define ETL_DEBUG_COUNT #define ETL_ARRAY_VIEW_IS_MUTABLE #define ETL_MESSAGE_TIMER_USE_ATOMIC_LOCK @@ -95,7 +95,7 @@ SOFTWARE. #define ETL_OBSERVER_FORCE_CPP03_IMPLEMENTATION #define ETL_MESSAGE_ROUTER_FORCE_CPP03_IMPLEMENTATION #define ETL_FSM_FORCE_CPP03_IMPLEMENTATION - #define ETL_DELEGATE_FORCE_CPP03_IMPLEMENTATION + //#define ETL_DELEGATE_FORCE_CPP03_IMPLEMENTATION // C++03 implementation is tested at the same time as the C++11 and above. #define ETL_SINGLETON_FORCE_CPP03_IMPLEMENTATION #define ETL_BYTE_FORCE_CPP03_IMPLEMENTATION #define ETL_LIST_FORCE_CPP03_IMPLEMENTATION @@ -114,10 +114,6 @@ SOFTWARE. #include "../include/etl/profiles/determine_compiler_version.h" #include "../include/etl/profiles/determine_development_os.h" -//#if ETL_CPP17_NOT_SUPPORTED -// #error THE UNIT TESTS REQUIRE C++17 SUPPORT -//#endif - #if defined(ETL_COMPILER_GCC) #if (ETL_COMPILER_VERSION < 8) #define ETL_TEMPLATE_DEDUCTION_GUIDE_TESTS_DISABLED diff --git a/test/meson.build b/test/meson.build index 67cb04b9..b84a21be 100644 --- a/test/meson.build +++ b/test/meson.build @@ -8,6 +8,18 @@ etl_test_sources = files( 'test_array_view.cpp', 'test_array_wrapper.cpp', 'test_atomic.cpp', + 'test_base64_RFC2152_decoder.cppp', + 'test_base64_RFC2152_encoder.cppp', + 'test_base64_RFC3501_decoder.cppp', + 'test_base64_RFC3501_encoder.cppp', + 'test_base64_RFC4648_decoder_with_no_padding.cppp', + 'test_base64_RFC4648_decoder_with_padding.cppp', + 'test_base64_RFC4648_encoder_with_no_padding.cppp', + 'test_base64_RFC4648_encoder_with_padding.cppp', + 'test_base64_RFC4648_URL_decoder_with_no_padding.cppp', + 'test_base64_RFC4648_URL_decoder_with_padding.cppp', + 'test_base64_RFC4648_URL_encoder_with_no_padding.cppp', + 'test_base64_RFC4648_URL_encoder_with_padding.cpp', 'test_binary.cpp', 'test_bip_buffer_spsc_atomic.cpp', 'test_bit.cpp', @@ -42,7 +54,7 @@ etl_test_sources = files( 'test_container.cpp', 'test_correlation.cpp', 'test_covariance.cpp', - 'test_crc.cpp', + 'test_crc1.cpp', 'test_crc16.cpp', 'test_crc16_a.cpp', 'test_crc16_arc.cpp', diff --git a/test/run-syntax-checks.sh b/test/run-syntax-checks.sh index 06932079..d2d06c7a 100644 --- a/test/run-syntax-checks.sh +++ b/test/run-syntax-checks.sh @@ -29,12 +29,12 @@ PrintHeader() { echo "$TitleColour" echo "============================================================================" | tee -a log.txt - echo " Configuration : $configuration_name" | tee -a log.txt - echo " Compiler : $compiler " | tee -a log.txt - echo " Language standard : C++$cxx_standard " | tee -a log.txt - echo " ETL version : $etl_version " | tee -a log.txt - echo " Git branch : $(ParseGitBranch) " | tee -a log.txt - echo " Processes : ${CMAKE_BUILD_PARALLEL_LEVEL}" | tee -a log.txt + echo " Configuration : $configuration_name" | tee -a log.txt + echo " Compiler : $compiler " | tee -a log.txt + echo " Language : C++$cxx_standard " | tee -a log.txt + echo " ETL version : $etl_version " | tee -a log.txt + echo " Git branch : $(ParseGitBranch) " | tee -a log.txt + echo " Processes : ${CMAKE_BUILD_PARALLEL_LEVEL}" | tee -a log.txt echo "============================================================================" | tee -a log.txt echo "$NoColour" } @@ -43,7 +43,7 @@ PassedCompilation() { echo "$PassColour" echo "-----------------------------------------------" | tee -a log.txt - echo " Passed Compilation - $configuration_name" | tee -a log.txt + echo " Compilation Success - $configuration_name" | tee -a log.txt echo "-----------------------------------------------" | tee -a log.txt echo "$NoColour" } diff --git a/test/run-tests.sh b/test/run-tests.sh index 41fd6b29..408c7481 100644 --- a/test/run-tests.sh +++ b/test/run-tests.sh @@ -38,14 +38,14 @@ PrintHeader() { echo "$TitleColour" echo "============================================================================" | tee -a log.txt - echo " Configuration : $configuration_name" | tee -a log.txt - echo " Compiler : $compiler " | tee -a log.txt - echo " Language standard : C++$cxx_standard " | tee -a log.txt - echo " Optimisation : $opt " | tee -a log.txt - echo " Sanitizer : $sanitize " | tee -a log.txt - echo " ETL version : $etl_version " | tee -a log.txt - echo " Git branch : $(ParseGitBranch) " | tee -a log.txt - echo " Processes : ${CMAKE_BUILD_PARALLEL_LEVEL}" | tee -a log.txt + echo " Configuration : $configuration_name" | tee -a log.txt + echo " Compiler : $compiler " | tee -a log.txt + echo " Language : C++$cxx_standard " | tee -a log.txt + echo " Optimisation : $opt " | tee -a log.txt + echo " Sanitizer : $sanitize " | tee -a log.txt + echo " ETL version : $etl_version " | tee -a log.txt + echo " Git branch : $(ParseGitBranch) " | tee -a log.txt + echo " Processes : ${CMAKE_BUILD_PARALLEL_LEVEL}" | tee -a log.txt echo "============================================================================" | tee -a log.txt echo "$NoColour" } @@ -67,7 +67,7 @@ PassedCompilation() { echo "$PassColour" echo "-----------------------------------------------" | tee -a log.txt - echo " Passed Compilation - $configuration_name" | tee -a log.txt + echo " Compilation Success - $configuration_name" | tee -a log.txt echo "-----------------------------------------------" | tee -a log.txt echo "$NoColour" } diff --git a/test/syntax_check/base64.h.t.cpp b/test/syntax_check/base64.h.t.cpp index 184c72bc..5d18409e 100644 --- a/test/syntax_check/base64.h.t.cpp +++ b/test/syntax_check/base64.h.t.cpp @@ -26,4 +26,5 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ******************************************************************************/ -#include +#include +#include diff --git a/test/test_base64_RFC2152_decoder.cpp b/test/test_base64_RFC2152_decoder.cpp new file mode 100644 index 00000000..f8a43451 --- /dev/null +++ b/test/test_base64_RFC2152_decoder.cpp @@ -0,0 +1,786 @@ +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Copyright(c) 2024 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 + +#include "etl/base64_decoder.h" + +#include "etl/string.h" +#include "etl/vector.h" + +#include +#include +#include +#include + +#if ETL_USING_STL + #include +#endif + +#include "etl/integral_limits.h" + +//***************************************************************************** +// Encode/decode using RFC-2152 +//***************************************************************************** + +namespace +{ + using codec = etl::base64_rfc2152_decoder; + using codec_larger_buffer = etl::base64_rfc2152_decoder; + +#if (ETL_USING_CPP14) + using codec_full_buffer = etl::base64_rfc2152_decoder< etl::base64_rfc2152_decoder<>::safe_output_buffer_size(342)>; +#else + using codec_full_buffer = etl::base64_rfc2152_decoder<256>; +#endif + + std::vector decoded_output; + bool received_final_block = false; + + codec::callback_type callback = [](const codec::span_type& sp) + { + if (sp.empty()) + { + received_final_block = true; + } + else + { + std::copy(sp.begin(), sp.end(), std::back_inserter(decoded_output)); + } + }; + + std::array input_data = + { + 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 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_rfc2152_with_no_padding) + { + //************************************************************************* + TEST(test_basic_information) + { + codec_full_buffer b64; + + CHECK_EQUAL(etl::base64::Encoding::RFC_2152, codec_full_buffer::Encoding); + CHECK_EQUAL("RFC_2152", codec_full_buffer::Encoding.c_str()); + } + + //************************************************************************* + TEST(test_check_encode_safe_buffer_sizes) + { + for (size_t i = 0; i < 256; ++i) + { + size_t minimum_size = i; + size_t safe_size = codec::safe_output_buffer_size(encoded[i].size()); + + CHECK_TRUE(safe_size >= minimum_size); + CHECK_TRUE((safe_size - minimum_size) <= 2U); + } + } + + //************************************************************************* + TEST(test_decode_pointer_size_single_pass_with_callback) + { + codec b64(callback); + + for (size_t i = 0; i < 256; ++i) + { + decoded_output.clear(); + received_final_block = false; + + b64.decode_final(encoded[i].data(), encoded[i].size()); + + std::vector expected(input_data.begin(), input_data.begin() + i); + std::vector actual(decoded_output); + + CHECK_TRUE(received_final_block); + CHECK_EQUAL(expected.size(), actual.size()); + CHECK_TRUE(std::equal(expected.begin(), expected.end(), actual.begin())); + CHECK_TRUE(codec::safe_output_buffer_size(encoded[i].size()) >= decoded_output.size()); + } + } + + //************************************************************************* + TEST(test_decode_pointer_size_single_pass_with_callback_and_larger_buffer) + { + codec_larger_buffer b64(callback); + + for (size_t i = 0; i < 256; ++i) + { + decoded_output.clear(); + received_final_block = false; + + b64.decode_final(encoded[i].data(), encoded[i].size()); + + std::vector expected(input_data.begin(), input_data.begin() + i); + std::vector actual(decoded_output); + + CHECK_TRUE(received_final_block); + CHECK_EQUAL(expected.size(), actual.size()); + CHECK_TRUE(std::equal(expected.begin(), expected.end(), actual.begin())); + CHECK_TRUE(codec_larger_buffer::safe_output_buffer_size(encoded[i].size()) >= decoded_output.size()); + } + } + + //************************************************************************* + TEST(test_decode_pointer_size_multi_pass_with_callback) + { + codec b64(callback); + + for (size_t i = 0; i < 256; ++i) + { + decoded_output.clear(); + received_final_block = false; + + auto start = encoded[i].data(); + auto length = encoded[i].size(); + + while (length >= 5) + { + b64.decode(start, 5); + length -= 5; + start += 5; + } + + if (length > 0) + { + b64.decode(start, length); + } + + CHECK_FALSE(received_final_block); + b64.flush(); + CHECK_TRUE(received_final_block); + + std::vector expected(input_data.begin(), input_data.begin() + i); + std::vector actual(decoded_output); + + CHECK_TRUE(received_final_block); + CHECK_EQUAL(expected.size(), actual.size()); + CHECK_TRUE(std::equal(expected.begin(), expected.end(), actual.begin())); + CHECK_TRUE(codec::safe_output_buffer_size(encoded[i].size()) >= decoded_output.size()); + } + } + + //************************************************************************* + TEST(test_decode_pointer_size_multi_pass_with_callback_and_larger_buffer) + { + codec_larger_buffer b64(callback); + + for (size_t i = 0; i < 256; ++i) + { + decoded_output.clear(); + received_final_block = false; + + auto start = encoded[i].data(); + auto length = encoded[i].size(); + + while (length >= 5) + { + b64.decode(start, 5); + length -= 5; + start += 5; + } + + if (length > 0) + { + b64.decode(start, length); + } + + CHECK_FALSE(received_final_block); + b64.flush(); + CHECK_TRUE(received_final_block); + + std::vector expected(input_data.begin(), input_data.begin() + i); + std::vector actual(decoded_output); + + CHECK_TRUE(received_final_block); + CHECK_EQUAL(expected.size(), actual.size()); + CHECK_TRUE(std::equal(expected.begin(), expected.end(), actual.begin())); + CHECK_TRUE(codec::safe_output_buffer_size(encoded[i].size()) >= decoded_output.size()); + } + } + + //************************************************************************* + TEST(test_decode_pointer_pointer_single_pass_with_callback) + { + codec b64(callback); + + for (size_t i = 0; i < 256; ++i) + { + decoded_output.clear(); + received_final_block = false; + + b64.decode_final(encoded[i].begin(), encoded[i].end()); + + std::vector expected(input_data.begin(), input_data.begin() + i); + std::vector actual(decoded_output); + + CHECK_TRUE(received_final_block); + CHECK_EQUAL(expected.size(), actual.size()); + CHECK_TRUE(std::equal(expected.begin(), expected.end(), actual.begin())); + CHECK_TRUE(codec::safe_output_buffer_size(encoded[i].size()) >= decoded_output.size()); + } + } + + //************************************************************************* + TEST(test_decode_pointer_pointer_single_pass_with_callback_and_larger_buffer) + { + codec_larger_buffer b64(callback); + + for (size_t i = 0; i < 256; ++i) + { + decoded_output.clear(); + received_final_block = false; + + b64.decode_final(encoded[i].begin(), encoded[i].end()); + + std::vector expected(input_data.begin(), input_data.begin() + i); + std::vector actual(decoded_output); + + CHECK_TRUE(received_final_block); + CHECK_EQUAL(expected.size(), actual.size()); + CHECK_TRUE(std::equal(expected.begin(), expected.end(), actual.begin())); + CHECK_TRUE(codec_larger_buffer::safe_output_buffer_size(encoded[i].size()) >= decoded_output.size()); + } + } + + //************************************************************************* + TEST(test_decode_pointer_pointer_multi_pass_with_callback) + { + codec b64(callback); + + for (size_t i = 0; i < 256; ++i) + { + decoded_output.clear(); + received_final_block = false; + + auto start = encoded[i].data(); + auto length = encoded[i].size(); + + while (length >= 5) + { + b64.decode(start, 5); + length -= 5; + start += 5; + } + + if (length > 0) + { + b64.decode(start, start + length); + } + + CHECK_FALSE(received_final_block); + b64.flush(); + CHECK_TRUE(received_final_block); + + std::vector expected(input_data.begin(), input_data.begin() + i); + std::vector actual(decoded_output); + + CHECK_TRUE(received_final_block); + CHECK_EQUAL(expected.size(), actual.size()); + CHECK_TRUE(std::equal(expected.begin(), expected.end(), actual.begin())); + CHECK_TRUE(codec::safe_output_buffer_size(encoded[i].size()) >= decoded_output.size()); + } + } + + //************************************************************************* + TEST(test_decode_pointer_pointer_multi_pass_with_callback_and_larger_buffer) + { + codec_larger_buffer b64(callback); + + for (size_t i = 0; i < 256; ++i) + { + decoded_output.clear(); + received_final_block = false; + + auto start = encoded[i].data(); + auto length = encoded[i].size(); + + while (length >= 5) + { + b64.decode(start, 5); + length -= 5; + start += 5; + } + + if (length > 0) + { + b64.decode(start, start + length); + } + + CHECK_FALSE(received_final_block); + b64.flush(); + CHECK_TRUE(received_final_block); + + std::vector expected(input_data.begin(), input_data.begin() + i); + std::vector actual(decoded_output); + + CHECK_TRUE(received_final_block); + CHECK_EQUAL(expected.size(), actual.size()); + CHECK_TRUE(std::equal(expected.begin(), expected.end(), actual.begin())); + CHECK_TRUE(codec::safe_output_buffer_size(encoded[i].size()) >= decoded_output.size()); + } + } + + //************************************************************************* + TEST(test_decode_multi_pass_by_char_with_callback) + { + codec b64(callback); + + for (size_t i = 0; i < 256; ++i) + { + decoded_output.clear(); + received_final_block = false; + + auto start = encoded[i].data(); + auto length = encoded[i].size(); + + while (length--) + { + b64.decode(*start++); + } + + CHECK_FALSE(received_final_block); + b64.flush(); + CHECK_TRUE(received_final_block); + + std::vector expected(input_data.begin(), input_data.begin() + i); + std::vector actual(decoded_output); + + CHECK_TRUE(received_final_block); + CHECK_EQUAL(expected.size(), actual.size()); + CHECK_TRUE(std::equal(expected.begin(), expected.end(), actual.begin())); + CHECK_TRUE(codec::safe_output_buffer_size(encoded[i].size()) >= decoded_output.size()); + } + } + + //************************************************************************* + TEST(test_decode_multi_pass_by_char_with_callback_and_larger_buffer) + { + codec_larger_buffer b64(callback); + + for (size_t i = 0; i < 256; ++i) + { + decoded_output.clear(); + received_final_block = false; + + auto start = encoded[i].data(); + auto length = encoded[i].size(); + + while (length--) + { + b64.decode(*start++); + } + + CHECK_FALSE(received_final_block); + b64.flush(); + CHECK_TRUE(received_final_block); + + std::vector expected(input_data.begin(), input_data.begin() + i); + std::vector actual(decoded_output); + + CHECK_TRUE(received_final_block); + CHECK_EQUAL(expected.size(), actual.size()); + CHECK_TRUE(std::equal(expected.begin(), expected.end(), actual.begin())); + CHECK_TRUE(codec::safe_output_buffer_size(encoded[i].size()) >= decoded_output.size()); + } + } + + //************************************************************************* + TEST(test_decode_multi_pass_blocks_with_no_callback_and_full_size_buffer) + { + codec_full_buffer b64; + + for (size_t i = 4; i < 256; ++i) + { + b64.restart(); + + auto start = encoded[i].data(); + auto length = encoded[i].size(); + + while (length >= 5) + { + b64.decode(start, 5); + length -= 5; + start += 5; + } + + if (length > 0) + { + b64.decode(start, length); + } + + b64.flush(); + + std::vector expected(input_data.begin(), input_data.begin() + i); + std::vector actual(b64.begin(), b64.end()); + + CHECK_EQUAL(expected.size(), actual.size()); + CHECK_TRUE(std::equal(expected.begin(), expected.end(), actual.begin())); + CHECK_TRUE(codec::safe_output_buffer_size(encoded[i].size()) >= b64.size()); + } + } + + //************************************************************************* +#if ETL_USING_CPP14 + template + constexpr auto GetConstexprBase64(const etl::array input) noexcept + { + etl::array output{ 0 }; + + using codec = etl::base64_rfc2152_decoder; + + codec b64; + b64.decode_final(input.begin(), input.end()); + etl::copy(b64.begin(), b64.end(), output.begin()); + + return output; + } + + TEST(test_encode_constexpr) + { + constexpr etl::array input = { 'A', 'A', 'E', 'C' ,'A' ,'w', 'Q', 'F', 'B', 'g', 'c', 'I', 'C', 'Q'}; + + constexpr auto output{ GetConstexprBase64(input) }; + + std::vector expected = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + std::vector actual(output.begin(), output.end()); + + CHECK_TRUE(std::equal(expected.begin(), expected.end(), actual.begin())); + CHECK_TRUE(codec::safe_output_buffer_size(14) >= output.size()); + } +#endif + + //************************************************************************* + TEST(test_decode_overflow) + { + codec b64; + +#if ETL_USING_EXCEPTIONS + CHECK_THROW((b64.decode(encoded[10].data(), encoded[10].size())), etl::base64_overflow); +#else + CHECK_FALSE(b64.decode(encoded[10].data(), encoded[10].size()); + CHECK_TRUE(b64.error()); +#endif + } + + //************************************************************************* + TEST(test_decode_invalid_character) + { + codec_larger_buffer b64; + + std::string invalid_chararacter("OycDQ#37KA"); + +#if ETL_USING_EXCEPTIONS + CHECK_THROW((b64.decode(invalid_chararacter.data(), invalid_chararacter.size())), etl::base64_invalid_data); +#else + CHECK_FALSE(b64.decode(invalid_chararacter.data(), invalid_chararacter.size())); + CHECK_TRUE(b64.error()); +#endif + } + }; +} + diff --git a/test/test_base64_RFC2152_encoder.cpp b/test/test_base64_RFC2152_encoder.cpp new file mode 100644 index 00000000..ecf5051c --- /dev/null +++ b/test/test_base64_RFC2152_encoder.cpp @@ -0,0 +1,756 @@ +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Copyright(c) 2024 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_encoder.h" + +#include "etl/string.h" +#include "etl/vector.h" + +#include +#include +#include +#include + +#if ETL_USING_STL + #include +#endif + +#include "etl/integral_limits.h" + +//***************************************************************************** +// Encode/decode using RFC-2152 with no padding +// Using minimum buffer size, with callback. +//***************************************************************************** + +namespace +{ + using codec = etl::base64_rfc2152_encoder; + using codec_larger_buffer = etl::base64_rfc2152_encoder; +#if ETL_USING_CPP14 + using codec_full_buffer = etl::base64_rfc2152_encoder::safe_output_buffer_size(256)>; +#else + using codec_full_buffer = etl::base64_rfc2152_encoder<344>; +#endif + + std::string encoded_output; + bool received_final_block = false; + + codec::callback_type callback = [](const codec::span_type& sp) + { + if (sp.empty()) + { + received_final_block = true; + } + else + { + std::copy(sp.begin(), sp.end(), std::back_inserter(encoded_output)); + } + }; + + std::array input_data = + { + 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 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", + "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" + }; + + SUITE(test_base64_rfc2152_with_no_padding) + { + //************************************************************************* + TEST(test_basic_information) + { + codec_full_buffer b64; + + CHECK_EQUAL(etl::base64::Encoding::RFC_2152, codec_full_buffer::Encoding); + CHECK_EQUAL("RFC_2152", codec_full_buffer::Encoding.c_str()); + } + + //************************************************************************* + TEST(test_check_encode_safe_buffer_sizes) + { + for (size_t i = 0; i < 256; ++i) + { + size_t minimum_size = encoded[i].size(); + size_t safe_size = codec::safe_output_buffer_size(i); + + CHECK_TRUE(safe_size >= minimum_size); + CHECK_TRUE((safe_size - minimum_size) <= 2U); + } + } + + //************************************************************************* + TEST(test_encode_pointer_size_single_pass_with_callback) + { + codec b64(callback); + + for (size_t i = 0; i < 256; ++i) + { + encoded_output.clear(); + received_final_block = false; + + b64.encode_final(input_data.data(), i); + + std::string expected(encoded[i]); + std::string actual(encoded_output); + + CHECK_TRUE(received_final_block); + CHECK_EQUAL(expected, actual); + CHECK_TRUE(codec::safe_output_buffer_size(i) >= encoded_output.size()); + } + } + + //************************************************************************* + TEST(test_encode_pointer_size_single_pass_with_callback_and_larger_buffer) + { + codec_larger_buffer b64(callback); + + for (size_t i = 0; i < 256; ++i) + { + encoded_output.clear(); + received_final_block = false; + + b64.encode_final(input_data.data(), i); + + std::string expected(encoded[i]); + std::string actual(encoded_output); + + CHECK_TRUE(received_final_block); + CHECK_EQUAL(expected, actual); + CHECK_TRUE(codec::safe_output_buffer_size(i) >= encoded_output.size()); + } + } + + //************************************************************************* + TEST(test_encode_pointer_size_multi_pass_blocks_with_callback) + { + codec b64(callback); + + for (size_t i = 0; i < 256; ++i) + { + encoded_output.clear(); + received_final_block = false; + + auto start = input_data.data(); + auto length = i; + + while (length >= 5) + { + b64.encode(start, 5); + length -= 5; + start += 5; + } + + if (length > 0) + { + b64.encode(start, length); + } + + CHECK_FALSE(received_final_block); + b64.flush(); + CHECK_TRUE(received_final_block); + + std::string expected(encoded[i]); + std::string actual(encoded_output); + + CHECK_EQUAL(expected, actual); + CHECK_TRUE(codec::safe_output_buffer_size(i) >= encoded_output.size()); + } + } + + //************************************************************************* + TEST(test_encode_pointer_size_multi_pass_blocks_with_callback_larger_buffer) + { + codec_larger_buffer b64(callback); + + for (size_t i = 0; i < 256; ++i) + { + encoded_output.clear(); + received_final_block = false; + + auto start = input_data.data(); + auto length = i; + + while (length >= 5) + { + b64.encode(start, 5); + length -= 5; + start += 5; + } + + if (length > 0) + { + b64.encode(start, length); + } + + CHECK_FALSE(received_final_block); + b64.flush(); + CHECK_TRUE(received_final_block); + + std::string expected(encoded[i]); + std::string actual(encoded_output); + + CHECK_EQUAL(expected, actual); + CHECK_TRUE(codec::safe_output_buffer_size(i) >= encoded_output.size()); + } + } + + //************************************************************************* + TEST(test_encode_pointer_pointer_single_pass_with_callback) + { + codec b64(callback); + + for (size_t i = 0; i < 256; ++i) + { + encoded_output.clear(); + received_final_block = false; + + b64.encode_final(input_data.data(), input_data.data() + i); + + std::string expected(encoded[i]); + std::string actual(encoded_output); + + CHECK_TRUE(received_final_block); + CHECK_EQUAL(expected, actual); + CHECK_TRUE(codec::safe_output_buffer_size(i) >= encoded_output.size()); + } + } + + //************************************************************************* + TEST(test_encode_pointer_pointer_single_pass_with_callback_larger_buffer) + { + codec_larger_buffer b64(callback); + + for (size_t i = 0; i < 256; ++i) + { + encoded_output.clear(); + received_final_block = false; + + b64.encode_final(input_data.data(), input_data.data() + i); + + std::string expected(encoded[i]); + std::string actual(encoded_output); + + CHECK_TRUE(received_final_block); + CHECK_EQUAL(expected, actual); + CHECK_TRUE(codec::safe_output_buffer_size(i) >= encoded_output.size()); + } + } + + //************************************************************************* + TEST(test_encode_pointer_pointer_multi_pass_blocks_with_callback) + { + codec b64(callback); + + for (size_t i = 0; i < 256; ++i) + { + encoded_output.clear(); + received_final_block = false; + + auto start = input_data.data(); + auto length = i; + + while (length >= 5) + { + b64.encode(start, start + 5); + length -= 5; + start += 5; + } + + if (length > 0) + { + b64.encode(start, length); + } + + CHECK_FALSE(received_final_block); + b64.flush(); + CHECK_TRUE(received_final_block); + + std::string expected(encoded[i]); + std::string actual(encoded_output); + + CHECK_EQUAL(expected, actual); + CHECK_TRUE(codec::safe_output_buffer_size(i) >= encoded_output.size()); + } + } + + //************************************************************************* + TEST(test_encode_pointer_pointer_multi_pass_blocks_with_callback_larger_buffer) + { + codec_larger_buffer b64(callback); + + for (size_t i = 0; i < 256; ++i) + { + encoded_output.clear(); + received_final_block = false; + + auto start = input_data.data(); + auto length = i; + + while (length >= 5) + { + b64.encode(start, start + 5); + length -= 5; + start += 5; + } + + if (length > 0) + { + b64.encode(start, length); + } + + CHECK_FALSE(received_final_block); + b64.flush(); + CHECK_TRUE(received_final_block); + + std::string expected(encoded[i]); + std::string actual(encoded_output); + + CHECK_EQUAL(expected, actual); + CHECK_TRUE(codec::safe_output_buffer_size(i) >= encoded_output.size()); + } + } + + //************************************************************************* + TEST(test_encode_multi_pass_by_char_with_callback) + { + codec b64(callback); + + for (size_t i = 0; i < 256; ++i) + { + encoded_output.clear(); + received_final_block = false; + + auto start = input_data.data(); + auto length = i; + + while (length--) + { + b64.encode(*start); + ++start; + } + + CHECK_FALSE(received_final_block); + b64.flush(); + CHECK_TRUE(received_final_block); + + std::string expected(encoded[i]); + std::string actual(encoded_output); + + CHECK_EQUAL(expected, actual); + CHECK_TRUE(codec::safe_output_buffer_size(i) >= encoded_output.size()); + } + } + + //************************************************************************* + TEST(test_encode_multi_pass_by_char_with_callback_larger_buffer) + { + codec_larger_buffer b64(callback); + + for (size_t i = 0; i < 256; ++i) + { + encoded_output.clear(); + received_final_block = false; + + auto start = input_data.data(); + auto length = i; + + while (length--) + { + b64.encode(*start); + ++start; + } + + CHECK_FALSE(received_final_block); + b64.flush(); + CHECK_TRUE(received_final_block); + + std::string expected(encoded[i]); + std::string actual(encoded_output); + + CHECK_EQUAL(expected, actual); + CHECK_TRUE(codec::safe_output_buffer_size(i) >= encoded_output.size()); + } + } + + //************************************************************************* + TEST(test_encode_multi_pass_blocks_with_no_callback_and_full_size_buffer) + { + codec_full_buffer b64; + + for (size_t i = 250; i < 256; ++i) + { + b64.restart(); + + auto start = input_data.data(); + auto length = i; + + while (length >= 5) + { + b64.encode(start, start + 5); + length -= 5; + start += 5; + } + + if (length > 0) + { + b64.encode(start, length); + } + + b64.flush(); + + std::string expected(encoded[i]); + std::string actual(b64.begin(), b64.end()); + + CHECK_EQUAL(expected, actual); + CHECK_TRUE(codec::safe_output_buffer_size(i) >= actual.size()); + } + } + + //************************************************************************* +#if ETL_USING_CPP14 + template + constexpr auto GetConstexprBase64(const etl::array input) noexcept + { + etl::array output{ 0 }; + + using codec = etl::base64_rfc4648_encoder; + + codec b64; + b64.encode_final(input.begin(), input.end()); + etl::copy(b64.begin(), b64.end(), output.begin()); + + return output; + } + + TEST(test_encode_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_TRUE(codec::safe_output_buffer_size(10) >= output.size()); + } +#endif + + //************************************************************************* + TEST(test_encode_overflow) + { + using codec = etl::base64_rfc2152_encoder<>; + + codec b64; + +#if ETL_USING_EXCEPTIONS + CHECK_THROW((b64.encode(input_data.data(), 10)), etl::base64_overflow); +#else + CHECK_FALSE(b64.encode(input_data.data(), 10)); + CHECK_TRUE(b64.overflow()); +#endif + } + }; +} + diff --git a/test/test_base64_RFC3501_decoder.cpp b/test/test_base64_RFC3501_decoder.cpp new file mode 100644 index 00000000..5a57b5a1 --- /dev/null +++ b/test/test_base64_RFC3501_decoder.cpp @@ -0,0 +1,783 @@ +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Copyright(c) 2024 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_decoder.h" + +#include "etl/string.h" +#include "etl/vector.h" + +#include +#include +#include +#include + +#if ETL_USING_STL + #include +#endif + +#include "etl/integral_limits.h" + +//***************************************************************************** +// Encode/decode using RFC-3501 +//***************************************************************************** + +namespace +{ + using codec = etl::base64_rfc3501_decoder; + using codec_larger_buffer = etl::base64_rfc3501_decoder; +#if (ETL_USING_CPP14) + using codec_full_buffer = etl::base64_rfc3501_decoder< etl::base64_rfc3501_decoder<>::safe_output_buffer_size(342)>; +#else + using codec_full_buffer = etl::base64_rfc3501_decoder<256>; +#endif + + std::vector decoded_output; + bool received_final_block = false; + + codec::callback_type callback = [](const codec::span_type& sp) + { + if (sp.empty()) + { + received_final_block = true; + } + else + { + std::copy(sp.begin(), sp.end(), std::back_inserter(decoded_output)); + } + }; + + std::array input_data = + { + 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 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_rfc3501_with_no_padding) + { + //************************************************************************* + TEST(test_basic_information) + { + codec_full_buffer b64; + + CHECK_EQUAL(etl::base64::Encoding::RFC_3501, codec_full_buffer::Encoding); + CHECK_EQUAL("RFC_3501", codec_full_buffer::Encoding.c_str()); + } + + //************************************************************************* + TEST(test_check_encode_safe_buffer_sizes) + { + for (size_t i = 0; i < 256; ++i) + { + size_t minimum_size = i; + size_t safe_size = codec::safe_output_buffer_size(encoded[i].size()); + + CHECK_TRUE(safe_size >= minimum_size); + CHECK_TRUE((safe_size - minimum_size) <= 2U); + } + } + + //************************************************************************* + TEST(test_decode_pointer_size_single_pass_with_callback) + { + codec b64(callback); + + for (size_t i = 0; i < 256; ++i) + { + decoded_output.clear(); + received_final_block = false; + + b64.decode_final(encoded[i].data(), encoded[i].size()); + + std::vector expected(input_data.begin(), input_data.begin() + i); + std::vector actual(decoded_output); + + CHECK_TRUE(received_final_block); + CHECK_EQUAL(expected.size(), actual.size()); + CHECK_TRUE(std::equal(expected.begin(), expected.end(), actual.begin())); + CHECK_TRUE(codec::safe_output_buffer_size(encoded[i].size()) >= decoded_output.size()); + } + } + + //************************************************************************* + TEST(test_decode_pointer_size_single_pass_with_callback_and_larger_buffer) + { + codec_larger_buffer b64(callback); + + for (size_t i = 0; i < 256; ++i) + { + decoded_output.clear(); + received_final_block = false; + + b64.decode_final(encoded[i].data(), encoded[i].size()); + + std::vector expected(input_data.begin(), input_data.begin() + i); + std::vector actual(decoded_output); + + CHECK_TRUE(received_final_block); + CHECK_EQUAL(expected.size(), actual.size()); + CHECK_TRUE(std::equal(expected.begin(), expected.end(), actual.begin())); + CHECK_TRUE(codec_larger_buffer::safe_output_buffer_size(encoded[i].size()) >= decoded_output.size()); + } + } + + //************************************************************************* + TEST(test_decode_pointer_size_multi_pass_with_callback) + { + codec b64(callback); + + for (size_t i = 0; i < 256; ++i) + { + decoded_output.clear(); + received_final_block = false; + + auto start = encoded[i].data(); + auto length = encoded[i].size(); + + while (length >= 5) + { + b64.decode(start, 5); + length -= 5; + start += 5; + } + + if (length > 0) + { + b64.decode(start, length); + } + + CHECK_FALSE(received_final_block); + b64.flush(); + CHECK_TRUE(received_final_block); + + std::vector expected(input_data.begin(), input_data.begin() + i); + std::vector actual(decoded_output); + + CHECK_TRUE(received_final_block); + CHECK_EQUAL(expected.size(), actual.size()); + CHECK_TRUE(std::equal(expected.begin(), expected.end(), actual.begin())); + CHECK_TRUE(codec::safe_output_buffer_size(encoded[i].size()) >= decoded_output.size()); + } + } + + //************************************************************************* + TEST(test_decode_pointer_size_multi_pass_with_callback_and_larger_buffer) + { + codec_larger_buffer b64(callback); + + for (size_t i = 0; i < 256; ++i) + { + decoded_output.clear(); + received_final_block = false; + + auto start = encoded[i].data(); + auto length = encoded[i].size(); + + while (length >= 5) + { + b64.decode(start, 5); + length -= 5; + start += 5; + } + + if (length > 0) + { + b64.decode(start, length); + } + + CHECK_FALSE(received_final_block); + b64.flush(); + CHECK_TRUE(received_final_block); + + std::vector expected(input_data.begin(), input_data.begin() + i); + std::vector actual(decoded_output); + + CHECK_TRUE(received_final_block); + CHECK_EQUAL(expected.size(), actual.size()); + CHECK_TRUE(std::equal(expected.begin(), expected.end(), actual.begin())); + CHECK_TRUE(codec::safe_output_buffer_size(encoded[i].size()) >= decoded_output.size()); + } + } + + //************************************************************************* + TEST(test_decode_pointer_pointer_single_pass_with_callback) + { + codec b64(callback); + + for (size_t i = 0; i < 256; ++i) + { + decoded_output.clear(); + received_final_block = false; + + b64.decode_final(encoded[i].begin(), encoded[i].end()); + + std::vector expected(input_data.begin(), input_data.begin() + i); + std::vector actual(decoded_output); + + CHECK_TRUE(received_final_block); + CHECK_EQUAL(expected.size(), actual.size()); + CHECK_TRUE(std::equal(expected.begin(), expected.end(), actual.begin())); + CHECK_TRUE(codec::safe_output_buffer_size(encoded[i].size()) >= decoded_output.size()); + } + } + + //************************************************************************* + TEST(test_decode_pointer_pointer_single_pass_with_callback_and_larger_buffer) + { + codec_larger_buffer b64(callback); + + for (size_t i = 0; i < 256; ++i) + { + decoded_output.clear(); + received_final_block = false; + + b64.decode_final(encoded[i].begin(), encoded[i].end()); + + std::vector expected(input_data.begin(), input_data.begin() + i); + std::vector actual(decoded_output); + + CHECK_TRUE(received_final_block); + CHECK_EQUAL(expected.size(), actual.size()); + CHECK_TRUE(std::equal(expected.begin(), expected.end(), actual.begin())); + CHECK_TRUE(codec_larger_buffer::safe_output_buffer_size(encoded[i].size()) >= decoded_output.size()); + } + } + + //************************************************************************* + TEST(test_decode_pointer_pointer_multi_pass_with_callback) + { + codec b64(callback); + + for (size_t i = 0; i < 256; ++i) + { + decoded_output.clear(); + received_final_block = false; + + auto start = encoded[i].data(); + auto length = encoded[i].size(); + + while (length >= 5) + { + b64.decode(start, 5); + length -= 5; + start += 5; + } + + if (length > 0) + { + b64.decode(start, start + length); + } + + CHECK_FALSE(received_final_block); + b64.flush(); + CHECK_TRUE(received_final_block); + + std::vector expected(input_data.begin(), input_data.begin() + i); + std::vector actual(decoded_output); + + CHECK_TRUE(received_final_block); + CHECK_EQUAL(expected.size(), actual.size()); + CHECK_TRUE(std::equal(expected.begin(), expected.end(), actual.begin())); + CHECK_TRUE(codec::safe_output_buffer_size(encoded[i].size()) >= decoded_output.size()); + } + } + + //************************************************************************* + TEST(test_decode_pointer_pointer_multi_pass_with_callback_and_larger_buffer) + { + codec_larger_buffer b64(callback); + + for (size_t i = 0; i < 256; ++i) + { + decoded_output.clear(); + received_final_block = false; + + auto start = encoded[i].data(); + auto length = encoded[i].size(); + + while (length >= 5) + { + b64.decode(start, 5); + length -= 5; + start += 5; + } + + if (length > 0) + { + b64.decode(start, start + length); + } + + CHECK_FALSE(received_final_block); + b64.flush(); + CHECK_TRUE(received_final_block); + + std::vector expected(input_data.begin(), input_data.begin() + i); + std::vector actual(decoded_output); + + CHECK_TRUE(received_final_block); + CHECK_EQUAL(expected.size(), actual.size()); + CHECK_TRUE(std::equal(expected.begin(), expected.end(), actual.begin())); + CHECK_TRUE(codec::safe_output_buffer_size(encoded[i].size()) >= decoded_output.size()); + } + } + + //************************************************************************* + TEST(test_decode_multi_pass_by_char_with_callback) + { + codec b64(callback); + + for (size_t i = 0; i < 256; ++i) + { + decoded_output.clear(); + received_final_block = false; + + auto start = encoded[i].data(); + auto length = encoded[i].size(); + + while (length--) + { + b64.decode(*start++); + } + + CHECK_FALSE(received_final_block); + b64.flush(); + CHECK_TRUE(received_final_block); + + std::vector expected(input_data.begin(), input_data.begin() + i); + std::vector actual(decoded_output); + + CHECK_TRUE(received_final_block); + CHECK_EQUAL(expected.size(), actual.size()); + CHECK_TRUE(std::equal(expected.begin(), expected.end(), actual.begin())); + CHECK_TRUE(codec::safe_output_buffer_size(encoded[i].size()) >= decoded_output.size()); + } + } + + //************************************************************************* + TEST(test_decode_multi_pass_by_char_with_callback_and_larger_buffer) + { + codec_larger_buffer b64(callback); + + for (size_t i = 0; i < 256; ++i) + { + decoded_output.clear(); + received_final_block = false; + + auto start = encoded[i].data(); + auto length = encoded[i].size(); + + while (length--) + { + b64.decode(*start++); + } + + CHECK_FALSE(received_final_block); + b64.flush(); + CHECK_TRUE(received_final_block); + + std::vector expected(input_data.begin(), input_data.begin() + i); + std::vector actual(decoded_output); + + CHECK_TRUE(received_final_block); + CHECK_EQUAL(expected.size(), actual.size()); + CHECK_TRUE(std::equal(expected.begin(), expected.end(), actual.begin())); + CHECK_TRUE(codec::safe_output_buffer_size(encoded[i].size()) >= decoded_output.size()); + } + } + + //************************************************************************* + TEST(test_decode_multi_pass_blocks_with_no_callback_and_full_size_buffer) + { + codec_full_buffer b64; + + for (size_t i = 4; i < 256; ++i) + { + b64.restart(); + + auto start = encoded[i].data(); + auto length = encoded[i].size(); + + while (length >= 5) + { + b64.decode(start, 5); + length -= 5; + start += 5; + } + + if (length > 0) + { + b64.decode(start, length); + } + + b64.flush(); + + std::vector expected(input_data.begin(), input_data.begin() + i); + std::vector actual(b64.begin(), b64.end()); + + CHECK_EQUAL(expected.size(), actual.size()); + CHECK_TRUE(std::equal(expected.begin(), expected.end(), actual.begin())); + CHECK_TRUE(codec::safe_output_buffer_size(encoded[i].size()) >= b64.size()); + } + } + + //************************************************************************* +#if ETL_USING_CPP14 + template + constexpr auto GetConstexprBase64(const etl::array input) noexcept + { + etl::array output{ 0 }; + + using codec = etl::base64_rfc3501_decoder; + + codec b64; + b64.decode_final(input.begin(), input.end()); + etl::copy(b64.begin(), b64.end(), output.begin()); + + return output; + } + + TEST(test_encode_constexpr) + { + constexpr etl::array input = { 'A', 'A', 'E', 'C' ,'A' ,'w', 'Q', 'F', 'B', 'g', 'c', 'I', 'C', 'Q'}; + + constexpr auto output{ GetConstexprBase64(input) }; + + std::vector expected = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + std::vector actual(output.begin(), output.end()); + + CHECK_TRUE(std::equal(expected.begin(), expected.end(), actual.begin())); + CHECK_TRUE(codec::safe_output_buffer_size(14) >= output.size()); + } +#endif + + //************************************************************************* + TEST(test_decode_overflow) + { + codec b64; + +#if ETL_USING_EXCEPTIONS + CHECK_THROW((b64.decode(encoded[10].data(), encoded[10].size())), etl::base64_overflow); +#else + CHECK_FALSE(b64.decode(encoded[10].data(), encoded[10].size()); + CHECK_TRUE(b64.error()); +#endif + } + + //************************************************************************* + TEST(test_decode_invalid_character) + { + codec_larger_buffer b64; + + std::string invalid_chararacter("OycDQ#37KA"); + +#if ETL_USING_EXCEPTIONS + CHECK_THROW((b64.decode(invalid_chararacter.data(), invalid_chararacter.size())), etl::base64_invalid_data); +#else + CHECK_FALSE(b64.decode(invalid_chararacter.data(), invalid_chararacter.size())); + CHECK_TRUE(b64.error()); +#endif + } + }; +} + diff --git a/test/test_base64_RFC3501.cpp b/test/test_base64_RFC3501_encoder.cpp similarity index 74% rename from test/test_base64_RFC3501.cpp rename to test/test_base64_RFC3501_encoder.cpp index a4223e6e..b975e84f 100644 --- a/test/test_base64_RFC3501.cpp +++ b/test/test_base64_RFC3501_encoder.cpp @@ -28,7 +28,7 @@ SOFTWARE. #include "unit_test_framework.h" -#include "etl/base64.h" +#include "etl/base64_encoder.h" #include "etl/string.h" #include "etl/vector.h" @@ -45,14 +45,36 @@ SOFTWARE. #include "etl/integral_limits.h" //***************************************************************************** -// Encode/decode using RFC-3501 +// Encode/decode using RFC-3501 with no padding +// Using minimum buffer size, with callback. //***************************************************************************** namespace { - using codec = etl::base64_rfc3501; + using codec = etl::base64_rfc3501_encoder; + using codec_larger_buffer = etl::base64_rfc3501_encoder; +#if ETL_USING_CPP14 + using codec_full_buffer = etl::base64_rfc3501_encoder::safe_output_buffer_size(256)>; +#else + using codec_full_buffer = etl::base64_rfc3501_encoder<344>; +#endif - std::array input_data_unsigned_char = + std::string encoded_output; + bool received_final_block = false; + + codec::callback_type callback = [](const codec::span_type& sp) + { + if (sp.empty()) + { + received_final_block = true; + } + else + { + std::copy(sp.begin(), sp.end(), std::back_inserter(encoded_output)); + } + }; + + std::array input_data = { 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, @@ -72,26 +94,6 @@ namespace 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 = { "", @@ -353,254 +355,355 @@ namespace "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N+27j,cebMXjnZljpYhuYjRbdDd,9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHACPltrIR4SYRva,sgO5xJ+06AaYIlhpXVTZHt0ncqJECK302ALc3VWiamcRVCDj+ycBQpH40jLsHqzvl+bN8co4QrJDWnY8gLH4u6Ub,pUYDSI7XRtFmufTAdABzYcGwWccdWCP6BrvvgktjbuVd8mctC7,yzVh7RQtMMGLPurxp3qFI8ns3eITQ+H7VU1,u0vQ" }; - SUITE(test_base64_rfc3501_url_url_with_no_padding) + SUITE(test_base64_rfc3501_with_no_padding) { //************************************************************************* - TEST(test_encode_unsigned_char_pointer_size) + TEST(test_basic_information) { - codec b64; - std::array encoded_output; + codec_full_buffer b64; + CHECK_EQUAL(etl::base64::Encoding::RFC_3501, codec_full_buffer::Encoding); + CHECK_EQUAL("RFC_3501", codec_full_buffer::Encoding.c_str()); + } + + //************************************************************************* + TEST(test_check_encode_safe_buffer_sizes) + { for (size_t i = 0; i < 256; ++i) { - encoded_output.fill(0); + size_t minimum_size = encoded[i].size(); + size_t safe_size = codec::safe_output_buffer_size(i); - 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(codec::encoded_size(i), size); + CHECK_TRUE(safe_size >= minimum_size); + CHECK_TRUE((safe_size - minimum_size) <= 2U); } } //************************************************************************* - TEST(test_encode_unsigned_char_pointer_size_no_output_length) + TEST(test_encode_pointer_size_single_pass_with_callback) { - codec b64; - std::array encoded_output; + codec b64(callback); for (size_t i = 0; i < 256; ++i) { - encoded_output.fill(0); + encoded_output.clear(); + received_final_block = false; - auto size = b64.encode(input_data_unsigned_char.data(), i, - encoded_output.data()); + b64.encode_final(input_data.data(), i); std::string expected(encoded[i]); - std::string actual(encoded_output.data(), size); + std::string actual(encoded_output); + CHECK_TRUE(received_final_block); CHECK_EQUAL(expected, actual); - CHECK_EQUAL(codec::encoded_size(i), size); + CHECK_TRUE(codec::safe_output_buffer_size(i) >= encoded_output.size()); } } //************************************************************************* - TEST(test_encode_unsigned_char_pointer_size_to_etl_back_inserter) + TEST(test_encode_pointer_size_single_pass_with_callback_and_larger_buffer) { - codec b64; + codec_larger_buffer b64(callback); - for (size_t i = 0; i < 256; ++i) + for (size_t i = 0; i < 256; ++i) { - std::string actual; + encoded_output.clear(); + received_final_block = false; - auto size = b64.encode(input_data_unsigned_char.data(), i, - etl::back_inserter(actual)); + b64.encode_final(input_data.data(), i); std::string expected(encoded[i]); + std::string actual(encoded_output); + + CHECK_TRUE(received_final_block); + CHECK_EQUAL(expected, actual); + CHECK_TRUE(codec::safe_output_buffer_size(i) >= encoded_output.size()); + } + } + + //************************************************************************* + TEST(test_encode_pointer_size_multi_pass_blocks_with_callback) + { + codec b64(callback); + + for (size_t i = 0; i < 256; ++i) + { + encoded_output.clear(); + received_final_block = false; + + auto start = input_data.data(); + auto length = i; + while (length >= 5) + { + b64.encode(start, 5); + length -= 5; + start += 5; + } + + if (length > 0) + { + b64.encode(start, length); + } + + CHECK_FALSE(received_final_block); + b64.flush(); + CHECK_TRUE(received_final_block); + + std::string expected(encoded[i]); + std::string actual(encoded_output); + CHECK_EQUAL(expected, actual); - CHECK_EQUAL(codec::encoded_size(i), size); + CHECK_TRUE(codec::safe_output_buffer_size(i) >= encoded_output.size()); } } -#if ETL_USING_STL //************************************************************************* - TEST(test_encode_unsigned_char_pointer_size_to_std_back_inserter) + TEST(test_encode_pointer_size_multi_pass_blocks_with_callback_larger_buffer) { - codec b64; + codec_larger_buffer b64(callback); for (size_t i = 0; i < 256; ++i) { - std::string actual; + encoded_output.clear(); + received_final_block = false; - auto size = b64.encode(input_data_unsigned_char.data(), i, - std::back_inserter(actual)); + auto start = input_data.data(); + auto length = i; + + while (length >= 5) + { + b64.encode(start, 5); + length -= 5; + start += 5; + } + + if (length > 0) + { + b64.encode(start, length); + } + + CHECK_FALSE(received_final_block); + b64.flush(); + CHECK_TRUE(received_final_block); std::string expected(encoded[i]); + std::string actual(encoded_output); CHECK_EQUAL(expected, actual); - CHECK_EQUAL(codec::encoded_size(i), size); + CHECK_TRUE(codec::safe_output_buffer_size(i) >= encoded_output.size()); } } -#endif //************************************************************************* - TEST(test_encode_unsigned_char_pointer_pointer) + TEST(test_encode_pointer_pointer_single_pass_with_callback) { - codec b64; - std::array encoded_output; + codec b64(callback); for (size_t i = 0; i < 256; ++i) { - encoded_output.fill(0); + encoded_output.clear(); + received_final_block = false; - auto size = b64.encode(input_data_unsigned_char.data(), input_data_unsigned_char.data() + i, - encoded_output.data(), encoded_output.data() + encoded_output.size()); + b64.encode_final(input_data.data(), input_data.data() + i); std::string expected(encoded[i]); - std::string actual(encoded_output.data(), size); + std::string actual(encoded_output); + CHECK_TRUE(received_final_block); CHECK_EQUAL(expected, actual); - CHECK_EQUAL(codec::encoded_size(i), size); + CHECK_TRUE(codec::safe_output_buffer_size(i) >= encoded_output.size()); } } //************************************************************************* - TEST(test_encode_unsigned_char_pointer_pointer_no_output_end_pointer) + TEST(test_encode_pointer_pointer_single_pass_with_callback_larger_buffer) { - codec b64; - 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(codec::encoded_size(i), size); - } - } - - //************************************************************************* - TEST(test_encode_int8_t_pointer_size) - { - codec b64; - 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(codec::encoded_size(i), size); - } - } - - //************************************************************************* - TEST(test_encode_int8_t_pointer_size_no_output_length) - { - codec b64; - 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(codec::encoded_size(i), size); - } - } - - //************************************************************************* - TEST(test_encode_int8_t_pointer_size_to_etl_back_inserter) - { - codec b64; + codec_larger_buffer b64(callback); for (size_t i = 0; i < 256; ++i) { - std::string actual; + encoded_output.clear(); + received_final_block = false; - auto size = b64.encode(input_data_int8_t.data(), i, - etl::back_inserter(actual)); + b64.encode_final(input_data.data(), input_data.data() + i); std::string expected(encoded[i]); + std::string actual(encoded_output); + CHECK_TRUE(received_final_block); CHECK_EQUAL(expected, actual); - CHECK_EQUAL(codec::encoded_size(i), size); - } - } - -#if ETL_USING_STL - //************************************************************************* - TEST(test_encode_int8_t_pointer_size_to_std_back_inserter) - { - codec b64; - - 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(codec::encoded_size(i), size); - } - } -#endif - - //************************************************************************* - TEST(test_encode_int8_t_pointer_pointer) - { - codec b64; - 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(codec::encoded_size(i), size); + CHECK_TRUE(codec::safe_output_buffer_size(i) >= encoded_output.size()); } } //************************************************************************* - TEST(test_encode_int8_t_pointer_pointer_no_end_pointer) + TEST(test_encode_pointer_pointer_multi_pass_blocks_with_callback) { - codec b64; - - std::array encoded_output; + codec b64(callback); for (size_t i = 0; i < 256; ++i) { - encoded_output.fill(0); + encoded_output.clear(); + received_final_block = false; - auto size = b64.encode(input_data_int8_t.data(), input_data_int8_t.data() + i, - encoded_output.data()); + auto start = input_data.data(); + auto length = i; + + while (length >= 5) + { + b64.encode(start, start + 5); + length -= 5; + start += 5; + } + + if (length > 0) + { + b64.encode(start, length); + } + + CHECK_FALSE(received_final_block); + b64.flush(); + CHECK_TRUE(received_final_block); std::string expected(encoded[i]); - std::string actual(encoded_output.data(), size); + std::string actual(encoded_output); CHECK_EQUAL(expected, actual); - CHECK_EQUAL(codec::encoded_size(i), size); + CHECK_TRUE(codec::safe_output_buffer_size(i) >= encoded_output.size()); + } + } + + //************************************************************************* + TEST(test_encode_pointer_pointer_multi_pass_blocks_with_callback_larger_buffer) + { + codec_larger_buffer b64(callback); + + for (size_t i = 0; i < 256; ++i) + { + encoded_output.clear(); + received_final_block = false; + + auto start = input_data.data(); + auto length = i; + + while (length >= 5) + { + b64.encode(start, start + 5); + length -= 5; + start += 5; + } + + if (length > 0) + { + b64.encode(start, length); + } + + CHECK_FALSE(received_final_block); + b64.flush(); + CHECK_TRUE(received_final_block); + + std::string expected(encoded[i]); + std::string actual(encoded_output); + + CHECK_EQUAL(expected, actual); + CHECK_TRUE(codec::safe_output_buffer_size(i) >= encoded_output.size()); + } + } + + //************************************************************************* + TEST(test_encode_multi_pass_by_char_with_callback) + { + codec b64(callback); + + for (size_t i = 0; i < 256; ++i) + { + encoded_output.clear(); + received_final_block = false; + + auto start = input_data.data(); + auto length = i; + + while (length--) + { + b64.encode(*start); + ++start; + } + + CHECK_FALSE(received_final_block); + b64.flush(); + CHECK_TRUE(received_final_block); + + std::string expected(encoded[i]); + std::string actual(encoded_output); + + CHECK_EQUAL(expected, actual); + CHECK_TRUE(codec::safe_output_buffer_size(i) >= encoded_output.size()); + } + } + + //************************************************************************* + TEST(test_encode_multi_pass_by_char_with_callback_larger_buffer) + { + codec_larger_buffer b64(callback); + + for (size_t i = 0; i < 256; ++i) + { + encoded_output.clear(); + received_final_block = false; + + auto start = input_data.data(); + auto length = i; + + while (length--) + { + b64.encode(*start); + ++start; + } + + CHECK_FALSE(received_final_block); + b64.flush(); + CHECK_TRUE(received_final_block); + + std::string expected(encoded[i]); + std::string actual(encoded_output); + + CHECK_EQUAL(expected, actual); + CHECK_TRUE(codec::safe_output_buffer_size(i) >= encoded_output.size()); + } + } + + //************************************************************************* + TEST(test_encode_multi_pass_blocks_with_no_callback_and_full_size_buffer) + { + codec_full_buffer b64; + + for (size_t i = 250; i < 256; ++i) + { + b64.restart(); + + auto start = input_data.data(); + auto length = i; + + while (length >= 5) + { + b64.encode(start, start + 5); + length -= 5; + start += 5; + } + + if (length > 0) + { + b64.encode(start, length); + } + + b64.flush(); + + std::string expected(encoded[i]); + std::string actual(b64.begin(), b64.end()); + + CHECK_EQUAL(expected, actual); + CHECK_TRUE(codec::safe_output_buffer_size(i) >= actual.size()); } } @@ -609,18 +712,18 @@ namespace template constexpr auto GetConstexprBase64(const etl::array input) noexcept { + etl::array output{ 0 }; + + using codec = etl::base64_rfc3501_encoder; + codec b64; - - constexpr size_t encoded_size = codec::encoded_size(Size); - etl::array output{ 0 }; - - b64.encode(input.begin(), Size, - output._buffer, encoded_size); + b64.encode_final(input.begin(), input.end()); + etl::copy(b64.begin(), b64.end(), output.begin()); return output; } - TEST(test_encode_int8_t_constexpr) + TEST(test_encode_constexpr) { constexpr etl::array input = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; @@ -630,284 +733,19 @@ namespace std::string actual(output.data(), output.size()); CHECK_EQUAL(expected, actual); - CHECK_EQUAL(codec::encoded_size(10), output.size()); + CHECK_TRUE(codec::safe_output_buffer_size(10) >= output.size()); } #endif //************************************************************************* TEST(test_encode_overflow) { + using codec = etl::base64_rfc3501_encoder<>; + codec b64; - 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) - { - codec b64; - 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, codec::decoded_size(encoded[i].data(), encoded[i].size())); - CHECK_EQUAL(i, decoded_size); - } - } - - //************************************************************************* - TEST(test_decode_unsigned_char_pointer_size_no_end_pointer) - { - codec b64; - 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, codec::decoded_size(encoded[i].data(), encoded[i].size())); - CHECK_EQUAL(i, decoded_size); - } - } - - //************************************************************************* - TEST(test_decode_unsigned_char_pointer_pointer) - { - codec b64; - 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, codec::decoded_size(encoded[i].data(), encoded[i].size())); - CHECK_EQUAL(i, decoded_size); - } - } - - //************************************************************************* - TEST(test_decode_unsigned_char_pointer_pointer_no_end_pointer) - { - codec b64; - 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, codec::decoded_size(encoded[i].data(), encoded[i].size())); - CHECK_EQUAL(i, decoded_size); - } - } - - //************************************************************************* - TEST(test_decode_int8_t_pointer_size) - { - codec b64; - 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, codec::decoded_size(encoded[i].data(), encoded[i].size())); - CHECK_EQUAL(i, decoded_size); - } - } - - //************************************************************************* - TEST(test_decode_int8_t_pointer_size_etl_back_inserter) - { - codec b64; - 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, codec::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) - { - codec b64; - 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, codec::decoded_size(encoded[i].data(), encoded[i].size())); - CHECK_EQUAL(i, decoded_size); - } - } -#endif - - //************************************************************************* - TEST(test_decode_int8_t_pointer_size_no_output_size) - { - codec b64; - 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, codec::decoded_size(encoded[i].data(), encoded[i].size())); - CHECK_EQUAL(i, decoded_size); - } - } - - //************************************************************************* - TEST(test_decode_int8_t_pointer_pointer) - { - codec b64; - 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, codec::decoded_size(encoded[i].data(), encoded[i].size())); - CHECK_EQUAL(i, decoded_size); - } - } - - //************************************************************************* - TEST(test_decode_int8_t_pointer_pointer_etl_back_inserter) - { - codec b64; - 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, codec::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) - { - codec b64; - 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, codec::decoded_size(encoded[i].data(), encoded[i].size())); - CHECK_EQUAL(i, decoded_size); - } - } -#endif - - //************************************************************************* - TEST(test_decode_int8_t_pointer_pointer_no_end_pointer) - { - codec b64; - 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, codec::decoded_size(encoded[i].data(), encoded[i].size())); - CHECK_EQUAL(i, decoded_size); - } - } - - //************************************************************************* - TEST(test_decode_overflow) - { - codec b64; - 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) - { - codec b64; - std::array decoded_output{ 0 }; - - std::string invalid_chararacter("OycDQ#37KA"); - - CHECK_THROW((b64.decode(invalid_chararacter.data(), invalid_chararacter.size(), - decoded_output.data(), decoded_output.size())), etl::base64_invalid_character); - - std::string invalid_length("OycDQy37K"); - -#if ETL_USING_EXCEPTIONS - CHECK_THROW((b64.decode(invalid_length.data(), invalid_length.size(), - decoded_output.data(), decoded_output.size())), etl::base64_invalid_decode_input_length); -#else - size_t size = b64.decode(invalid_length.data(), invalid_length.size(), - decoded_output.data(), decoded_output.size()); - CHECK_EQUAL(size, codec::Invalid_Data); -#endif + CHECK_THROW((b64.encode(input_data.data(), 10)), etl::base64_overflow); + CHECK_TRUE(b64.overflow()); } }; } diff --git a/test/test_base64_RFC4648_URL_decoder_with_no_padding.cpp b/test/test_base64_RFC4648_URL_decoder_with_no_padding.cpp new file mode 100644 index 00000000..c3bb650d --- /dev/null +++ b/test/test_base64_RFC4648_URL_decoder_with_no_padding.cpp @@ -0,0 +1,798 @@ +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Copyright(c) 2024 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_decoder.h" + +#include "etl/string.h" +#include "etl/vector.h" + +#include +#include +#include +#include + +#if ETL_USING_STL + #include +#endif + +#include "etl/integral_limits.h" + +//***************************************************************************** +// Encode/decode using RFC-4648-URL with no padding +//***************************************************************************** + +namespace +{ + using codec = etl::base64_rfc4648_url_decoder ; + using codec_larger_buffer = etl::base64_rfc4648_url_decoder; +#if ETL_USING_CPP14 + using codec_full_buffer = etl::base64_rfc4648_url_decoder::safe_output_buffer_size(342)>; +#else + using codec_full_buffer = etl::base64_rfc4648_url_decoder<256>; +#endif + + std::vector decoded_output; + bool received_final_block = false; + + codec::callback_type callback = [](const codec::span_type& sp) + { + if (sp.empty()) + { + received_final_block = true; + } + else + { + std::copy(sp.begin(), sp.end(), std::back_inserter(decoded_output)); + } + }; + + std::array input_data = + { + 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 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_with_no_padding) + { + //************************************************************************* + TEST(test_basic_information) + { + codec_full_buffer b64; + + CHECK_EQUAL(etl::base64::Encoding::RFC_4648_URL, codec_full_buffer::Encoding); + CHECK_EQUAL("RFC_4648_URL", codec_full_buffer::Encoding.c_str()); + } + + //************************************************************************* + TEST(test_check_encode_safe_buffer_sizes) + { + for (size_t i = 0; i < 256; ++i) + { + size_t minimum_size = i; + size_t safe_size = codec::safe_output_buffer_size(encoded[i].size()); + + CHECK_TRUE(safe_size >= minimum_size); + CHECK_TRUE((safe_size - minimum_size) <= 2U); + } + } + + //************************************************************************* + TEST(test_decode_pointer_size_single_pass_with_callback) + { + codec b64(callback); + + for (size_t i = 0; i < 256; ++i) + { + decoded_output.clear(); + received_final_block = false; + + b64.decode_final(encoded[i].data(), encoded[i].size()); + + std::vector expected(input_data.begin(), input_data.begin() + i); + std::vector actual(decoded_output); + + CHECK_TRUE(received_final_block); + CHECK_EQUAL(expected.size(), actual.size()); + CHECK_TRUE(std::equal(expected.begin(), expected.end(), actual.begin())); + CHECK_TRUE(codec::safe_output_buffer_size(encoded[i].size()) >= decoded_output.size()); + } + } + + //************************************************************************* + TEST(test_decode_pointer_size_single_pass_with_callback_and_larger_buffer) + { + codec_larger_buffer b64(callback); + + for (size_t i = 0; i < 256; ++i) + { + decoded_output.clear(); + received_final_block = false; + + b64.decode_final(encoded[i].data(), encoded[i].size()); + + std::vector expected(input_data.begin(), input_data.begin() + i); + std::vector actual(decoded_output); + + CHECK_TRUE(received_final_block); + CHECK_EQUAL(expected.size(), actual.size()); + CHECK_TRUE(std::equal(expected.begin(), expected.end(), actual.begin())); + CHECK_TRUE(codec_larger_buffer::safe_output_buffer_size(encoded[i].size()) >= decoded_output.size()); + } + } + + //************************************************************************* + TEST(test_decode_pointer_size_multi_pass_with_callback) + { + codec b64(callback); + + for (size_t i = 0; i < 256; ++i) + { + decoded_output.clear(); + received_final_block = false; + + auto start = encoded[i].data(); + auto length = encoded[i].size(); + + while (length >= 5) + { + b64.decode(start, 5); + length -= 5; + start += 5; + } + + if (length > 0) + { + b64.decode(start, length); + } + + CHECK_FALSE(received_final_block); + b64.flush(); + CHECK_TRUE(received_final_block); + + std::vector expected(input_data.begin(), input_data.begin() + i); + std::vector actual(decoded_output); + + CHECK_TRUE(received_final_block); + CHECK_EQUAL(expected.size(), actual.size()); + CHECK_TRUE(std::equal(expected.begin(), expected.end(), actual.begin())); + CHECK_TRUE(codec::safe_output_buffer_size(encoded[i].size()) >= decoded_output.size()); + } + } + + //************************************************************************* + TEST(test_decode_pointer_size_multi_pass_with_callback_and_larger_buffer) + { + codec_larger_buffer b64(callback); + + for (size_t i = 0; i < 256; ++i) + { + decoded_output.clear(); + received_final_block = false; + + auto start = encoded[i].data(); + auto length = encoded[i].size(); + + while (length >= 5) + { + b64.decode(start, 5); + length -= 5; + start += 5; + } + + if (length > 0) + { + b64.decode(start, length); + } + + CHECK_FALSE(received_final_block); + b64.flush(); + CHECK_TRUE(received_final_block); + + std::vector expected(input_data.begin(), input_data.begin() + i); + std::vector actual(decoded_output); + + CHECK_TRUE(received_final_block); + CHECK_EQUAL(expected.size(), actual.size()); + CHECK_TRUE(std::equal(expected.begin(), expected.end(), actual.begin())); + CHECK_TRUE(codec::safe_output_buffer_size(encoded[i].size()) >= decoded_output.size()); + } + } + + //************************************************************************* + TEST(test_decode_pointer_pointer_single_pass_with_callback) + { + codec b64(callback); + + for (size_t i = 0; i < 256; ++i) + { + decoded_output.clear(); + received_final_block = false; + + b64.decode_final(encoded[i].begin(), encoded[i].end()); + + std::vector expected(input_data.begin(), input_data.begin() + i); + std::vector actual(decoded_output); + + CHECK_TRUE(received_final_block); + CHECK_EQUAL(expected.size(), actual.size()); + CHECK_TRUE(std::equal(expected.begin(), expected.end(), actual.begin())); + CHECK_TRUE(codec::safe_output_buffer_size(encoded[i].size()) >= decoded_output.size()); + } + } + + //************************************************************************* + TEST(test_decode_pointer_pointer_single_pass_with_callback_and_larger_buffer) + { + codec_larger_buffer b64(callback); + + for (size_t i = 0; i < 256; ++i) + { + decoded_output.clear(); + received_final_block = false; + + b64.decode_final(encoded[i].begin(), encoded[i].end()); + + std::vector expected(input_data.begin(), input_data.begin() + i); + std::vector actual(decoded_output); + + CHECK_TRUE(received_final_block); + CHECK_EQUAL(expected.size(), actual.size()); + CHECK_TRUE(std::equal(expected.begin(), expected.end(), actual.begin())); + CHECK_TRUE(codec_larger_buffer::safe_output_buffer_size(encoded[i].size()) >= decoded_output.size()); + } + } + + //************************************************************************* + TEST(test_decode_pointer_pointer_multi_pass_with_callback) + { + codec b64(callback); + + for (size_t i = 0; i < 256; ++i) + { + decoded_output.clear(); + received_final_block = false; + + auto start = encoded[i].data(); + auto length = encoded[i].size(); + + while (length >= 5) + { + b64.decode(start, 5); + length -= 5; + start += 5; + } + + if (length > 0) + { + b64.decode(start, start + length); + } + + CHECK_FALSE(received_final_block); + b64.flush(); + CHECK_TRUE(received_final_block); + + std::vector expected(input_data.begin(), input_data.begin() + i); + std::vector actual(decoded_output); + + CHECK_TRUE(received_final_block); + CHECK_EQUAL(expected.size(), actual.size()); + CHECK_TRUE(std::equal(expected.begin(), expected.end(), actual.begin())); + CHECK_TRUE(codec::safe_output_buffer_size(encoded[i].size()) >= decoded_output.size()); + } + } + + //************************************************************************* + TEST(test_decode_pointer_pointer_multi_pass_with_callback_and_larger_buffer) + { + codec_larger_buffer b64(callback); + + for (size_t i = 0; i < 256; ++i) + { + decoded_output.clear(); + received_final_block = false; + + auto start = encoded[i].data(); + auto length = encoded[i].size(); + + while (length >= 5) + { + b64.decode(start, 5); + length -= 5; + start += 5; + } + + if (length > 0) + { + b64.decode(start, start + length); + } + + CHECK_FALSE(received_final_block); + b64.flush(); + CHECK_TRUE(received_final_block); + + std::vector expected(input_data.begin(), input_data.begin() + i); + std::vector actual(decoded_output); + + CHECK_TRUE(received_final_block); + CHECK_EQUAL(expected.size(), actual.size()); + CHECK_TRUE(std::equal(expected.begin(), expected.end(), actual.begin())); + CHECK_TRUE(codec::safe_output_buffer_size(encoded[i].size()) >= decoded_output.size()); + } + } + + //************************************************************************* + TEST(test_decode_multi_pass_by_char_with_callback) + { + codec b64(callback); + + for (size_t i = 0; i < 256; ++i) + { + decoded_output.clear(); + received_final_block = false; + + auto start = encoded[i].data(); + auto length = encoded[i].size(); + + while (length--) + { + b64.decode(*start++); + } + + CHECK_FALSE(received_final_block); + b64.flush(); + CHECK_TRUE(received_final_block); + + std::vector expected(input_data.begin(), input_data.begin() + i); + std::vector actual(decoded_output); + + CHECK_TRUE(received_final_block); + CHECK_EQUAL(expected.size(), actual.size()); + CHECK_TRUE(std::equal(expected.begin(), expected.end(), actual.begin())); + CHECK_TRUE(codec::safe_output_buffer_size(encoded[i].size()) >= decoded_output.size()); + } + } + + //************************************************************************* + TEST(test_decode_multi_pass_by_char_with_callback_and_larger_buffer) + { + codec_larger_buffer b64(callback); + + for (size_t i = 0; i < 256; ++i) + { + decoded_output.clear(); + received_final_block = false; + + auto start = encoded[i].data(); + auto length = encoded[i].size(); + + while (length--) + { + b64.decode(*start++); + } + + CHECK_FALSE(received_final_block); + b64.flush(); + CHECK_TRUE(received_final_block); + + std::vector expected(input_data.begin(), input_data.begin() + i); + std::vector actual(decoded_output); + + CHECK_TRUE(received_final_block); + CHECK_EQUAL(expected.size(), actual.size()); + CHECK_TRUE(std::equal(expected.begin(), expected.end(), actual.begin())); + CHECK_TRUE(codec::safe_output_buffer_size(encoded[i].size()) >= decoded_output.size()); + } + } + + //************************************************************************* + TEST(test_decode_multi_pass_blocks_with_no_callback_and_full_size_buffer) + { + codec_full_buffer b64; + + for (size_t i = 4; i < 256; ++i) + { + b64.restart(); + + auto start = encoded[i].data(); + auto length = encoded[i].size(); + + while (length >= 5) + { + b64.decode(start, 5); + length -= 5; + start += 5; + } + + if (length > 0) + { + b64.decode(start, length); + } + + b64.flush(); + + std::vector expected(input_data.begin(), input_data.begin() + i); + std::vector actual(b64.begin(), b64.end()); + + CHECK_EQUAL(expected.size(), actual.size()); + CHECK_TRUE(std::equal(expected.begin(), expected.end(), actual.begin())); + CHECK_TRUE(codec::safe_output_buffer_size(encoded[i].size()) >= b64.size()); + } + } + + //************************************************************************* +#if ETL_USING_CPP14 + template + constexpr auto GetConstexprBase64(const etl::array input) noexcept + { + etl::array output{ 0 }; + + using codec = etl::base64_rfc4648_url_decoder; + + codec b64; + b64.decode_final(input.begin(), input.end()); + etl::copy(b64.begin(), b64.end(), output.begin()); + + return output; + } + + TEST(test_encode_constexpr) + { + constexpr etl::array input = { 'A', 'A', 'E', 'C' ,'A' ,'w', 'Q', 'F', 'B', 'g', 'c', 'I', 'C', 'Q' }; + + constexpr auto output{ GetConstexprBase64(input) }; + + std::vector expected = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + std::vector actual(output.begin(), output.end()); + + CHECK_TRUE(std::equal(expected.begin(), expected.end(), actual.begin())); + CHECK_TRUE(codec::safe_output_buffer_size(14) >= output.size()); + } +#endif + + //************************************************************************* + TEST(test_decode_overflow) + { + codec b64; + +#if ETL_USING_EXCEPTIONS + CHECK_THROW((b64.decode(encoded[10].data(), encoded[10].size())), etl::base64_overflow); +#else + CHECK_FALSE(b64.decode(encoded[10].data(), encoded[10].size()); + CHECK_TRUE(b64.error()); +#endif + } + + //************************************************************************* + TEST(test_decode_invalid_character) + { + codec_larger_buffer b64; + + std::string invalid_chararacter("OycDQ#37KA"); + +#if ETL_USING_EXCEPTIONS + CHECK_THROW((b64.decode(invalid_chararacter.data(), invalid_chararacter.size())), etl::base64_invalid_data); +#else + CHECK_FALSE(b64.decode(invalid_chararacter.data(), invalid_chararacter.size())); + CHECK_TRUE(b64.error()); +#endif + } + + //************************************************************************* + TEST(test_decode_invalid_padding) + { + codec_larger_buffer b64; + + std::string invalid_chararacter("OycD=y37KA"); + +#if ETL_USING_EXCEPTIONS + CHECK_THROW((b64.decode(invalid_chararacter.data(), invalid_chararacter.size())), etl::base64_invalid_data); +#else + CHECK_FALSE(b64.decode(invalid_chararacter.data(), invalid_chararacter.size())); + CHECK_TRUE(b64.error()); +#endif + } + }; +} + diff --git a/test/test_base64_RFC4648_URL_decoder_with_padding.cpp b/test/test_base64_RFC4648_URL_decoder_with_padding.cpp new file mode 100644 index 00000000..6dd57f44 --- /dev/null +++ b/test/test_base64_RFC4648_URL_decoder_with_padding.cpp @@ -0,0 +1,797 @@ +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Copyright(c) 2024 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_decoder.h" + +#include "etl/string.h" +#include "etl/vector.h" + +#include +#include +#include +#include + +#if ETL_USING_STL + #include +#endif + +#include "etl/integral_limits.h" + +//***************************************************************************** +// Encode/decode using RFC-4648-URL with no padding +//***************************************************************************** + +namespace +{ + using codec = etl::base64_rfc4648_url_padding_decoder ; + using codec_larger_buffer = etl::base64_rfc4648_url_padding_decoder; +#if ETL_USING_CPP14 + using codec_full_buffer = etl::base64_rfc4648_url_padding_decoder::safe_output_buffer_size(344)>; +#else + using codec_full_buffer = etl::base64_rfc4648_url_padding_decoder<256>; +#endif + + std::vector decoded_output; + bool received_final_block = false; + + codec::callback_type callback = [](const codec::span_type& sp) + { + if (sp.empty()) + { + received_final_block = true; + } + else + { + std::copy(sp.begin(), sp.end(), std::back_inserter(decoded_output)); + } + }; + + std::array input_data = + { + 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 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_with_padding) + { + //************************************************************************* + TEST(test_basic_information) + { + codec_full_buffer b64; + + CHECK_EQUAL(etl::base64::Encoding::RFC_4648_URL_PADDING, codec_full_buffer::Encoding); + CHECK_EQUAL("RFC_4648_URL_PADDING", codec_full_buffer::Encoding.c_str()); + } + + //************************************************************************* + TEST(test_check_encode_safe_buffer_sizes) + { + for (size_t i = 0; i < 256; ++i) + { + size_t minimum_size = i; + size_t safe_size = codec::safe_output_buffer_size(encoded[i].size()); + + CHECK_TRUE(safe_size >= minimum_size); + CHECK_TRUE((safe_size - minimum_size) <= 2U); + } + } + + //************************************************************************* + TEST(test_decode_pointer_size_single_pass_with_callback) + { + codec b64(callback); + + for (size_t i = 0; i < 256; ++i) + { + decoded_output.clear(); + received_final_block = false; + + b64.decode_final(encoded[i].data(), encoded[i].size()); + + std::vector expected(input_data.begin(), input_data.begin() + i); + std::vector actual(decoded_output); + + CHECK_TRUE(received_final_block); + CHECK_EQUAL(expected.size(), actual.size()); + CHECK_TRUE(std::equal(expected.begin(), expected.end(), actual.begin())); + CHECK_TRUE(codec::safe_output_buffer_size(encoded[i].size()) >= decoded_output.size()); + } + } + + //************************************************************************* + TEST(test_decode_pointer_size_single_pass_with_callback_and_larger_buffer) + { + codec_larger_buffer b64(callback); + + for (size_t i = 0; i < 256; ++i) + { + decoded_output.clear(); + received_final_block = false; + + b64.decode_final(encoded[i].data(), encoded[i].size()); + + std::vector expected(input_data.begin(), input_data.begin() + i); + std::vector actual(decoded_output); + + CHECK_TRUE(received_final_block); + CHECK_EQUAL(expected.size(), actual.size()); + CHECK_TRUE(std::equal(expected.begin(), expected.end(), actual.begin())); + CHECK_TRUE(codec_larger_buffer::safe_output_buffer_size(encoded[i].size()) >= decoded_output.size()); + } + } + + //************************************************************************* + TEST(test_decode_pointer_size_multi_pass_with_callback) + { + codec b64(callback); + + for (size_t i = 0; i < 256; ++i) + { + decoded_output.clear(); + received_final_block = false; + + auto start = encoded[i].data(); + auto length = encoded[i].size(); + + while (length >= 5) + { + b64.decode(start, 5); + length -= 5; + start += 5; + } + + if (length > 0) + { + b64.decode(start, length); + } + + CHECK_FALSE(received_final_block); + b64.flush(); + CHECK_TRUE(received_final_block); + + std::vector expected(input_data.begin(), input_data.begin() + i); + std::vector actual(decoded_output); + + CHECK_TRUE(received_final_block); + CHECK_EQUAL(expected.size(), actual.size()); + CHECK_TRUE(std::equal(expected.begin(), expected.end(), actual.begin())); + CHECK_TRUE(codec::safe_output_buffer_size(encoded[i].size()) >= decoded_output.size()); + } + } + + //************************************************************************* + TEST(test_decode_pointer_size_multi_pass_with_callback_and_larger_buffer) + { + codec_larger_buffer b64(callback); + + for (size_t i = 0; i < 256; ++i) + { + decoded_output.clear(); + received_final_block = false; + + auto start = encoded[i].data(); + auto length = encoded[i].size(); + + while (length >= 5) + { + b64.decode(start, 5); + length -= 5; + start += 5; + } + + if (length > 0) + { + b64.decode(start, length); + } + + CHECK_FALSE(received_final_block); + b64.flush(); + CHECK_TRUE(received_final_block); + + std::vector expected(input_data.begin(), input_data.begin() + i); + std::vector actual(decoded_output); + + CHECK_TRUE(received_final_block); + CHECK_EQUAL(expected.size(), actual.size()); + CHECK_TRUE(std::equal(expected.begin(), expected.end(), actual.begin())); + CHECK_TRUE(codec::safe_output_buffer_size(encoded[i].size()) >= decoded_output.size()); + } + } + + //************************************************************************* + TEST(test_decode_pointer_pointer_single_pass_with_callback) + { + codec b64(callback); + + for (size_t i = 0; i < 256; ++i) + { + decoded_output.clear(); + received_final_block = false; + + b64.decode_final(encoded[i].begin(), encoded[i].end()); + + std::vector expected(input_data.begin(), input_data.begin() + i); + std::vector actual(decoded_output); + + CHECK_TRUE(received_final_block); + CHECK_EQUAL(expected.size(), actual.size()); + CHECK_TRUE(std::equal(expected.begin(), expected.end(), actual.begin())); + CHECK_TRUE(codec::safe_output_buffer_size(encoded[i].size()) >= decoded_output.size()); + } + } + + //************************************************************************* + TEST(test_decode_pointer_pointer_single_pass_with_callback_and_larger_buffer) + { + codec_larger_buffer b64(callback); + + for (size_t i = 0; i < 256; ++i) + { + decoded_output.clear(); + received_final_block = false; + + b64.decode_final(encoded[i].begin(), encoded[i].end()); + + std::vector expected(input_data.begin(), input_data.begin() + i); + std::vector actual(decoded_output); + + CHECK_TRUE(received_final_block); + CHECK_EQUAL(expected.size(), actual.size()); + CHECK_TRUE(std::equal(expected.begin(), expected.end(), actual.begin())); + CHECK_TRUE(codec_larger_buffer::safe_output_buffer_size(encoded[i].size()) >= decoded_output.size()); + } + } + + //************************************************************************* + TEST(test_decode_pointer_pointer_multi_pass_with_callback) + { + codec b64(callback); + + for (size_t i = 0; i < 256; ++i) + { + decoded_output.clear(); + received_final_block = false; + + auto start = encoded[i].data(); + auto length = encoded[i].size(); + + while (length >= 5) + { + b64.decode(start, 5); + length -= 5; + start += 5; + } + + if (length > 0) + { + b64.decode(start, start + length); + } + + CHECK_FALSE(received_final_block); + b64.flush(); + CHECK_TRUE(received_final_block); + + std::vector expected(input_data.begin(), input_data.begin() + i); + std::vector actual(decoded_output); + + CHECK_TRUE(received_final_block); + CHECK_EQUAL(expected.size(), actual.size()); + CHECK_TRUE(std::equal(expected.begin(), expected.end(), actual.begin())); + CHECK_TRUE(codec::safe_output_buffer_size(encoded[i].size()) >= decoded_output.size()); + } + } + + //************************************************************************* + TEST(test_decode_pointer_pointer_multi_pass_with_callback_and_larger_buffer) + { + codec_larger_buffer b64(callback); + + for (size_t i = 0; i < 256; ++i) + { + decoded_output.clear(); + received_final_block = false; + + auto start = encoded[i].data(); + auto length = encoded[i].size(); + + while (length >= 5) + { + b64.decode(start, 5); + length -= 5; + start += 5; + } + + if (length > 0) + { + b64.decode(start, start + length); + } + + CHECK_FALSE(received_final_block); + b64.flush(); + CHECK_TRUE(received_final_block); + + std::vector expected(input_data.begin(), input_data.begin() + i); + std::vector actual(decoded_output); + + CHECK_TRUE(received_final_block); + CHECK_EQUAL(expected.size(), actual.size()); + CHECK_TRUE(std::equal(expected.begin(), expected.end(), actual.begin())); + CHECK_TRUE(codec::safe_output_buffer_size(encoded[i].size()) >= decoded_output.size()); + } + } + + //************************************************************************* + TEST(test_decode_multi_pass_by_char_with_callback) + { + codec b64(callback); + + for (size_t i = 0; i < 256; ++i) + { + decoded_output.clear(); + received_final_block = false; + + auto start = encoded[i].data(); + auto length = encoded[i].size(); + + while (length--) + { + b64.decode(*start++); + } + + CHECK_FALSE(received_final_block); + b64.flush(); + CHECK_TRUE(received_final_block); + + std::vector expected(input_data.begin(), input_data.begin() + i); + std::vector actual(decoded_output); + + CHECK_TRUE(received_final_block); + CHECK_EQUAL(expected.size(), actual.size()); + CHECK_TRUE(std::equal(expected.begin(), expected.end(), actual.begin())); + CHECK_TRUE(codec::safe_output_buffer_size(encoded[i].size()) >= decoded_output.size()); + } + } + + //************************************************************************* + TEST(test_decode_multi_pass_by_char_with_callback_and_larger_buffer) + { + codec_larger_buffer b64(callback); + + for (size_t i = 0; i < 256; ++i) + { + decoded_output.clear(); + received_final_block = false; + + auto start = encoded[i].data(); + auto length = encoded[i].size(); + + while (length--) + { + b64.decode(*start++); + } + + CHECK_FALSE(received_final_block); + b64.flush(); + CHECK_TRUE(received_final_block); + + std::vector expected(input_data.begin(), input_data.begin() + i); + std::vector actual(decoded_output); + + CHECK_TRUE(received_final_block); + CHECK_EQUAL(expected.size(), actual.size()); + CHECK_TRUE(std::equal(expected.begin(), expected.end(), actual.begin())); + CHECK_TRUE(codec::safe_output_buffer_size(encoded[i].size()) >= decoded_output.size()); + } + } + + //************************************************************************* + TEST(test_decode_multi_pass_blocks_with_no_callback_and_full_size_buffer) + { + codec_full_buffer b64; + + for (size_t i = 4; i < 256; ++i) + { + b64.restart(); + + auto start = encoded[i].data(); + auto length = encoded[i].size(); + + while (length >= 5) + { + b64.decode(start, 5); + length -= 5; + start += 5; + } + + if (length > 0) + { + b64.decode(start, length); + } + + b64.flush(); + + std::vector expected(input_data.begin(), input_data.begin() + i); + std::vector actual(b64.begin(), b64.end()); + + CHECK_EQUAL(expected.size(), actual.size()); + CHECK_TRUE(std::equal(expected.begin(), expected.end(), actual.begin())); + CHECK_TRUE(codec::safe_output_buffer_size(encoded[i].size()) >= b64.size()); + } + } + + //************************************************************************* +#if ETL_USING_CPP14 + template + constexpr auto GetConstexprBase64(const etl::array input) noexcept + { + etl::array output{ 0 }; + + using codec = etl::base64_rfc4648_url_padding_decoder; + + codec b64; + b64.decode_final(input.begin(), input.end()); + etl::copy(b64.begin(), b64.end(), output.begin()); + + return output; + } + + TEST(test_encode_constexpr) + { + constexpr etl::array input = { 'A', 'A', 'E', 'C' ,'A' ,'w', 'Q', 'F', 'B', 'g', 'c', 'I', 'C', 'Q' }; + + constexpr auto output{ GetConstexprBase64(input) }; + + std::vector expected = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + std::vector actual(output.begin(), output.end()); + + CHECK_TRUE(std::equal(expected.begin(), expected.end(), actual.begin())); + CHECK_TRUE(codec::safe_output_buffer_size(14) >= output.size()); + } +#endif + + //************************************************************************* + TEST(test_decode_overflow) + { + codec b64; + +#if ETL_USING_EXCEPTIONS + CHECK_THROW((b64.decode(encoded[10].data(), encoded[10].size())), etl::base64_overflow); +#else + CHECK_FALSE(b64.decode(encoded[10].data(), encoded[10].size()); + CHECK_TRUE(b64.error()); +#endif + } + + //************************************************************************* + TEST(test_decode_invalid_character) + { + codec_larger_buffer b64; + + std::string invalid_chararacter("OycDQ#37KA"); + +#if ETL_USING_EXCEPTIONS + CHECK_THROW((b64.decode(invalid_chararacter.data(), invalid_chararacter.size())), etl::base64_invalid_data); +#else + CHECK_FALSE(b64.decode(invalid_chararacter.data(), invalid_chararacter.size())); + CHECK_TRUE(b64.error()); +#endif + } + + //************************************************************************* + TEST(test_decode_invalid_padding) + { + codec_larger_buffer b64; + + std::string invalid_chararacter("OycD=y37KA=="); + +#if ETL_USING_EXCEPTIONS + CHECK_THROW((b64.decode(invalid_chararacter.data(), invalid_chararacter.size())), etl::base64_invalid_data); +#else + CHECK_FALSE(b64.decode(invalid_chararacter.data(), invalid_chararacter.size())); + CHECK_TRUE(b64.error()); +#endif + } + }; +} diff --git a/test/test_base64_RFC4648_URL_with_no_padding.cpp b/test/test_base64_RFC4648_URL_encoder_with_no_padding.cpp similarity index 74% rename from test/test_base64_RFC4648_URL_with_no_padding.cpp rename to test/test_base64_RFC4648_URL_encoder_with_no_padding.cpp index 0646287d..1a4b59a4 100644 --- a/test/test_base64_RFC4648_URL_with_no_padding.cpp +++ b/test/test_base64_RFC4648_URL_encoder_with_no_padding.cpp @@ -5,7 +5,7 @@ Embedded Template Library. https://github.com/ETLCPP/etl https://www.etlcpp.com -Copyright(c) 2023 John Wellbelove +Copyright(c) 2024 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 @@ -28,7 +28,7 @@ SOFTWARE. #include "unit_test_framework.h" -#include "etl/base64.h" +#include "etl/base64_encoder.h" #include "etl/string.h" #include "etl/vector.h" @@ -45,14 +45,36 @@ SOFTWARE. #include "etl/integral_limits.h" //***************************************************************************** -// Ecode/decode using RFC-4648-URL with no padding +// Encode/decode using RFC-4648-URL with no padding +// Using minimum buffer size, with callback. //***************************************************************************** namespace { - using codec = etl::base64_rfc4648_url; + using codec = etl::base64_rfc4648_url_encoder; + using codec_larger_buffer = etl::base64_rfc4648_url_encoder; +#if ETL_USING_CPP14 + using codec_full_buffer = etl::base64_rfc4648_url_encoder::safe_output_buffer_size(256)>; +#else + using codec_full_buffer = etl::base64_rfc4648_url_encoder<344>; +#endif - std::array input_data_unsigned_char = + std::string encoded_output; + bool received_final_block = false; + + codec::callback_type callback = [](const codec::span_type& sp) + { + if (sp.empty()) + { + received_final_block = true; + } + else + { + std::copy(sp.begin(), sp.end(), std::back_inserter(encoded_output)); + } + }; + + std::array input_data = { 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, @@ -72,26 +94,6 @@ namespace 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 = { "", @@ -353,254 +355,355 @@ namespace "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHACPltrIR4SYRva_sgO5xJ-06AaYIlhpXVTZHt0ncqJECK302ALc3VWiamcRVCDj-ycBQpH40jLsHqzvl-bN8co4QrJDWnY8gLH4u6Ub_pUYDSI7XRtFmufTAdABzYcGwWccdWCP6BrvvgktjbuVd8mctC7_yzVh7RQtMMGLPurxp3qFI8ns3eITQ-H7VU1_u0vQ==" }; - SUITE(test_base64_rfc4648_url_url_with_no_padding) + SUITE(test_base64_rfc4648_url_with_no_padding) { //************************************************************************* - TEST(test_encode_unsigned_char_pointer_size) + TEST(test_basic_information) { - codec b64; - std::array encoded_output; + codec_full_buffer b64; + CHECK_EQUAL(etl::base64::Encoding::RFC_4648_URL, codec_full_buffer::Encoding); + CHECK_EQUAL("RFC_4648_URL", codec_full_buffer::Encoding.c_str()); + } + + //************************************************************************* + TEST(test_check_encode_safe_buffer_sizes) + { for (size_t i = 0; i < 256; ++i) { - encoded_output.fill(0); + size_t minimum_size = encoded[i].size(); + size_t safe_size = codec::safe_output_buffer_size(i); - 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(codec::encoded_size(i), size); + CHECK_TRUE(safe_size >= minimum_size); + CHECK_TRUE((safe_size - minimum_size) <= 2U); } } //************************************************************************* - TEST(test_encode_unsigned_char_pointer_size_no_output_length) + TEST(test_encode_pointer_size_single_pass_with_callback) { - codec b64; - std::array encoded_output; + codec b64(callback); for (size_t i = 0; i < 256; ++i) { - encoded_output.fill(0); + encoded_output.clear(); + received_final_block = false; - auto size = b64.encode(input_data_unsigned_char.data(), i, - encoded_output.data()); + b64.encode_final(input_data.data(), i); std::string expected(encoded[i]); - std::string actual(encoded_output.data(), size); + std::string actual(encoded_output); + CHECK_TRUE(received_final_block); CHECK_EQUAL(expected, actual); - CHECK_EQUAL(codec::encoded_size(i), size); + CHECK_TRUE(codec::safe_output_buffer_size(i) >= encoded_output.size()); } } //************************************************************************* - TEST(test_encode_unsigned_char_pointer_size_to_etl_back_inserter) + TEST(test_encode_pointer_size_single_pass_with_callback_and_larger_buffer) { - codec b64; + codec_larger_buffer b64(callback); - for (size_t i = 0; i < 256; ++i) + for (size_t i = 0; i < 256; ++i) { - std::string actual; + encoded_output.clear(); + received_final_block = false; - auto size = b64.encode(input_data_unsigned_char.data(), i, - etl::back_inserter(actual)); + b64.encode_final(input_data.data(), i); std::string expected(encoded[i]); + std::string actual(encoded_output); + + CHECK_TRUE(received_final_block); + CHECK_EQUAL(expected, actual); + CHECK_TRUE(codec::safe_output_buffer_size(i) >= encoded_output.size()); + } + } + + //************************************************************************* + TEST(test_encode_pointer_size_multi_pass_blocks_with_callback) + { + codec b64(callback); + + for (size_t i = 0; i < 256; ++i) + { + encoded_output.clear(); + received_final_block = false; + + auto start = input_data.data(); + auto length = i; + while (length >= 5) + { + b64.encode(start, 5); + length -= 5; + start += 5; + } + + if (length > 0) + { + b64.encode(start, length); + } + + CHECK_FALSE(received_final_block); + b64.flush(); + CHECK_TRUE(received_final_block); + + std::string expected(encoded[i]); + std::string actual(encoded_output); + CHECK_EQUAL(expected, actual); - CHECK_EQUAL(codec::encoded_size(i), size); + CHECK_TRUE(codec::safe_output_buffer_size(i) >= encoded_output.size()); } } -#if ETL_USING_STL //************************************************************************* - TEST(test_encode_unsigned_char_pointer_size_to_std_back_inserter) + TEST(test_encode_pointer_size_multi_pass_blocks_with_callback_larger_buffer) { - codec b64; + codec_larger_buffer b64(callback); for (size_t i = 0; i < 256; ++i) { - std::string actual; + encoded_output.clear(); + received_final_block = false; - auto size = b64.encode(input_data_unsigned_char.data(), i, - std::back_inserter(actual)); + auto start = input_data.data(); + auto length = i; + + while (length >= 5) + { + b64.encode(start, 5); + length -= 5; + start += 5; + } + + if (length > 0) + { + b64.encode(start, length); + } + + CHECK_FALSE(received_final_block); + b64.flush(); + CHECK_TRUE(received_final_block); std::string expected(encoded[i]); + std::string actual(encoded_output); CHECK_EQUAL(expected, actual); - CHECK_EQUAL(codec::encoded_size(i), size); + CHECK_TRUE(codec::safe_output_buffer_size(i) >= encoded_output.size()); } } -#endif //************************************************************************* - TEST(test_encode_unsigned_char_pointer_pointer) + TEST(test_encode_pointer_pointer_single_pass_with_callback) { - codec b64; - std::array encoded_output; + codec b64(callback); for (size_t i = 0; i < 256; ++i) { - encoded_output.fill(0); + encoded_output.clear(); + received_final_block = false; - auto size = b64.encode(input_data_unsigned_char.data(), input_data_unsigned_char.data() + i, - encoded_output.data(), encoded_output.data() + encoded_output.size()); + b64.encode_final(input_data.data(), input_data.data() + i); std::string expected(encoded[i]); - std::string actual(encoded_output.data(), size); + std::string actual(encoded_output); + CHECK_TRUE(received_final_block); CHECK_EQUAL(expected, actual); - CHECK_EQUAL(codec::encoded_size(i), size); + CHECK_TRUE(codec::safe_output_buffer_size(i) >= encoded_output.size()); } } //************************************************************************* - TEST(test_encode_unsigned_char_pointer_pointer_no_output_end_pointer) + TEST(test_encode_pointer_pointer_single_pass_with_callback_larger_buffer) { - codec b64; - 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(codec::encoded_size(i), size); - } - } - - //************************************************************************* - TEST(test_encode_int8_t_pointer_size) - { - codec b64; - 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(codec::encoded_size(i), size); - } - } - - //************************************************************************* - TEST(test_encode_int8_t_pointer_size_no_output_length) - { - codec b64; - 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(codec::encoded_size(i), size); - } - } - - //************************************************************************* - TEST(test_encode_int8_t_pointer_size_to_etl_back_inserter) - { - codec b64; + codec_larger_buffer b64(callback); for (size_t i = 0; i < 256; ++i) { - std::string actual; + encoded_output.clear(); + received_final_block = false; - auto size = b64.encode(input_data_int8_t.data(), i, - etl::back_inserter(actual)); + b64.encode_final(input_data.data(), input_data.data() + i); std::string expected(encoded[i]); + std::string actual(encoded_output); + CHECK_TRUE(received_final_block); CHECK_EQUAL(expected, actual); - CHECK_EQUAL(codec::encoded_size(i), size); - } - } - -#if ETL_USING_STL - //************************************************************************* - TEST(test_encode_int8_t_pointer_size_to_std_back_inserter) - { - codec b64; - - 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(codec::encoded_size(i), size); - } - } -#endif - - //************************************************************************* - TEST(test_encode_int8_t_pointer_pointer) - { - codec b64; - 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(codec::encoded_size(i), size); + CHECK_TRUE(codec::safe_output_buffer_size(i) >= encoded_output.size()); } } //************************************************************************* - TEST(test_encode_int8_t_pointer_pointer_no_end_pointer) + TEST(test_encode_pointer_pointer_multi_pass_blocks_with_callback) { - codec b64; - - std::array encoded_output; + codec b64(callback); for (size_t i = 0; i < 256; ++i) { - encoded_output.fill(0); + encoded_output.clear(); + received_final_block = false; - auto size = b64.encode(input_data_int8_t.data(), input_data_int8_t.data() + i, - encoded_output.data()); + auto start = input_data.data(); + auto length = i; + + while (length >= 5) + { + b64.encode(start, start + 5); + length -= 5; + start += 5; + } + + if (length > 0) + { + b64.encode(start, length); + } + + CHECK_FALSE(received_final_block); + b64.flush(); + CHECK_TRUE(received_final_block); std::string expected(encoded[i]); - std::string actual(encoded_output.data(), size); + std::string actual(encoded_output); CHECK_EQUAL(expected, actual); - CHECK_EQUAL(codec::encoded_size(i), size); + CHECK_TRUE(codec::safe_output_buffer_size(i) >= encoded_output.size()); + } + } + + //************************************************************************* + TEST(test_encode_pointer_pointer_multi_pass_blocks_with_callback_larger_buffer) + { + codec_larger_buffer b64(callback); + + for (size_t i = 0; i < 256; ++i) + { + encoded_output.clear(); + received_final_block = false; + + auto start = input_data.data(); + auto length = i; + + while (length >= 5) + { + b64.encode(start, start + 5); + length -= 5; + start += 5; + } + + if (length > 0) + { + b64.encode(start, length); + } + + CHECK_FALSE(received_final_block); + b64.flush(); + CHECK_TRUE(received_final_block); + + std::string expected(encoded[i]); + std::string actual(encoded_output); + + CHECK_EQUAL(expected, actual); + CHECK_TRUE(codec::safe_output_buffer_size(i) >= encoded_output.size()); + } + } + + //************************************************************************* + TEST(test_encode_multi_pass_by_char_with_callback) + { + codec b64(callback); + + for (size_t i = 0; i < 256; ++i) + { + encoded_output.clear(); + received_final_block = false; + + auto start = input_data.data(); + auto length = i; + + while (length--) + { + b64.encode(*start); + ++start; + } + + CHECK_FALSE(received_final_block); + b64.flush(); + CHECK_TRUE(received_final_block); + + std::string expected(encoded[i]); + std::string actual(encoded_output); + + CHECK_EQUAL(expected, actual); + CHECK_TRUE(codec::safe_output_buffer_size(i) >= encoded_output.size()); + } + } + + //************************************************************************* + TEST(test_encode_multi_pass_by_char_with_callback_larger_buffer) + { + codec_larger_buffer b64(callback); + + for (size_t i = 0; i < 256; ++i) + { + encoded_output.clear(); + received_final_block = false; + + auto start = input_data.data(); + auto length = i; + + while (length--) + { + b64.encode(*start); + ++start; + } + + CHECK_FALSE(received_final_block); + b64.flush(); + CHECK_TRUE(received_final_block); + + std::string expected(encoded[i]); + std::string actual(encoded_output); + + CHECK_EQUAL(expected, actual); + CHECK_TRUE(codec::safe_output_buffer_size(i) >= encoded_output.size()); + } + } + + //************************************************************************* + TEST(test_encode_multi_pass_blocks_with_no_callback_and_full_size_buffer) + { + codec_full_buffer b64; + + for (size_t i = 250; i < 256; ++i) + { + b64.restart(); + + auto start = input_data.data(); + auto length = i; + + while (length >= 5) + { + b64.encode(start, start + 5); + length -= 5; + start += 5; + } + + if (length > 0) + { + b64.encode(start, length); + } + + b64.flush(); + + std::string expected(encoded[i]); + std::string actual(b64.begin(), b64.end()); + + CHECK_EQUAL(expected, actual); + CHECK_TRUE(codec::safe_output_buffer_size(i) >= actual.size()); } } @@ -609,18 +712,18 @@ namespace template constexpr auto GetConstexprBase64(const etl::array input) noexcept { + etl::array output{ 0 }; + + using codec = etl::base64_rfc4648_encoder; + codec b64; - - constexpr size_t encoded_size = codec::encoded_size(Size); - etl::array output{ 0 }; - - b64.encode(input.begin(), Size, - output._buffer, encoded_size); + b64.encode_final(input.begin(), input.end()); + etl::copy(b64.begin(), b64.end(), output.begin()); return output; } - TEST(test_encode_int8_t_constexpr) + TEST(test_encode_constexpr) { constexpr etl::array input = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; @@ -630,7 +733,7 @@ namespace std::string actual(output.data(), output.size()); CHECK_EQUAL(expected, actual); - CHECK_EQUAL(codec::encoded_size(10), output.size()); + CHECK_TRUE(codec::safe_output_buffer_size(10) >= output.size()); } #endif @@ -638,284 +741,10 @@ namespace TEST(test_encode_overflow) { codec b64; - std::array encoded_output{ 0 }; - CHECK_THROW((b64.encode(input_data_unsigned_char.data(), 10, - encoded_output.data(), encoded_output.size())), - etl::base64_overflow); + CHECK_THROW((b64.encode(input_data.data(), 10)), etl::base64_overflow); + CHECK_TRUE(b64.overflow()); } - - //************************************************************************* - TEST(test_decode_unsigned_char_pointer_size) - { - codec b64; - 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, codec::decoded_size(encoded[i].data(), encoded[i].size())); - CHECK_EQUAL(i, decoded_size); - } - } - - //************************************************************************* - TEST(test_decode_unsigned_char_pointer_size_no_end_pointer) - { - codec b64; - 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, codec::decoded_size(encoded[i].data(), encoded[i].size())); - CHECK_EQUAL(i, decoded_size); - } - } - - //************************************************************************* - TEST(test_decode_unsigned_char_pointer_pointer) - { - codec b64; - 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, codec::decoded_size(encoded[i].data(), encoded[i].size())); - CHECK_EQUAL(i, decoded_size); - } - } - - //************************************************************************* - TEST(test_decode_unsigned_char_pointer_pointer_no_end_pointer) - { - codec b64; - 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, codec::decoded_size(encoded[i].data(), encoded[i].size())); - CHECK_EQUAL(i, decoded_size); - } - } - - //************************************************************************* - TEST(test_decode_int8_t_pointer_size) - { - codec b64; - 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, codec::decoded_size(encoded[i].data(), encoded[i].size())); - CHECK_EQUAL(i, decoded_size); - } - } - - //************************************************************************* - TEST(test_decode_int8_t_pointer_size_etl_back_inserter) - { - codec b64; - 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, codec::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) - { - codec b64; - 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, codec::decoded_size(encoded[i].data(), encoded[i].size())); - CHECK_EQUAL(i, decoded_size); - } - } -#endif - - //************************************************************************* - TEST(test_decode_int8_t_pointer_size_no_output_size) - { - codec b64; - 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, codec::decoded_size(encoded[i].data(), encoded[i].size())); - CHECK_EQUAL(i, decoded_size); - } - } - - //************************************************************************* - TEST(test_decode_int8_t_pointer_pointer) - { - codec b64; - 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, codec::decoded_size(encoded[i].data(), encoded[i].size())); - CHECK_EQUAL(i, decoded_size); - } - } - - //************************************************************************* - TEST(test_decode_int8_t_pointer_pointer_etl_back_inserter) - { - codec b64; - 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, codec::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) - { - codec b64; - 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, codec::decoded_size(encoded[i].data(), encoded[i].size())); - CHECK_EQUAL(i, decoded_size); - } - } -#endif - - //************************************************************************* - TEST(test_decode_int8_t_pointer_pointer_no_end_pointer) - { - codec b64; - 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, codec::decoded_size(encoded[i].data(), encoded[i].size())); - CHECK_EQUAL(i, decoded_size); - } - } - - //************************************************************************* - TEST(test_decode_overflow) - { - codec b64; - 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) - { - codec b64; - std::array decoded_output{ 0 }; - - std::string invalid_chararacter("OycDQ#37KA"); - - CHECK_THROW((b64.decode(invalid_chararacter.data(), invalid_chararacter.size(), - decoded_output.data(), decoded_output.size())), etl::base64_invalid_character); - - std::string invalid_length("OycDQy37K"); - - CHECK_THROW((b64.decode(invalid_length.data(), invalid_length.size(), - decoded_output.data(), decoded_output.size())), etl::base64_invalid_decode_input_length); - } - - //************************************************************************* - //TEST(test_decoded_size) - //{ - // codec b64; - - // for (size_t i = 0; i < 256; ++i) - // { - // size_t length = codec::decoded_size(encoded[i].size()); - - // CHECK_EQUAL(length, codec::decoded_size(encoded[i].data(), encoded[i].size())); - // } - //} }; } diff --git a/test/test_base64_RFC4648_URL_with_padding.cpp b/test/test_base64_RFC4648_URL_encoder_with_padding.cpp similarity index 74% rename from test/test_base64_RFC4648_URL_with_padding.cpp rename to test/test_base64_RFC4648_URL_encoder_with_padding.cpp index 2d3725ac..e3f8b3e2 100644 --- a/test/test_base64_RFC4648_URL_with_padding.cpp +++ b/test/test_base64_RFC4648_URL_encoder_with_padding.cpp @@ -5,7 +5,7 @@ Embedded Template Library. https://github.com/ETLCPP/etl https://www.etlcpp.com -Copyright(c) 2023 John Wellbelove +Copyright(c) 2024 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 @@ -28,7 +28,7 @@ SOFTWARE. #include "unit_test_framework.h" -#include "etl/base64.h" +#include "etl/base64_encoder.h" #include "etl/string.h" #include "etl/vector.h" @@ -45,14 +45,36 @@ SOFTWARE. #include "etl/integral_limits.h" //***************************************************************************** -// Ecode/decode using RFC-4648-URL with padding +// Encode/decode using RFC-4648-URL with padding +// Using minimum buffer size, with callback. //***************************************************************************** namespace { - using codec = etl::base64_rfc4648_url; + using codec = etl::base64_rfc4648_url_padding_encoder; + using codec_larger_buffer = etl::base64_rfc4648_url_padding_encoder; +#if ETL_USING_CPP14 + using codec_full_buffer = etl::base64_rfc4648_url_padding_encoder::safe_output_buffer_size(256)>; +#else + using codec_full_buffer = etl::base64_rfc4648_url_padding_encoder<344>; +#endif - std::array input_data_unsigned_char = + std::string encoded_output; + bool received_final_block = false; + + codec::callback_type callback = [](const codec::span_type& sp) + { + if (sp.empty()) + { + received_final_block = true; + } + else + { + std::copy(sp.begin(), sp.end(), std::back_inserter(encoded_output)); + } + }; + + std::array input_data = { 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, @@ -72,26 +94,6 @@ namespace 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 = { "", @@ -353,254 +355,355 @@ namespace "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N-27j_cebMXjnZljpYhuYjRbdDd_9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHACPltrIR4SYRva_sgO5xJ-06AaYIlhpXVTZHt0ncqJECK302ALc3VWiamcRVCDj-ycBQpH40jLsHqzvl-bN8co4QrJDWnY8gLH4u6Ub_pUYDSI7XRtFmufTAdABzYcGwWccdWCP6BrvvgktjbuVd8mctC7_yzVh7RQtMMGLPurxp3qFI8ns3eITQ-H7VU1_u0vQ==" }; - SUITE(test_base64_rfc4648_url_url_with_padding) + SUITE(test_base64_rfc4648_url_with_no_padding) { //************************************************************************* - TEST(test_encode_unsigned_char_pointer_size) + TEST(test_basic_information) { - codec b64; - std::array encoded_output; + codec_full_buffer b64; + CHECK_EQUAL(etl::base64::Encoding::RFC_4648_URL, codec_full_buffer::Encoding); + CHECK_EQUAL("RFC_4648_URL", codec_full_buffer::Encoding.c_str()); + } + + //************************************************************************* + TEST(test_check_encode_safe_buffer_sizes) + { for (size_t i = 0; i < 256; ++i) { - encoded_output.fill(0); + size_t minimum_size = encoded[i].size(); + size_t safe_size = codec::safe_output_buffer_size(i); - 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(codec::encoded_size(i), size); + CHECK_TRUE(safe_size >= minimum_size); + CHECK_TRUE((safe_size - minimum_size) <= 2U); } } //************************************************************************* - TEST(test_encode_unsigned_char_pointer_size_no_output_length) + TEST(test_encode_pointer_size_single_pass_with_callback) { - codec b64; - std::array encoded_output; + codec b64(callback); for (size_t i = 0; i < 256; ++i) { - encoded_output.fill(0); + encoded_output.clear(); + received_final_block = false; - auto size = b64.encode(input_data_unsigned_char.data(), i, - encoded_output.data()); + b64.encode_final(input_data.data(), i); std::string expected(encoded[i]); - std::string actual(encoded_output.data(), size); + std::string actual(encoded_output); + CHECK_TRUE(received_final_block); CHECK_EQUAL(expected, actual); - CHECK_EQUAL(codec::encoded_size(i), size); + CHECK_TRUE(codec::safe_output_buffer_size(i) >= encoded_output.size()); } } //************************************************************************* - TEST(test_encode_unsigned_char_pointer_size_to_etl_back_inserter) + TEST(test_encode_pointer_size_single_pass_with_callback_and_larger_buffer) { - codec b64; + codec_larger_buffer b64(callback); - for (size_t i = 0; i < 256; ++i) + for (size_t i = 0; i < 256; ++i) { - std::string actual; + encoded_output.clear(); + received_final_block = false; - auto size = b64.encode(input_data_unsigned_char.data(), i, - etl::back_inserter(actual)); + b64.encode_final(input_data.data(), i); std::string expected(encoded[i]); + std::string actual(encoded_output); + + CHECK_TRUE(received_final_block); + CHECK_EQUAL(expected, actual); + CHECK_TRUE(codec::safe_output_buffer_size(i) >= encoded_output.size()); + } + } + + //************************************************************************* + TEST(test_encode_pointer_size_multi_pass_blocks_with_callback) + { + codec b64(callback); + + for (size_t i = 0; i < 256; ++i) + { + encoded_output.clear(); + received_final_block = false; + + auto start = input_data.data(); + auto length = i; + while (length >= 5) + { + b64.encode(start, 5); + length -= 5; + start += 5; + } + + if (length > 0) + { + b64.encode(start, length); + } + + CHECK_FALSE(received_final_block); + b64.flush(); + CHECK_TRUE(received_final_block); + + std::string expected(encoded[i]); + std::string actual(encoded_output); + CHECK_EQUAL(expected, actual); - CHECK_EQUAL(codec::encoded_size(i), size); + CHECK_TRUE(codec::safe_output_buffer_size(i) >= encoded_output.size()); } } -#if ETL_USING_STL //************************************************************************* - TEST(test_encode_unsigned_char_pointer_size_to_std_back_inserter) + TEST(test_encode_pointer_size_multi_pass_blocks_with_callback_larger_buffer) { - codec b64; + codec_larger_buffer b64(callback); for (size_t i = 0; i < 256; ++i) { - std::string actual; + encoded_output.clear(); + received_final_block = false; - auto size = b64.encode(input_data_unsigned_char.data(), i, - std::back_inserter(actual)); + auto start = input_data.data(); + auto length = i; + + while (length >= 5) + { + b64.encode(start, 5); + length -= 5; + start += 5; + } + + if (length > 0) + { + b64.encode(start, length); + } + + CHECK_FALSE(received_final_block); + b64.flush(); + CHECK_TRUE(received_final_block); std::string expected(encoded[i]); + std::string actual(encoded_output); CHECK_EQUAL(expected, actual); - CHECK_EQUAL(codec::encoded_size(i), size); + CHECK_TRUE(codec::safe_output_buffer_size(i) >= encoded_output.size()); } } -#endif //************************************************************************* - TEST(test_encode_unsigned_char_pointer_pointer) + TEST(test_encode_pointer_pointer_single_pass_with_callback) { - codec b64; - std::array encoded_output; + codec b64(callback); for (size_t i = 0; i < 256; ++i) { - encoded_output.fill(0); + encoded_output.clear(); + received_final_block = false; - auto size = b64.encode(input_data_unsigned_char.data(), input_data_unsigned_char.data() + i, - encoded_output.data(), encoded_output.data() + encoded_output.size()); + b64.encode_final(input_data.data(), input_data.data() + i); std::string expected(encoded[i]); - std::string actual(encoded_output.data(), size); + std::string actual(encoded_output); + CHECK_TRUE(received_final_block); CHECK_EQUAL(expected, actual); - CHECK_EQUAL(codec::encoded_size(i), size); + CHECK_TRUE(codec::safe_output_buffer_size(i) >= encoded_output.size()); } } //************************************************************************* - TEST(test_encode_unsigned_char_pointer_pointer_no_output_end_pointer) + TEST(test_encode_pointer_pointer_single_pass_with_callback_larger_buffer) { - codec b64; - 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(codec::encoded_size(i), size); - } - } - - //************************************************************************* - TEST(test_encode_int8_t_pointer_size) - { - codec b64; - 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(codec::encoded_size(i), size); - } - } - - //************************************************************************* - TEST(test_encode_int8_t_pointer_size_no_output_length) - { - codec b64; - 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(codec::encoded_size(i), size); - } - } - - //************************************************************************* - TEST(test_encode_int8_t_pointer_size_to_etl_back_inserter) - { - codec b64; + codec_larger_buffer b64(callback); for (size_t i = 0; i < 256; ++i) { - std::string actual; + encoded_output.clear(); + received_final_block = false; - auto size = b64.encode(input_data_int8_t.data(), i, - etl::back_inserter(actual)); + b64.encode_final(input_data.data(), input_data.data() + i); std::string expected(encoded[i]); + std::string actual(encoded_output); + CHECK_TRUE(received_final_block); CHECK_EQUAL(expected, actual); - CHECK_EQUAL(codec::encoded_size(i), size); - } - } - -#if ETL_USING_STL - //************************************************************************* - TEST(test_encode_int8_t_pointer_size_to_std_back_inserter) - { - codec b64; - - 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(codec::encoded_size(i), size); - } - } -#endif - - //************************************************************************* - TEST(test_encode_int8_t_pointer_pointer) - { - codec b64; - 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(codec::encoded_size(i), size); + CHECK_TRUE(codec::safe_output_buffer_size(i) >= encoded_output.size()); } } //************************************************************************* - TEST(test_encode_int8_t_pointer_pointer_no_end_pointer) + TEST(test_encode_pointer_pointer_multi_pass_blocks_with_callback) { - codec b64; - - std::array encoded_output; + codec b64(callback); for (size_t i = 0; i < 256; ++i) { - encoded_output.fill(0); + encoded_output.clear(); + received_final_block = false; - auto size = b64.encode(input_data_int8_t.data(), input_data_int8_t.data() + i, - encoded_output.data()); + auto start = input_data.data(); + auto length = i; + + while (length >= 5) + { + b64.encode(start, start + 5); + length -= 5; + start += 5; + } + + if (length > 0) + { + b64.encode(start, length); + } + + CHECK_FALSE(received_final_block); + b64.flush(); + CHECK_TRUE(received_final_block); std::string expected(encoded[i]); - std::string actual(encoded_output.data(), size); + std::string actual(encoded_output); CHECK_EQUAL(expected, actual); - CHECK_EQUAL(codec::encoded_size(i), size); + CHECK_TRUE(codec::safe_output_buffer_size(i) >= encoded_output.size()); + } + } + + //************************************************************************* + TEST(test_encode_pointer_pointer_multi_pass_blocks_with_callback_larger_buffer) + { + codec_larger_buffer b64(callback); + + for (size_t i = 0; i < 256; ++i) + { + encoded_output.clear(); + received_final_block = false; + + auto start = input_data.data(); + auto length = i; + + while (length >= 5) + { + b64.encode(start, start + 5); + length -= 5; + start += 5; + } + + if (length > 0) + { + b64.encode(start, length); + } + + CHECK_FALSE(received_final_block); + b64.flush(); + CHECK_TRUE(received_final_block); + + std::string expected(encoded[i]); + std::string actual(encoded_output); + + CHECK_EQUAL(expected, actual); + CHECK_TRUE(codec::safe_output_buffer_size(i) >= encoded_output.size()); + } + } + + //************************************************************************* + TEST(test_encode_multi_pass_by_char_with_callback) + { + codec b64(callback); + + for (size_t i = 0; i < 256; ++i) + { + encoded_output.clear(); + received_final_block = false; + + auto start = input_data.data(); + auto length = i; + + while (length--) + { + b64.encode(*start); + ++start; + } + + CHECK_FALSE(received_final_block); + b64.flush(); + CHECK_TRUE(received_final_block); + + std::string expected(encoded[i]); + std::string actual(encoded_output); + + CHECK_EQUAL(expected, actual); + CHECK_TRUE(codec::safe_output_buffer_size(i) >= encoded_output.size()); + } + } + + //************************************************************************* + TEST(test_encode_multi_pass_by_char_with_callback_larger_buffer) + { + codec_larger_buffer b64(callback); + + for (size_t i = 0; i < 256; ++i) + { + encoded_output.clear(); + received_final_block = false; + + auto start = input_data.data(); + auto length = i; + + while (length--) + { + b64.encode(*start); + ++start; + } + + CHECK_FALSE(received_final_block); + b64.flush(); + CHECK_TRUE(received_final_block); + + std::string expected(encoded[i]); + std::string actual(encoded_output); + + CHECK_EQUAL(expected, actual); + CHECK_TRUE(codec::safe_output_buffer_size(i) >= encoded_output.size()); + } + } + + //************************************************************************* + TEST(test_encode_multi_pass_blocks_with_no_callback_and_full_size_buffer) + { + codec_full_buffer b64; + + for (size_t i = 250; i < 256; ++i) + { + b64.restart(); + + auto start = input_data.data(); + auto length = i; + + while (length >= 5) + { + b64.encode(start, start + 5); + length -= 5; + start += 5; + } + + if (length > 0) + { + b64.encode(start, length); + } + + b64.flush(); + + std::string expected(encoded[i]); + std::string actual(b64.begin(), b64.end()); + + CHECK_EQUAL(expected, actual); + CHECK_TRUE(codec::safe_output_buffer_size(i) >= actual.size()); } } @@ -609,28 +712,28 @@ namespace template constexpr auto GetConstexprBase64(const etl::array input) noexcept { + etl::array output{ 0 }; + + using codec = etl::base64_rfc4648_encoder; + codec b64; - - constexpr size_t encoded_size = codec::encoded_size(Size); - etl::array output{ 0 }; - - b64.encode(input.begin(), Size, - output._buffer, encoded_size); + b64.encode_final(input.begin(), input.end()); + etl::copy(b64.begin(), b64.end(), output.begin()); return output; } - TEST(test_encode_int8_t_constexpr) + TEST(test_encode_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 expected("AAECAwQFBgcICQ"); std::string actual(output.data(), output.size()); CHECK_EQUAL(expected, actual); - CHECK_EQUAL(codec::encoded_size(10), output.size()); + CHECK_TRUE(codec::safe_output_buffer_size(10) >= output.size()); } #endif @@ -638,284 +741,10 @@ namespace TEST(test_encode_overflow) { codec b64; - std::array encoded_output{ 0 }; - CHECK_THROW((b64.encode(input_data_unsigned_char.data(), 10, - encoded_output.data(), encoded_output.size())), - etl::base64_overflow); + CHECK_THROW((b64.encode(input_data.data(), 10)), etl::base64_overflow); + CHECK_TRUE(b64.overflow()); } - - //************************************************************************* - TEST(test_decode_unsigned_char_pointer_size) - { - codec b64; - 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, codec::decoded_size(encoded[i].data(), encoded[i].size())); - CHECK_EQUAL(i, decoded_size); - } - } - - //************************************************************************* - TEST(test_decode_unsigned_char_pointer_size_no_end_pointer) - { - codec b64; - 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, codec::decoded_size(encoded[i].data(), encoded[i].size())); - CHECK_EQUAL(i, decoded_size); - } - } - - //************************************************************************* - TEST(test_decode_unsigned_char_pointer_pointer) - { - codec b64; - 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, codec::decoded_size(encoded[i].data(), encoded[i].size())); - CHECK_EQUAL(i, decoded_size); - } - } - - //************************************************************************* - TEST(test_decode_unsigned_char_pointer_pointer_no_end_pointer) - { - codec b64; - 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, codec::decoded_size(encoded[i].data(), encoded[i].size())); - CHECK_EQUAL(i, decoded_size); - } - } - - //************************************************************************* - TEST(test_decode_int8_t_pointer_size) - { - codec b64; - 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, codec::decoded_size(encoded[i].data(), encoded[i].size())); - CHECK_EQUAL(i, decoded_size); - } - } - - //************************************************************************* - TEST(test_decode_int8_t_pointer_size_etl_back_inserter) - { - codec b64; - 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, codec::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) - { - codec b64; - 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, codec::decoded_size(encoded[i].data(), encoded[i].size())); - CHECK_EQUAL(i, decoded_size); - } - } -#endif - - //************************************************************************* - TEST(test_decode_int8_t_pointer_size_no_output_size) - { - codec b64; - 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, codec::decoded_size(encoded[i].data(), encoded[i].size())); - CHECK_EQUAL(i, decoded_size); - } - } - - //************************************************************************* - TEST(test_decode_int8_t_pointer_pointer) - { - codec b64; - 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, codec::decoded_size(encoded[i].data(), encoded[i].size())); - CHECK_EQUAL(i, decoded_size); - } - } - - //************************************************************************* - TEST(test_decode_int8_t_pointer_pointer_etl_back_inserter) - { - codec b64; - 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, codec::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) - { - codec b64; - 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, codec::decoded_size(encoded[i].data(), encoded[i].size())); - CHECK_EQUAL(i, decoded_size); - } - } -#endif - - //************************************************************************* - TEST(test_decode_int8_t_pointer_pointer_no_end_pointer) - { - codec b64; - 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, codec::decoded_size(encoded[i].data(), encoded[i].size())); - CHECK_EQUAL(i, decoded_size); - } - } - - //************************************************************************* - TEST(test_decode_overflow) - { - codec b64; - 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) - { - codec b64; - std::array decoded_output{ 0 }; - - std::string invalid_chararacter("OycDQ#37KA=="); - - CHECK_THROW((b64.decode(invalid_chararacter.data(), invalid_chararacter.size(), - decoded_output.data(), decoded_output.size())), etl::base64_invalid_character); - - std::string invalid_length("OycDQy37K=="); - - CHECK_THROW((b64.decode(invalid_length.data(), invalid_length.size(), - decoded_output.data(), decoded_output.size())), etl::base64_invalid_decode_input_length); - } - - //************************************************************************* - //TEST(test_decoded_size) - //{ - // codec b64; - - // for (size_t i = 0; i < 256; ++i) - // { - // size_t length = codec::decoded_size(encoded[i].size()); - - // CHECK_EQUAL(length, codec::decoded_size(encoded[i].data(), encoded[i].size())); - // } - //} }; } diff --git a/test/test_base64_RFC4648_with_no_padding.cpp b/test/test_base64_RFC4648_decoder_with_no_padding.cpp similarity index 73% rename from test/test_base64_RFC4648_with_no_padding.cpp rename to test/test_base64_RFC4648_decoder_with_no_padding.cpp index a1f8b50f..b8ca1eae 100644 --- a/test/test_base64_RFC4648_with_no_padding.cpp +++ b/test/test_base64_RFC4648_decoder_with_no_padding.cpp @@ -5,7 +5,7 @@ Embedded Template Library. https://github.com/ETLCPP/etl https://www.etlcpp.com -Copyright(c) 2023 John Wellbelove +Copyright(c) 2024 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 @@ -28,7 +28,7 @@ SOFTWARE. #include "unit_test_framework.h" -#include "etl/base64.h" +#include "etl/base64_decoder.h" #include "etl/string.h" #include "etl/vector.h" @@ -39,20 +39,41 @@ SOFTWARE. #include #if ETL_USING_STL - #include +#include #endif #include "etl/integral_limits.h" //***************************************************************************** -// Ecode/decode using RFC-4648 with padding +// Encode/decode using RFC-4648 with no padding //***************************************************************************** namespace { - using codec = etl::base64_rfc4648; + using codec = etl::base64_rfc4648_decoder ; + using codec_larger_buffer = etl::base64_rfc4648_decoder; +#if ETL_USING_CPP14 + using codec_full_buffer = etl::base64_rfc4648_decoder< etl::base64_rfc4648_decoder<>::safe_output_buffer_size(342)>; +#else + using codec_full_buffer = etl::base64_rfc4648_decoder<256>; +#endif - std::array input_data_unsigned_char = + std::vector decoded_output; + bool received_final_block = false; + + codec::callback_type callback = [](const codec::span_type& sp) + { + if (sp.empty()) + { + received_final_block = true; + } + else + { + std::copy(sp.begin(), sp.end(), std::back_inserter(decoded_output)); + } + }; + + std::array input_data = { 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, @@ -72,26 +93,6 @@ namespace 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 = { "", @@ -356,566 +357,442 @@ namespace SUITE(test_base64_rfc4648_with_no_padding) { //************************************************************************* - TEST(test_encode_unsigned_char_pointer_size) + TEST(test_basic_information) { - codec b64; - std::array encoded_output; + codec_full_buffer b64; + + CHECK_EQUAL(etl::base64::Encoding::RFC_4648, codec_full_buffer::Encoding); + CHECK_EQUAL("RFC_4648", codec_full_buffer::Encoding.c_str()); + } + + //************************************************************************* + TEST(test_check_encode_safe_buffer_sizes) + { + for (size_t i = 0; i < 256; ++i) + { + size_t minimum_size = i; + size_t safe_size = codec::safe_output_buffer_size(encoded[i].size()); + + CHECK_TRUE(safe_size >= minimum_size); + CHECK_TRUE((safe_size - minimum_size) <= 2U); + } + } + + //************************************************************************* + TEST(test_decode_pointer_size_single_pass_with_callback) + { + codec b64(callback); for (size_t i = 0; i < 256; ++i) { - encoded_output.fill(0); + decoded_output.clear(); + received_final_block = false; - auto size = b64.encode(input_data_unsigned_char.data(), i, - encoded_output.data(), encoded_output.size()); + b64.decode_final(encoded[i].data(), encoded[i].size()); - std::string expected(encoded[i]); - std::string actual(encoded_output.data(), size); + std::vector expected(input_data.begin(), input_data.begin() + i); + std::vector actual(decoded_output); - CHECK_EQUAL(expected, actual); - CHECK_EQUAL(codec::encoded_size(i), size); + CHECK_TRUE(received_final_block); + CHECK_EQUAL(expected.size(), actual.size()); + CHECK_TRUE(std::equal(expected.begin(), expected.end(), actual.begin())); + CHECK_TRUE(codec::safe_output_buffer_size(encoded[i].size()) >= decoded_output.size()); } } //************************************************************************* - TEST(test_encode_unsigned_char_pointer_size_no_output_length) + TEST(test_decode_pointer_size_single_pass_with_callback_and_larger_buffer) { - codec b64; - std::array encoded_output; + codec_larger_buffer b64(callback); for (size_t i = 0; i < 256; ++i) { - encoded_output.fill(0); + decoded_output.clear(); + received_final_block = false; - auto size = b64.encode(input_data_unsigned_char.data(), i, - encoded_output.data()); + b64.decode_final(encoded[i].data(), encoded[i].size()); - std::string expected(encoded[i]); - std::string actual(encoded_output.data(), size); + std::vector expected(input_data.begin(), input_data.begin() + i); + std::vector actual(decoded_output); - CHECK_EQUAL(expected, actual); - CHECK_EQUAL(codec::encoded_size(i), size); + CHECK_TRUE(received_final_block); + CHECK_EQUAL(expected.size(), actual.size()); + CHECK_TRUE(std::equal(expected.begin(), expected.end(), actual.begin())); + CHECK_TRUE(codec_larger_buffer::safe_output_buffer_size(encoded[i].size()) >= decoded_output.size()); } } //************************************************************************* - TEST(test_encode_unsigned_char_pointer_size_to_etl_back_inserter) + TEST(test_decode_pointer_size_multi_pass_with_callback) { - codec b64; - - 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(codec::encoded_size(i), size); - } - } - -#if ETL_USING_STL - //************************************************************************* - TEST(test_encode_unsigned_char_pointer_size_to_std_back_inserter) - { - codec b64; + codec b64(callback); for (size_t i = 0; i < 256; ++i) { - std::string actual; + decoded_output.clear(); + received_final_block = false; - auto size = b64.encode(input_data_unsigned_char.data(), i, - std::back_inserter(actual)); + auto start = encoded[i].data(); + auto length = encoded[i].size(); - std::string expected(encoded[i]); + while (length >= 5) + { + b64.decode(start, 5); + length -= 5; + start += 5; + } - CHECK_EQUAL(expected, actual); - CHECK_EQUAL(codec::encoded_size(i), size); + if (length > 0) + { + b64.decode(start, length); + } + + CHECK_FALSE(received_final_block); + b64.flush(); + CHECK_TRUE(received_final_block); + + std::vector expected(input_data.begin(), input_data.begin() + i); + std::vector actual(decoded_output); + + CHECK_TRUE(received_final_block); + CHECK_EQUAL(expected.size(), actual.size()); + CHECK_TRUE(std::equal(expected.begin(), expected.end(), actual.begin())); + CHECK_TRUE(codec::safe_output_buffer_size(encoded[i].size()) >= decoded_output.size()); } } -#endif //************************************************************************* - TEST(test_encode_unsigned_char_pointer_pointer) + TEST(test_decode_pointer_size_multi_pass_with_callback_and_larger_buffer) { - codec b64; - std::array encoded_output; + codec_larger_buffer b64(callback); for (size_t i = 0; i < 256; ++i) { - encoded_output.fill(0); + decoded_output.clear(); + received_final_block = false; - auto size = b64.encode(input_data_unsigned_char.data(), input_data_unsigned_char.data() + i, - encoded_output.data(), encoded_output.data() + encoded_output.size()); + auto start = encoded[i].data(); + auto length = encoded[i].size(); - std::string expected(encoded[i]); - std::string actual(encoded_output.data(), size); + while (length >= 5) + { + b64.decode(start, 5); + length -= 5; + start += 5; + } - CHECK_EQUAL(expected, actual); - CHECK_EQUAL(codec::encoded_size(i), size); + if (length > 0) + { + b64.decode(start, length); + } + + CHECK_FALSE(received_final_block); + b64.flush(); + CHECK_TRUE(received_final_block); + + std::vector expected(input_data.begin(), input_data.begin() + i); + std::vector actual(decoded_output); + + CHECK_TRUE(received_final_block); + CHECK_EQUAL(expected.size(), actual.size()); + CHECK_TRUE(std::equal(expected.begin(), expected.end(), actual.begin())); + CHECK_TRUE(codec::safe_output_buffer_size(encoded[i].size()) >= decoded_output.size()); } } //************************************************************************* - TEST(test_encode_unsigned_char_pointer_pointer_no_output_end_pointer) + TEST(test_decode_pointer_pointer_single_pass_with_callback) { - codec b64; - 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(codec::encoded_size(i), size); - } - } - - //************************************************************************* - TEST(test_encode_int8_t_pointer_size) - { - codec b64; - 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(codec::encoded_size(i), size); - } - } - - //************************************************************************* - TEST(test_encode_int8_t_pointer_size_no_output_length) - { - codec b64; - 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(codec::encoded_size(i), size); - } - } - - //************************************************************************* - TEST(test_encode_int8_t_pointer_size_to_etl_back_inserter) - { - codec b64; + codec b64(callback); for (size_t i = 0; i < 256; ++i) { - std::string actual; + decoded_output.clear(); + received_final_block = false; - auto size = b64.encode(input_data_int8_t.data(), i, - etl::back_inserter(actual)); + b64.decode_final(encoded[i].begin(), encoded[i].end()); - std::string expected(encoded[i]); + std::vector expected(input_data.begin(), input_data.begin() + i); + std::vector actual(decoded_output); - CHECK_EQUAL(expected, actual); - CHECK_EQUAL(codec::encoded_size(i), size); - } - } - -#if ETL_USING_STL - //************************************************************************* - TEST(test_encode_int8_t_pointer_size_to_std_back_inserter) - { - codec b64; - - 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(codec::encoded_size(i), size); - } - } -#endif - - //************************************************************************* - TEST(test_encode_int8_t_pointer_pointer) - { - codec b64; - 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(codec::encoded_size(i), size); + CHECK_TRUE(received_final_block); + CHECK_EQUAL(expected.size(), actual.size()); + CHECK_TRUE(std::equal(expected.begin(), expected.end(), actual.begin())); + CHECK_TRUE(codec::safe_output_buffer_size(encoded[i].size()) >= decoded_output.size()); } } //************************************************************************* - TEST(test_encode_int8_t_pointer_pointer_no_end_pointer) + TEST(test_decode_pointer_pointer_single_pass_with_callback_and_larger_buffer) { - codec b64; - - std::array encoded_output; + codec_larger_buffer b64(callback); for (size_t i = 0; i < 256; ++i) { - encoded_output.fill(0); + decoded_output.clear(); + received_final_block = false; - auto size = b64.encode(input_data_int8_t.data(), input_data_int8_t.data() + i, - encoded_output.data()); + b64.decode_final(encoded[i].begin(), encoded[i].end()); - std::string expected(encoded[i]); - std::string actual(encoded_output.data(), size); + std::vector expected(input_data.begin(), input_data.begin() + i); + std::vector actual(decoded_output); - CHECK_EQUAL(expected, actual); - CHECK_EQUAL(codec::encoded_size(i), size); + CHECK_TRUE(received_final_block); + CHECK_EQUAL(expected.size(), actual.size()); + CHECK_TRUE(std::equal(expected.begin(), expected.end(), actual.begin())); + CHECK_TRUE(codec_larger_buffer::safe_output_buffer_size(encoded[i].size()) >= decoded_output.size()); + } + } + + //************************************************************************* + TEST(test_decode_pointer_pointer_multi_pass_with_callback) + { + codec b64(callback); + + for (size_t i = 0; i < 256; ++i) + { + decoded_output.clear(); + received_final_block = false; + + auto start = encoded[i].data(); + auto length = encoded[i].size(); + + while (length >= 5) + { + b64.decode(start, 5); + length -= 5; + start += 5; + } + + if (length > 0) + { + b64.decode(start, start + length); + } + + CHECK_FALSE(received_final_block); + b64.flush(); + CHECK_TRUE(received_final_block); + + std::vector expected(input_data.begin(), input_data.begin() + i); + std::vector actual(decoded_output); + + CHECK_TRUE(received_final_block); + CHECK_EQUAL(expected.size(), actual.size()); + CHECK_TRUE(std::equal(expected.begin(), expected.end(), actual.begin())); + CHECK_TRUE(codec::safe_output_buffer_size(encoded[i].size()) >= decoded_output.size()); + } + } + + //************************************************************************* + TEST(test_decode_pointer_pointer_multi_pass_with_callback_and_larger_buffer) + { + codec_larger_buffer b64(callback); + + for (size_t i = 0; i < 256; ++i) + { + decoded_output.clear(); + received_final_block = false; + + auto start = encoded[i].data(); + auto length = encoded[i].size(); + + while (length >= 5) + { + b64.decode(start, 5); + length -= 5; + start += 5; + } + + if (length > 0) + { + b64.decode(start, start + length); + } + + CHECK_FALSE(received_final_block); + b64.flush(); + CHECK_TRUE(received_final_block); + + std::vector expected(input_data.begin(), input_data.begin() + i); + std::vector actual(decoded_output); + + CHECK_TRUE(received_final_block); + CHECK_EQUAL(expected.size(), actual.size()); + CHECK_TRUE(std::equal(expected.begin(), expected.end(), actual.begin())); + CHECK_TRUE(codec::safe_output_buffer_size(encoded[i].size()) >= decoded_output.size()); + } + } + + //************************************************************************* + TEST(test_decode_multi_pass_by_char_with_callback) + { + codec b64(callback); + + for (size_t i = 0; i < 256; ++i) + { + decoded_output.clear(); + received_final_block = false; + + auto start = encoded[i].data(); + auto length = encoded[i].size(); + + while (length--) + { + b64.decode(*start++); + } + + CHECK_FALSE(received_final_block); + b64.flush(); + CHECK_TRUE(received_final_block); + + std::vector expected(input_data.begin(), input_data.begin() + i); + std::vector actual(decoded_output); + + CHECK_TRUE(received_final_block); + CHECK_EQUAL(expected.size(), actual.size()); + CHECK_TRUE(std::equal(expected.begin(), expected.end(), actual.begin())); + CHECK_TRUE(codec::safe_output_buffer_size(encoded[i].size()) >= decoded_output.size()); + } + } + + //************************************************************************* + TEST(test_decode_multi_pass_by_char_with_callback_and_larger_buffer) + { + codec_larger_buffer b64(callback); + + for (size_t i = 0; i < 256; ++i) + { + decoded_output.clear(); + received_final_block = false; + + auto start = encoded[i].data(); + auto length = encoded[i].size(); + + while (length--) + { + b64.decode(*start++); + } + + CHECK_FALSE(received_final_block); + b64.flush(); + CHECK_TRUE(received_final_block); + + std::vector expected(input_data.begin(), input_data.begin() + i); + std::vector actual(decoded_output); + + CHECK_TRUE(received_final_block); + CHECK_EQUAL(expected.size(), actual.size()); + CHECK_TRUE(std::equal(expected.begin(), expected.end(), actual.begin())); + CHECK_TRUE(codec::safe_output_buffer_size(encoded[i].size()) >= decoded_output.size()); + } + } + + //************************************************************************* + TEST(test_decode_multi_pass_blocks_with_no_callback_and_full_size_buffer) + { + codec_full_buffer b64; + + for (size_t i = 4; i < 256; ++i) + { + b64.restart(); + + auto start = encoded[i].data(); + auto length = encoded[i].size(); + + while (length >= 5) + { + b64.decode(start, 5); + length -= 5; + start += 5; + } + + if (length > 0) + { + b64.decode(start, length); + } + + b64.flush(); + + std::vector expected(input_data.begin(), input_data.begin() + i); + std::vector actual(b64.begin(), b64.end()); + + CHECK_EQUAL(expected.size(), actual.size()); + CHECK_TRUE(std::equal(expected.begin(), expected.end(), actual.begin())); + CHECK_TRUE(codec::safe_output_buffer_size(encoded[i].size()) >= b64.size()); } } //************************************************************************* #if ETL_USING_CPP14 template - constexpr auto GetConstexprBase64(const etl::array input) noexcept + constexpr auto GetConstexprBase64(const etl::array input) noexcept { + etl::array output{ 0 }; + + using codec = etl::base64_rfc4648_decoder; + codec b64; - - constexpr size_t encoded_size = codec::encoded_size(Size); - etl::array output{ 0 }; - - b64.encode(input.begin(), Size, - output._buffer, encoded_size); + b64.decode_final(input.begin(), input.end()); + etl::copy(b64.begin(), b64.end(), output.begin()); return output; } - TEST(test_encode_int8_t_constexpr) + TEST(test_encode_constexpr) { - constexpr etl::array input = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + constexpr etl::array input = { 'A', 'A', 'E', 'C' ,'A' ,'w', 'Q', 'F', 'B', 'g', 'c', 'I', 'C', 'Q' }; constexpr auto output{ GetConstexprBase64(input) }; - std::string expected("AAECAwQFBgcICQ"); - std::string actual(output.data(), output.size()); + std::vector expected = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + std::vector actual(output.begin(), output.end()); - CHECK_EQUAL(expected, actual); - CHECK_EQUAL(codec::encoded_size(10), output.size()); + CHECK_TRUE(std::equal(expected.begin(), expected.end(), actual.begin())); + CHECK_TRUE(codec::safe_output_buffer_size(14) >= output.size()); } #endif - //************************************************************************* - TEST(test_encode_overflow) - { - codec b64; - 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) - { - codec b64; - 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, codec::decoded_size(encoded[i].data(), encoded[i].size())); - CHECK_EQUAL(i, decoded_size); - } - } - - //************************************************************************* - TEST(test_decode_unsigned_char_pointer_size_no_end_pointer) - { - codec b64; - 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, codec::decoded_size(encoded[i].data(), encoded[i].size())); - CHECK_EQUAL(i, decoded_size); - } - } - - //************************************************************************* - TEST(test_decode_unsigned_char_pointer_pointer) - { - codec b64; - 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, codec::decoded_size(encoded[i].data(), encoded[i].size())); - CHECK_EQUAL(i, decoded_size); - } - } - - //************************************************************************* - TEST(test_decode_unsigned_char_pointer_pointer_no_end_pointer) - { - codec b64; - 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, codec::decoded_size(encoded[i].data(), encoded[i].size())); - CHECK_EQUAL(i, decoded_size); - } - } - - //************************************************************************* - TEST(test_decode_int8_t_pointer_size) - { - codec b64; - 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, codec::decoded_size(encoded[i].data(), encoded[i].size())); - CHECK_EQUAL(i, decoded_size); - } - } - - //************************************************************************* - TEST(test_decode_int8_t_pointer_size_etl_back_inserter) - { - codec b64; - 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, codec::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) - { - codec b64; - 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, codec::decoded_size(encoded[i].data(), encoded[i].size())); - CHECK_EQUAL(i, decoded_size); - } - } -#endif - - //************************************************************************* - TEST(test_decode_int8_t_pointer_size_no_output_size) - { - codec b64; - 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, codec::decoded_size(encoded[i].data(), encoded[i].size())); - CHECK_EQUAL(i, decoded_size); - } - } - - //************************************************************************* - TEST(test_decode_int8_t_pointer_pointer) - { - codec b64; - 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, codec::decoded_size(encoded[i].data(), encoded[i].size())); - CHECK_EQUAL(i, decoded_size); - } - } - - //************************************************************************* - TEST(test_decode_int8_t_pointer_pointer_etl_back_inserter) - { - codec b64; - 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, codec::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) - { - codec b64; - 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, codec::decoded_size(encoded[i].data(), encoded[i].size())); - CHECK_EQUAL(i, decoded_size); - } - } -#endif - - //************************************************************************* - TEST(test_decode_int8_t_pointer_pointer_no_end_pointer) - { - codec b64; - 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, codec::decoded_size(encoded[i].data(), encoded[i].size())); - CHECK_EQUAL(i, decoded_size); - } - } - //************************************************************************* TEST(test_decode_overflow) { codec b64; - std::array decoded_output{ 0 }; - CHECK_THROW((b64.decode(encoded[10].data(), encoded[10].size(), - decoded_output.data(), decoded_output.size())), etl::base64_overflow); +#if ETL_USING_EXCEPTIONS + CHECK_THROW((b64.decode(encoded[10].data(), encoded[10].size())), etl::base64_overflow); +#else + CHECK_FALSE(b64.decode(encoded[10].data(), encoded[10].size()); + CHECK_TRUE(b64.error()); +#endif } //************************************************************************* TEST(test_decode_invalid_character) { - codec b64; - std::array decoded_output{ 0 }; + codec_larger_buffer b64; std::string invalid_chararacter("OycDQ#37KA"); - CHECK_THROW((b64.decode(invalid_chararacter.data(), invalid_chararacter.size(), - decoded_output.data(), decoded_output.size())), etl::base64_invalid_character); - - std::string invalid_length("OycDQy37K"); - - CHECK_THROW((b64.decode(invalid_length.data(), invalid_length.size(), - decoded_output.data(), decoded_output.size())), etl::base64_invalid_decode_input_length); +#if ETL_USING_EXCEPTIONS + CHECK_THROW((b64.decode(invalid_chararacter.data(), invalid_chararacter.size())), etl::base64_invalid_data); +#else + CHECK_FALSE(b64.decode(invalid_chararacter.data(), invalid_chararacter.size())); + CHECK_TRUE(b64.error()); +#endif } //************************************************************************* - //TEST(test_decoded_size) - //{ - // codec b64; + TEST(test_decode_invalid_padding) + { + codec_larger_buffer b64; - // for (size_t i = 0; i < 256; ++i) - // { - // size_t length = codec::decoded_size(encoded[i].size()); + std::string invalid_chararacter("OycD=y37KA"); - // CHECK_EQUAL(length, codec::decoded_size(encoded[i].data() + encoded[i].size())); - // } - //} +#if ETL_USING_EXCEPTIONS + CHECK_THROW((b64.decode(invalid_chararacter.data(), invalid_chararacter.size())), etl::base64_invalid_data); +#else + CHECK_FALSE(b64.decode(invalid_chararacter.data(), invalid_chararacter.size())); + CHECK_TRUE(b64.error()); +#endif + } }; } diff --git a/test/test_base64_RFC4648_decoder_with_padding.cpp b/test/test_base64_RFC4648_decoder_with_padding.cpp new file mode 100644 index 00000000..43229afb --- /dev/null +++ b/test/test_base64_RFC4648_decoder_with_padding.cpp @@ -0,0 +1,798 @@ +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Copyright(c) 2024 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_decoder.h" + +#include "etl/string.h" +#include "etl/vector.h" + +#include +#include +#include +#include + +#if ETL_USING_STL +#include +#endif + +#include "etl/integral_limits.h" + +//***************************************************************************** +// Encode/decode using RFC-4648 with no padding +//***************************************************************************** + +namespace +{ + using codec = etl::base64_rfc4648_padding_decoder ; + using codec_larger_buffer = etl::base64_rfc4648_padding_decoder; +#if ETL_USING_CPP14 + using codec_full_buffer = etl::base64_rfc4648_padding_decoder::safe_output_buffer_size(344)>; +#else + using codec_full_buffer = etl::base64_rfc4648_padding_decoder<256>; +#endif + + std::vector decoded_output; + bool received_final_block = false; + + codec::callback_type callback = [](const codec::span_type& sp) + { + if (sp.empty()) + { + received_final_block = true; + } + else + { + std::copy(sp.begin(), sp.end(), std::back_inserter(decoded_output)); + } + }; + + std::array input_data = + { + 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 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", + "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" + }; + + SUITE(test_base64_rfc4648_with_no_padding) + { + //************************************************************************* + TEST(test_basic_information) + { + codec_full_buffer b64; + + CHECK_EQUAL(etl::base64::Encoding::RFC_4648_PADDING, codec_full_buffer::Encoding); + CHECK_EQUAL("RFC_4648_PADDING", codec_full_buffer::Encoding.c_str()); + } + + //************************************************************************* + TEST(test_check_encode_safe_buffer_sizes) + { + for (size_t i = 0; i < 256; ++i) + { + size_t minimum_size = i; + size_t safe_size = codec::safe_output_buffer_size(encoded[i].size()); + + CHECK_TRUE(safe_size >= minimum_size); + CHECK_TRUE((safe_size - minimum_size) <= 2U); + } + } + + //************************************************************************* + TEST(test_decode_pointer_size_single_pass_with_callback) + { + codec b64(callback); + + for (size_t i = 0; i < 256; ++i) + { + decoded_output.clear(); + received_final_block = false; + + b64.decode_final(encoded[i].data(), encoded[i].size()); + + std::vector expected(input_data.begin(), input_data.begin() + i); + std::vector actual(decoded_output); + + CHECK_TRUE(received_final_block); + CHECK_EQUAL(expected.size(), actual.size()); + CHECK_TRUE(std::equal(expected.begin(), expected.end(), actual.begin())); + CHECK_TRUE(codec::safe_output_buffer_size(encoded[i].size()) >= decoded_output.size()); + } + } + + //************************************************************************* + TEST(test_decode_pointer_size_single_pass_with_callback_and_larger_buffer) + { + codec_larger_buffer b64(callback); + + for (size_t i = 0; i < 256; ++i) + { + decoded_output.clear(); + received_final_block = false; + + b64.decode_final(encoded[i].data(), encoded[i].size()); + + std::vector expected(input_data.begin(), input_data.begin() + i); + std::vector actual(decoded_output); + + CHECK_TRUE(received_final_block); + CHECK_EQUAL(expected.size(), actual.size()); + CHECK_TRUE(std::equal(expected.begin(), expected.end(), actual.begin())); + CHECK_TRUE(codec_larger_buffer::safe_output_buffer_size(encoded[i].size()) >= decoded_output.size()); + } + } + + //************************************************************************* + TEST(test_decode_pointer_size_multi_pass_with_callback) + { + codec b64(callback); + + for (size_t i = 0; i < 256; ++i) + { + decoded_output.clear(); + received_final_block = false; + + auto start = encoded[i].data(); + auto length = encoded[i].size(); + + while (length >= 5) + { + b64.decode(start, 5); + length -= 5; + start += 5; + } + + if (length > 0) + { + b64.decode(start, length); + } + + CHECK_FALSE(received_final_block); + b64.flush(); + CHECK_TRUE(received_final_block); + + std::vector expected(input_data.begin(), input_data.begin() + i); + std::vector actual(decoded_output); + + CHECK_TRUE(received_final_block); + CHECK_EQUAL(expected.size(), actual.size()); + CHECK_TRUE(std::equal(expected.begin(), expected.end(), actual.begin())); + CHECK_TRUE(codec::safe_output_buffer_size(encoded[i].size()) >= decoded_output.size()); + } + } + + //************************************************************************* + TEST(test_decode_pointer_size_multi_pass_with_callback_and_larger_buffer) + { + codec_larger_buffer b64(callback); + + for (size_t i = 0; i < 256; ++i) + { + decoded_output.clear(); + received_final_block = false; + + auto start = encoded[i].data(); + auto length = encoded[i].size(); + + while (length >= 5) + { + b64.decode(start, 5); + length -= 5; + start += 5; + } + + if (length > 0) + { + b64.decode(start, length); + } + + CHECK_FALSE(received_final_block); + b64.flush(); + CHECK_TRUE(received_final_block); + + std::vector expected(input_data.begin(), input_data.begin() + i); + std::vector actual(decoded_output); + + CHECK_TRUE(received_final_block); + CHECK_EQUAL(expected.size(), actual.size()); + CHECK_TRUE(std::equal(expected.begin(), expected.end(), actual.begin())); + CHECK_TRUE(codec::safe_output_buffer_size(encoded[i].size()) >= decoded_output.size()); + } + } + + //************************************************************************* + TEST(test_decode_pointer_pointer_single_pass_with_callback) + { + codec b64(callback); + + for (size_t i = 0; i < 256; ++i) + { + decoded_output.clear(); + received_final_block = false; + + b64.decode_final(encoded[i].begin(), encoded[i].end()); + + std::vector expected(input_data.begin(), input_data.begin() + i); + std::vector actual(decoded_output); + + CHECK_TRUE(received_final_block); + CHECK_EQUAL(expected.size(), actual.size()); + CHECK_TRUE(std::equal(expected.begin(), expected.end(), actual.begin())); + CHECK_TRUE(codec::safe_output_buffer_size(encoded[i].size()) >= decoded_output.size()); + } + } + + //************************************************************************* + TEST(test_decode_pointer_pointer_single_pass_with_callback_and_larger_buffer) + { + codec_larger_buffer b64(callback); + + for (size_t i = 0; i < 256; ++i) + { + decoded_output.clear(); + received_final_block = false; + + b64.decode_final(encoded[i].begin(), encoded[i].end()); + + std::vector expected(input_data.begin(), input_data.begin() + i); + std::vector actual(decoded_output); + + CHECK_TRUE(received_final_block); + CHECK_EQUAL(expected.size(), actual.size()); + CHECK_TRUE(std::equal(expected.begin(), expected.end(), actual.begin())); + CHECK_TRUE(codec_larger_buffer::safe_output_buffer_size(encoded[i].size()) >= decoded_output.size()); + } + } + + //************************************************************************* + TEST(test_decode_pointer_pointer_multi_pass_with_callback) + { + codec b64(callback); + + for (size_t i = 0; i < 256; ++i) + { + decoded_output.clear(); + received_final_block = false; + + auto start = encoded[i].data(); + auto length = encoded[i].size(); + + while (length >= 5) + { + b64.decode(start, 5); + length -= 5; + start += 5; + } + + if (length > 0) + { + b64.decode(start, start + length); + } + + CHECK_FALSE(received_final_block); + b64.flush(); + CHECK_TRUE(received_final_block); + + std::vector expected(input_data.begin(), input_data.begin() + i); + std::vector actual(decoded_output); + + CHECK_TRUE(received_final_block); + CHECK_EQUAL(expected.size(), actual.size()); + CHECK_TRUE(std::equal(expected.begin(), expected.end(), actual.begin())); + CHECK_TRUE(codec::safe_output_buffer_size(encoded[i].size()) >= decoded_output.size()); + } + } + + //************************************************************************* + TEST(test_decode_pointer_pointer_multi_pass_with_callback_and_larger_buffer) + { + codec_larger_buffer b64(callback); + + for (size_t i = 0; i < 256; ++i) + { + decoded_output.clear(); + received_final_block = false; + + auto start = encoded[i].data(); + auto length = encoded[i].size(); + + while (length >= 5) + { + b64.decode(start, 5); + length -= 5; + start += 5; + } + + if (length > 0) + { + b64.decode(start, start + length); + } + + CHECK_FALSE(received_final_block); + b64.flush(); + CHECK_TRUE(received_final_block); + + std::vector expected(input_data.begin(), input_data.begin() + i); + std::vector actual(decoded_output); + + CHECK_TRUE(received_final_block); + CHECK_EQUAL(expected.size(), actual.size()); + CHECK_TRUE(std::equal(expected.begin(), expected.end(), actual.begin())); + CHECK_TRUE(codec::safe_output_buffer_size(encoded[i].size()) >= decoded_output.size()); + } + } + + //************************************************************************* + TEST(test_decode_multi_pass_by_char_with_callback) + { + codec b64(callback); + + for (size_t i = 0; i < 256; ++i) + { + decoded_output.clear(); + received_final_block = false; + + auto start = encoded[i].data(); + auto length = encoded[i].size(); + + while (length--) + { + b64.decode(*start++); + } + + CHECK_FALSE(received_final_block); + b64.flush(); + CHECK_TRUE(received_final_block); + + std::vector expected(input_data.begin(), input_data.begin() + i); + std::vector actual(decoded_output); + + CHECK_TRUE(received_final_block); + CHECK_EQUAL(expected.size(), actual.size()); + CHECK_TRUE(std::equal(expected.begin(), expected.end(), actual.begin())); + CHECK_TRUE(codec::safe_output_buffer_size(encoded[i].size()) >= decoded_output.size()); + } + } + + //************************************************************************* + TEST(test_decode_multi_pass_by_char_with_callback_and_larger_buffer) + { + codec_larger_buffer b64(callback); + + for (size_t i = 0; i < 256; ++i) + { + decoded_output.clear(); + received_final_block = false; + + auto start = encoded[i].data(); + auto length = encoded[i].size(); + + while (length--) + { + b64.decode(*start++); + } + + CHECK_FALSE(received_final_block); + b64.flush(); + CHECK_TRUE(received_final_block); + + std::vector expected(input_data.begin(), input_data.begin() + i); + std::vector actual(decoded_output); + + CHECK_TRUE(received_final_block); + CHECK_EQUAL(expected.size(), actual.size()); + CHECK_TRUE(std::equal(expected.begin(), expected.end(), actual.begin())); + CHECK_TRUE(codec::safe_output_buffer_size(encoded[i].size()) >= decoded_output.size()); + } + } + + //************************************************************************* + TEST(test_decode_multi_pass_blocks_with_no_callback_and_full_size_buffer) + { + codec_full_buffer b64; + + for (size_t i = 4; i < 256; ++i) + { + b64.restart(); + + auto start = encoded[i].data(); + auto length = encoded[i].size(); + + while (length >= 5) + { + b64.decode(start, 5); + length -= 5; + start += 5; + } + + if (length > 0) + { + b64.decode(start, length); + } + + b64.flush(); + + std::vector expected(input_data.begin(), input_data.begin() + i); + std::vector actual(b64.begin(), b64.end()); + + CHECK_EQUAL(expected.size(), actual.size()); + CHECK_TRUE(std::equal(expected.begin(), expected.end(), actual.begin())); + CHECK_TRUE(codec::safe_output_buffer_size(encoded[i].size()) >= b64.size()); + } + } + + //************************************************************************* +#if ETL_USING_CPP14 + template + constexpr auto GetConstexprBase64(const etl::array input) noexcept + { + etl::array output{ 0 }; + + using codec = etl::base64_rfc4648_padding_decoder; + + codec b64; + b64.decode_final(input.begin(), input.end()); + etl::copy(b64.begin(), b64.end(), output.begin()); + + return output; + } + + TEST(test_encode_constexpr) + { + constexpr etl::array input = { 'A', 'A', 'E', 'C' ,'A' ,'w', 'Q', 'F', 'B', 'g', 'c', 'I', 'C', 'Q' }; + + constexpr auto output{ GetConstexprBase64(input) }; + + std::vector expected = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + std::vector actual(output.begin(), output.end()); + + CHECK_TRUE(std::equal(expected.begin(), expected.end(), actual.begin())); + CHECK_TRUE(codec::safe_output_buffer_size(14) >= output.size()); + } +#endif + + //************************************************************************* + TEST(test_decode_overflow) + { + codec b64; + +#if ETL_USING_EXCEPTIONS + CHECK_THROW((b64.decode(encoded[10].data(), encoded[10].size())), etl::base64_overflow); +#else + CHECK_FALSE(b64.decode(encoded[10].data(), encoded[10].size()); + CHECK_TRUE(b64.error()); +#endif + } + + //************************************************************************* + TEST(test_decode_invalid_character) + { + codec_larger_buffer b64; + + std::string invalid_chararacter("OycDQ#37KA"); + +#if ETL_USING_EXCEPTIONS + CHECK_THROW((b64.decode(invalid_chararacter.data(), invalid_chararacter.size())), etl::base64_invalid_data); +#else + CHECK_FALSE(b64.decode(invalid_chararacter.data(), invalid_chararacter.size())); + CHECK_TRUE(b64.error()); +#endif + } + + //************************************************************************* + TEST(test_decode_invalid_padding) + { + codec_larger_buffer b64; + + std::string invalid_chararacter("OycD=y37KA=="); + +#if ETL_USING_EXCEPTIONS + CHECK_THROW((b64.decode(invalid_chararacter.data(), invalid_chararacter.size())), etl::base64_invalid_data); +#else + CHECK_FALSE(b64.decode(invalid_chararacter.data(), invalid_chararacter.size())); + CHECK_TRUE(b64.error()); +#endif + } + }; +} + diff --git a/test/test_base64_RFC2152.cpp b/test/test_base64_RFC4648_encoder_with_no_padding.cpp similarity index 74% rename from test/test_base64_RFC2152.cpp rename to test/test_base64_RFC4648_encoder_with_no_padding.cpp index d590b6d8..21b22579 100644 --- a/test/test_base64_RFC2152.cpp +++ b/test/test_base64_RFC4648_encoder_with_no_padding.cpp @@ -28,7 +28,7 @@ SOFTWARE. #include "unit_test_framework.h" -#include "etl/base64.h" +#include "etl/base64_encoder.h" #include "etl/string.h" #include "etl/vector.h" @@ -45,14 +45,36 @@ SOFTWARE. #include "etl/integral_limits.h" //***************************************************************************** -// Encode/decode using RFC-2152 +// Encode/decode using RFC-4648 with no padding +// Using minimum buffer size, with callback. //***************************************************************************** namespace { - using codec = etl::base64_rfc2152; + using codec = etl::base64_rfc4648_encoder; + using codec_larger_buffer = etl::base64_rfc4648_encoder; +#if ETL_USING_CPP14 + using codec_full_buffer = etl::base64_rfc4648_encoder::safe_output_buffer_size(256)>; +#else + using codec_full_buffer = etl::base64_rfc4648_encoder<344>; +#endif - std::array input_data_unsigned_char = + std::string encoded_output; + bool received_final_block = false; + + codec::callback_type callback = [](const codec::span_type& sp) + { + if (sp.empty()) + { + received_final_block = true; + } + else + { + std::copy(sp.begin(), sp.end(), std::back_inserter(encoded_output)); + } + }; + + std::array input_data = { 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, @@ -72,26 +94,6 @@ namespace 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 = { "", @@ -353,254 +355,355 @@ namespace "OycDQy37KCphrrxJcTIBFWlcXvXVm96lV8nBfYDeTIHAzyrRhlbVcTfrgDLf5N+27j/cebMXjnZljpYhuYjRbdDd/9qoek31cXf9LvLkQHKMgwBvE3JT5GtwDjfKJc1oYsCrFMdZg9KCjJNtEyHACPltrIR4SYRva/sgO5xJ+06AaYIlhpXVTZHt0ncqJECK302ALc3VWiamcRVCDj+ycBQpH40jLsHqzvl+bN8co4QrJDWnY8gLH4u6Ub/pUYDSI7XRtFmufTAdABzYcGwWccdWCP6BrvvgktjbuVd8mctC7/yzVh7RQtMMGLPurxp3qFI8ns3eITQ+H7VU1/u0vQ" }; - SUITE(test_base64_rfc2152_with_no_padding) + SUITE(test_base64_rfc4648_with_no_padding) { //************************************************************************* - TEST(test_encode_unsigned_char_pointer_size) + TEST(test_basic_information) { - codec b64; - std::array encoded_output; + codec_full_buffer b64; + CHECK_EQUAL(etl::base64::Encoding::RFC_4648, codec_full_buffer::Encoding); + CHECK_EQUAL("RFC_4648", codec_full_buffer::Encoding.c_str()); + } + + //************************************************************************* + TEST(test_check_encode_safe_buffer_sizes) + { for (size_t i = 0; i < 256; ++i) { - encoded_output.fill(0); + size_t minimum_size = encoded[i].size(); + size_t safe_size = codec::safe_output_buffer_size(i); - 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(codec::encoded_size(i), size); + CHECK_TRUE(safe_size >= minimum_size); + CHECK_TRUE((safe_size - minimum_size) <= 2U); } } //************************************************************************* - TEST(test_encode_unsigned_char_pointer_size_no_output_length) + TEST(test_encode_pointer_size_single_pass_with_callback) { - codec b64; - std::array encoded_output; + codec b64(callback); for (size_t i = 0; i < 256; ++i) { - encoded_output.fill(0); + encoded_output.clear(); + received_final_block = false; - auto size = b64.encode(input_data_unsigned_char.data(), i, - encoded_output.data()); + b64.encode_final(input_data.data(), i); std::string expected(encoded[i]); - std::string actual(encoded_output.data(), size); + std::string actual(encoded_output); + CHECK_TRUE(received_final_block); CHECK_EQUAL(expected, actual); - CHECK_EQUAL(codec::encoded_size(i), size); + CHECK_TRUE(codec::safe_output_buffer_size(i) >= encoded_output.size()); } } //************************************************************************* - TEST(test_encode_unsigned_char_pointer_size_to_etl_back_inserter) + TEST(test_encode_pointer_size_single_pass_with_callback_and_larger_buffer) { - codec b64; + codec_larger_buffer b64(callback); - for (size_t i = 0; i < 256; ++i) + for (size_t i = 0; i < 256; ++i) { - std::string actual; + encoded_output.clear(); + received_final_block = false; - auto size = b64.encode(input_data_unsigned_char.data(), i, - etl::back_inserter(actual)); + b64.encode_final(input_data.data(), i); std::string expected(encoded[i]); + std::string actual(encoded_output); + + CHECK_TRUE(received_final_block); + CHECK_EQUAL(expected, actual); + CHECK_TRUE(codec::safe_output_buffer_size(i) >= encoded_output.size()); + } + } + + //************************************************************************* + TEST(test_encode_pointer_size_multi_pass_blocks_with_callback) + { + codec b64(callback); + + for (size_t i = 0; i < 256; ++i) + { + encoded_output.clear(); + received_final_block = false; + + auto start = input_data.data(); + auto length = i; + while (length >= 5) + { + b64.encode(start, 5); + length -= 5; + start += 5; + } + + if (length > 0) + { + b64.encode(start, length); + } + + CHECK_FALSE(received_final_block); + b64.flush(); + CHECK_TRUE(received_final_block); + + std::string expected(encoded[i]); + std::string actual(encoded_output); + CHECK_EQUAL(expected, actual); - CHECK_EQUAL(codec::encoded_size(i), size); + CHECK_TRUE(codec::safe_output_buffer_size(i) >= encoded_output.size()); } } -#if ETL_USING_STL //************************************************************************* - TEST(test_encode_unsigned_char_pointer_size_to_std_back_inserter) + TEST(test_encode_pointer_size_multi_pass_blocks_with_callback_larger_buffer) { - codec b64; + codec_larger_buffer b64(callback); for (size_t i = 0; i < 256; ++i) { - std::string actual; + encoded_output.clear(); + received_final_block = false; - auto size = b64.encode(input_data_unsigned_char.data(), i, - std::back_inserter(actual)); + auto start = input_data.data(); + auto length = i; + + while (length >= 5) + { + b64.encode(start, 5); + length -= 5; + start += 5; + } + + if (length > 0) + { + b64.encode(start, length); + } + + CHECK_FALSE(received_final_block); + b64.flush(); + CHECK_TRUE(received_final_block); std::string expected(encoded[i]); + std::string actual(encoded_output); CHECK_EQUAL(expected, actual); - CHECK_EQUAL(codec::encoded_size(i), size); + CHECK_TRUE(codec::safe_output_buffer_size(i) >= encoded_output.size()); } } -#endif //************************************************************************* - TEST(test_encode_unsigned_char_pointer_pointer) + TEST(test_encode_pointer_pointer_single_pass_with_callback) { - codec b64; - std::array encoded_output; + codec b64(callback); for (size_t i = 0; i < 256; ++i) { - encoded_output.fill(0); + encoded_output.clear(); + received_final_block = false; - auto size = b64.encode(input_data_unsigned_char.data(), input_data_unsigned_char.data() + i, - encoded_output.data(), encoded_output.data() + encoded_output.size()); + b64.encode_final(input_data.data(), input_data.data() + i); std::string expected(encoded[i]); - std::string actual(encoded_output.data(), size); + std::string actual(encoded_output); + CHECK_TRUE(received_final_block); CHECK_EQUAL(expected, actual); - CHECK_EQUAL(codec::encoded_size(i), size); + CHECK_TRUE(codec::safe_output_buffer_size(i) >= encoded_output.size()); } } //************************************************************************* - TEST(test_encode_unsigned_char_pointer_pointer_no_output_end_pointer) + TEST(test_encode_pointer_pointer_single_pass_with_callback_larger_buffer) { - codec b64; - 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(codec::encoded_size(i), size); - } - } - - //************************************************************************* - TEST(test_encode_int8_t_pointer_size) - { - codec b64; - 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(codec::encoded_size(i), size); - } - } - - //************************************************************************* - TEST(test_encode_int8_t_pointer_size_no_output_length) - { - codec b64; - 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(codec::encoded_size(i), size); - } - } - - //************************************************************************* - TEST(test_encode_int8_t_pointer_size_to_etl_back_inserter) - { - codec b64; + codec_larger_buffer b64(callback); for (size_t i = 0; i < 256; ++i) { - std::string actual; + encoded_output.clear(); + received_final_block = false; - auto size = b64.encode(input_data_int8_t.data(), i, - etl::back_inserter(actual)); + b64.encode_final(input_data.data(), input_data.data() + i); std::string expected(encoded[i]); + std::string actual(encoded_output); + CHECK_TRUE(received_final_block); CHECK_EQUAL(expected, actual); - CHECK_EQUAL(codec::encoded_size(i), size); - } - } - -#if ETL_USING_STL - //************************************************************************* - TEST(test_encode_int8_t_pointer_size_to_std_back_inserter) - { - codec b64; - - 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(codec::encoded_size(i), size); - } - } -#endif - - //************************************************************************* - TEST(test_encode_int8_t_pointer_pointer) - { - codec b64; - 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(codec::encoded_size(i), size); + CHECK_TRUE(codec::safe_output_buffer_size(i) >= encoded_output.size()); } } //************************************************************************* - TEST(test_encode_int8_t_pointer_pointer_no_end_pointer) + TEST(test_encode_pointer_pointer_multi_pass_blocks_with_callback) { - codec b64; - - std::array encoded_output; + codec b64(callback); for (size_t i = 0; i < 256; ++i) { - encoded_output.fill(0); + encoded_output.clear(); + received_final_block = false; - auto size = b64.encode(input_data_int8_t.data(), input_data_int8_t.data() + i, - encoded_output.data()); + auto start = input_data.data(); + auto length = i; + + while (length >= 5) + { + b64.encode(start, start + 5); + length -= 5; + start += 5; + } + + if (length > 0) + { + b64.encode(start, length); + } + + CHECK_FALSE(received_final_block); + b64.flush(); + CHECK_TRUE(received_final_block); std::string expected(encoded[i]); - std::string actual(encoded_output.data(), size); + std::string actual(encoded_output); CHECK_EQUAL(expected, actual); - CHECK_EQUAL(codec::encoded_size(i), size); + CHECK_TRUE(codec::safe_output_buffer_size(i) >= encoded_output.size()); + } + } + + //************************************************************************* + TEST(test_encode_pointer_pointer_multi_pass_blocks_with_callback_larger_buffer) + { + codec_larger_buffer b64(callback); + + for (size_t i = 0; i < 256; ++i) + { + encoded_output.clear(); + received_final_block = false; + + auto start = input_data.data(); + auto length = i; + + while (length >= 5) + { + b64.encode(start, start + 5); + length -= 5; + start += 5; + } + + if (length > 0) + { + b64.encode(start, length); + } + + CHECK_FALSE(received_final_block); + b64.flush(); + CHECK_TRUE(received_final_block); + + std::string expected(encoded[i]); + std::string actual(encoded_output); + + CHECK_EQUAL(expected, actual); + CHECK_TRUE(codec::safe_output_buffer_size(i) >= encoded_output.size()); + } + } + + //************************************************************************* + TEST(test_encode_multi_pass_by_char_with_callback) + { + codec b64(callback); + + for (size_t i = 0; i < 256; ++i) + { + encoded_output.clear(); + received_final_block = false; + + auto start = input_data.data(); + auto length = i; + + while (length--) + { + b64.encode(*start); + ++start; + } + + CHECK_FALSE(received_final_block); + b64.flush(); + CHECK_TRUE(received_final_block); + + std::string expected(encoded[i]); + std::string actual(encoded_output); + + CHECK_EQUAL(expected, actual); + CHECK_TRUE(codec::safe_output_buffer_size(i) >= encoded_output.size()); + } + } + + //************************************************************************* + TEST(test_encode_multi_pass_by_char_with_callback_larger_buffer) + { + codec_larger_buffer b64(callback); + + for (size_t i = 0; i < 256; ++i) + { + encoded_output.clear(); + received_final_block = false; + + auto start = input_data.data(); + auto length = i; + + while (length--) + { + b64.encode(*start); + ++start; + } + + CHECK_FALSE(received_final_block); + b64.flush(); + CHECK_TRUE(received_final_block); + + std::string expected(encoded[i]); + std::string actual(encoded_output); + + CHECK_EQUAL(expected, actual); + CHECK_TRUE(codec::safe_output_buffer_size(i) >= encoded_output.size()); + } + } + + //************************************************************************* + TEST(test_encode_multi_pass_blocks_with_no_callback_and_full_size_buffer) + { + codec_full_buffer b64; + + for (size_t i = 250; i < 256; ++i) + { + b64.restart(); + + auto start = input_data.data(); + auto length = i; + + while (length >= 5) + { + b64.encode(start, start + 5); + length -= 5; + start += 5; + } + + if (length > 0) + { + b64.encode(start, length); + } + + b64.flush(); + + std::string expected(encoded[i]); + std::string actual(b64.begin(), b64.end()); + + CHECK_EQUAL(expected, actual); + CHECK_TRUE(codec::safe_output_buffer_size(i) >= actual.size()); } } @@ -609,18 +712,18 @@ namespace template constexpr auto GetConstexprBase64(const etl::array input) noexcept { + etl::array output{ 0 }; + + using codec = etl::base64_rfc4648_encoder; + codec b64; - - constexpr size_t encoded_size = codec::encoded_size(Size); - etl::array output{ 0 }; - - b64.encode(input.begin(), Size, - output._buffer, encoded_size); + b64.encode_final(input.begin(), input.end()); + etl::copy(b64.begin(), b64.end(), output.begin()); return output; } - TEST(test_encode_int8_t_constexpr) + TEST(test_encode_constexpr) { constexpr etl::array input = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; @@ -630,7 +733,7 @@ namespace std::string actual(output.data(), output.size()); CHECK_EQUAL(expected, actual); - CHECK_EQUAL(codec::encoded_size(10), output.size()); + CHECK_TRUE(codec::safe_output_buffer_size(10) >= output.size()); } #endif @@ -638,276 +741,9 @@ namespace TEST(test_encode_overflow) { codec b64; - 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) - { - codec b64; - 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, codec::decoded_size(encoded[i].data(), encoded[i].size())); - CHECK_EQUAL(i, decoded_size); - } - } - - //************************************************************************* - TEST(test_decode_unsigned_char_pointer_size_no_end_pointer) - { - codec b64; - 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, codec::decoded_size(encoded[i].data(), encoded[i].size())); - CHECK_EQUAL(i, decoded_size); - } - } - - //************************************************************************* - TEST(test_decode_unsigned_char_pointer_pointer) - { - codec b64; - 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, codec::decoded_size(encoded[i].data(), encoded[i].size())); - CHECK_EQUAL(i, decoded_size); - } - } - - //************************************************************************* - TEST(test_decode_unsigned_char_pointer_pointer_no_end_pointer) - { - codec b64; - 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, codec::decoded_size(encoded[i].data(), encoded[i].size())); - CHECK_EQUAL(i, decoded_size); - } - } - - //************************************************************************* - TEST(test_decode_int8_t_pointer_size) - { - codec b64; - 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, codec::decoded_size(encoded[i].data(), encoded[i].size())); - CHECK_EQUAL(i, decoded_size); - } - } - - //************************************************************************* - TEST(test_decode_int8_t_pointer_size_etl_back_inserter) - { - codec b64; - 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, codec::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) - { - codec b64; - 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, codec::decoded_size(encoded[i].data(), encoded[i].size())); - CHECK_EQUAL(i, decoded_size); - } - } -#endif - - //************************************************************************* - TEST(test_decode_int8_t_pointer_size_no_output_size) - { - codec b64; - 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, codec::decoded_size(encoded[i].data(), encoded[i].size())); - CHECK_EQUAL(i, decoded_size); - } - } - - //************************************************************************* - TEST(test_decode_int8_t_pointer_pointer) - { - codec b64; - 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, codec::decoded_size(encoded[i].data(), encoded[i].size())); - CHECK_EQUAL(i, decoded_size); - } - } - - //************************************************************************* - TEST(test_decode_int8_t_pointer_pointer_etl_back_inserter) - { - codec b64; - 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, codec::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) - { - codec b64; - 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, codec::decoded_size(encoded[i].data(), encoded[i].size())); - CHECK_EQUAL(i, decoded_size); - } - } -#endif - - //************************************************************************* - TEST(test_decode_int8_t_pointer_pointer_no_end_pointer) - { - codec b64; - 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, codec::decoded_size(encoded[i].data(), encoded[i].size())); - CHECK_EQUAL(i, decoded_size); - } - } - - //************************************************************************* - TEST(test_decode_overflow) - { - codec b64; - 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) - { - codec b64; - std::array decoded_output{ 0 }; - - std::string invalid_chararacter("OycDQ#37KA"); - - CHECK_THROW((b64.decode(invalid_chararacter.data(), invalid_chararacter.size(), - decoded_output.data(), decoded_output.size())), etl::base64_invalid_character); - - std::string invalid_length("OycDQy37K"); - -#if ETL_USING_EXCEPTIONS - CHECK_THROW((b64.decode(invalid_length.data(), invalid_length.size(), - decoded_output.data(), decoded_output.size())), etl::base64_invalid_decode_input_length); -#else - size_t size = b64.decode(invalid_length.data(), invalid_length.size(), - decoded_output.data(), decoded_output.size()); - CHECK_EQUAL(size, codec::Invalid_Data); -#endif + CHECK_THROW((b64.encode(input_data.data(), 10)), etl::base64_overflow); + CHECK_TRUE(b64.overflow()); } }; } diff --git a/test/test_base64_RFC4648_with_padding.cpp b/test/test_base64_RFC4648_encoder_with_padding.cpp similarity index 74% rename from test/test_base64_RFC4648_with_padding.cpp rename to test/test_base64_RFC4648_encoder_with_padding.cpp index 34375ce1..56e9f822 100644 --- a/test/test_base64_RFC4648_with_padding.cpp +++ b/test/test_base64_RFC4648_encoder_with_padding.cpp @@ -5,7 +5,7 @@ Embedded Template Library. https://github.com/ETLCPP/etl https://www.etlcpp.com -Copyright(c) 2023 John Wellbelove +Copyright(c) 2024 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 @@ -28,7 +28,7 @@ SOFTWARE. #include "unit_test_framework.h" -#include "etl/base64.h" +#include "etl/base64_encoder.h" #include "etl/string.h" #include "etl/vector.h" @@ -45,14 +45,36 @@ SOFTWARE. #include "etl/integral_limits.h" //***************************************************************************** -// Ecode/decode using RFC-4648 with padding +// Encode/decode using RFC-4648 with padding +// Using minimum buffer size, with callback. //***************************************************************************** namespace { - using codec = etl::base64_rfc4648; + using codec = etl::base64_rfc4648_padding_encoder; + using codec_larger_buffer = etl::base64_rfc4648_padding_encoder; +#if ETL_USING_CPP14 + using codec_full_buffer = etl::base64_rfc4648_padding_encoder::safe_output_buffer_size(256)>; +#else + using codec_full_buffer = etl::base64_rfc4648_padding_encoder<344>; +#endif - std::array input_data_unsigned_char = + std::string encoded_output; + bool received_final_block = false; + + codec::callback_type callback = [](const codec::span_type& sp) + { + if (sp.empty()) + { + received_final_block = true; + } + else + { + std::copy(sp.begin(), sp.end(), std::back_inserter(encoded_output)); + } + }; + + std::array input_data = { 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, @@ -72,26 +94,6 @@ namespace 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 = { "", @@ -356,251 +358,352 @@ namespace SUITE(test_base64_rfc4648_with_padding) { //************************************************************************* - TEST(test_encode_unsigned_char_pointer_size) + TEST(test_basic_information) { - codec b64; - std::array encoded_output; + codec_full_buffer b64; + CHECK_EQUAL(etl::base64::Encoding::RFC_4648_PADDING, codec_full_buffer::Encoding); + CHECK_EQUAL("RFC_4648_PADDING", codec_full_buffer::Encoding.c_str()); + } + + //************************************************************************* + TEST(test_check_encode_safe_buffer_sizes) + { for (size_t i = 0; i < 256; ++i) { - encoded_output.fill(0); + size_t minimum_size = encoded[i].size(); + size_t safe_size = codec::safe_output_buffer_size(i); - 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(codec::encoded_size(i), size); + CHECK_TRUE(safe_size >= minimum_size); + CHECK_TRUE((safe_size - minimum_size) <= 2U); } } //************************************************************************* - TEST(test_encode_unsigned_char_pointer_size_no_output_length) + TEST(test_encode_pointer_size_single_pass_with_callback) { - codec b64; - std::array encoded_output; + codec b64(callback); for (size_t i = 0; i < 256; ++i) { - encoded_output.fill(0); + encoded_output.clear(); + received_final_block = false; - auto size = b64.encode(input_data_unsigned_char.data(), i, - encoded_output.data()); + b64.encode_final(input_data.data(), i); std::string expected(encoded[i]); - std::string actual(encoded_output.data(), size); + std::string actual(encoded_output); + CHECK_TRUE(received_final_block); CHECK_EQUAL(expected, actual); - CHECK_EQUAL(codec::encoded_size(i), size); + CHECK_TRUE(codec::safe_output_buffer_size(i) >= encoded_output.size()); } } //************************************************************************* - TEST(test_encode_unsigned_char_pointer_size_to_etl_back_inserter) + TEST(test_encode_pointer_size_single_pass_with_callback_and_larger_buffer) { - codec b64; + codec_larger_buffer b64(callback); - for (size_t i = 0; i < 256; ++i) + for (size_t i = 0; i < 256; ++i) { - std::string actual; + encoded_output.clear(); + received_final_block = false; - auto size = b64.encode(input_data_unsigned_char.data(), i, - etl::back_inserter(actual)); + b64.encode_final(input_data.data(), i); std::string expected(encoded[i]); + std::string actual(encoded_output); + + CHECK_TRUE(received_final_block); + CHECK_EQUAL(expected, actual); + CHECK_TRUE(codec::safe_output_buffer_size(i) >= encoded_output.size()); + } + } + + //************************************************************************* + TEST(test_encode_pointer_size_multi_pass_blocks_with_callback) + { + codec b64(callback); + + for (size_t i = 0; i < 256; ++i) + { + encoded_output.clear(); + received_final_block = false; + + auto start = input_data.data(); + auto length = i; + while (length >= 5) + { + b64.encode(start, 5); + length -= 5; + start += 5; + } + + if (length > 0) + { + b64.encode(start, length); + } + + CHECK_FALSE(received_final_block); + b64.flush(); + CHECK_TRUE(received_final_block); + + std::string expected(encoded[i]); + std::string actual(encoded_output); + CHECK_EQUAL(expected, actual); - CHECK_EQUAL(codec::encoded_size(i), size); + CHECK_TRUE(codec::safe_output_buffer_size(i) >= encoded_output.size()); } } -#if ETL_USING_STL //************************************************************************* - TEST(test_encode_unsigned_char_pointer_size_to_std_back_inserter) + TEST(test_encode_pointer_size_multi_pass_blocks_with_callback_larger_buffer) { - codec b64; + codec_larger_buffer b64(callback); for (size_t i = 0; i < 256; ++i) { - std::string actual; + encoded_output.clear(); + received_final_block = false; - auto size = b64.encode(input_data_unsigned_char.data(), i, - std::back_inserter(actual)); + auto start = input_data.data(); + auto length = i; + + while (length >= 5) + { + b64.encode(start, 5); + length -= 5; + start += 5; + } + + if (length > 0) + { + b64.encode(start, length); + } + + CHECK_FALSE(received_final_block); + b64.flush(); + CHECK_TRUE(received_final_block); std::string expected(encoded[i]); + std::string actual(encoded_output); CHECK_EQUAL(expected, actual); - CHECK_EQUAL(codec::encoded_size(i), size); + CHECK_TRUE(codec::safe_output_buffer_size(i) >= encoded_output.size()); } } -#endif //************************************************************************* - TEST(test_encode_unsigned_char_pointer_pointer) + TEST(test_encode_pointer_pointer_single_pass_with_callback) { - codec b64; - std::array encoded_output; + codec b64(callback); for (size_t i = 0; i < 256; ++i) { - encoded_output.fill(0); + encoded_output.clear(); + received_final_block = false; - auto size = b64.encode(input_data_unsigned_char.data(), input_data_unsigned_char.data() + i, - encoded_output.data(), encoded_output.data() + encoded_output.size()); + b64.encode_final(input_data.data(), input_data.data() + i); std::string expected(encoded[i]); - std::string actual(encoded_output.data(), size); + std::string actual(encoded_output); + CHECK_TRUE(received_final_block); CHECK_EQUAL(expected, actual); - CHECK_EQUAL(codec::encoded_size(i), size); + CHECK_TRUE(codec::safe_output_buffer_size(i) >= encoded_output.size()); } } //************************************************************************* - TEST(test_encode_unsigned_char_pointer_pointer_no_output_end_pointer) + TEST(test_encode_pointer_pointer_single_pass_with_callback_larger_buffer) { - codec b64; - 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(codec::encoded_size(i), size); - } - } - - //************************************************************************* - TEST(test_encode_int8_t_pointer_size) - { - codec b64; - 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(codec::encoded_size(i), size); - } - } - - //************************************************************************* - TEST(test_encode_int8_t_pointer_size_no_output_length) - { - codec b64; - 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(codec::encoded_size(i), size); - } - } - - //************************************************************************* - TEST(test_encode_int8_t_pointer_size_to_etl_back_inserter) - { - codec b64; + codec_larger_buffer b64(callback); for (size_t i = 0; i < 256; ++i) { - std::string actual; + encoded_output.clear(); + received_final_block = false; - auto size = b64.encode(input_data_int8_t.data(), i, - etl::back_inserter(actual)); + b64.encode_final(input_data.data(), input_data.data() + i); std::string expected(encoded[i]); + std::string actual(encoded_output); + CHECK_TRUE(received_final_block); CHECK_EQUAL(expected, actual); - CHECK_EQUAL(codec::encoded_size(i), size); - } - } - -#if ETL_USING_STL - //************************************************************************* - TEST(test_encode_int8_t_pointer_size_to_std_back_inserter) - { - codec b64; - - 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(codec::encoded_size(i), size); - } - } -#endif - - //************************************************************************* - TEST(test_encode_int8_t_pointer_pointer) - { - codec b64; - 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(codec::encoded_size(i), size); + CHECK_TRUE(codec::safe_output_buffer_size(i) >= encoded_output.size()); } } //************************************************************************* - TEST(test_encode_int8_t_pointer_pointer_no_end_pointer) + TEST(test_encode_pointer_pointer_multi_pass_blocks_with_callback) { - codec b64; - - std::array encoded_output; + codec b64(callback); for (size_t i = 0; i < 256; ++i) { - encoded_output.fill(0); + encoded_output.clear(); + received_final_block = false; - auto size = b64.encode(input_data_int8_t.data(), input_data_int8_t.data() + i, - encoded_output.data()); + auto start = input_data.data(); + auto length = i; + + while (length >= 5) + { + b64.encode(start, start + 5); + length -= 5; + start += 5; + } + + if (length > 0) + { + b64.encode(start, length); + } + + CHECK_FALSE(received_final_block); + b64.flush(); + CHECK_TRUE(received_final_block); std::string expected(encoded[i]); - std::string actual(encoded_output.data(), size); + std::string actual(encoded_output); CHECK_EQUAL(expected, actual); - CHECK_EQUAL(codec::encoded_size(i), size); + CHECK_TRUE(codec::safe_output_buffer_size(i) >= encoded_output.size()); + } + } + + //************************************************************************* + TEST(test_encode_pointer_pointer_multi_pass_blocks_with_callback_larger_buffer) + { + codec_larger_buffer b64(callback); + + for (size_t i = 0; i < 256; ++i) + { + encoded_output.clear(); + received_final_block = false; + + auto start = input_data.data(); + auto length = i; + + while (length >= 5) + { + b64.encode(start, start + 5); + length -= 5; + start += 5; + } + + if (length > 0) + { + b64.encode(start, length); + } + + CHECK_FALSE(received_final_block); + b64.flush(); + CHECK_TRUE(received_final_block); + + std::string expected(encoded[i]); + std::string actual(encoded_output); + + CHECK_EQUAL(expected, actual); + CHECK_TRUE(codec::safe_output_buffer_size(i) >= encoded_output.size()); + } + } + + //************************************************************************* + TEST(test_encode_multi_pass_by_char_with_callback) + { + codec b64(callback); + + for (size_t i = 0; i < 256; ++i) + { + encoded_output.clear(); + received_final_block = false; + + auto start = input_data.data(); + auto length = i; + + while (length--) + { + b64.encode(*start); + ++start; + } + + CHECK_FALSE(received_final_block); + b64.flush(); + CHECK_TRUE(received_final_block); + + std::string expected(encoded[i]); + std::string actual(encoded_output); + + CHECK_EQUAL(expected, actual); + CHECK_TRUE(codec::safe_output_buffer_size(i) >= encoded_output.size()); + } + } + + //************************************************************************* + TEST(test_encode_multi_pass_by_char_with_callback_larger_buffer) + { + codec_larger_buffer b64(callback); + + for (size_t i = 0; i < 256; ++i) + { + encoded_output.clear(); + received_final_block = false; + + auto start = input_data.data(); + auto length = i; + + while (length--) + { + b64.encode(*start); + ++start; + } + + CHECK_FALSE(received_final_block); + b64.flush(); + CHECK_TRUE(received_final_block); + + std::string expected(encoded[i]); + std::string actual(encoded_output); + + CHECK_EQUAL(expected, actual); + CHECK_TRUE(codec::safe_output_buffer_size(i) >= encoded_output.size()); + } + } + + //************************************************************************* + TEST(test_encode_multi_pass_blocks_with_no_callback_and_full_size_buffer) + { + codec_full_buffer b64; + + for (size_t i = 250; i < 256; ++i) + { + b64.restart(); + + auto start = input_data.data(); + auto length = i; + + while (length >= 5) + { + b64.encode(start, start + 5); + length -= 5; + start += 5; + } + + if (length > 0) + { + b64.encode(start, length); + } + + b64.flush(); + + std::string expected(encoded[i]); + std::string actual(b64.begin(), b64.end()); + + CHECK_EQUAL(expected, actual); + CHECK_TRUE(codec::safe_output_buffer_size(i) >= actual.size()); } } @@ -609,28 +712,28 @@ namespace template constexpr auto GetConstexprBase64(const etl::array input) noexcept { + etl::array output{ 0 }; + + using codec = etl::base64_rfc4648_encoder; + codec b64; - - constexpr size_t encoded_size = codec::encoded_size(Size); - etl::array output{ 0 }; - - b64.encode(input.begin(), Size, - output._buffer, encoded_size); + b64.encode_final(input.begin(), input.end()); + etl::copy(b64.begin(), b64.end(), output.begin()); return output; } - TEST(test_encode_int8_t_constexpr) + TEST(test_encode_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 expected("AAECAwQFBgcICQ"); std::string actual(output.data(), output.size()); CHECK_EQUAL(expected, actual); - CHECK_EQUAL(codec::encoded_size(10), output.size()); + CHECK_TRUE(codec::safe_output_buffer_size(10) >= output.size()); } #endif @@ -638,284 +741,10 @@ namespace TEST(test_encode_overflow) { codec b64; - std::array encoded_output{ 0 }; - CHECK_THROW((b64.encode(input_data_unsigned_char.data(), 10, - encoded_output.data(), encoded_output.size())), - etl::base64_overflow); + CHECK_THROW((b64.encode(input_data.data(), 10)), etl::base64_overflow); + CHECK_TRUE(b64.overflow()); } - - //************************************************************************* - TEST(test_decode_unsigned_char_pointer_size) - { - codec b64; - 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, codec::decoded_size(encoded[i].data(), encoded[i].size())); - CHECK_EQUAL(i, decoded_size); - } - } - - //************************************************************************* - TEST(test_decode_unsigned_char_pointer_size_no_end_pointer) - { - codec b64; - 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, codec::decoded_size(encoded[i].data(), encoded[i].size())); - CHECK_EQUAL(i, decoded_size); - } - } - - //************************************************************************* - TEST(test_decode_unsigned_char_pointer_pointer) - { - codec b64; - 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, codec::decoded_size(encoded[i].data(), encoded[i].size())); - CHECK_EQUAL(i, decoded_size); - } - } - - //************************************************************************* - TEST(test_decode_unsigned_char_pointer_pointer_no_end_pointer) - { - codec b64; - 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, codec::decoded_size(encoded[i].data(), encoded[i].size())); - CHECK_EQUAL(i, decoded_size); - } - } - - //************************************************************************* - TEST(test_decode_int8_t_pointer_size) - { - codec b64; - 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, codec::decoded_size(encoded[i].data(), encoded[i].size())); - CHECK_EQUAL(i, decoded_size); - } - } - - //************************************************************************* - TEST(test_decode_int8_t_pointer_size_etl_back_inserter) - { - codec b64; - 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, codec::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) - { - codec b64; - 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, codec::decoded_size(encoded[i].data(), encoded[i].size())); - CHECK_EQUAL(i, decoded_size); - } - } -#endif - - //************************************************************************* - TEST(test_decode_int8_t_pointer_size_no_output_size) - { - codec b64; - 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, codec::decoded_size(encoded[i].data(), encoded[i].size())); - CHECK_EQUAL(i, decoded_size); - } - } - - //************************************************************************* - TEST(test_decode_int8_t_pointer_pointer) - { - codec b64; - 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, codec::decoded_size(encoded[i].data(), encoded[i].size())); - CHECK_EQUAL(i, decoded_size); - } - } - - //************************************************************************* - TEST(test_decode_int8_t_pointer_pointer_etl_back_inserter) - { - codec b64; - 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, codec::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) - { - codec b64; - 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, codec::decoded_size(encoded[i].data(), encoded[i].size())); - CHECK_EQUAL(i, decoded_size); - } - } -#endif - - //************************************************************************* - TEST(test_decode_int8_t_pointer_pointer_no_end_pointer) - { - codec b64; - 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, codec::decoded_size(encoded[i].data(), encoded[i].size())); - CHECK_EQUAL(i, decoded_size); - } - } - - //************************************************************************* - TEST(test_decode_overflow) - { - codec b64; - 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) - { - codec b64; - std::array decoded_output{ 0 }; - - std::string invalid_chararacter("OycDQ#37KA=="); - - CHECK_THROW((b64.decode(invalid_chararacter.data(), invalid_chararacter.size(), - decoded_output.data(), decoded_output.size())), etl::base64_invalid_character); - - std::string invalid_length("OycDQy37K=="); - - CHECK_THROW((b64.decode(invalid_length.data(), invalid_length.size(), - decoded_output.data(), decoded_output.size())), etl::base64_invalid_decode_input_length); - } - - //************************************************************************* - //TEST(test_decoded_size) - //{ - // codec b64; - - // for (size_t i = 0; i < 256; ++i) - // { - // size_t length = codec::decoded_size(encoded[i].size()); - - // CHECK_EQUAL(length, codec::decoded_size(encoded[i].data() + encoded[i].size())); - // } - //} }; } diff --git a/test/test_crc.cpp b/test/test_crc.cpp deleted file mode 100644 index f0c69cfa..00000000 --- a/test/test_crc.cpp +++ /dev/null @@ -1,1258 +0,0 @@ -/****************************************************************************** -The MIT License(MIT) - -Embedded Template Library. -https://github.com/ETLCPP/etl -https://www.etlcpp.com - -Copyright(c) 2014 jwellbelove - -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 -#include -#include -#include - -#include "etl/crc8_ccitt.h" -#include "etl/crc8_rohc.h" -#include "etl/crc16.h" -#include "etl/crc16_ccitt.h" -#include "etl/crc16_aug_ccitt.h" -#include "etl/crc16_kermit.h" -#include "etl/crc16_modbus.h" -#include "etl/crc16_usb.h" -#include "etl/crc16_xmodem.h" -#include "etl/crc16_genibus.h" -#include "etl/crc16_x25.h" -#include "etl/crc32.h" -#include "etl/crc32_c.h" -#include "etl/crc32_bzip2.h" -#include "etl/crc32_mpeg2.h" -#include "etl/crc32_posix.h" -#include "etl/crc64_ecma.h" - -//***************************************************************************** -// The results for these tests were created from https://crccalc.com/ -//***************************************************************************** - -namespace -{ - SUITE(test_crc) - { - //************************************************************************* - TEST(test_crc8_ccitt_constructor) - { - std::string data("123456789"); - - uint8_t crc = etl::crc8_ccitt(data.begin(), data.end()); - - CHECK_EQUAL(0xF4, int(crc)); - } - - //************************************************************************* - TEST(test_crc8_ccitt_add_values) - { - std::string data("123456789"); - - etl::crc8_ccitt crc_calculator; - - for (size_t i = 0UL; i < data.size(); ++i) - { - crc_calculator.add(data[i]); - } - - uint8_t crc = crc_calculator; - - CHECK_EQUAL(0xF4, int(crc)); - } - - //************************************************************************* - TEST(test_crc8_ccitt_add_range) - { - std::string data("123456789"); - - etl::crc8_ccitt crc_calculator; - - crc_calculator.add(data.begin(), data.end()); - - uint8_t crc = crc_calculator.value(); - - CHECK_EQUAL(0xF4, int(crc)); - } - - //************************************************************************* - TEST(test_crc8_ccitt_add_range_via_iterator) - { - std::string data("123456789"); - - etl::crc8_ccitt crc_calculator; - - std::copy(data.begin(), data.end(), crc_calculator.input()); - - uint8_t crc = crc_calculator.value(); - - CHECK_EQUAL(0xF4, int(crc)); - } - - //************************************************************************* - TEST(test_crc8_ccitt_add_range_endian) - { - std::vector data1 = { 0x01U, 0x02U, 0x03U, 0x04U, 0x05U, 0x06U, 0x07U, 0x08U }; - std::vector data2 = { 0x04030201UL, 0x08070605UL }; - std::vector data3 = { 0x08U, 0x07U, 0x06U, 0x05U, 0x04U, 0x03U, 0x02U, 0x01U }; - - uint8_t crc1 = etl::crc32(data1.begin(), data1.end()); - uint8_t crc2 = etl::crc32((uint8_t*)&data2[0], (uint8_t*)(&data2[0] + data2.size())); - CHECK_EQUAL(int(crc1), int(crc2)); - - uint8_t crc3 = etl::crc32(data3.rbegin(), data3.rend()); - CHECK_EQUAL(int(crc1), int(crc3)); - } - - //************************************************************************* - TEST(test_crc8_rohc_constructor) - { - std::string data("123456789"); - - uint8_t crc = etl::crc8_rohc(data.begin(), data.end()); - - CHECK_EQUAL(0xD0, int(crc)); - } - - //************************************************************************* - TEST(test_crc8_rohc_add_values) - { - std::string data("123456789"); - - etl::crc8_rohc crc_calculator; - - for (size_t i = 0UL; i < data.size(); ++i) - { - crc_calculator.add(data[i]); - } - - uint8_t crc = crc_calculator; - - CHECK_EQUAL(0xD0, int(crc)); - } - - //************************************************************************* - TEST(test_crc8_rohc_add_range) - { - std::string data("123456789"); - - etl::crc8_rohc crc_calculator; - - crc_calculator.add(data.begin(), data.end()); - - uint8_t crc = crc_calculator.value(); - - CHECK_EQUAL(0xD0, int(crc)); - } - - //************************************************************************* - TEST(test_crc8_rohc_add_range_via_iterator) - { - std::string data("123456789"); - - etl::crc8_rohc crc_calculator; - - std::copy(data.begin(), data.end(), crc_calculator.input()); - - uint8_t crc = crc_calculator.value(); - - CHECK_EQUAL(0xD0, int(crc)); - } - - //************************************************************************* - TEST(test_crc8_rohc_add_range_endian) - { - std::vector data1 = { 0x01U, 0x02U, 0x03U, 0x04U, 0x05U, 0x06U, 0x07U, 0x08U }; - std::vector data2 = { 0x04030201UL, 0x08070605UL }; - std::vector data3 = { 0x08U, 0x07U, 0x06U, 0x05U, 0x04U, 0x03U, 0x02U, 0x01U }; - - uint8_t crc1 = etl::crc32(data1.begin(), data1.end()); - uint8_t crc2 = etl::crc32((uint8_t*)&data2[0], (uint8_t*)(&data2[0] + data2.size())); - CHECK_EQUAL(int(crc1), int(crc2)); - - uint8_t crc3 = etl::crc32(data3.rbegin(), data3.rend()); - CHECK_EQUAL(int(crc1), int(crc3)); - } - - //************************************************************************* - TEST(test_crc16) - { - std::string data("123456789"); - - uint16_t crc = etl::crc16(data.begin(), data.end()); - - CHECK_EQUAL(0xBB3DU, crc); - } - - //************************************************************************* - TEST(test_crc16_add_values) - { - std::string data("123456789"); - - etl::crc16 crc_calculator; - - for (size_t i = 0UL; i < data.size(); ++i) - { - crc_calculator.add(data[i]); - } - - uint16_t crc = crc_calculator; - - CHECK_EQUAL(0xBB3DU, crc); - } - - //************************************************************************* - TEST(test_crc16_add_range) - { - std::string data("123456789"); - - etl::crc16 crc_calculator; - - crc_calculator.add(data.begin(), data.end()); - - uint16_t crc = crc_calculator.value(); - - CHECK_EQUAL(0xBB3DU, crc); - } - - //************************************************************************* - TEST(test_crc16_add_range_via_iterator) - { - std::string data("123456789"); - - etl::crc16 crc_calculator; - - std::copy(data.begin(), data.end(), crc_calculator.input()); - - uint16_t crc = crc_calculator.value(); - - CHECK_EQUAL(0xBB3DU, crc); - } - - //************************************************************************* - TEST(test_crc16_add_range_endian) - { - std::vector data1 = { 0x01U, 0x02U, 0x03U, 0x04U, 0x05U, 0x06U, 0x07U, 0x08U }; - std::vector data2 = { 0x04030201UL, 0x08070605UL }; - std::vector data3 = { 0x08U, 0x07U, 0x06U, 0x05U, 0x04U, 0x03U, 0x02U, 0x01U }; - - uint16_t crc1 = etl::crc16(data1.begin(), data1.end()); - uint16_t crc2 = etl::crc16((uint8_t*)&data2[0], (uint8_t*)(&data2[0] + data2.size())); - CHECK_EQUAL(crc1, crc2); - - uint16_t crc3 = etl::crc16(data3.rbegin(), data3.rend()); - CHECK_EQUAL(crc1, crc3); - } - - //************************************************************************* - TEST(test_crc16_ccitt) - { - std::string data("123456789"); - - uint16_t crc = etl::crc16_ccitt(data.begin(), data.end()); - - CHECK_EQUAL(0x29B1U, crc); - } - - //************************************************************************* - TEST(test_crc16_ccitt_add_values) - { - std::string data("123456789"); - - etl::crc16_ccitt crc_calculator; - - for (size_t i = 0UL; i < data.size(); ++i) - { - crc_calculator.add(data[i]); - } - - uint16_t crc = crc_calculator; - - CHECK_EQUAL(0x29B1U, crc); - } - - //************************************************************************* - TEST(test_crc16_ccitt_add_range) - { - std::string data("123456789"); - - etl::crc16_ccitt crc_calculator; - - crc_calculator.add(data.begin(), data.end()); - - uint16_t crc = crc_calculator.value(); - - CHECK_EQUAL(0x29B1U, crc); - } - - //************************************************************************* - TEST(test_crc16_ccitt_add_range_via_iterator) - { - std::string data("123456789"); - - etl::crc16_ccitt crc_calculator; - - std::copy(data.begin(), data.end(), crc_calculator.input()); - - uint16_t crc = crc_calculator.value(); - - CHECK_EQUAL(0x29B1U, crc); - } - - //************************************************************************* - TEST(test_crc16_ccitt_add_range_endian) - { - std::vector data1 = { 0x01U, 0x02U, 0x03U, 0x04U, 0x05U, 0x06U, 0x07U, 0x08U }; - std::vector data2 = { 0x04030201UL, 0x08070605UL }; - std::vector data3 = { 0x08U, 0x07U, 0x06U, 0x05U, 0x04U, 0x03U, 0x02U, 0x01U }; - - uint16_t crc1 = etl::crc16_ccitt(data1.begin(), data1.end()); - uint16_t crc2 = etl::crc16_ccitt((uint8_t*)&data2[0], (uint8_t*)(&data2[0] + data2.size())); - CHECK_EQUAL(crc1, crc2); - - uint16_t crc3 = etl::crc16_ccitt(data3.rbegin(), data3.rend()); - CHECK_EQUAL(crc1, crc3); - } - - //************************************************************************* - TEST(test_crc16_kermit) - { - std::string data("123456789"); - - uint16_t crc = etl::crc16_kermit(data.begin(), data.end()); - - CHECK_EQUAL(0x2189U, crc); - } - - //************************************************************************* - TEST(test_crc16_kermit_add_values) - { - std::string data("123456789"); - - etl::crc16_kermit crc_calculator; - - for (size_t i = 0UL; i < data.size(); ++i) - { - crc_calculator.add(data[i]); - } - - uint16_t crc = crc_calculator; - - CHECK_EQUAL(0x2189U, crc); - } - - //************************************************************************* - TEST(test_crc16_kermit_add_range) - { - std::string data("123456789"); - - etl::crc16_kermit crc_calculator; - - crc_calculator.add(data.begin(), data.end()); - - uint16_t crc = crc_calculator.value(); - - CHECK_EQUAL(0x2189U, crc); - } - - //************************************************************************* - TEST(test_crc16_kermit_add_range_via_iterator) - { - std::string data("123456789"); - - etl::crc16_kermit crc_calculator; - - std::copy(data.begin(), data.end(), crc_calculator.input()); - - uint16_t crc = crc_calculator.value(); - - CHECK_EQUAL(0x2189U, crc); - } - - //************************************************************************* - TEST(test_crc16_kermit_add_range_endian) - { - std::vector data1 = { 0x01U, 0x02U, 0x03U, 0x04U, 0x05U, 0x06U, 0x07U, 0x08U }; - std::vector data2 = { 0x04030201UL, 0x08070605UL }; - std::vector data3 = { 0x08U, 0x07U, 0x06U, 0x05U, 0x04U, 0x03U, 0x02U, 0x01U }; - - uint16_t crc1 = etl::crc16_kermit(data1.begin(), data1.end()); - uint16_t crc2 = etl::crc16_kermit((uint8_t*)&data2[0], (uint8_t*)(&data2[0] + data2.size())); - CHECK_EQUAL(crc1, crc2); - - uint16_t crc3 = etl::crc16_kermit(data3.rbegin(), data3.rend()); - CHECK_EQUAL(crc1, crc3); - } - - //************************************************************************* - TEST(test_crc16_modbus) - { - std::string data("123456789"); - - uint16_t crc = etl::crc16_modbus(data.begin(), data.end()); - - CHECK_EQUAL(0x4B37U, crc); - } - - //************************************************************************* - TEST(test_crc16_modbus_add_values) - { - std::string data("123456789"); - - etl::crc16_modbus crc_calculator; - - for (size_t i = 0UL; i < data.size(); ++i) - { - crc_calculator.add(data[i]); - } - - uint16_t crc = crc_calculator; - - CHECK_EQUAL(0x4B37U, crc); - } - - //************************************************************************* - TEST(test_crc16_modbus_add_range) - { - std::string data("123456789"); - - etl::crc16_modbus crc_calculator; - - crc_calculator.add(data.begin(), data.end()); - - uint16_t crc = crc_calculator.value(); - - CHECK_EQUAL(0x4B37U, crc); - } - - //************************************************************************* - TEST(test_crc16_modbus_add_range_via_iterator) - { - std::string data("123456789"); - - etl::crc16_modbus crc_calculator; - - std::copy(data.begin(), data.end(), crc_calculator.input()); - - uint16_t crc = crc_calculator.value(); - - CHECK_EQUAL(0x4B37U, crc); - } - - //************************************************************************* - TEST(test_crc16_modbus_add_range_endian) - { - std::vector data1 = { 0x01U, 0x02U, 0x03U, 0x04U, 0x05U, 0x06U, 0x07U, 0x08U }; - std::vector data2 = { 0x04030201UL, 0x08070605UL }; - std::vector data3 = { 0x08U, 0x07U, 0x06U, 0x05U, 0x04U, 0x03U, 0x02U, 0x01U }; - - uint16_t crc1 = etl::crc16_modbus(data1.begin(), data1.end()); - uint16_t crc2 = etl::crc16_modbus((uint8_t*)&data2[0], (uint8_t*)(&data2[0] + data2.size())); - CHECK_EQUAL(crc1, crc2); - - uint16_t crc3 = etl::crc16_modbus(data3.rbegin(), data3.rend()); - CHECK_EQUAL(crc1, crc3); - } - - //************************************************************************* - TEST(test_crc16_usb) - { - std::string data("123456789"); - - uint16_t crc = etl::crc16_usb(data.begin(), data.end()); - - CHECK_EQUAL(0xB4C8U, crc); - } - - //************************************************************************* - TEST(test_crc16_usb_add_values) - { - std::string data("123456789"); - - etl::crc16_usb crc_calculator; - - for (size_t i = 0UL; i < data.size(); ++i) - { - crc_calculator.add(data[i]); - } - - uint16_t crc = crc_calculator; - - CHECK_EQUAL(0xB4C8U, crc); - } - - //************************************************************************* - TEST(test_crc16_usb_add_range) - { - std::string data("123456789"); - - etl::crc16_usb crc_calculator; - - crc_calculator.add(data.begin(), data.end()); - - uint16_t crc = crc_calculator.value(); - - CHECK_EQUAL(0xB4C8U, crc); - } - - //************************************************************************* - TEST(test_crc16_usb_add_range_via_iterator) - { - std::string data("123456789"); - - etl::crc16_usb crc_calculator; - - std::copy(data.begin(), data.end(), crc_calculator.input()); - - uint16_t crc = crc_calculator.value(); - - CHECK_EQUAL(0xB4C8U, crc); - } - - //************************************************************************* - TEST(test_crc16_usb_add_range_endian) - { - std::vector data1 = { 0x01U, 0x02U, 0x03U, 0x04U, 0x05U, 0x06U, 0x07U, 0x08U }; - std::vector data2 = { 0x04030201UL, 0x08070605UL }; - std::vector data3 = { 0x08U, 0x07U, 0x06U, 0x05U, 0x04U, 0x03U, 0x02U, 0x01U }; - - uint16_t crc1 = etl::crc16_usb(data1.begin(), data1.end()); - uint16_t crc2 = etl::crc16_usb((uint8_t*)&data2[0], (uint8_t*)(&data2[0] + data2.size())); - CHECK_EQUAL(crc1, crc2); - - uint16_t crc3 = etl::crc16_usb(data3.rbegin(), data3.rend()); - CHECK_EQUAL(crc1, crc3); - } - - //************************************************************************* - TEST(test_crc16_xmodem) - { - std::string data("123456789"); - - uint16_t crc = etl::crc16_xmodem(data.begin(), data.end()); - - CHECK_EQUAL(0x31C3U, crc); - } - - //************************************************************************* - TEST(test_crc16_xmodem_add_values) - { - std::string data("123456789"); - - etl::crc16_xmodem crc_calculator; - - for (size_t i = 0UL; i < data.size(); ++i) - { - crc_calculator.add(data[i]); - } - - uint16_t crc = crc_calculator; - - CHECK_EQUAL(0x31C3U, crc); - } - - //************************************************************************* - TEST(test_crc16_xmodem_add_range) - { - std::string data("123456789"); - - etl::crc16_xmodem crc_calculator; - - crc_calculator.add(data.begin(), data.end()); - - uint16_t crc = crc_calculator.value(); - - CHECK_EQUAL(0x31C3U, crc); - } - - //************************************************************************* - TEST(test_crc16_xmodem_add_range_via_iterator) - { - std::string data("123456789"); - - etl::crc16_xmodem crc_calculator; - - std::copy(data.begin(), data.end(), crc_calculator.input()); - - uint16_t crc = crc_calculator.value(); - - CHECK_EQUAL(0x31C3U, crc); - } - - //************************************************************************* - TEST(test_crc16_xmodem_add_range_endian) - { - std::vector data1 = { 0x01U, 0x02U, 0x03U, 0x04U, 0x05U, 0x06U, 0x07U, 0x08U }; - std::vector data2 = { 0x04030201UL, 0x08070605UL }; - std::vector data3 = { 0x08U, 0x07U, 0x06U, 0x05U, 0x04U, 0x03U, 0x02U, 0x01U }; - - uint16_t crc1 = etl::crc16_xmodem(data1.begin(), data1.end()); - uint16_t crc2 = etl::crc16_xmodem((uint8_t*)&data2[0], (uint8_t*)(&data2[0] + data2.size())); - CHECK_EQUAL(crc1, crc2); - - uint16_t crc3 = etl::crc16_xmodem(data3.rbegin(), data3.rend()); - CHECK_EQUAL(crc1, crc3); - } - - //************************************************************************* - TEST(test_crc16_aug_ccitt) - { - std::string data("123456789"); - - uint16_t crc = etl::crc16_aug_ccitt(data.begin(), data.end()); - - CHECK_EQUAL(0xE5CCU, crc); - } - - //************************************************************************* - TEST(test_crc16_aug_ccitt_add_values) - { - std::string data("123456789"); - - etl::crc16_aug_ccitt crc_calculator; - - for (size_t i = 0UL; i < data.size(); ++i) - { - crc_calculator.add(data[i]); - } - - uint16_t crc = crc_calculator; - - CHECK_EQUAL(0xE5CCU, crc); - } - - //************************************************************************* - TEST(test_crc16_aug_ccitt_add_range) - { - std::string data("123456789"); - - etl::crc16_aug_ccitt crc_calculator; - - crc_calculator.add(data.begin(), data.end()); - - uint16_t crc = crc_calculator.value(); - - CHECK_EQUAL(0xE5CCU, crc); - } - - //************************************************************************* - TEST(test_crc16_aug_ccitt_add_range_via_iterator) - { - std::string data("123456789"); - - etl::crc16_aug_ccitt crc_calculator; - - std::copy(data.begin(), data.end(), crc_calculator.input()); - - uint16_t crc = crc_calculator.value(); - - CHECK_EQUAL(0xE5CCU, crc); - } - - //************************************************************************* - TEST(test_crc16_aug_ccitt_add_range_endian) - { - std::vector data1 = { 0x01U, 0x02U, 0x03U, 0x04U, 0x05U, 0x06U, 0x07U, 0x08U }; - std::vector data2 = { 0x04030201UL, 0x08070605UL }; - std::vector data3 = { 0x08U, 0x07U, 0x06U, 0x05U, 0x04U, 0x03U, 0x02U, 0x01U }; - - uint16_t crc1 = etl::crc16_aug_ccitt(data1.begin(), data1.end()); - uint16_t crc2 = etl::crc16_aug_ccitt((uint8_t*)&data2[0], (uint8_t*)(&data2[0] + data2.size())); - CHECK_EQUAL(crc1, crc2); - - uint16_t crc3 = etl::crc16_aug_ccitt(data3.rbegin(), data3.rend()); - CHECK_EQUAL(crc1, crc3); - } - - //************************************************************************* - TEST(test_crc16_genibus) - { - std::string data("123456789"); - - uint16_t crc = etl::crc16_genibus(data.begin(), data.end()); - - CHECK_EQUAL(0xD64EU, crc); - } - - //************************************************************************* - TEST(test_crc16_genibus_add_values) - { - std::string data("123456789"); - - etl::crc16_genibus crc_calculator; - - for (size_t i = 0UL; i < data.size(); ++i) - { - crc_calculator.add(data[i]); - } - - uint16_t crc = crc_calculator; - - CHECK_EQUAL(0xD64EU, crc); - } - - //************************************************************************* - TEST(test_crc16_genibus_add_range) - { - std::string data("123456789"); - - etl::crc16_genibus crc_calculator; - - crc_calculator.add(data.begin(), data.end()); - - uint16_t crc = crc_calculator.value(); - - CHECK_EQUAL(0xD64EU, crc); - } - - //************************************************************************* - TEST(test_crc16_genibus_add_range_via_iterator) - { - std::string data("123456789"); - - etl::crc16_genibus crc_calculator; - - std::copy(data.begin(), data.end(), crc_calculator.input()); - - uint16_t crc = crc_calculator.value(); - - CHECK_EQUAL(0xD64EU, crc); - } - - //************************************************************************* - TEST(test_crc16_genibus_add_range_endian) - { - std::vector data1 = { 0x01U, 0x02U, 0x03U, 0x04U, 0x05U, 0x06U, 0x07U, 0x08U }; - std::vector data2 = { 0x04030201UL, 0x08070605UL }; - std::vector data3 = { 0x08U, 0x07U, 0x06U, 0x05U, 0x04U, 0x03U, 0x02U, 0x01U }; - - uint16_t crc1 = etl::crc16_genibus(data1.begin(), data1.end()); - uint16_t crc2 = etl::crc16_genibus((uint8_t*)&data2[0], (uint8_t*)(&data2[0] + data2.size())); - CHECK_EQUAL(crc1, crc2); - - uint16_t crc3 = etl::crc16_genibus(data3.rbegin(), data3.rend()); - CHECK_EQUAL(crc1, crc3); - } - - //************************************************************************* - TEST(test_crc16_x25) - { - std::string data("123456789"); - - uint16_t crc = etl::crc16_x25(data.begin(), data.end()); - - CHECK_EQUAL(0x906EU, crc); - } - - //************************************************************************* - TEST(test_crc16_x25_add_values) - { - std::string data("123456789"); - - etl::crc16_x25 crc_calculator; - - for (size_t i = 0UL; i < data.size(); ++i) - { - crc_calculator.add(data[i]); - } - - uint16_t crc = crc_calculator; - - CHECK_EQUAL(0x906EU, crc); - } - - //************************************************************************* - TEST(test_crc16_x25_add_range) - { - std::string data("123456789"); - - etl::crc16_x25 crc_calculator; - - crc_calculator.add(data.begin(), data.end()); - - uint16_t crc = crc_calculator.value(); - - CHECK_EQUAL(0x906EU, crc); - } - - //************************************************************************* - TEST(test_crc16_x25_add_range_via_iterator) - { - std::string data("123456789"); - - etl::crc16_x25 crc_calculator; - - std::copy(data.begin(), data.end(), crc_calculator.input()); - - uint16_t crc = crc_calculator.value(); - - CHECK_EQUAL(0x906EU, crc); - } - - //************************************************************************* - TEST(test_crc16_x25_add_range_endian) - { - std::vector data1 = { 0x01U, 0x02U, 0x03U, 0x04U, 0x05U, 0x06U, 0x07U, 0x08U }; - std::vector data2 = { 0x04030201UL, 0x08070605UL }; - std::vector data3 = { 0x08U, 0x07U, 0x06U, 0x05U, 0x04U, 0x03U, 0x02U, 0x01U }; - - uint16_t crc1 = etl::crc16_x25(data1.begin(), data1.end()); - uint16_t crc2 = etl::crc16_x25((uint8_t*)&data2[0], (uint8_t*)(&data2[0] + data2.size())); - CHECK_EQUAL(crc1, crc2); - - uint16_t crc3 = etl::crc16_x25(data3.rbegin(), data3.rend()); - CHECK_EQUAL(crc1, crc3); - } - - //************************************************************************* - TEST(test_crc32) - { - std::string data("123456789"); - - uint32_t crc = etl::crc32(data.begin(), data.end()); - - CHECK_EQUAL(0xCBF43926UL, crc); - } - - //************************************************************************* - TEST(test_crc32_add_values) - { - std::string data("123456789"); - - etl::crc32 crc_calculator; - - for (size_t i = 0UL; i < data.size(); ++i) - { - crc_calculator.add(data[i]); - } - - uint32_t crc = crc_calculator; - - - CHECK_EQUAL(0xCBF43926UL, crc); - } - - //************************************************************************* - TEST(test_crc32_add_range) - { - std::string data("123456789"); - - etl::crc32 crc_calculator; - - crc_calculator.add(data.begin(), data.end()); - - uint32_t crc = crc_calculator.value(); - - CHECK_EQUAL(0xCBF43926UL, crc); - } - - //************************************************************************* - TEST(test_crc32_add_range_via_iterator) - { - std::string data("123456789"); - - etl::crc32 crc_calculator; - - std::copy(data.begin(), data.end(), crc_calculator.input()); - - uint32_t crc = crc_calculator.value(); - - CHECK_EQUAL(0xCBF43926UL, crc); - } - - //************************************************************************* - TEST(test_crc32_add_range_endian) - { - std::vector data1 = { 0x01U, 0x02U, 0x03U, 0x04U, 0x05U, 0x06U, 0x07U, 0x08U }; - std::vector data2 = { 0x04030201UL, 0x08070605UL }; - std::vector data3 = { 0x08U, 0x07U, 0x06U, 0x05U, 0x04U, 0x03U, 0x02U, 0x01U }; - - uint32_t crc1 = etl::crc32(data1.begin(), data1.end()); - uint32_t crc2 = etl::crc32((uint8_t*)&data2[0], (uint8_t*)(&data2[0] + data2.size())); - CHECK_EQUAL(crc1, crc2); - - uint32_t crc3 = etl::crc32(data3.rbegin(), data3.rend()); - CHECK_EQUAL(crc1, crc3); - } - - //************************************************************************* - TEST(test_crc32_c) - { - std::string data("123456789"); - - uint32_t crc = etl::crc32_c(data.begin(), data.end()); - - CHECK_EQUAL(0xE3069283UL, crc); - } - - //************************************************************************* - TEST(test_crc32_c_add_values) - { - std::string data("123456789"); - - etl::crc32_c crc_calculator; - - for (size_t i = 0UL; i < data.size(); ++i) - { - crc_calculator.add(data[i]); - } - - uint32_t crc = crc_calculator; - - - CHECK_EQUAL(0xE3069283UL, crc); - } - - //************************************************************************* - TEST(test_crc32_c_add_range) - { - std::string data("123456789"); - - etl::crc32_c crc_calculator; - - crc_calculator.add(data.begin(), data.end()); - - uint32_t crc = crc_calculator.value(); - - CHECK_EQUAL(0xE3069283UL, crc); - } - - //************************************************************************* - TEST(test_crc32_c_add_range_via_iterator) - { - std::string data("123456789"); - - etl::crc32_c crc_calculator; - - std::copy(data.begin(), data.end(), crc_calculator.input()); - - uint32_t crc = crc_calculator.value(); - - CHECK_EQUAL(0xE3069283UL, crc); - } - - //************************************************************************* - TEST(test_crc32_c_add_range_endian) - { - std::vector data1 = { 0x01U, 0x02U, 0x03U, 0x04U, 0x05U, 0x06U, 0x07U, 0x08U }; - std::vector data2 = { 0x04030201UL, 0x08070605UL }; - std::vector data3 = { 0x08U, 0x07U, 0x06U, 0x05U, 0x04U, 0x03U, 0x02U, 0x01U }; - - uint32_t crc1 = etl::crc32_c(data1.begin(), data1.end()); - uint32_t crc2 = etl::crc32_c((uint8_t*)&data2[0], (uint8_t*)(&data2[0] + data2.size())); - CHECK_EQUAL(crc1, crc2); - - uint32_t crc3 = etl::crc32_c(data3.rbegin(), data3.rend()); - CHECK_EQUAL(crc1, crc3); - } - - //************************************************************************* - TEST(test_crc32_bzip2) - { - std::string data("123456789"); - - uint32_t crc = etl::crc32_bzip2(data.begin(), data.end()); - - CHECK_EQUAL(0xFC891918UL, crc); - } - - //************************************************************************* - TEST(test_crc32_bzip2_add_values) - { - std::string data("123456789"); - - etl::crc32_bzip2 crc_calculator; - - for (size_t i = 0UL; i < data.size(); ++i) - { - crc_calculator.add(data[i]); - } - - uint32_t crc = crc_calculator; - - - CHECK_EQUAL(0xFC891918UL, crc); - } - - //************************************************************************* - TEST(test_crc32_bzip2_add_range) - { - std::string data("123456789"); - - etl::crc32_bzip2 crc_calculator; - - crc_calculator.add(data.begin(), data.end()); - - uint32_t crc = crc_calculator.value(); - - CHECK_EQUAL(0xFC891918UL, crc); - } - - //************************************************************************* - TEST(test_crc32_bzip2_add_range_via_iterator) - { - std::string data("123456789"); - - etl::crc32_bzip2 crc_calculator; - - std::copy(data.begin(), data.end(), crc_calculator.input()); - - uint32_t crc = crc_calculator.value(); - - CHECK_EQUAL(0xFC891918UL, crc); - } - - //************************************************************************* - TEST(test_crc32_bzip2_add_range_endian) - { - std::vector data1 = { 0x01U, 0x02U, 0x03U, 0x04U, 0x05U, 0x06U, 0x07U, 0x08U }; - std::vector data2 = { 0x04030201UL, 0x08070605UL }; - std::vector data3 = { 0x08U, 0x07U, 0x06U, 0x05U, 0x04U, 0x03U, 0x02U, 0x01U }; - - uint32_t crc1 = etl::crc32_bzip2(data1.begin(), data1.end()); - uint32_t crc2 = etl::crc32_bzip2((uint8_t*)&data2[0], (uint8_t*)(&data2[0] + data2.size())); - CHECK_EQUAL(crc1, crc2); - - uint32_t crc3 = etl::crc32_bzip2(data3.rbegin(), data3.rend()); - CHECK_EQUAL(crc1, crc3); - } - - //************************************************************************* - TEST(test_crc32_posix) - { - std::string data("123456789"); - - uint32_t crc = etl::crc32_posix(data.begin(), data.end()); - - CHECK_EQUAL(0x765E7680UL, crc); - } - - //************************************************************************* - TEST(test_crc32_posix_add_values) - { - std::string data("123456789"); - - etl::crc32_posix crc_calculator; - - for (size_t i = 0UL; i < data.size(); ++i) - { - crc_calculator.add(data[i]); - } - - uint32_t crc = crc_calculator; - - - CHECK_EQUAL(0x765E7680UL, crc); - } - - //************************************************************************* - TEST(test_crc32_posix_add_range) - { - std::string data("123456789"); - - etl::crc32_posix crc_calculator; - - crc_calculator.add(data.begin(), data.end()); - - uint32_t crc = crc_calculator.value(); - - CHECK_EQUAL(0x765E7680UL, crc); - } - - //************************************************************************* - TEST(test_crc32_posix_add_range_via_iterator) - { - std::string data("123456789"); - - etl::crc32_posix crc_calculator; - - std::copy(data.begin(), data.end(), crc_calculator.input()); - - uint32_t crc = crc_calculator.value(); - - CHECK_EQUAL(0x765E7680UL, crc); - } - - //************************************************************************* - TEST(test_crc32_posix_add_range_endian) - { - std::vector data1 = { 0x01U, 0x02U, 0x03U, 0x04U, 0x05U, 0x06U, 0x07U, 0x08U }; - std::vector data2 = { 0x04030201UL, 0x08070605UL }; - std::vector data3 = { 0x08U, 0x07U, 0x06U, 0x05U, 0x04U, 0x03U, 0x02U, 0x01U }; - - uint32_t crc1 = etl::crc32_posix(data1.begin(), data1.end()); - uint32_t crc2 = etl::crc32_posix((uint8_t*)&data2[0], (uint8_t*)(&data2[0] + data2.size())); - CHECK_EQUAL(crc1, crc2); - - uint32_t crc3 = etl::crc32_posix(data3.rbegin(), data3.rend()); - CHECK_EQUAL(crc1, crc3); - } - - //************************************************************************* - TEST(test_crc32_mpeg2) - { - std::string data("123456789"); - - uint32_t crc = etl::crc32_mpeg2(data.begin(), data.end()); - - CHECK_EQUAL(0x0376E6E7UL, crc); - } - - //************************************************************************* - TEST(test_crc32_mpeg2_add_values) - { - std::string data("123456789"); - - etl::crc32_mpeg2 crc_calculator; - - for (size_t i = 0UL; i < data.size(); ++i) - { - crc_calculator.add(data[i]); - } - - uint32_t crc = crc_calculator; - - - CHECK_EQUAL(0x0376E6E7UL, crc); - } - - //************************************************************************* - TEST(test_crc32_mpeg2_add_range) - { - std::string data("123456789"); - - etl::crc32_mpeg2 crc_calculator; - - crc_calculator.add(data.begin(), data.end()); - - uint32_t crc = crc_calculator.value(); - - CHECK_EQUAL(0x0376E6E7UL, crc); - } - - //************************************************************************* - TEST(test_crc32_mpeg2_add_range_via_iterator) - { - std::string data("123456789"); - - etl::crc32_mpeg2 crc_calculator; - - std::copy(data.begin(), data.end(), crc_calculator.input()); - - uint32_t crc = crc_calculator.value(); - - CHECK_EQUAL(0x0376E6E7UL, crc); - } - - //************************************************************************* - TEST(test_crc32_mpeg2_add_range_endian) - { - std::vector data1 = { 0x01U, 0x02U, 0x03U, 0x04U, 0x05U, 0x06U, 0x07U, 0x08U }; - std::vector data2 = { 0x04030201UL, 0x08070605UL }; - std::vector data3 = { 0x08U, 0x07U, 0x06U, 0x05U, 0x04U, 0x03U, 0x02U, 0x01U }; - - uint32_t crc1 = etl::crc32_mpeg2(data1.begin(), data1.end()); - uint32_t crc2 = etl::crc32_mpeg2((uint8_t*)&data2[0], (uint8_t*)(&data2[0] + data2.size())); - CHECK_EQUAL(crc1, crc2); - - uint32_t crc3 = etl::crc32_mpeg2(data3.rbegin(), data3.rend()); - CHECK_EQUAL(crc1, crc3); - } - - //************************************************************************* - TEST(test_crc64_ecma) - { - std::string data("123456789"); - - uint64_t crc = etl::crc64_ecma(data.begin(), data.end()); - - CHECK_EQUAL(0x6C40DF5F0B497347ULL, crc); - } - - //************************************************************************* - TEST(test_crc64_ecma_add_values) - { - std::string data("123456789"); - - etl::crc64_ecma crc_calculator; - - for (size_t i = 0UL; i < data.size(); ++i) - { - crc_calculator.add(data[i]); - } - - uint64_t crc = crc_calculator; - - CHECK_EQUAL(0x6C40DF5F0B497347ULL, crc); - } - - //************************************************************************* - TEST(test_crc64_ecma_add_range) - { - std::string data("123456789"); - - etl::crc64_ecma crc_calculator; - - crc_calculator.add(data.begin(), data.end()); - - uint64_t crc = crc_calculator.value(); - - CHECK_EQUAL(0x6C40DF5F0B497347ULL, crc); - } - - //************************************************************************* - TEST(test_crc64_ecma_add_range_via_iterator) - { - std::string data("123456789"); - - etl::crc64_ecma crc_calculator; - - std::copy(data.begin(), data.end(), crc_calculator.input()); - - uint64_t crc = crc_calculator.value(); - - CHECK_EQUAL(0x6C40DF5F0B497347ULL, crc); - } - - //************************************************************************* - TEST(test_crc64_ecma_add_range_endian) - { - std::vector data1 = { 0x01U, 0x02U, 0x03U, 0x04U, 0x05U, 0x06U, 0x07U, 0x08U }; - std::vector data2 = { 0x04030201UL, 0x08070605UL }; - std::vector data3 = { 0x08U, 0x07U, 0x06U, 0x05U, 0x04U, 0x03U, 0x02U, 0x01U }; - - uint64_t crc1 = etl::crc64_ecma(data1.begin(), data1.end()); - uint64_t crc2 = etl::crc64_ecma((uint8_t*)&data2[0], (uint8_t*)(&data2[0] + data2.size())); - CHECK_EQUAL(crc1, crc2); - - uint64_t crc3 = etl::crc64_ecma(data3.rbegin(), data3.rend()); - CHECK_EQUAL(crc1, crc3); - } - }; -} - diff --git a/test/vs2022/etl.vcxproj b/test/vs2022/etl.vcxproj index 30ee8ba7..e57c97f8 100644 --- a/test/vs2022/etl.vcxproj +++ b/test/vs2022/etl.vcxproj @@ -3011,6 +3011,8 @@ + + @@ -7703,10 +7705,32 @@ - - - - + + + + + + false + false + false + false + false + false + false + false + false + false + false + false + false + + + + + + + + diff --git a/test/vs2022/etl.vcxproj.filters b/test/vs2022/etl.vcxproj.filters index 3387d94e..4d906660 100644 --- a/test/vs2022/etl.vcxproj.filters +++ b/test/vs2022/etl.vcxproj.filters @@ -226,6 +226,9 @@ {9713a35d-8f0e-4722-9b15-a5c477c9ecdb} + + {e2e649e4-10ee-4ed7-baa3-eb889e552ba1} + @@ -1368,7 +1371,7 @@ ETL\Utilities - + ETL\Codecs @@ -1401,6 +1404,12 @@ ETL\Maths + + ETL\Codecs + + + ETL\Codecs + @@ -2474,9 +2483,6 @@ Tests\Misc - - Tests\Codecs - Tests\Syntax Checks\Source @@ -3320,14 +3326,41 @@ Tests\Messaging - - Tests\Codecs + + Tests\Codecs\Base64 - - Tests\Codecs + + Tests\Codecs\Base64 - - Tests\Codecs + + Tests\Codecs\Base64 + + + Tests\Codecs\Base64 + + + Tests\Codecs\Base64 + + + Tests\Codecs\Base64 + + + Tests\Codecs\Base64 + + + Tests\Codecs\Base64 + + + Tests\Codecs\Base64 + + + Tests\Codecs\Base64 + + + Tests\Codecs\Base64 + + + Tests\Codecs\Base64