feat(baseN): encode
This commit is contained in:
172
src/baseN.cpp
172
src/baseN.cpp
@ -25,129 +25,63 @@ namespace baseN
|
||||
{
|
||||
throw std::overflow_error("baseN::sizeEncoded: overflow");
|
||||
}
|
||||
return data.size() * log256 / std::log(base) + 1;
|
||||
return data.size() * log256 / std::log(base) + 1;
|
||||
}
|
||||
uint64_t sizeDecoded(std::string_view str, uint8_t base) noexcept
|
||||
{
|
||||
return str.size() * std::log(base) / log256 + 1;
|
||||
}
|
||||
// void encode(const uint8_t *data, uint64_t data_size, char *str, uint8_t base, const char *digits, uint64_t enc_size) noexcept
|
||||
// {
|
||||
// if (data_size == 0)
|
||||
// {
|
||||
// return;
|
||||
// }
|
||||
// char res_str[enc_size];
|
||||
// uint8_t div_buf[data_size];
|
||||
// std::copy(data, data + data_size, div_buf);
|
||||
// int64_t
|
||||
// zero_count = 0,
|
||||
// idx_div = 0,
|
||||
// idx_quo = 0,
|
||||
// idx_quo_last = data_size,
|
||||
// idx_str = enc_size - 1;
|
||||
// uint16_t div = data[idx_div++];
|
||||
void encode(const uint8_t *data, uint64_t data_size, char *str, uint64_t str_size, uint8_t base, const char *digits)
|
||||
{
|
||||
std::vector<uint8_t> dv(std::find_if(data, data + data_size, [](uint8_t item)
|
||||
{ return item != 0; }),
|
||||
data + data_size);
|
||||
if (dv.size() == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
std::span<char> sv(str, str_size);
|
||||
auto sv_it = sv.rbegin();
|
||||
auto dv_it = dv.begin();
|
||||
auto quo_it = dv.begin();
|
||||
auto quo_it_last = dv.end();
|
||||
uint16_t div = *dv_it++;
|
||||
|
||||
// while (zero_count < (int64_t)data_size && data[zero_count] == 0)
|
||||
// {
|
||||
// zero_count++;
|
||||
// }
|
||||
// while (idx_quo_last > 1 || div_buf[0] > base)
|
||||
// {
|
||||
// if (div < base)
|
||||
// {
|
||||
// div <<= 8;
|
||||
// div += div_buf[idx_div++];
|
||||
// }
|
||||
// div_buf[idx_quo++] = div / base;
|
||||
// div %= base;
|
||||
// while (idx_div < idx_quo_last)
|
||||
// {
|
||||
// div <<= 8;
|
||||
// div += div_buf[idx_div++];
|
||||
// div_buf[idx_quo++] = div / base;
|
||||
// div %= base;
|
||||
// }
|
||||
// idx_quo_last = idx_quo;
|
||||
// idx_quo = 0;
|
||||
// idx_div = 0;
|
||||
// res_str[idx_str--] = digits[div];
|
||||
// div = div_buf[idx_div++];
|
||||
// }
|
||||
// res_str[idx_str--] = digits[div];
|
||||
// while (zero_count > 0 && idx_str >= 0)
|
||||
// {
|
||||
// res_str[idx_str--] = digits[0];
|
||||
// zero_count--;
|
||||
// }
|
||||
// while (idx_str >= 0)
|
||||
// {
|
||||
// res_str[idx_str--] = ' ';
|
||||
// }
|
||||
// std::copy(res_str, res_str + enc_size, str);
|
||||
// }
|
||||
// std::string encode(std::span<const uint8_t> data, uint8_t base, const char *digits, uint64_t enc_size) noexcept
|
||||
// {
|
||||
// std::string str(enc_size, ' ');
|
||||
// baseN::encode(data.data(), data.size(), str.data(), base, digits, enc_size);
|
||||
// str.erase(str.begin(), std::find_if(
|
||||
// str.begin(), str.end(), [](char ch)
|
||||
// { return ch != ' '; }));
|
||||
// return str;
|
||||
// }
|
||||
// std::string encode(std::span<const uint8_t> data, uint8_t base, const char *digits) noexcept
|
||||
// {
|
||||
// return baseN::encode(data, base, digits, data.size() * std::log(256) / std::log(base) + 1);
|
||||
// }
|
||||
// void decode(const char *str, uint8_t *data, uint64_t data_size, uint8_t base, const char *digits, const int8_t *map, uint64_t dec_size)
|
||||
// {
|
||||
// if (str[0] == '\0')
|
||||
// {
|
||||
// return;
|
||||
// }
|
||||
// if (!baseN::isValid(str, map))
|
||||
// {
|
||||
// throw std::logic_error("baseN::decode: out of digits map");
|
||||
// }
|
||||
// uint8_t res_data[dec_size];
|
||||
// uint64_t idx_str = 0;
|
||||
// int64_t
|
||||
// zero_count = 0,
|
||||
// idx_quo = dec_size - 1,
|
||||
// idx_quo_last = dec_size - 2;
|
||||
// uint16_t div;
|
||||
|
||||
// while (str[zero_count] != '\0' && str[zero_count] == digits[0])
|
||||
// {
|
||||
// zero_count++;
|
||||
// }
|
||||
// res_data[idx_quo] = map[(int8_t)str[idx_str++]];
|
||||
// while (str[idx_str] != '\0')
|
||||
// {
|
||||
// div = map[(int8_t)str[idx_str++]];
|
||||
// while (idx_quo > idx_quo_last && idx_quo > 0)
|
||||
// {
|
||||
// div += res_data[idx_quo] * base;
|
||||
// res_data[idx_quo--] = div;
|
||||
// div >>= 8;
|
||||
// }
|
||||
// res_data[idx_quo--] = div;
|
||||
// idx_quo_last = idx_quo;
|
||||
// idx_quo = dec_size - 1;
|
||||
// }
|
||||
// std::copy(res_data, res_data + std::min(dec_size, data_size), data);
|
||||
// }
|
||||
// std::vector<uint8_t> decode(std::string_view str, uint8_t base, const char *digits, const int8_t *map, uint64_t dec_size)
|
||||
// {
|
||||
// std::vector<uint8_t> data(dec_size);
|
||||
// baseN::decode(str.data(), data.data(), data.size(), base, digits, map, dec_size);
|
||||
// data.erase(data.begin(), std::find_if(
|
||||
// data.begin(), data.end(), [](uint8_t byte)
|
||||
// { return byte != 0; }));
|
||||
// return data;
|
||||
// }
|
||||
// std::vector<uint8_t> decode(std::string_view str, uint8_t base, const char *digits, const int8_t *map)
|
||||
// {
|
||||
// return baseN::decode(str, base, digits, map, str.size() * std::log(base) / std::log(256) + 1);
|
||||
// }
|
||||
while ((dv[0] > base || quo_it_last > dv.begin() + 1) && sv_it < sv.rend() - 1)
|
||||
{
|
||||
if (div < base)
|
||||
{
|
||||
div <<= 8;
|
||||
div += *dv_it++;
|
||||
}
|
||||
*quo_it++ = div / base;
|
||||
div %= base;
|
||||
while (dv_it < quo_it_last)
|
||||
{
|
||||
div <<= 8;
|
||||
div += *dv_it++;
|
||||
*quo_it++ = div / base;
|
||||
div %= base;
|
||||
}
|
||||
quo_it_last = quo_it;
|
||||
dv_it = dv.begin();
|
||||
quo_it = dv.begin();
|
||||
*sv_it++ = digits[div];
|
||||
div = *dv_it++;
|
||||
}
|
||||
*sv_it++ = digits[div];
|
||||
for (uint64_t i = 0; i < data_size - dv.size() && sv_it < sv.rend(); i++)
|
||||
{
|
||||
*sv_it++ = digits[0];
|
||||
}
|
||||
}
|
||||
std::string encode(std::span<const uint8_t> data, uint8_t base, const char *digits) noexcept
|
||||
{
|
||||
std::string str(baseN::sizeEncoded(data, base), ' ');
|
||||
baseN::encode(data.data(), data.size(), str.data(), str.size(), base, digits);
|
||||
str.erase(str.begin(), std::find_if(
|
||||
str.begin(), str.end(), [](char ch)
|
||||
{ return ch != ' '; }));
|
||||
return str;
|
||||
}
|
||||
}
|
||||
@ -32,19 +32,21 @@ TEST(baseN, isValid)
|
||||
EXPECT_EQ(true, isValid("123", b58map));
|
||||
EXPECT_EQ(false, isValid("@#$", b58map));
|
||||
}
|
||||
// TEST(baseN, encode)
|
||||
// {
|
||||
// EXPECT_EQ("Ky", encode(hex::decode("044c"), 58, b58digits));
|
||||
// EXPECT_EQ("KyK", encode(hex::decode("f94a"), 58, b58digits));
|
||||
// EXPECT_EQ("KyKX", encode(hex::decode("387ae2"), 58, b58digits));
|
||||
// EXPECT_EQ("KyKXa", encode(hex::decode("0ccbd755"), 58, b58digits));
|
||||
// EXPECT_EQ("KyKXaa", encode(hex::decode("02e62ec963"), 58, b58digits));
|
||||
// }
|
||||
// TEST(baseN, encode_1e3)
|
||||
// {
|
||||
// std::vector<uint8_t> data(1e3);
|
||||
// encode(data, 58, b58digits, data.size() * 138 / 100 + 1);
|
||||
// }
|
||||
TEST(baseN, encode)
|
||||
{
|
||||
EXPECT_EQ("", encode(hex::decode(""), 58, b58digits));
|
||||
EXPECT_EQ("Ky", encode(hex::decode("044c"), 58, b58digits));
|
||||
EXPECT_EQ("KyK", encode(hex::decode("f94a"), 58, b58digits));
|
||||
EXPECT_EQ("KyKX", encode(hex::decode("387ae2"), 58, b58digits));
|
||||
EXPECT_EQ("KyKXa", encode(hex::decode("0ccbd755"), 58, b58digits));
|
||||
EXPECT_EQ("KyKXaa", encode(hex::decode("02e62ec963"), 58, b58digits));
|
||||
}
|
||||
TEST(baseN, encode_1e3)
|
||||
{
|
||||
std::vector<uint8_t> data(1e3);
|
||||
std::fill(data.begin(), data.end(), 1);
|
||||
encode(data, 58, b58digits);
|
||||
}
|
||||
// TEST(baseN, decode)
|
||||
// {
|
||||
// EXPECT_EQ(hex::encode(decode("Ky", 58, b58digits, b58map)), "044c");
|
||||
|
||||
Reference in New Issue
Block a user