diff --git a/encode/number.hpp b/encode/number.hpp index e99d90d6..9ee674fe 100644 --- a/encode/number.hpp +++ b/encode/number.hpp @@ -9,6 +9,11 @@ #pragma once #include "../view.hpp" +#include "../maths.hpp" + +#include +#include + /////////////////////////////////////////////////////////////////////////////// namespace cruft::encode { @@ -31,4 +36,31 @@ namespace cruft::encode { return accum; } + + + template + OutputT + encode36 (OutputT out, ValueT val) + { + constexpr auto count = digits(std::numeric_limits::max (), 36u); + std::array res; + + auto cursor = res.begin (); + // Ensure we do at least one iteration so we output a zero. + do { + switch (auto const d = val % 36; d) { + case 0 ... 9: *cursor = d + '0'; break; + case 10 ...35: *cursor = d - 10 + 'a'; break; + } + + val /= 36; + ++cursor; + } while (val); + + return std::copy ( + std::make_reverse_iterator (cursor), + res.rend (), + out + ); + } } diff --git a/test/encode/number.cpp b/test/encode/number.cpp index 56c49f2d..6984615f 100644 --- a/test/encode/number.cpp +++ b/test/encode/number.cpp @@ -20,8 +20,22 @@ int main () cruft::TAP::logger tap; for (auto const &t: TESTS) { + // decode the truth string and test against the truth number cruft::view src (t.str); tap.expect_eq (cruft::encode::decode36 (src), t.value, "base36 decode '%!'", t.str); + + // encode the truth number + std::ostringstream dst; + cruft::encode::encode36 (std::ostream_iterator (dst), t.value); + + // covert computed and truth strings to lower case + std::string encoded_computed = dst.str (); + std::string encoded_truth = t.str; + std::transform (encoded_computed.begin (), encoded_computed.end (), encoded_computed.begin (), ::tolower); + std::transform (encoded_truth.begin (), encoded_truth.end (), encoded_truth.begin (), ::tolower); + + // compare lower case encoded strings + tap.expect_eq (encoded_computed, encoded_truth, "base36 encode '%!'", t.value); } return tap.status ();