From af1aacc5bdee097fc9915aa04ef0523c6031c3db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Lam?= Date: Fri, 18 Sep 2020 16:06:44 +0200 Subject: [PATCH] ksys/utils: Add FixedString for light constexpr string manipulation --- CMakeLists.txt | 1 + src/KingSystem/Utils/FixedString.h | 94 ++++++++++++++++++++++++++++++ 2 files changed, 95 insertions(+) create mode 100644 src/KingSystem/Utils/FixedString.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 16745d2d..264f9bd5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -111,6 +111,7 @@ add_executable(uking src/KingSystem/Utils/ByamlLocal.h src/KingSystem/Utils/ByamlUtil.cpp src/KingSystem/Utils/Debug.h + src/KingSystem/Utils/FixedString.h src/KingSystem/Utils/HashUtil.h src/KingSystem/Utils/HeapUtil.cpp src/KingSystem/Utils/HeapUtil.h diff --git a/src/KingSystem/Utils/FixedString.h b/src/KingSystem/Utils/FixedString.h new file mode 100644 index 00000000..039df272 --- /dev/null +++ b/src/KingSystem/Utils/FixedString.h @@ -0,0 +1,94 @@ +#pragma once + +#include +#include +#include + +namespace ksys::util { + +// https://stackoverflow.com/a/53190503/1636285 + +struct concat_op {}; + +template +struct FixedString { + constexpr static std::size_t length() { return N; } + constexpr static std::size_t capacity() { return N + 1; } + + template + constexpr FixedString(concat_op, FixedString l, FixedString r) : FixedString() { + static_assert(L + R == N); + overwrite(0, l.data(), L); + overwrite(L, r.data(), R); + } + + constexpr FixedString() : buffer_{} {} + + constexpr FixedString(const char (&source)[N + 1]) : FixedString() { + do_copy(source, buffer_.data()); + } + + constexpr const char* data() const { return buffer_.data(); } + + constexpr char* data() { return buffer_.data(); } + +private: + static constexpr void do_copy(const char (&source)[N + 1], char* dest) { + for (std::size_t i = 0; i < capacity(); ++i) + dest[i] = source[i]; + } + + constexpr void overwrite(std::size_t where, const char* source, std::size_t len) { + auto dest = buffer_.data() + where; + while (len--) + *dest++ = *source++; + } + + std::array buffer_; +}; + +template +constexpr FixedString Str(const char (&c)[N]) { + return FixedString(c); +} + +template +constexpr auto Str() { + constexpr char digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + + FixedString<([]() constexpr noexcept { + unsigned int len = N > 0 ? 0 : 1; + for (auto n = N; n; len++, n /= base) + continue; + return len; + }())> + buf{}; + + auto ptr = buf.data() + buf.length(); + if (N == 0) { + buf.data()[0] = '0'; + } else { + for (auto n = N; n; n /= base) + *--ptr = digits[(N < 0 ? -1 : 1) * (n % base)]; + if (N < 0) + *--ptr = '-'; + } + + return buf; +} + +template +constexpr auto operator+(FixedString l, FixedString r) -> FixedString { + auto result = FixedString(concat_op(), l, r); + return result; +} + +/// Takes any expression that returns a FixedString and returns a const char*. +#define KSYS_STR(STR) \ + ([]() -> const char* { \ + using ksys::util::Str; \ + static constexpr auto x = STR; \ + return x.data(); \ + }()) + +} // namespace ksys::util