Added etl::string interface to etl::base64

This commit is contained in:
John Wellbelove 2023-10-05 13:29:45 +01:00
parent 21a9b884bc
commit 5ca6e05eb8
4 changed files with 233 additions and 53 deletions

View File

@ -30,6 +30,7 @@ SOFTWARE.
#include "etl/platform.h"
#include "etl/span.h"
#include "etl/static_assert.h"
#include "etl/error_handler.h"
#include "etl/exception.h"
#include "etl/type_traits.h"
@ -37,9 +38,14 @@ SOFTWARE.
#include "etl/algorithm.h"
#include "etl/integral_limits.h"
#include "etl/iterator.h"
#include "etl/string.h"
#include <stdint.h>
#if ETL_USING_STL
#include <string>
#endif
namespace etl
{
//***************************************************************************
@ -90,17 +96,9 @@ namespace etl
}
// Figure out if the output buffer is large enough.
size_t required_output_length = (input_length * 8U) / 6U;
size_t required_output_length = encode_size(input_length);
if ((input_length % 3U) != 0U)
{
while ((required_output_length % 4U) != 0)
{
++required_output_length;
}
}
ETL_ASSERT_OR_RETURN_VALUE(output_length >= required_output_length, ETL_ERROR(base64_overflow), etl::span<const T>());
ETL_ASSERT_OR_RETURN_VALUE(output_length >= required_output_length, ETL_ERROR(base64_overflow), 0U);
const T* p_in = input;
const T* p_in_end = input + input_length;
@ -187,6 +185,19 @@ namespace etl
return static_cast<size_t>(etl::distance(output, p_out));
}
//*************************************************************************
/// Encode to Base64 from and to pointer/pointer
//*************************************************************************
template <typename T>
ETL_CONSTEXPR14
static
typename etl::enable_if<etl::is_integral<T>::value && (etl::integral_limits<T>::bits == 8U), size_t>::type
encode(const T* input_begin, const T* input_end, char* output_begin, char* output_end)
{
return encode(input_begin, static_cast<size_t>(etl::distance(input_begin, input_end)),
output_begin, static_cast<size_t>(etl::distance(output_begin, output_end)));
}
//*************************************************************************
/// Encode to Base64 from and to span/span
//*************************************************************************
@ -202,16 +213,51 @@ namespace etl
}
//*************************************************************************
/// Encode to Base64 from and to pointer/pointer
/// Encode to Base64 from pointer/length to etl::istring
//*************************************************************************
template <typename T>
ETL_CONSTEXPR14
static
typename etl::enable_if<etl::is_integral<T>::value && (etl::integral_limits<T>::bits == 8U), size_t>::type
encode(const T* input_begin, const T* input_end, char* output_begin, char* output_end)
encode(const T* input_begin, size_t input_length,
etl::istring& output)
{
return encode(input_begin, static_cast<size_t>(etl::distance(input_begin, input_end)),
output_begin, static_cast<size_t>(etl::distance(output_begin, output_end)));
output.resize(etl::base64::encode_size(input_length));
return encode(input_begin, input_length,
output.data(), output.size());
}
//*************************************************************************
/// Encode to Base64 from pointer/pointer to etl::istring
//*************************************************************************
template <typename T>
ETL_CONSTEXPR14
static
typename etl::enable_if<etl::is_integral<T>::value && (etl::integral_limits<T>::bits == 8U), size_t>::type
encode(const T* input_begin, const T* input_end,
etl::istring& output)
{
output.resize(etl::base64::encode_size(etl::distance(input_begin, input_end)));
return encode(input_begin, static_cast<size_t>(etl::distance(input_begin, input_end)),
output.data(), output.size());
}
//*************************************************************************
/// Encode to Base64 from span to etl::istring
//*************************************************************************
template <typename T, size_t Length1>
ETL_CONSTEXPR14
static
typename etl::enable_if<etl::is_integral<T>::value && (etl::integral_limits<T>::bits == 8U), size_t>::type
encode(const etl::span<const T, Length1>& input_span,
etl::istring& output)
{
output.resize(etl::base64::encode_size(Length1));
return encode(input_span.begin(), input_span.size(),
output.data(), output.size());
}
//*************************************************************************
@ -250,10 +296,9 @@ namespace etl
}
// Figure out if the output buffer is large enough.
size_t length = static_cast<size_t>(etl::distance(input, etl::find(input, input + input_length, padding())) - 1);
size_t required_output_length = length - (length / 4U);
size_t required_output_length = etl::base64::decode_size(input, input_length);
ETL_ASSERT_OR_RETURN_VALUE(output_length >= required_output_length, ETL_ERROR(base64_overflow), etl::span<const T>());
ETL_ASSERT_OR_RETURN_VALUE(output_length >= required_output_length, ETL_ERROR(base64_overflow), 0U);
const char* p_in = input;
const char* p_in_end = input + input_length;
@ -327,20 +372,6 @@ namespace etl
return static_cast<size_t>(etl::distance(output, p_out));
}
//*************************************************************************
/// Decode from Base64 from and to span/span
//*************************************************************************
template <typename T, size_t Length1, size_t Length2>
ETL_CONSTEXPR14
static
typename etl::enable_if<etl::is_integral<T>::value && (etl::integral_limits<T>::bits == 8U), size_t>::type
decode(const etl::span<const char, Length1>& input_span,
const etl::span<T, Length2>& output_span)
{
return decode(input_span.begin(), input_span.size(),
output_span.begin(), output_span.size());
}
//*************************************************************************
/// Decode from Base64 from and to pointer/pointer
//*************************************************************************
@ -354,6 +385,20 @@ namespace etl
output_begin, static_cast<size_t>(etl::distance(output_begin, output_end)));
}
//*************************************************************************
/// Decode from Base64 from and to span/span
//*************************************************************************
template <typename T, size_t Length1, size_t Length2>
ETL_CONSTEXPR14
static
typename etl::enable_if<etl::is_integral<T>::value && (etl::integral_limits<T>::bits == 8U), size_t>::type
decode(const etl::span<const char, Length1>& input_span,
const etl::span<T, Length2>& output_span)
{
return decode(input_span.begin(), input_span.size(),
output_span.begin(), output_span.size());
}
//*************************************************************************
/// Calculates the buffer size required to decode from Base64
//*************************************************************************

