summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLéo Lam <leo@leolam.fr>2020-09-18 16:06:44 +0200
committerLéo Lam <leo@leolam.fr>2020-09-18 20:37:54 +0200
commitaf1aacc5bdee097fc9915aa04ef0523c6031c3db (patch)
treeb4468ddb92f53d203ae65b2350c36648f4ef7e05
parent7828ee535d15a1fad6a4c74757c96d3decdffa33 (diff)
ksys/utils: Add FixedString for light constexpr string manipulation
-rw-r--r--CMakeLists.txt1
-rw-r--r--src/KingSystem/Utils/FixedString.h94
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