From 961e54c08b3c341321501988700cb8792a56bd09 Mon Sep 17 00:00:00 2001 From: SEK1RO Date: Wed, 18 Sep 2024 23:29:21 +0300 Subject: [PATCH] feat(baseN): decode --- src/baseN.cpp | 42 ++++++++++++++++++++++++++++++++++++++++++ test/test-baseN.cpp | 27 ++++++++++++++------------- 2 files changed, 56 insertions(+), 13 deletions(-) diff --git a/src/baseN.cpp b/src/baseN.cpp index 68d53b8..4614b79 100644 --- a/src/baseN.cpp +++ b/src/baseN.cpp @@ -84,4 +84,46 @@ namespace baseN { return ch != ' '; })); 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) + { + std::string_view sv(std::find_if(str, str + str_size, [digits](char ch) + { return ch != digits[0]; }), + str_size); + if (sv.size() == 0) + { + return; + } + if (!baseN::isValid(sv, map)) + { + throw std::logic_error("baseN::decode: out of digits map"); + } + std::span dv(data, data_size); + auto sv_it = sv.begin(); + auto quo_it = dv.rbegin(); + auto quo_it_last = dv.rbegin() + 1; + uint16_t div; + + *quo_it = map[(int8_t)*sv_it++]; + while (sv_it < sv.end()) + { + div = map[(int8_t)*sv_it++]; + while (quo_it < quo_it_last && quo_it < dv.rend() - 1) + { + div += *quo_it * base; + *quo_it++ = div; + div >>= 8; + } + *quo_it++ = div; + quo_it_last = quo_it; + quo_it = dv.rbegin(); + } + } + std::vector decode(std::string_view str, uint8_t base, const char *digits, const int8_t *map) noexcept + { + std::vector data(baseN::sizeDecoded(str, base)); + 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) + { return item != 0; })); + return data; + } } \ No newline at end of file diff --git a/test/test-baseN.cpp b/test/test-baseN.cpp index a53e824..d895d9b 100644 --- a/test/test-baseN.cpp +++ b/test/test-baseN.cpp @@ -47,19 +47,20 @@ TEST(baseN, encode_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"); -// EXPECT_EQ(hex::encode(decode("KyK", 58, b58digits, b58map)), "f94a"); -// EXPECT_EQ(hex::encode(decode("KyKX", 58, b58digits, b58map)), "387ae2"); -// EXPECT_EQ(hex::encode(decode("KyKXa", 58, b58digits, b58map)), "0ccbd755"); -// EXPECT_EQ(hex::encode(decode("KyKXaa", 58, b58digits, b58map)), "02e62ec963"); -// } -// TEST(baseN, decode_1e4) -// { -// std::string str(1e4, '1'); -// decode(str, 58, b58digits, b58map, str.size() * 733 / 1000 + 1); -// } +TEST(baseN, decode) +{ + EXPECT_EQ(hex::encode(decode("", 58, b58digits, b58map)), ""); + EXPECT_EQ(hex::encode(decode("Ky", 58, b58digits, b58map)), "044c"); + EXPECT_EQ(hex::encode(decode("KyK", 58, b58digits, b58map)), "f94a"); + EXPECT_EQ(hex::encode(decode("KyKX", 58, b58digits, b58map)), "387ae2"); + EXPECT_EQ(hex::encode(decode("KyKXa", 58, b58digits, b58map)), "0ccbd755"); + EXPECT_EQ(hex::encode(decode("KyKXaa", 58, b58digits, b58map)), "02e62ec963"); +} +TEST(baseN, decode_1e3) +{ + std::string str(1e3, '2'); + decode(str, 58, b58digits, b58map); +} int main(int argc, char **argv) {