mirror of
https://github.com/ETLCPP/etl.git
synced 2026-04-30 19:09:10 +08:00
Final changes
This commit is contained in:
parent
f7281dc680
commit
6bc244cf8e
@ -1,4 +1,6 @@
|
||||
///\file
|
||||
//*************************************************************************
|
||||
///Decode from Base64 from and to pointer/length
|
||||
//*************************************************************************///\file
|
||||
|
||||
/******************************************************************************
|
||||
The MIT License(MIT)
|
||||
@ -34,6 +36,7 @@ SOFTWARE.
|
||||
#include "etl/binary.h"
|
||||
#include "etl/algorithm.h"
|
||||
#include "etl/integral_limits.h"
|
||||
#include "etl/iterator.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
@ -65,136 +68,156 @@ namespace etl
|
||||
}
|
||||
};
|
||||
|
||||
//*************************************************************************
|
||||
/// Codec for Base64
|
||||
//*************************************************************************
|
||||
class base64
|
||||
{
|
||||
public:
|
||||
|
||||
//*************************************************************************
|
||||
/// Encode to Base64 from and to pointer/length
|
||||
//*************************************************************************
|
||||
template <typename T>
|
||||
ETL_CONSTEXPR14
|
||||
static
|
||||
typename etl::enable_if<etl::is_integral<T>::value && (etl::integral_limits<T>::bits == 8U), etl::span<const char> >::type
|
||||
typename etl::enable_if<etl::is_integral<T>::value && (etl::integral_limits<T>::bits == 8U), size_t>::type
|
||||
encode(const T* input, size_t input_length, char* output, size_t output_length)
|
||||
{
|
||||
etl::span<const char> result;
|
||||
|
||||
int count = 0;
|
||||
|
||||
if (input_length > 0U)
|
||||
if (input_length == 0U)
|
||||
{
|
||||
// Figure out if the output buffer is large enough.
|
||||
size_t required_output_length = (input_length * 8U) / 6U;
|
||||
|
||||
if ((input_length % 3U) != 0U)
|
||||
{
|
||||
while ((required_output_length % 4U) != 0)
|
||||
{
|
||||
++required_output_length;
|
||||
}
|
||||
}
|
||||
|
||||
ETL_ASSERT_OR_RETURN_VALUE(output_length >= required_output_length, ETL_ERROR(base64_overflow), etl::span<const T>());
|
||||
|
||||
const T* p_in = input;
|
||||
const T* p_in_end = input + input_length;
|
||||
|
||||
char* p_out = output;
|
||||
char* p_out_end = output + required_output_length;
|
||||
|
||||
int next_sextet = First_Sextet;
|
||||
|
||||
// Step through the input buffer, creating the output sextets.
|
||||
while (p_in != p_in_end)
|
||||
{
|
||||
T c = *p_in;
|
||||
char index = 0;
|
||||
|
||||
switch (next_sextet)
|
||||
{
|
||||
case First_Sextet:
|
||||
{
|
||||
index = static_cast<char>((c & b11111100) >> 2);
|
||||
next_sextet = Second_Sextet;
|
||||
break;
|
||||
}
|
||||
|
||||
case Second_Sextet:
|
||||
{
|
||||
index = static_cast<char>((c & b00000011) << 4);
|
||||
++p_in;
|
||||
++count;
|
||||
|
||||
// Next byte valid?
|
||||
if (p_in != p_in_end)
|
||||
{
|
||||
c = *p_in;
|
||||
index = index | ((c & b11110000) >> 4);
|
||||
}
|
||||
next_sextet = Third_Sextet;
|
||||
break;
|
||||
}
|
||||
|
||||
case Third_Sextet:
|
||||
{
|
||||
index = (c & b00001111) << 2;
|
||||
++p_in;
|
||||
++count;
|
||||
|
||||
// Next byte valid?
|
||||
if (p_in != p_in_end)
|
||||
{
|
||||
c = *p_in;
|
||||
index = index | static_cast<char>((c & b11000000) >> 6);
|
||||
}
|
||||
next_sextet = Fourth_Sextet;
|
||||
break;
|
||||
}
|
||||
|
||||
case Fourth_Sextet:
|
||||
{
|
||||
index = static_cast<char>(c & b00111111);
|
||||
++p_in;
|
||||
++count;
|
||||
next_sextet = First_Sextet;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
// Should never get here.
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
*p_out = get_sextet_from_index(index);
|
||||
++p_out;
|
||||
}
|
||||
|
||||
// Pad out the end of the output buffer.
|
||||
while (p_out != p_out_end)
|
||||
{
|
||||
*p_out++ = Padding;
|
||||
}
|
||||
|
||||
result = etl::span<const char>(output, p_out);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return result;
|
||||
// Figure out if the output buffer is large enough.
|
||||
size_t required_output_length = (input_length * 8U) / 6U;
|
||||
|
||||
if ((input_length % 3U) != 0U)
|
||||
{
|
||||
while ((required_output_length % 4U) != 0)
|
||||
{
|
||||
++required_output_length;
|
||||
}
|
||||
}
|
||||
|
||||
ETL_ASSERT_OR_RETURN_VALUE(output_length >= required_output_length, ETL_ERROR(base64_overflow), etl::span<const T>());
|
||||
|
||||
const T* p_in = input;
|
||||
const T* p_in_end = input + input_length;
|
||||
|
||||
char* p_out = output;
|
||||
char* p_out_end = output + required_output_length;
|
||||
|
||||
int next_sextet = First_Sextet;
|
||||
|
||||
// Step through the input buffer, creating the output sextets.
|
||||
while (p_in != p_in_end)
|
||||
{
|
||||
T c = *p_in;
|
||||
char index = 0;
|
||||
|
||||
switch (next_sextet)
|
||||
{
|
||||
//**************************
|
||||
case First_Sextet:
|
||||
{
|
||||
index = static_cast<char>((*p_in & b11111100) >> 2);
|
||||
next_sextet = Second_Sextet;
|
||||
break;
|
||||
}
|
||||
|
||||
//**************************
|
||||
case Second_Sextet:
|
||||
{
|
||||
index = static_cast<char>((c & b00000011) << 4);
|
||||
++p_in;
|
||||
|
||||
// Next byte valid?
|
||||
if (p_in != p_in_end)
|
||||
{
|
||||
index = index | ((*p_in & b11110000) >> 4);
|
||||
}
|
||||
next_sextet = Third_Sextet;
|
||||
break;
|
||||
}
|
||||
|
||||
//**************************
|
||||
case Third_Sextet:
|
||||
{
|
||||
index = (c & b00001111) << 2;
|
||||
++p_in;
|
||||
|
||||
// Next byte valid?
|
||||
if (p_in != p_in_end)
|
||||
{
|
||||
index = index | static_cast<char>((*p_in & b11000000) >> 6);
|
||||
}
|
||||
next_sextet = Fourth_Sextet;
|
||||
break;
|
||||
}
|
||||
|
||||
//**************************
|
||||
case Fourth_Sextet:
|
||||
{
|
||||
index = static_cast<char>(c & b00111111);
|
||||
++p_in;
|
||||
next_sextet = First_Sextet;
|
||||
break;
|
||||
}
|
||||
|
||||
//**************************
|
||||
default:
|
||||
{
|
||||
// Should never get here.
|
||||
assert(false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
*p_out = get_sextet_from_index(index);
|
||||
++p_out;
|
||||
}
|
||||
|
||||
// Pad out the end of the output buffer.
|
||||
while (p_out != p_out_end)
|
||||
{
|
||||
*p_out++ = padding();
|
||||
}
|
||||
|
||||
return static_cast<size_t>(etl::distance(output, p_out));
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Encode to Base64 from and to span/span
|
||||
//*************************************************************************
|
||||
template <typename T, size_t Length1, size_t Length2>
|
||||
ETL_CONSTEXPR14
|
||||
static
|
||||
typename etl::enable_if<etl::is_integral<T>::value && (etl::integral_limits<T>::bits == 8U), etl::span<const char> >::type
|
||||
encode(const etl::span<const T, Length1>& input_span,
|
||||
const etl::span<char, Length2>& output_span)
|
||||
typename etl::enable_if<etl::is_integral<T>::value && (etl::integral_limits<T>::bits == 8U), size_t>::type
|
||||
encode(const etl::span<const T, Length1>& input_span,
|
||||
const etl::span<char, Length2>& output_span)
|
||||
{
|
||||
return encode(input_span.begin(), input_span.size(),
|
||||
output_span.begin(), output_span.size());
|
||||
return encode(input_span.begin(), input_span.size(),
|
||||
output_span.begin(), output_span.size());
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Encode to Base64 from and to pointer/pointer
|
||||
//*************************************************************************
|
||||
template <typename T>
|
||||
ETL_CONSTEXPR14
|
||||
static
|
||||
typename etl::enable_if<etl::is_integral<T>::value && (etl::integral_limits<T>::bits == 8U), size_t>::type
|
||||
encode(const T* input_begin, const T* input_end, char* output_begin, char* output_end)
|
||||
{
|
||||
return encode(input_begin, static_cast<size_t>(etl::distance(input_begin, input_end)),
|
||||
output_begin, static_cast<size_t>(etl::distance(output_begin, output_end)));
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Calculates the buffer size required to encode to Base64
|
||||
//*************************************************************************
|
||||
ETL_NODISCARD
|
||||
ETL_CONSTEXPR14
|
||||
static
|
||||
size_t encode_size(size_t input_length)
|
||||
@ -212,98 +235,105 @@ namespace etl
|
||||
return required_output_length;
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Decode from Base64 from and to pointer/length
|
||||
//*************************************************************************
|
||||
template <typename T>
|
||||
ETL_CONSTEXPR14
|
||||
static
|
||||
typename etl::enable_if<etl::is_integral<T>::value && (etl::integral_limits<T>::bits == 8U), etl::span<const T> >::type
|
||||
typename etl::enable_if<etl::is_integral<T>::value && (etl::integral_limits<T>::bits == 8U), size_t>::type
|
||||
decode(const char* input, size_t input_length, T* output, size_t output_length)
|
||||
{
|
||||
etl::span<const T> result;
|
||||
|
||||
if (input_length > 0)
|
||||
if (input_length == 0)
|
||||
{
|
||||
// Figure out if the output buffer is large enough.
|
||||
size_t length = etl::distance(input, etl::find(input, input + input_length, Padding)) - 1;
|
||||
size_t required_output_length = length - (length / 4U);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ETL_ASSERT_OR_RETURN_VALUE(output_length >= required_output_length, ETL_ERROR(base64_overflow), etl::span<const T>());
|
||||
// Figure out if the output buffer is large enough.
|
||||
size_t length = static_cast<size_t>(etl::distance(input, etl::find(input, input + input_length, padding())) - 1);
|
||||
size_t required_output_length = length - (length / 4U);
|
||||
|
||||
const char* p_in = input;
|
||||
const char* p_in_end = input + input_length;
|
||||
ETL_ASSERT_OR_RETURN_VALUE(output_length >= required_output_length, ETL_ERROR(base64_overflow), etl::span<const T>());
|
||||
|
||||
T* p_out = output;
|
||||
T* p_out_end = output + output_length;
|
||||
const char* p_in = input;
|
||||
const char* p_in_end = input + input_length;
|
||||
|
||||
T c = 0;
|
||||
int next_sextet = First_Sextet;
|
||||
T* p_out = output;
|
||||
|
||||
// Step through the input buffer, creating the output binary.
|
||||
while (p_in != p_in_end)
|
||||
T c = 0;
|
||||
int next_sextet = First_Sextet;
|
||||
|
||||
// Step through the input buffer, creating the output binary.
|
||||
while (p_in != p_in_end)
|
||||
{
|
||||
char sextet = *p_in++; // Get the sextet as a T.
|
||||
|
||||
if (sextet == padding())
|
||||
{
|
||||
char sextet = *p_in++; // Get the sextet as a T.
|
||||
break;
|
||||
}
|
||||
|
||||
if (sextet == Padding)
|
||||
char index = get_index_from_sextet(sextet);
|
||||
|
||||
switch (next_sextet)
|
||||
{
|
||||
//**************************
|
||||
case First_Sextet:
|
||||
{
|
||||
c = (index & b00111111) << 2;
|
||||
next_sextet = Second_Sextet;
|
||||
break;
|
||||
}
|
||||
|
||||
char index = get_index_from_sextet(sextet);
|
||||
|
||||
switch (next_sextet)
|
||||
//**************************
|
||||
case Second_Sextet:
|
||||
{
|
||||
case First_Sextet:
|
||||
{
|
||||
c = (index & b00111111) << 2;
|
||||
next_sextet = Second_Sextet;
|
||||
break;
|
||||
}
|
||||
c |= (index & b00110000) >> 4;
|
||||
*p_out++ = static_cast<T>(c);
|
||||
c = (index & b00001111) << 4;
|
||||
next_sextet = Third_Sextet;
|
||||
break;
|
||||
}
|
||||
|
||||
case Second_Sextet:
|
||||
{
|
||||
c |= (index & b00110000) >> 4;
|
||||
*p_out++ = static_cast<T>(c);
|
||||
c = (index & b00001111) << 4;
|
||||
next_sextet = Third_Sextet;
|
||||
break;
|
||||
}
|
||||
//**************************
|
||||
case Third_Sextet:
|
||||
{
|
||||
c |= (index & b00111100) >> 2;
|
||||
*p_out++ = static_cast<T>(c);
|
||||
c = (index & b00000011) << 6;
|
||||
next_sextet = Fourth_Sextet;
|
||||
break;
|
||||
}
|
||||
|
||||
case Third_Sextet:
|
||||
{
|
||||
c |= (index & b00111100) >> 2;
|
||||
*p_out++ = static_cast<T>(c);
|
||||
c = (index & b00000011) << 6;
|
||||
next_sextet = Fourth_Sextet;
|
||||
break;
|
||||
}
|
||||
//**************************
|
||||
case Fourth_Sextet:
|
||||
{
|
||||
c |= (index & b00111111);
|
||||
*p_out++ = static_cast<T>(c);
|
||||
next_sextet = First_Sextet;
|
||||
break;
|
||||
}
|
||||
|
||||
case Fourth_Sextet:
|
||||
{
|
||||
c |= (index & b00111111);
|
||||
*p_out++ = static_cast<T>(c);
|
||||
next_sextet = First_Sextet;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
// Should never get here.
|
||||
break;
|
||||
}
|
||||
//**************************
|
||||
default:
|
||||
{
|
||||
// Should never get here.
|
||||
assert(false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
result = etl::span<const T>(output, p_out);
|
||||
}
|
||||
|
||||
return result;
|
||||
return static_cast<size_t>(etl::distance(output, p_out));
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Decode from Base64 from and to span/span
|
||||
//*************************************************************************
|
||||
template <typename T, size_t Length1, size_t Length2>
|
||||
ETL_CONSTEXPR14
|
||||
static
|
||||
typename etl::enable_if<etl::is_integral<T>::value && (etl::integral_limits<T>::bits == 8U), etl::span<const T> >::type
|
||||
typename etl::enable_if<etl::is_integral<T>::value && (etl::integral_limits<T>::bits == 8U), size_t>::type
|
||||
decode(const etl::span<const char, Length1>& input_span,
|
||||
const etl::span<T, Length2>& output_span)
|
||||
{
|
||||
@ -311,26 +341,33 @@ namespace etl
|
||||
output_span.begin(), output_span.size());
|
||||
}
|
||||
|
||||
////*************************************************************************
|
||||
//template <typename T, size_t Length>
|
||||
//ETL_CONSTEXPR14
|
||||
//static
|
||||
//typename etl::enable_if<etl::is_integral<T>::value && (etl::integral_limits<T>::bits == 8U), etl::span<const T> >::type
|
||||
// decode_size(const etl::span<const char, Length>& input_span)
|
||||
//{
|
||||
// // Figure out the minimum output buffer size.
|
||||
// size_t length = etl::distance(input, etl::find(input, input + input_length, Padding)) - 1;
|
||||
// size_t required_output_length = length - (length / 4U);
|
||||
|
||||
// return required_output_length;
|
||||
//}
|
||||
//*************************************************************************
|
||||
/// Decode from Base64 from and to pointer/pointer
|
||||
//*************************************************************************
|
||||
template <typename T>
|
||||
ETL_CONSTEXPR14
|
||||
static
|
||||
typename etl::enable_if<etl::is_integral<T>::value && (etl::integral_limits<T>::bits == 8U), size_t>::type
|
||||
decode(const char* input_begin, const char* input_end, T* output_begin, T* output_end)
|
||||
{
|
||||
return decode(input_begin, static_cast<size_t>(etl::distance(input_begin, input_end)),
|
||||
output_begin, static_cast<size_t>(etl::distance(output_begin, output_end)));
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Calculates the buffer size required to decode from Base64
|
||||
//*************************************************************************
|
||||
ETL_NODISCARD
|
||||
ETL_CONSTEXPR14
|
||||
static size_t decode_size(const char* input, size_t input_length)
|
||||
{
|
||||
if (input_length == 0U)
|
||||
{
|
||||
return 0U;
|
||||
}
|
||||
|
||||
// Figure out the minimum output buffer size.
|
||||
size_t length = etl::distance(input, etl::find(input, input + input_length, Padding)) - 1;
|
||||
size_t length = static_cast<size_t>(etl::distance(input, etl::find(input, input + input_length, padding())) - 1);
|
||||
size_t required_output_length = length - (length / 4U);
|
||||
|
||||
return required_output_length;
|
||||
@ -348,38 +385,92 @@ namespace etl
|
||||
Fourth_Sextet
|
||||
};
|
||||
|
||||
//*************************************************************************
|
||||
/// The Base64 padding character
|
||||
static ETL_CONSTANT char Padding = '=';
|
||||
|
||||
//*************************************************************************
|
||||
// Sextet lookup.
|
||||
static ETL_CONSTANT char lookup_char[64] =
|
||||
{
|
||||
'A', 'B', 'C', 'D', 'E', 'F' , 'G', 'H',
|
||||
'I', 'J', 'K', 'L', 'M', 'N' , 'O', 'P',
|
||||
'Q', 'R', 'S', 'T', 'U', 'V' , 'W', 'X',
|
||||
'Y', 'Z', 'a', 'b', 'c', 'd' , 'e', 'f',
|
||||
'g', 'h', 'i', 'j', 'k', 'l' , 'm', 'n',
|
||||
'o', 'p', 'q', 'r', 's', 't' , 'u', 'v',
|
||||
'w', 'x', 'y', 'z', '0', '1' , '2', '3',
|
||||
'4', '5', '6', '7', '8', '9' , '+', '/'
|
||||
};
|
||||
// Sextets
|
||||
// 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
|
||||
// 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
|
||||
// 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
|
||||
// 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
|
||||
// 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
|
||||
// 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
|
||||
// 'w', 'x', 'y', 'z', '0', '1', '2', '3',
|
||||
// '4', '5', '6', '7', '8', '9', '+', '/'
|
||||
|
||||
//*************************************************************************
|
||||
// Translates an index into a sextet
|
||||
//*************************************************************************
|
||||
ETL_CONSTEXPR14 static char get_sextet_from_index(char index)
|
||||
{
|
||||
return lookup_char[index];
|
||||
if ((index >= 0) && (index < 26))
|
||||
{
|
||||
return 'A' + index;
|
||||
}
|
||||
else if ((index >= 26) && (index < 52))
|
||||
{
|
||||
index -= 26;
|
||||
return 'a' + index;
|
||||
}
|
||||
else if ((index >= 52) && (index < 62))
|
||||
{
|
||||
index -= 52;
|
||||
return '0' + index;
|
||||
}
|
||||
else if (index == 62)
|
||||
{
|
||||
return '+';
|
||||
}
|
||||
else if (index == 63)
|
||||
{
|
||||
return '/';
|
||||
}
|
||||
else
|
||||
{
|
||||
// Should never get here.
|
||||
assert(false);
|
||||
return padding();
|
||||
}
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
// Translates a sextet into an index
|
||||
//*************************************************************************
|
||||
ETL_CONSTEXPR14 static char get_index_from_sextet(char sextet)
|
||||
{
|
||||
const char* p = etl::find(lookup_char, lookup_char + 64, sextet);
|
||||
if ((sextet >= 'A') && (sextet <= 'Z'))
|
||||
{
|
||||
return sextet - 'A';
|
||||
}
|
||||
else if ((sextet >= 'a') && (sextet <= 'z'))
|
||||
{
|
||||
return sextet - 'a' + 26;
|
||||
}
|
||||
else if ((sextet >= '0') && (sextet <= '9'))
|
||||
{
|
||||
return sextet - '0' + 52;
|
||||
}
|
||||
else if (sextet == '+')
|
||||
{
|
||||
return 62;
|
||||
}
|
||||
else if (sextet == '/')
|
||||
{
|
||||
return 63;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Should never get here.
|
||||
assert(false);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return static_cast<char>(etl::distance(lookup_char, p));
|
||||
//*************************************************************************
|
||||
/// Gets the padding character
|
||||
//*************************************************************************
|
||||
ETL_NODISCARD
|
||||
ETL_CONSTEXPR14
|
||||
static char padding()
|
||||
{
|
||||
return '=';
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@ -19,6 +19,7 @@ add_executable(etl_tests
|
||||
test_array_view.cpp
|
||||
test_array_wrapper.cpp
|
||||
test_atomic.cpp
|
||||
test_base64.cpp
|
||||
test_binary.cpp
|
||||
test_bip_buffer_spsc_atomic.cpp
|
||||
test_bit.cpp
|
||||
|
||||
29
test/syntax_check/base64.h.t.cpp
Normal file
29
test/syntax_check/base64.h.t.cpp
Normal file
@ -0,0 +1,29 @@
|
||||
/******************************************************************************
|
||||
The MIT License(MIT)
|
||||
|
||||
Embedded Template Library.
|
||||
https://github.com/ETLCPP/etl
|
||||
https://www.etlcpp.com
|
||||
|
||||
Copyright(c) 2023 John Wellbelove
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files(the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions :
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
******************************************************************************/
|
||||
|
||||
#include <etl/base64.h>
|
||||
@ -46,6 +46,7 @@ target_sources(t98 PRIVATE etl_profile.h
|
||||
../array_view.h.t.cpp
|
||||
../array_wrapper.h.t.cpp
|
||||
../atomic.h.t.cpp
|
||||
../base64.h.t.cpp
|
||||
../basic_format_spec.h.t.cpp
|
||||
../basic_string.h.t.cpp
|
||||
../basic_string_stream.h.t.cpp
|
||||
|
||||
@ -46,6 +46,7 @@ target_sources(t11 PRIVATE etl_profile.h
|
||||
../array_view.h.t.cpp
|
||||
../array_wrapper.h.t.cpp
|
||||
../atomic.h.t.cpp
|
||||
../base64.h.t.cpp
|
||||
../basic_format_spec.h.t.cpp
|
||||
../basic_string.h.t.cpp
|
||||
../basic_string_stream.h.t.cpp
|
||||
|
||||
@ -46,6 +46,7 @@ target_sources(t14 PRIVATE etl_profile.h
|
||||
../array_view.h.t.cpp
|
||||
../array_wrapper.h.t.cpp
|
||||
../atomic.h.t.cpp
|
||||
../base64.h.t.cpp
|
||||
../basic_format_spec.h.t.cpp
|
||||
../basic_string.h.t.cpp
|
||||
../basic_string_stream.h.t.cpp
|
||||
|
||||
@ -46,6 +46,7 @@ target_sources(t17 PRIVATE etl_profile.h
|
||||
../array_view.h.t.cpp
|
||||
../array_wrapper.h.t.cpp
|
||||
../atomic.h.t.cpp
|
||||
../base64.h.t.cpp
|
||||
../basic_format_spec.h.t.cpp
|
||||
../basic_string.h.t.cpp
|
||||
../basic_string_stream.h.t.cpp
|
||||
|
||||
@ -46,6 +46,7 @@ target_sources(t20 PRIVATE etl_profile.h
|
||||
../array_view.h.t.cpp
|
||||
../array_wrapper.h.t.cpp
|
||||
../atomic.h.t.cpp
|
||||
../base64.h.t.cpp
|
||||
../basic_format_spec.h.t.cpp
|
||||
../basic_string.h.t.cpp
|
||||
../basic_string_stream.h.t.cpp
|
||||
|
||||
@ -32,10 +32,12 @@ SOFTWARE.
|
||||
|
||||
#include <string>
|
||||
#include <array>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
|
||||
namespace
|
||||
{
|
||||
std::array<unsigned char, 256> input_data =
|
||||
std::array<unsigned char, 256> input_data_unsigned_char =
|
||||
{
|
||||
0x3B, 0x27, 0x03, 0x43, 0x2D, 0xFB, 0x28, 0x2A, 0x61, 0xAE, 0xBC, 0x49, 0x71, 0x32, 0x01, 0x15,
|
||||
0x69, 0x5C, 0x5E, 0xF5, 0xD5, 0x9B, 0xDE, 0xA5, 0x57, 0xC9, 0xC1, 0x7D, 0x80, 0xDE, 0x4C, 0x81,
|
||||
@ -55,6 +57,26 @@ namespace
|
||||
0xA8, 0x52, 0x3C, 0x9E, 0xCD, 0xDE, 0x21, 0x34, 0x3E, 0x1F, 0xB5, 0x54, 0xD7, 0xFB, 0xB4, 0xBD
|
||||
};
|
||||
|
||||
std::array<int8_t, 256> input_data_int8_t =
|
||||
{
|
||||
int8_t(0x3B), int8_t(0x27), int8_t(0x03), int8_t(0x43), int8_t(0x2D), int8_t(0xFB), int8_t(0x28), int8_t(0x2A), int8_t(0x61), int8_t(0xAE), int8_t(0xBC), int8_t(0x49), int8_t(0x71), int8_t(0x32), int8_t(0x01), int8_t(0x15),
|
||||
int8_t(0x69), int8_t(0x5C), int8_t(0x5E), int8_t(0xF5), int8_t(0xD5), int8_t(0x9B), int8_t(0xDE), int8_t(0xA5), int8_t(0x57), int8_t(0xC9), int8_t(0xC1), int8_t(0x7D), int8_t(0x80), int8_t(0xDE), int8_t(0x4C), int8_t(0x81),
|
||||
int8_t(0xC0), int8_t(0xCF), int8_t(0x2A), int8_t(0xD1), int8_t(0x86), int8_t(0x56), int8_t(0xD5), int8_t(0x71), int8_t(0x37), int8_t(0xEB), int8_t(0x80), int8_t(0x32), int8_t(0xDF), int8_t(0xE4), int8_t(0xDF), int8_t(0xB6),
|
||||
int8_t(0xEE), int8_t(0x3F), int8_t(0xDC), int8_t(0x79), int8_t(0xB3), int8_t(0x17), int8_t(0x8E), int8_t(0x76), int8_t(0x65), int8_t(0x8E), int8_t(0x96), int8_t(0x21), int8_t(0xB9), int8_t(0x88), int8_t(0xD1), int8_t(0x6D),
|
||||
int8_t(0xD0), int8_t(0xDD), int8_t(0xFF), int8_t(0xDA), int8_t(0xA8), int8_t(0x7A), int8_t(0x4D), int8_t(0xF5), int8_t(0x71), int8_t(0x77), int8_t(0xFD), int8_t(0x2E), int8_t(0xF2), int8_t(0xE4), int8_t(0x40), int8_t(0x72),
|
||||
int8_t(0x8C), int8_t(0x83), int8_t(0x00), int8_t(0x6F), int8_t(0x13), int8_t(0x72), int8_t(0x53), int8_t(0xE4), int8_t(0x6B), int8_t(0x70), int8_t(0x0E), int8_t(0x37), int8_t(0xCA), int8_t(0x25), int8_t(0xCD), int8_t(0x68),
|
||||
int8_t(0x62), int8_t(0xC0), int8_t(0xAB), int8_t(0x14), int8_t(0xC7), int8_t(0x59), int8_t(0x83), int8_t(0xD2), int8_t(0x82), int8_t(0x8C), int8_t(0x93), int8_t(0x6D), int8_t(0x13), int8_t(0x21), int8_t(0xC0), int8_t(0x08),
|
||||
int8_t(0xF9), int8_t(0x6D), int8_t(0xAC), int8_t(0x84), int8_t(0x78), int8_t(0x49), int8_t(0x84), int8_t(0x6F), int8_t(0x6B), int8_t(0xFB), int8_t(0x20), int8_t(0x3B), int8_t(0x9C), int8_t(0x49), int8_t(0xFB), int8_t(0x4E),
|
||||
int8_t(0x80), int8_t(0x69), int8_t(0x82), int8_t(0x25), int8_t(0x86), int8_t(0x95), int8_t(0xD5), int8_t(0x4D), int8_t(0x91), int8_t(0xED), int8_t(0xD2), int8_t(0x77), int8_t(0x2A), int8_t(0x24), int8_t(0x40), int8_t(0x8A),
|
||||
int8_t(0xDF), int8_t(0x4D), int8_t(0x80), int8_t(0x2D), int8_t(0xCD), int8_t(0xD5), int8_t(0x5A), int8_t(0x26), int8_t(0xA6), int8_t(0x71), int8_t(0x15), int8_t(0x42), int8_t(0x0E), int8_t(0x3F), int8_t(0xB2), int8_t(0x70),
|
||||
int8_t(0x14), int8_t(0x29), int8_t(0x1F), int8_t(0x8D), int8_t(0x23), int8_t(0x2E), int8_t(0xC1), int8_t(0xEA), int8_t(0xCE), int8_t(0xF9), int8_t(0x7E), int8_t(0x6C), int8_t(0xDF), int8_t(0x1C), int8_t(0xA3), int8_t(0x84),
|
||||
int8_t(0x2B), int8_t(0x24), int8_t(0x35), int8_t(0xA7), int8_t(0x63), int8_t(0xC8), int8_t(0x0B), int8_t(0x1F), int8_t(0x8B), int8_t(0xBA), int8_t(0x51), int8_t(0xBF), int8_t(0xE9), int8_t(0x51), int8_t(0x80), int8_t(0xD2),
|
||||
int8_t(0x23), int8_t(0xB5), int8_t(0xD1), int8_t(0xB4), int8_t(0x59), int8_t(0xAE), int8_t(0x7D), int8_t(0x30), int8_t(0x1D), int8_t(0x00), int8_t(0x1C), int8_t(0xD8), int8_t(0x70), int8_t(0x6C), int8_t(0x16), int8_t(0x71),
|
||||
int8_t(0xC7), int8_t(0x56), int8_t(0x08), int8_t(0xFE), int8_t(0x81), int8_t(0xAE), int8_t(0xFB), int8_t(0xE0), int8_t(0x92), int8_t(0xD8), int8_t(0xDB), int8_t(0xB9), int8_t(0x57), int8_t(0x7C), int8_t(0x99), int8_t(0xCB),
|
||||
int8_t(0x42), int8_t(0xEF), int8_t(0xFC), int8_t(0xB3), int8_t(0x56), int8_t(0x1E), int8_t(0xD1), int8_t(0x42), int8_t(0xD3), int8_t(0x0C), int8_t(0x18), int8_t(0xB3), int8_t(0xEE), int8_t(0xAF), int8_t(0x1A), int8_t(0x77),
|
||||
int8_t(0xA8), int8_t(0x52), int8_t(0x3C), int8_t(0x9E), int8_t(0xCD), int8_t(0xDE), int8_t(0x21), int8_t(0x34), int8_t(0x3E), int8_t(0x1F), int8_t(0xB5), int8_t(0x54), int8_t(0xD7), int8_t(0xFB), int8_t(0xB4), int8_t(0xBD)
|
||||
};
|
||||
|
||||
std::array<std::string, 257> encoded =
|
||||
{
|
||||
"",
|
||||
@ -318,27 +340,210 @@ namespace
|
||||
|
||||
SUITE(test_base64)
|
||||
{
|
||||
TEST(test_encode)
|
||||
//*************************************************************************
|
||||
TEST(test_encode_unsigned_char_pointer_size)
|
||||
{
|
||||
constexpr int length = 200;
|
||||
std::array<char, 344U> encoded_output;
|
||||
|
||||
constexpr size_t require_encoded_length = etl::base64::encode_size(length);
|
||||
for (size_t i = 0; i < 256; ++i)
|
||||
{
|
||||
encoded_output.fill(0);
|
||||
|
||||
std::array<char, require_encoded_length> encoded_output;
|
||||
auto size = etl::base64::encode(input_data_unsigned_char.data(), i,
|
||||
encoded_output.data(), encoded_output.size());
|
||||
|
||||
auto result = etl::base64::encode(input_data.data(), length, encoded_output.data(), encoded_output.size());
|
||||
std::string expected(encoded[i]);
|
||||
std::string actual(encoded_output.data(), size);
|
||||
|
||||
std::string expected(encoded[length]);
|
||||
std::string actual(result.begin(), result.end());
|
||||
|
||||
bool equal = actual == expected;
|
||||
|
||||
CHECK_EQUAL(require_encoded_length, result.size());
|
||||
CHECK_EQUAL(expected, actual);
|
||||
CHECK_EQUAL(etl::base64::encode_size(i), size);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(test_decode)
|
||||
//*************************************************************************
|
||||
TEST(test_encode_unsigned_char_pointer_pointer)
|
||||
{
|
||||
std::array<char, 344U> encoded_output;
|
||||
|
||||
for (size_t i = 0; i < 256; ++i)
|
||||
{
|
||||
encoded_output.fill(0);
|
||||
|
||||
auto size = etl::base64::encode(input_data_unsigned_char.data(), input_data_unsigned_char.data() + i,
|
||||
encoded_output.data(), encoded_output.data() + encoded_output.size());
|
||||
|
||||
std::string expected(encoded[i]);
|
||||
std::string actual(encoded_output.data(), size);
|
||||
|
||||
CHECK_EQUAL(expected, actual);
|
||||
CHECK_EQUAL(etl::base64::encode_size(i), size);
|
||||
}
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_encode_unsigned_char_span)
|
||||
{
|
||||
std::array<char, 344U> encoded_output;
|
||||
|
||||
for (size_t i = 0; i < 256; ++i)
|
||||
{
|
||||
encoded_output.fill(0);
|
||||
|
||||
etl::span<const unsigned char> input_span(input_data_unsigned_char.data(), i);
|
||||
etl::span<char> output_span(encoded_output.data(), encoded_output.size());
|
||||
|
||||
auto size = etl::base64::encode(input_span, output_span);
|
||||
|
||||
std::string expected(encoded[i]);
|
||||
std::string actual(encoded_output.data(), size);
|
||||
|
||||
CHECK_EQUAL(expected, actual);
|
||||
CHECK_EQUAL(etl::base64::encode_size(i), size);
|
||||
}
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_encode_int8_t_pointer_size)
|
||||
{
|
||||
std::array<char, 344U> encoded_output;
|
||||
|
||||
for (size_t i = 0; i < 256; ++i)
|
||||
{
|
||||
encoded_output.fill(0);
|
||||
|
||||
auto size = etl::base64::encode(input_data_int8_t.data(), i,
|
||||
encoded_output.data(), encoded_output.size());
|
||||
|
||||
std::string expected(encoded[i]);
|
||||
std::string actual(encoded_output.data(), size);
|
||||
|
||||
CHECK_EQUAL(expected, actual);
|
||||
CHECK_EQUAL(etl::base64::encode_size(i), size);
|
||||
}
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_encode_int8_t_pointer_pointer)
|
||||
{
|
||||
std::array<char, 344U> encoded_output;
|
||||
|
||||
for (size_t i = 0; i < 256; ++i)
|
||||
{
|
||||
encoded_output.fill(0);
|
||||
|
||||
auto size = etl::base64::encode(input_data_int8_t.data(), input_data_int8_t.data() + i,
|
||||
encoded_output.data(), encoded_output.data() + encoded_output.size());
|
||||
|
||||
std::string expected(encoded[i]);
|
||||
std::string actual(encoded_output.data(), size);
|
||||
|
||||
CHECK_EQUAL(expected, actual);
|
||||
CHECK_EQUAL(etl::base64::encode_size(i), size);
|
||||
}
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_encode_int8_t_span)
|
||||
{
|
||||
std::array<char, 344U> encoded_output;
|
||||
|
||||
for (size_t i = 0; i < 256; ++i)
|
||||
{
|
||||
encoded_output.fill(0);
|
||||
|
||||
etl::span<const int8_t> input_span(input_data_int8_t.data(), i);
|
||||
etl::span<char> output_span(encoded_output.data(), encoded_output.size());
|
||||
|
||||
auto size = etl::base64::encode(input_span, output_span);
|
||||
|
||||
std::string expected(encoded[i]);
|
||||
std::string actual(encoded_output.data(), size);
|
||||
|
||||
CHECK_EQUAL(expected, actual);
|
||||
CHECK_EQUAL(etl::base64::encode_size(i), size);
|
||||
}
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
#if ETL_USING_CPP14
|
||||
template <size_t Size>
|
||||
constexpr auto GetConstexprBase64(const etl::array<int8_t, Size> input) noexcept
|
||||
{
|
||||
constexpr size_t encode_size = etl::base64::encode_size(Size);
|
||||
etl::array<char, etl::base64::encode_size(Size)> output{ 0 };
|
||||
|
||||
etl::base64::encode(input.begin(), Size,
|
||||
output._buffer, encode_size);
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
TEST(test_encode_int8_t_constexpr)
|
||||
{
|
||||
constexpr etl::array<int8_t, 10> input = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
|
||||
|
||||
constexpr auto output{ GetConstexprBase64(input) };
|
||||
|
||||
std::string expected("AAECAwQFBgcICQ==");
|
||||
std::string actual(output.data(), output.size());
|
||||
|
||||
CHECK_EQUAL(expected, actual);
|
||||
CHECK_EQUAL(etl::base64::encode_size(10), output.size());
|
||||
}
|
||||
#endif
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_encode_overflow)
|
||||
{
|
||||
std::array<char, 1> encoded_output;
|
||||
|
||||
CHECK_THROW((etl::base64::encode(input_data_unsigned_char.data(), 10,
|
||||
encoded_output.data(), encoded_output.size())), etl::base64_overflow);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_decode_unsigned_char)
|
||||
{
|
||||
std::array<unsigned char, 256> decoded_output;
|
||||
|
||||
for (size_t i = 0; i < 256; ++i)
|
||||
{
|
||||
decoded_output.fill(0);
|
||||
|
||||
auto decoded_size = etl::base64::decode(encoded[i].data(), encoded[i].size(),
|
||||
decoded_output.data(), decoded_output.size());
|
||||
|
||||
CHECK_ARRAY_EQUAL(input_data_unsigned_char.data(), decoded_output.data(), i);
|
||||
CHECK_EQUAL(i, etl::base64::decode_size(encoded[i].data(), encoded[i].size()));
|
||||
CHECK_EQUAL(i, decoded_size);
|
||||
}
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_decode_int8_t)
|
||||
{
|
||||
std::array<int8_t, 256> decoded_output;
|
||||
|
||||
for (size_t i = 0; i < 256; ++i)
|
||||
{
|
||||
decoded_output.fill(0);
|
||||
|
||||
auto decoded_size = etl::base64::decode(encoded[i].data(), encoded[i].size(),
|
||||
decoded_output.data(), decoded_output.size());
|
||||
|
||||
CHECK_ARRAY_EQUAL(input_data_int8_t.data(), decoded_output.data(), i);
|
||||
CHECK_EQUAL(i, etl::base64::decode_size(encoded[i].data(), encoded[i].size()));
|
||||
CHECK_EQUAL(i, decoded_size);
|
||||
}
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_decode_overflow)
|
||||
{
|
||||
std::array<unsigned char, 1> decoded_output;
|
||||
|
||||
CHECK_THROW((etl::base64::decode(encoded[10].data(), encoded[10].size(),
|
||||
decoded_output.data(), decoded_output.size())), etl::base64_overflow);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
10700
test/vs2022/etl.vcxproj
10700
test/vs2022/etl.vcxproj
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user