feat(base64): encode
This commit is contained in:
@ -7,12 +7,12 @@
|
||||
|
||||
namespace base64
|
||||
{
|
||||
bool isValid(const char *str) noexcept;
|
||||
bool isValid(const char *str, size_t str_size) noexcept;
|
||||
bool isValid(std::string_view str) noexcept;
|
||||
|
||||
void encode(const uint8_t *data, uint64_t data_size, char *str) noexcept;
|
||||
void encode(const uint8_t *data, size_t data_size, char *str, size_t str_size);
|
||||
std::string encode(std::span<const uint8_t> data) noexcept;
|
||||
|
||||
void decode(const char *str, uint8_t *data, uint64_t data_size);
|
||||
std::vector<uint8_t> decode(std::string_view str);
|
||||
void decode(const char *str, size_t str_size, uint8_t *data, size_t data_size);
|
||||
std::vector<uint8_t> decode(std::string_view str) noexcept;
|
||||
}
|
||||
@ -29,9 +29,9 @@ static const int8_t b64map[] = {
|
||||
|
||||
namespace base64
|
||||
{
|
||||
bool isValid(const char *str) noexcept
|
||||
bool isValid(const char *str, size_t str_size) noexcept
|
||||
{
|
||||
return base64::isValid(std::string_view(str));
|
||||
return base64::isValid(std::string_view(str, str_size));
|
||||
}
|
||||
bool isValid(std::string_view str) noexcept
|
||||
{
|
||||
@ -44,12 +44,47 @@ namespace base64
|
||||
}
|
||||
return baseN::isValid(sv, b64map);
|
||||
}
|
||||
// void encode(const uint8_t *data, uint64_t data_size, char *str) noexcept
|
||||
// {
|
||||
// }
|
||||
// std::string encode(std::span<const uint8_t> data) noexcept
|
||||
// {
|
||||
// }
|
||||
void encode(const uint8_t *data, size_t data_size, char *str, size_t str_size)
|
||||
{
|
||||
if (str_size < data_size / 3 * 4 + (data_size % 3 ? 4 : 0))
|
||||
{
|
||||
throw std::logic_error("base64::encode: not enough allocated length");
|
||||
}
|
||||
for (size_t i = 0; i < data_size / 3; i++)
|
||||
{
|
||||
str[i * 4] = b64digits[data[i * 3] >> 2];
|
||||
str[i * 4 + 1] = b64digits[(data[i * 3] << 4 | data[i * 3 + 1] >> 4) & 0x3F];
|
||||
str[i * 4 + 2] = b64digits[(data[i * 3 + 1] << 2 | data[i * 3 + 2] >> 6) & 0x3F];
|
||||
str[i * 4 + 3] = b64digits[data[i * 3 + 2] & 0x3F];
|
||||
}
|
||||
uint64_t last_idx = data_size / 3 * 4;
|
||||
if (last_idx + 3 < str_size)
|
||||
{
|
||||
switch (data_size % 3)
|
||||
{
|
||||
case 1:
|
||||
str[last_idx] = b64digits[data[data_size - 1] >> 2];
|
||||
str[last_idx + 1] = b64digits[data[data_size - 1] << 4 & 0x30];
|
||||
str[last_idx + 2] = '=';
|
||||
str[last_idx + 3] = '=';
|
||||
break;
|
||||
case 2:
|
||||
str[last_idx] = b64digits[data[data_size - 2] >> 2];
|
||||
str[last_idx + 1] = b64digits[(data[data_size - 2] << 4 | data[data_size - 1] >> 4) & 0x3F];
|
||||
str[last_idx + 2] = b64digits[data[data_size - 1] & 0x0F];
|
||||
str[last_idx + 3] = '=';
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
std::string encode(std::span<const uint8_t> data) noexcept
|
||||
{
|
||||
std::string str(data.size() / 3 * 4 + (data.size() % 3 ? 4 : 0), ' ');
|
||||
base64::encode(data.data(), data.size(), str.data(), str.size());
|
||||
return str;
|
||||
}
|
||||
// void decode(const char *str, uint8_t *data, uint64_t data_size)
|
||||
// {
|
||||
// }
|
||||
|
||||
@ -13,14 +13,18 @@ TEST(base64, isValid)
|
||||
EXPECT_FALSE(isValid("1==="));
|
||||
EXPECT_FALSE(isValid("?!*"));
|
||||
}
|
||||
// TEST(base64, encode)
|
||||
// {
|
||||
// }
|
||||
// TEST(base64, encode_1e6)
|
||||
// {
|
||||
// std::vector<uint8_t> data(1e6);
|
||||
// encode(data);
|
||||
// }
|
||||
TEST(base64, encode)
|
||||
{
|
||||
EXPECT_EQ(encode(hex::decode("")), "");
|
||||
EXPECT_EQ(encode(hex::decode("04a504a5")), "BKUEpQ==");
|
||||
EXPECT_EQ(encode(hex::decode("04a504a500")), "BKUEpQA=");
|
||||
EXPECT_EQ(encode(hex::decode("04a504a50000")), "BKUEpQAA");
|
||||
}
|
||||
TEST(base64, encode_1e7)
|
||||
{
|
||||
std::vector<uint8_t> data(1e7);
|
||||
encode(data);
|
||||
}
|
||||
// TEST(base64, decode)
|
||||
// {
|
||||
// }
|
||||
|
||||
Reference in New Issue
Block a user