From 227579d1e2085333c7e4cf261eaa02f18042a9d8 Mon Sep 17 00:00:00 2001 From: SEK1RO Date: Mon, 30 Sep 2024 17:23:23 +0300 Subject: [PATCH] fix(baseN): basen::Exception --- Makefile | 2 +- include/basen/baseN.hpp | 15 ++++++++++----- src/baseN.cpp | 29 +++++++++++++++++++++++------ test/test-baseN.cpp | 11 +++++++++-- 4 files changed, 43 insertions(+), 14 deletions(-) diff --git a/Makefile b/Makefile index 64c3342..76ee129 100644 --- a/Makefile +++ b/Makefile @@ -85,7 +85,7 @@ docs: cover: ${DIRS} ${patsubst %, ${BINDIR}/%${-g}-cov, ${TESTS}} rm -f **/*.gcda ${patsubst %, ./${BINDIR}/%${-g}-cov;, ${TESTS}} - mkdir cov + mkdir -p cov gcovr --html-nested cov/index.html --txt --exclude-throw-branches ${OBJDIR}/%${-g}-cov.o: ${SRCDIR}/%.cpp ${INCDIR}/${LIB}/%.hpp diff --git a/include/basen/baseN.hpp b/include/basen/baseN.hpp index a3a9485..a7bb5ca 100644 --- a/include/basen/baseN.hpp +++ b/include/basen/baseN.hpp @@ -11,7 +11,7 @@ namespace baseN * @param digits char[base] array of digits * @param digits_size size of digits array. Equals to base * @param map [out] uint8_t[256] array, where at an index equal to the value of the symbol is the index of this symbol in the digits array. 255 if there is no symbol - * @throw std::logic_error if alphabet contain same chars + * @throw basen::Exception(ALPH_COLLISION) if alphabet contain same chars */ void digitsMap(const char *digits, uint8_t digits_size, uint8_t *map); /** @@ -32,6 +32,7 @@ namespace baseN * @param data vector or span of data which you want to encode * @param base from 1 to 255 * @return estimated size after encoding + * @throw basen::Exception(BASE) if base < 2 || base > 254 */ size_t sizeEncoded(std::span data, uint8_t base); /** @@ -39,9 +40,10 @@ namespace baseN * @param base from 1 to 255 * @param digits char[base] array of digits * @return estimated size after decoding - * @throw std::overflow_error if if there is an overflow + * @throw basen::Exception(BASE) if base < 2 || base > 254 + * @throw basen::Exception(OVERFLOW) if if there is an overflow */ - size_t sizeDecoded(std::string_view str, uint8_t base, const char *digits) noexcept; + size_t sizeDecoded(std::string_view str, uint8_t base, const char *digits); /** * @param data [in] pointer to data which you want encode @@ -59,6 +61,7 @@ namespace baseN * str.erase(str.begin(), str.begin() + offset); * @endcode * @return number of leading chars, which should be trimmed + * @throw basen::Exception(BASE) if base < 2 || base > 254 * @warning contain leading zeros, returns count of them */ size_t encode(const uint8_t *data, size_t data_size, char *str, size_t str_size, uint8_t base, const char *digits); @@ -72,7 +75,7 @@ namespace baseN * @endcode * @return encoded string */ - std::string encode(std::span data, uint8_t base, const char *digits) noexcept; + std::string encode(std::span data, uint8_t base, const char *digits); /** * @param str [in] pointer to string which you want decode @@ -91,6 +94,8 @@ namespace baseN * data.erase(data.begin(), data.begin() + offset); * @endcode * @return number of leading chars, which should be trimmed + * @throw basen::Exception(BASE) if base < 2 || base > 254 + * @throw basen::Exception(OUT_OF_ALPH) if out of alphabet * @warning contain leading zeros, returns count of them */ size_t decode(const char *str, size_t str_size, uint8_t *data, size_t data_size, uint8_t base, const char *digits, const uint8_t *map); @@ -105,5 +110,5 @@ namespace baseN * @endcode * @return decoded data */ - std::vector decode(std::string_view str, uint8_t base, const char *digits, const uint8_t *map) noexcept; + std::vector decode(std::string_view str, uint8_t base, const char *digits, const uint8_t *map); } \ No newline at end of file diff --git a/src/baseN.cpp b/src/baseN.cpp index 9059f33..8370d2d 100644 --- a/src/baseN.cpp +++ b/src/baseN.cpp @@ -4,6 +4,7 @@ #include #include +#include static constexpr auto log256 = std::log(256); @@ -16,7 +17,7 @@ namespace baseN { if (map[(uint8_t)digits[i]] != 255) { - throw std::logic_error("baseN::digitsMap: alphabet contain same chars"); + throw basen::Exception(basen::Exception::Code::ALPH_COLLISION); } map[(uint8_t)digits[i]] = i; } @@ -32,17 +33,25 @@ namespace baseN } size_t sizeEncoded(std::span data, uint8_t base) { + if (base < 2 || base > 254) + { + throw basen::Exception(basen::Exception::Code::BASE); + } std::span dv(std::find_if(data.begin(), data.end(), [](uint8_t item) { return item != 0; }), data.end()); if (dv.size() > std::numeric_limits::max() / log256) { - throw std::overflow_error("baseN::sizeEncoded: overflow"); + throw basen::Exception(basen::Exception::Code::OVERFLOW); } return dv.size() * log256 / std::log(base) + 1 + (data.size() - dv.size()); } - size_t sizeDecoded(std::string_view str, uint8_t base, const char *digits) noexcept + size_t sizeDecoded(std::string_view str, uint8_t base, const char *digits) { + if (base < 2 || base > 254) + { + throw basen::Exception(basen::Exception::Code::BASE); + } std::string_view sv(std::find_if(str.begin(), str.end(), [digits](uint8_t ch) { return ch != digits[0]; }), str.end()); @@ -50,6 +59,10 @@ namespace baseN } size_t encode(const uint8_t *data, size_t data_size, char *str, size_t str_size, uint8_t base, const char *digits) { + if (base < 2 || base > 254) + { + throw basen::Exception(basen::Exception::Code::BASE); + } std::vector dv(std::find_if(data, data + data_size, [](uint8_t item) { return item != 0; }), data + data_size); @@ -92,7 +105,7 @@ namespace baseN } return std::distance(sv_it, sv.rend()); } - std::string encode(std::span data, uint8_t base, const char *digits) noexcept + std::string encode(std::span data, uint8_t base, const char *digits) { std::string str(baseN::sizeEncoded(data, base), ' '); size_t offset = baseN::encode(data.data(), data.size(), str.data(), str.size(), base, digits); @@ -101,12 +114,16 @@ namespace baseN } size_t decode(const char *str, size_t str_size, uint8_t *data, size_t data_size, uint8_t base, const char *digits, const uint8_t *map) { + if (base < 2 || base > 254) + { + throw basen::Exception(basen::Exception::Code::BASE); + } std::string_view sv(std::find_if(str, str + str_size, [digits](char ch) { return ch != digits[0]; }), str + str_size); if (!baseN::isValid(sv, map)) { - throw std::logic_error("baseN::decode: out of digits map"); + throw basen::Exception(basen::Exception::Code::OUT_OF_ALPH); } std::span dv(data, data_size); auto sv_it = sv.begin(); @@ -141,7 +158,7 @@ namespace baseN } return std::distance(quo_it_last, dv.rend()); } - std::vector decode(std::string_view str, uint8_t base, const char *digits, const uint8_t *map) noexcept + std::vector decode(std::string_view str, uint8_t base, const char *digits, const uint8_t *map) { std::vector data(baseN::sizeDecoded(str, base, digits)); size_t offset = baseN::decode(str.data(), str.size(), data.data(), data.size(), base, digits, map); diff --git a/test/test-baseN.cpp b/test/test-baseN.cpp index dcd3f8c..1918e2b 100644 --- a/test/test-baseN.cpp +++ b/test/test-baseN.cpp @@ -2,6 +2,7 @@ #include #include +#include #include #include @@ -13,7 +14,7 @@ TEST(baseN, digitsMap) digitsMap(base58::digits, 58, map); EXPECT_TRUE(std::equal(map, map + 256, base58::map)); - EXPECT_THROW(digitsMap("11", 2, map), std::logic_error); + EXPECT_THROW(digitsMap("11", 2, map), basen::Exception); } TEST(baseN, isValid) { @@ -30,8 +31,10 @@ TEST(baseN, sizeEncoded) {6, "12341234"}, {5, "00000000"}, }; - for (auto it : tests) + for (auto it : tests) EXPECT_EQ(it.first, sizeEncoded(hex::decode(it.second), 58)); + + EXPECT_THROW(sizeEncoded(hex::decode(""), 0), basen::Exception); } TEST(baseN, sizeDecoded) { @@ -41,6 +44,8 @@ TEST(baseN, sizeDecoded) }; for (auto it : tests) EXPECT_EQ(it.first, sizeDecoded(it.second, 58, base58::digits)); + + EXPECT_THROW(sizeDecoded("", 0, base58::digits), basen::Exception); } std::vector> tests = { {"", ""}, @@ -68,6 +73,8 @@ TEST(baseN, decode) { for (auto it : tests) EXPECT_EQ(hex::encode(decode(it.first, 58, base58::digits, base58::map)), it.second); + + EXPECT_THROW(decode("!@#", 58, base58::digits, base58::map), basen::Exception); } TEST(baseN, decode_1e3) {