fix(baseN): encode, decode now return uint8_t zero offset

This commit is contained in:
2024-09-19 08:41:59 +03:00
parent f49c0463d4
commit 0086092bd9
2 changed files with 51 additions and 47 deletions

View File

@ -13,9 +13,9 @@ namespace baseN
uint64_t sizeEncoded(std::span<const uint8_t> data, uint8_t base); uint64_t sizeEncoded(std::span<const uint8_t> data, uint8_t base);
uint64_t sizeDecoded(std::string_view str, uint8_t base, const char* digits) noexcept; uint64_t sizeDecoded(std::string_view str, uint8_t base, const char* digits) noexcept;
void encode(const uint8_t *data, uint64_t data_size, char *str, uint64_t str_size, uint8_t base, const char *digits); uint64_t encode(const uint8_t *data, uint64_t data_size, char *str, uint64_t str_size, uint8_t base, const char *digits);
std::string encode(std::span<const uint8_t> data, uint8_t base, const char *digits) noexcept; std::string encode(std::span<const uint8_t> data, uint8_t base, const char *digits) noexcept;
void decode(const char *str, uint64_t str_size, uint8_t *data, uint64_t data_size, uint8_t base, const char *digits, const int8_t *map); uint64_t decode(const char *str, uint64_t str_size, uint8_t *data, uint64_t data_size, uint8_t base, const char *digits, const int8_t *map);
std::vector<uint8_t> decode(std::string_view str, uint8_t base, const char *digits, const int8_t *map) noexcept; std::vector<uint8_t> decode(std::string_view str, uint8_t base, const char *digits, const int8_t *map) noexcept;
} }

View File

@ -36,22 +36,20 @@ namespace baseN
str.end()); str.end());
return sv.size() * std::log(base) / log256 + 1 + (str.size() - sv.size()); return sv.size() * std::log(base) / log256 + 1 + (str.size() - sv.size());
} }
void encode(const uint8_t *data, uint64_t data_size, char *str, uint64_t str_size, uint8_t base, const char *digits) uint64_t 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) std::vector<uint8_t> dv(std::find_if(data, data + data_size, [](uint8_t item)
{ return item != 0; }), { return item != 0; }),
data + data_size); data + data_size);
if (dv.size() == 0)
{
return;
}
std::span<char> sv(str, str_size); std::span<char> sv(str, str_size);
auto sv_it = sv.rbegin(); auto sv_it = sv.rbegin();
auto dv_it = dv.begin(); auto dv_it = dv.begin();
auto quo_it = dv.begin(); auto quo_it = dv.begin();
auto quo_it_last = dv.end(); auto quo_it_last = dv.end();
uint16_t div = *dv_it++;
if (dv.size() != 0)
{
uint16_t div = *dv_it++;
while ((dv[0] > base || quo_it_last > dv.begin() + 1) && sv_it < sv.rend() - 1) while ((dv[0] > base || quo_it_last > dv.begin() + 1) && sv_it < sv.rend() - 1)
{ {
if (div < base) if (div < base)
@ -75,29 +73,25 @@ namespace baseN
div = *dv_it++; div = *dv_it++;
} }
*sv_it++ = digits[div]; *sv_it++ = digits[div];
}
for (uint64_t i = 0; i < data_size - dv.size() && sv_it < sv.rend(); i++) for (uint64_t i = 0; i < data_size - dv.size() && sv_it < sv.rend(); i++)
{ {
*sv_it++ = digits[0]; *sv_it++ = digits[0];
} }
return std::distance(sv_it, sv.rend());
} }
std::string encode(std::span<const uint8_t> data, uint8_t base, const char *digits) noexcept std::string encode(std::span<const uint8_t> data, uint8_t base, const char *digits) noexcept
{ {
std::string str(baseN::sizeEncoded(data, base), ' '); std::string str(baseN::sizeEncoded(data, base), ' ');
baseN::encode(data.data(), data.size(), str.data(), str.size(), base, digits); uint64_t offset = baseN::encode(data.data(), data.size(), str.data(), str.size(), base, digits);
str.erase(str.begin(), std::find_if( str.erase(str.begin(), str.begin() + offset);
str.begin(), str.end(), [](char ch)
{ return ch != ' '; }));
return str; return str;
} }
void decode(const char *str, uint64_t str_size, uint8_t *data, uint64_t data_size, uint8_t base, const char *digits, const int8_t *map) uint64_t decode(const char *str, uint64_t str_size, uint8_t *data, uint64_t data_size, uint8_t base, const char *digits, const int8_t *map)
{ {
std::string_view sv(std::find_if(str, str + str_size, [digits](char ch) std::string_view sv(std::find_if(str, str + str_size, [digits](char ch)
{ return ch != digits[0]; }), { return ch != digits[0]; }),
str_size); str + str_size);
if (sv.size() == 0)
{
return;
}
if (!baseN::isValid(sv, map)) if (!baseN::isValid(sv, map))
{ {
throw std::logic_error("baseN::decode: out of digits map"); throw std::logic_error("baseN::decode: out of digits map");
@ -108,6 +102,8 @@ namespace baseN
auto quo_it_last = dv.rbegin() + 1; auto quo_it_last = dv.rbegin() + 1;
uint16_t div; uint16_t div;
if (sv.size() != 0)
{
*quo_it = map[(int8_t)*sv_it++]; *quo_it = map[(int8_t)*sv_it++];
while (sv_it < sv.end()) while (sv_it < sv.end())
{ {
@ -118,17 +114,25 @@ namespace baseN
*quo_it++ = div; *quo_it++ = div;
div >>= 8; div >>= 8;
} }
if (div != 0)
{
*quo_it++ = div; *quo_it++ = div;
}
quo_it_last = quo_it; quo_it_last = quo_it;
quo_it = dv.rbegin(); quo_it = dv.rbegin();
} }
} }
for (uint64_t i = 0; i < str_size - sv.size() && quo_it_last < dv.rend(); i++)
{
*quo_it_last++ = 0;
}
return std::distance(quo_it_last, dv.rend());
}
std::vector<uint8_t> decode(std::string_view str, uint8_t base, const char *digits, const int8_t *map) noexcept std::vector<uint8_t> decode(std::string_view str, uint8_t base, const char *digits, const int8_t *map) noexcept
{ {
std::vector<uint8_t> data(baseN::sizeDecoded(str, base, digits)); std::vector<uint8_t> data(baseN::sizeDecoded(str, base, digits));
baseN::decode(str.data(), str.size(), data.data(), data.size(), base, digits, map); uint64_t offset = baseN::decode(str.data(), str.size(), data.data(), data.size(), base, digits, map);
data.erase(data.begin(), std::find_if(data.begin(), data.end(), [](uint8_t item) data.erase(data.begin(), data.begin() + offset);
{ return item != 0; }));
return data; return data;
} }
} }