ksys/utils: Add FixedString for light constexpr string manipulation

This commit is contained in:
Léo Lam 2020-09-18 16:06:44 +02:00
parent 7828ee535d
commit af1aacc5bd
No known key found for this signature in database
GPG Key ID: 0DF30F9081000741
2 changed files with 95 additions and 0 deletions

View File

@ -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

View File

@ -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