diff --git a/src/baseN.cpp b/src/baseN.cpp index 9d7c0e1..68d53b8 100644 --- a/src/baseN.cpp +++ b/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 dv(std::find_if(data, data + data_size, [](uint8_t item) + { return item != 0; }), + data + data_size); + if (dv.size() == 0) + { + return; + } + std::span 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 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 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 decode(std::string_view str, uint8_t base, const char *digits, const int8_t *map, uint64_t dec_size) - // { - // std::vector 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 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 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; + } } \ No newline at end of file diff --git a/test/test-baseN.cpp b/test/test-baseN.cpp index 96ebe7f..a53e824 100644 --- a/test/test-baseN.cpp +++ b/test/test-baseN.cpp @@ -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 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 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");