diff options
| author | Léo Lam <leo@leolam.fr> | 2020-09-18 16:06:44 +0200 |
|---|---|---|
| committer | Léo Lam <leo@leolam.fr> | 2020-09-18 20:37:54 +0200 |
| commit | af1aacc5bdee097fc9915aa04ef0523c6031c3db (patch) | |
| tree | b4468ddb92f53d203ae65b2350c36648f4ef7e05 | |
| parent | 7828ee535d15a1fad6a4c74757c96d3decdffa33 (diff) | |
ksys/utils: Add FixedString for light constexpr string manipulation
| -rw-r--r-- | CMakeLists.txt | 1 | ||||
| -rw-r--r-- | src/KingSystem/Utils/FixedString.h | 94 |
2 files changed, 95 insertions, 0 deletions
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 <array> +#include <cstddef> +#include <type_traits> + +namespace ksys::util { + +// https://stackoverflow.com/a/53190503/1636285 + +struct concat_op {}; + +template <std::size_t N> +struct FixedString { + constexpr static std::size_t length() { return N; } + constexpr static std::size_t capacity() { return N + 1; } + + template <std::size_t L, std::size_t R> + constexpr FixedString(concat_op, FixedString<L> l, FixedString<R> 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<char, capacity()> buffer_; +}; + +template <std::size_t N> +constexpr FixedString<N - 1> Str(const char (&c)[N]) { + return FixedString<N - 1>(c); +} + +template <auto N, int base = 10> +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 <std::size_t L, std::size_t R> +constexpr auto operator+(FixedString<L> l, FixedString<R> r) -> FixedString<L + R> { + auto result = FixedString<L + R>(concat_op(), l, r); + return result; +} + +/// Takes any expression that returns a FixedString<N> 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 |
