types: Add constexpr int encoder
Change-Id: I4a3117f442c5a829faffbb5897eb2a0ea013f63a
Signed-off-by: William A. Kennington III <wak@google.com>
diff --git a/src/types.hpp b/src/types.hpp
index 73d2778..4bbff0d 100644
--- a/src/types.hpp
+++ b/src/types.hpp
@@ -198,7 +198,19 @@
}
return ret;
}();
-}
+inline constexpr auto intLookup = []() {
+ std::array<char, 36> ret;
+ for (int8_t i = 0; i < 10; ++i)
+ {
+ ret[i] = i + '0';
+ }
+ for (int8_t i = 0; i < 26; ++i)
+ {
+ ret[i + 10] = i + 'a';
+ }
+ return ret;
+}();
+} // namespace detail
template <typename T, uint8_t base>
struct DecodeInt
@@ -249,6 +261,59 @@
}
};
+template <typename T, uint8_t base>
+struct EncodeInt
+{
+ static_assert(base > 1 && base <= 36);
+ static_assert(std::is_unsigned_v<T>);
+
+ static constexpr uint8_t buf_size = []() {
+ T v = std::numeric_limits<T>::max();
+ uint8_t i = 0;
+ for (; v != 0; ++i)
+ {
+ v /= base;
+ }
+ return i;
+ }();
+ using buf_type = std::array<char, buf_size>;
+
+ constexpr uint8_t reverseFill(char* buf, T v) const noexcept
+ {
+ uint8_t i = 0;
+ do
+ {
+ if constexpr (std::popcount(base) == 1)
+ {
+ buf[i++] = detail::intLookup[v & 0xf];
+ v >>= 4;
+ }
+ else
+ {
+ buf[i++] = detail::intLookup[v % base];
+ v /= base;
+ }
+ } while (v > 0);
+ return i;
+ }
+
+ constexpr char* operator()(char* buf, T v) const noexcept
+ {
+ uint8_t i = reverseFill(buf, v);
+ std::reverse(buf, buf + i);
+ return buf + i;
+ }
+
+ constexpr char* operator()(char* buf, T v, uint8_t min_width) const noexcept
+ {
+ uint8_t i = reverseFill(buf, v);
+ auto end = buf + std::max(i, min_width);
+ std::fill(buf + i, end, '0');
+ std::reverse(buf, end);
+ return end;
+ }
+};
+
template <typename T>
struct ToAddr
{