View File

@ -173,7 +173,7 @@ namespace etl
/// Gets the current size of the string.
///\return The current size of the string.
//*************************************************************************
size_type size() const
ETL_CONSTEXPR size_type size() const
{
return current_size;
}
@ -605,7 +605,7 @@ namespace etl
/// Returns a const pointer to the beginning of the string data.
///\return A const pointer to the beginning of the string data.
//*********************************************************************
const_pointer data() const
ETL_CONSTEXPR const_pointer data() const
{
return p_buffer;
}

View File

@ -365,7 +365,7 @@ namespace etl
/// Returns a const pointer to the beginning of the vector data.
///\return A const pointer to the beginning of the vector data.
//*********************************************************************
const_pointer data() const
ETL_CONSTEXPR const_pointer data() const
{
return p_buffer;
}
@ -974,7 +974,7 @@ namespace etl
/// Gets the current size of the vector.
///\return The current size of the vector.
//*************************************************************************
size_type size() const
ETL_CONSTEXPR size_type size() const
{
return size_t(p_end - p_buffer);
}

View File

@ -30,6 +30,9 @@ SOFTWARE.
#include "etl/base64.h"
#include "etl/string.h"
#include "etl/vector.h"
#include <string>
#include <array>
#include <vector>
@ -349,8 +352,8 @@ namespace
{
encoded_output.fill(0);
auto size = etl::base64::encode(input_data_unsigned_char.data(), i,
encoded_output.data(), encoded_output.size());
auto size = etl::base64::encode(input_data_unsigned_char.data(), i,
encoded_output.data(), encoded_output.size());
std::string expected(encoded[i]);
std::string actual(encoded_output.data(), size);
@ -369,8 +372,8 @@ namespace
{
encoded_output.fill(0);
auto size = etl::base64::encode(input_data_unsigned_char.data(), input_data_unsigned_char.data() + i,
encoded_output.data(), encoded_output.data() + encoded_output.size());
auto size = etl::base64::encode(input_data_unsigned_char.data(), input_data_unsigned_char.data() + i,
encoded_output.data(), encoded_output.data() + encoded_output.size());
std::string expected(encoded[i]);
std::string actual(encoded_output.data(), size);
@ -402,6 +405,130 @@ namespace
}
}
//*************************************************************************
TEST(test_encode_unsigned_char_pointer_size_to_etl_string)
{
etl::string<344U> encoded_output;
for (size_t i = 0; i < 256; ++i)
{
encoded_output.clear();
auto size = etl::base64::encode(input_data_unsigned_char.data(), i,
encoded_output);
std::string expected(encoded[i]);
std::string actual(encoded_output.data(), size);
CHECK_EQUAL(expected, actual);
CHECK_EQUAL(etl::base64::encode_size(i), size);
}
}
//*************************************************************************
TEST(test_encode_unsigned_char_pointer_pointer_to_etl_string)
{
etl::string<344U> encoded_output;
for (size_t i = 0; i < 256; ++i)
{
encoded_output.clear();
auto size = etl::base64::encode(input_data_unsigned_char.data(), input_data_unsigned_char.data() + i,
encoded_output);
std::string expected(encoded[i]);
std::string actual(encoded_output.data(), size);
CHECK_EQUAL(expected, actual);
CHECK_EQUAL(etl::base64::encode_size(i), size);
}
}
//*************************************************************************
TEST(test_encode_unsigned_char_span_to_etl_string)
{
etl::string<344U> encoded_output;
for (size_t i = 0; i < 256; ++i)
{
encoded_output.clear();
etl::span<const unsigned char> input_span(input_data_unsigned_char.data(), i);
auto size = etl::base64::encode(input_span,
encoded_output);
std::string expected(encoded[i]);
std::string actual(encoded_output.data(), size);
CHECK_EQUAL(expected, actual);
CHECK_EQUAL(etl::base64::encode_size(i), size);
}
}
//*************************************************************************
TEST(test_encode_int8_t_pointer_size_to_etl_string)
{
etl::string<344U> encoded_output;
for (size_t i = 0; i < 256; ++i)
{
encoded_output.clear();
auto size = etl::base64::encode(input_data_int8_t.data(), i,
encoded_output);
std::string expected(encoded[i]);
std::string actual(encoded_output.data(), size);
CHECK_EQUAL(expected, actual);
CHECK_EQUAL(etl::base64::encode_size(i), size);
}
}
//*************************************************************************
TEST(test_encode_int8_t_pointer_pointer_to_etl_string)
{
etl::string<344U> encoded_output;
for (size_t i = 0; i < 256; ++i)
{
encoded_output.clear();
auto size = etl::base64::encode(input_data_int8_t.data(), input_data_int8_t.data() + i,
encoded_output);
std::string expected(encoded[i]);
std::string actual(encoded_output.data(), size);
CHECK_EQUAL(expected, actual);
CHECK_EQUAL(etl::base64::encode_size(i), size);
}
}
//*************************************************************************
TEST(test_encode_int8_t_span_to_etl_string)
{
etl::string<344U> encoded_output;
for (size_t i = 0; i < 256; ++i)
{
encoded_output.clear();
etl::span<const int8_t> input_span(input_data_int8_t.data(), i);
auto size = etl::base64::encode(input_span,
encoded_output);
std::string expected(encoded[i]);
std::string actual(encoded_output.data(), size);
CHECK_EQUAL(expected, actual);
CHECK_EQUAL(etl::base64::encode_size(i), size);
}
}
//*************************************************************************
TEST(test_encode_int8_t_pointer_size)
{
@ -411,8 +538,8 @@ namespace
{
encoded_output.fill(0);
auto size = etl::base64::encode(input_data_int8_t.data(), i,
encoded_output.data(), encoded_output.size());
auto size = etl::base64::encode(input_data_int8_t.data(), i,
encoded_output.data(), encoded_output.size());
std::string expected(encoded[i]);
std::string actual(encoded_output.data(), size);
@ -431,8 +558,8 @@ namespace
{
encoded_output.fill(0);
auto size = etl::base64::encode(input_data_int8_t.data(), input_data_int8_t.data() + i,
encoded_output.data(), encoded_output.data() + encoded_output.size());
auto size = etl::base64::encode(input_data_int8_t.data(), 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);
@ -472,8 +599,8 @@ namespace
constexpr size_t encode_size = etl::base64::encode_size(Size);
etl::array<char, etl::base64::encode_size(Size)> output{ 0 };
etl::base64::encode(input.begin(), Size,
output._buffer, encode_size);
etl::base64::encode(input.begin(), Size,
output._buffer, encode_size);
return output;
}
@ -497,8 +624,16 @@ namespace
{
std::array<char, 1> encoded_output{ 0 };
CHECK_THROW((etl::base64::encode(input_data_unsigned_char.data(), 10,
encoded_output.data(), encoded_output.size())), etl::base64_overflow);
CHECK_THROW((etl::base64::encode(input_data_unsigned_char.data(), 10,
encoded_output.data(), encoded_output.size())), etl::base64_overflow);
}
//*************************************************************************
TEST(test_encode_overflow_for_etl_string)
{
etl::string<10> output;
CHECK_THROW((etl::base64::encode(input_data_unsigned_char.data(), 10, output)), etl::base64_overflow);
}
//*************************************************************************
@ -510,8 +645,8 @@ namespace
{
decoded_output.fill(0);
auto decoded_size = etl::base64::decode(encoded[i].data(), encoded[i].size(),
decoded_output.data(), decoded_output.size());
auto decoded_size = etl::base64::decode(encoded[i].data(), encoded[i].size(),
decoded_output.data(), decoded_output.size());
CHECK_ARRAY_EQUAL(input_data_unsigned_char.data(), decoded_output.data(), i);
CHECK_EQUAL(i, etl::base64::decode_size(encoded[i].data(), encoded[i].size()));
@ -528,8 +663,8 @@ namespace
{
decoded_output.fill(0);
auto decoded_size = etl::base64::decode(encoded[i].data(), encoded[i].size(),
decoded_output.data(), decoded_output.size());
auto decoded_size = etl::base64::decode(encoded[i].data(), encoded[i].size(),
decoded_output.data(), decoded_output.size());
CHECK_ARRAY_EQUAL(input_data_int8_t.data(), decoded_output.data(), i);
CHECK_EQUAL(i, etl::base64::decode_size(encoded[i].data(), encoded[i].size()));
@ -542,8 +677,8 @@ namespace
{
std::array<unsigned char, 1> decoded_output{ 0 };
CHECK_THROW((etl::base64::decode(encoded[10].data(), encoded[10].size(),
decoded_output.data(), decoded_output.size())), etl::base64_overflow);
CHECK_THROW((etl::base64::decode(encoded[10].data(), encoded[10].size(),
decoded_output.data(), decoded_output.size())), etl::base64_overflow);
}
};
}