Skip to content

Instantly share code, notes, and snippets.

@Atari2
Last active May 18, 2022 11:18

Revisions

  1. Atari2 revised this gist May 18, 2022. 1 changed file with 386 additions and 397 deletions.
    783 changes: 386 additions & 397 deletions Common.h
    Original file line number Diff line number Diff line change
    @@ -7,6 +7,9 @@
    #include <stdexcept>
    #include <string>
    #include <string_view>
    #ifdef BACKTRACE_AVAILABLE
    #include "BackTrace.h"
    #endif

    // common and useful macros / functions
    #define STRIMPL(x) #x
    @@ -15,53 +18,49 @@
    #define DEBUGINFO(info) "DEBUG [" __FILE__ ":" STR(__LINE__) "]: " STR(info)
    #define WIDEIMPL(str) L##str
    #define WIDE(str) WIDEIMPL(str)

    // A catch-all tag type.
    template <typename T>
    struct TagType {};

    // Concept for enum template parameters
    template <typename T>
    concept EnumT = std::is_enum_v<T>;

    template <typename T, size_t N>
    constexpr size_t sizeof_array(const T (&)[N]) {
    return N;
    }
    // Simple choice support
    template <typename T>
    constexpr auto choice(bool t, T ret_true, T ret_false) {
    return (t ? ret_true : ret_false);
    }

    template <typename T>
    constexpr auto triple_choice(bool a, bool b, T reta, T retb, T retc) {
    return (a ? reta : (b ? retb : retc));
    }

    // enum conversions
    template <EnumT T>
    constexpr auto from_enum(T val) {
    return static_cast<std::underlying_type_t<T>>(val);
    }

    template <EnumT T>
    constexpr auto to_enum(std::integral auto val) {
    return static_cast<T>(static_cast<std::underlying_type_t<T>>(val));
    }

    // an always_false template dependant bool for static_asserts in if constexpr code
    template <typename T>
    inline constexpr bool always_false_v = false;
    constexpr inline bool always_false_v = false;

    // size explicit integer shorthands and operators
    using u8 = uint8_t;
    using i8 = int8_t;
    using u8 = uint8_t;
    using i8 = int8_t;
    using u16 = uint16_t;
    using i16 = int16_t;
    using u32 = uint32_t;
    using i32 = int32_t;
    using u64 = uint64_t;
    using i64 = int64_t;
    using c = char;
    using uc = unsigned char;

    using c = char;
    using uc = unsigned char;
    constexpr u8 operator""_u8(unsigned long long val) {
    return static_cast<u8>(val);
    }
    @@ -106,267 +105,261 @@ constexpr uc operator""_uc(char val) {
    enum class PlatformType { Windows = 0, Apple = 1, Unix = 2 };
    enum class PlatformWidth { x64 = 0, x86 = 1 };
    namespace __internal {
    template <PlatformType TType, PlatformWidth TWidth>
    struct PlatformInfoImpl {
    static_assert(TType == PlatformType::Windows || TType == PlatformType::Apple || TType == PlatformType::Unix,
    "Invalid platform type");
    static_assert(TWidth == PlatformWidth::x64 || TWidth == PlatformWidth::x86, "Invalid platform width");
    static constexpr PlatformType Type = TType;
    static constexpr bool WINDOWS = (TType == PlatformType::Windows);
    static constexpr bool UNIX = (TType == PlatformType::Unix);
    static constexpr bool APPLE = (TType == PlatformType::Apple);
    static constexpr PlatformWidth Width = TWidth;
    static constexpr bool X64 = (TWidth == PlatformWidth::x64);
    static constexpr bool X86 = (TWidth == PlatformWidth::x86);
    static constexpr const char* Name = triple_choice(WINDOWS, UNIX, "Windows", "Unix", "Apple");
    static constexpr const char* StrWidth = choice(X64, "x64", "x86");
    constexpr static auto type() { return Type; }
    constexpr static bool is_windows() { return WINDOWS; }
    constexpr static bool is_unix() { return UNIX; }
    constexpr static bool is_apple() { return APPLE; }
    template <typename T = PlatformWidth>
    constexpr static auto width() {
    if constexpr (std::same_as<T, PlatformWidth>) {
    return Width;
    } else if constexpr (std::same_as<T, char*>) {
    return StrWidth;
    } else {
    static_assert(always_false_v<T>,
    "width() call is only valid with PlatformWidth or char* as template parameters");
    return nullptr;
    }
    template <PlatformType TType, PlatformWidth TWidth>
    struct PlatformInfoImpl {
    static_assert(
    TType == PlatformType::Windows || TType == PlatformType::Apple || TType == PlatformType::Unix,
    "Invalid platform type"
    );
    static_assert(TWidth == PlatformWidth::x64 || TWidth == PlatformWidth::x86, "Invalid platform width");
    constexpr static PlatformType Type = TType;
    constexpr static bool WINDOWS = (TType == PlatformType::Windows);
    constexpr static bool UNIX = (TType == PlatformType::Unix);
    constexpr static bool APPLE = (TType == PlatformType::Apple);
    constexpr static PlatformWidth Width = TWidth;
    constexpr static bool X64 = (TWidth == PlatformWidth::x64);
    constexpr static bool X86 = (TWidth == PlatformWidth::x86);
    constexpr static const char* Name = triple_choice(WINDOWS, UNIX, "Windows", "Unix", "Apple");
    constexpr static const char* StrWidth = choice(X64, "x64", "x86");
    constexpr static auto type() { return Type; }
    constexpr static bool is_windows() { return WINDOWS; }
    constexpr static bool is_unix() { return UNIX; }
    constexpr static bool is_apple() { return APPLE; }
    template <typename T = PlatformWidth>
    constexpr static auto width() {
    if constexpr (std::same_as<T, PlatformWidth>) {
    return Width;
    } else if constexpr (std::same_as<T, char*>) {
    return StrWidth;
    } else {
    static_assert(
    always_false_v<T>, "width() call is only valid with PlatformWidth or char* as template parameters"
    );
    return nullptr;
    }
    constexpr static bool x64() { return X64; }
    constexpr static bool x86() { return X86; }
    constexpr static auto name() { return Name; }
    };
    } // namespace __internal

    }
    constexpr static bool x64() { return X64; }
    constexpr static bool x86() { return X86; }
    constexpr static auto name() { return Name; }
    };
    } // namespace __internal
    #ifdef _WIN32
    // Windows
    #ifdef _WIN64
    #ifdef _WIN64
    using PlatformInfo = __internal::PlatformInfoImpl<PlatformType::Windows, PlatformWidth::x64>;
    #else
    #else
    using PlatformInfo = __internal::PlatformInfoImpl<PlatformType::Windows, PlatformWidth::x86>;
    #endif
    #endif

    #define unreachable __assume(0)
    #define forceinline __forceinline
    #define noop __noop
    #define NEWLINE "\r\n"
    #define unreachable __assume(0)
    #define forceinline __forceinline
    #define noop __noop
    #define NEWLINE "\r\n"

    #elif __APPLE__
    // Apple
    #if defined(__LP64__) || defined(__x86_64__)
    #if defined(__LP64__) || defined(__x86_64__)
    using PlatformInfo = __internal::PlatformInfoImpl<PlatformType::Apple, PlatformWidth::x64>;
    #else
    #else
    using PlatformInfo = __internal::PlatformInfoImpl<PlatformType::Apple, PlatformWidth::x86>;
    #endif
    #endif

    #define unreachable __builtin_unreachable();
    #define forceinline __attribute__((always_inline))
    #define noop ((void)0)
    #define NEWLINE "\n"
    #define unreachable __builtin_unreachable();
    #define forceinline __attribute__((always_inline))
    #define noop ((void)0)
    #define NEWLINE "\n"

    #elif __unix__
    // Unix
    #if defined(__LP64__) || defined(__x86_64__)
    #if defined(__LP64__) || defined(__x86_64__)
    using PlatformInfo = __internal::PlatformInfoImpl<PlatformType::Unix, PlatformWidth::x64>;
    #else
    #else
    using PlatformInfo = __internal::PlatformInfoImpl<PlatformType::Unix, PlatformWidth::x86>;
    #endif
    #endif

    #define unreachable __builtin_unreachable();
    #define forceinline __attribute__((always_inline))
    #define noop ((void)0)
    #define NEWLINE "\n"
    #define unreachable __builtin_unreachable();
    #define forceinline __attribute__((always_inline))
    #define noop ((void)0)
    #define NEWLINE "\n"

    #else
    #error "Unknown platform"
    #error "Unknown platform"
    #endif

    /* Constexpr support for various utilities */
    namespace cxpr {
    constexpr size_t strlen(const char* ptr) {
    if (!ptr) return 0;
    size_t len = 0;
    while (*(ptr++))
    len++;
    return len;
    }

    constexpr bool isspace(const unsigned char c) {
    constexpr const std::array whitespaces{'\t'_uc, '\n'_uc, '\v'_uc, '\f'_uc, '\r'_uc};
    constexpr size_t strlen(const char* ptr) {
    if (!ptr) return 0;
    size_t len = 0;
    while (*(ptr++)) len++;
    return len;
    }
    constexpr bool isspace(const unsigned char c) {
    constexpr const std::array whitespaces{ '\t'_uc, '\n'_uc, '\v'_uc, '\f'_uc, '\r'_uc };

    constexpr unsigned char begin_ws_range = whitespaces.front();
    constexpr unsigned char end_ws_range = whitespaces.back();
    constexpr unsigned char begin_ws_range = whitespaces.front();
    constexpr unsigned char end_ws_range = whitespaces.back();

    return c == ' ' || (c >= begin_ws_range && c <= end_ws_range);
    return c == ' ' || (c >= begin_ws_range && c <= end_ws_range);
    }
    constexpr bool strncmp(const char* lhs, const char* rhs, size_t size) {
    for (size_t i = 0; i < size; i++) {
    if (lhs[i] != rhs[i]) return false;
    }
    return true;
    }
    constexpr size_t min(size_t lhs, size_t rhs) {
    return (lhs < rhs) ? lhs : rhs;
    }
    // minimal string_view constexpr implementation
    // this exists only because std::string_view is constexpr-capable only on msvc
    // (as of 20 april 2022)
    class string_view {
    const char* m_ptr = nullptr;
    size_t m_size = 0;

    constexpr bool strncmp(const char* lhs, const char* rhs, size_t size) {
    for (size_t i = 0; i < size; i++) {
    if (lhs[i] != rhs[i]) return false;
    }
    return true;
    public:
    constexpr static size_t npos = static_cast<size_t>(-1);
    constexpr string_view(const char* ptr, size_t size) : m_ptr(ptr), m_size(size) {}
    constexpr string_view(const char* ptr) : m_ptr(ptr), m_size(strlen(ptr)) {}
    constexpr string_view() = default;
    constexpr const char* data() const { return m_ptr; }
    constexpr size_t size() const { return m_size; }
    constexpr size_t length() const { return m_size; }
    constexpr char operator[](size_t index) const { return m_ptr[index]; }
    constexpr bool operator==(const char* ptr) const {
    if (strlen(ptr) == m_size) return strncmp(ptr, m_ptr, m_size);
    return false;
    }

    constexpr size_t min(size_t lhs, size_t rhs) { return (lhs < rhs) ? lhs : rhs; }

    // minimal string_view constexpr implementation
    // this exists only because std::string_view is constexpr-capable only on msvc
    // (as of 20 april 2022)
    class string_view {
    const char* m_ptr = nullptr;
    size_t m_size = 0;

    public:
    constexpr static size_t npos = static_cast<size_t>(-1);
    constexpr string_view(const char* ptr, size_t size) : m_ptr(ptr), m_size(size) {}
    constexpr string_view(const char* ptr) : m_ptr(ptr), m_size(strlen(ptr)) {}
    constexpr string_view() = default;

    constexpr const char* data() const { return m_ptr; }
    constexpr size_t size() const { return m_size; }
    constexpr size_t length() const { return m_size; }
    constexpr char operator[](size_t index) const { return m_ptr[index]; }
    constexpr bool operator==(const char* ptr) const {
    if (strlen(ptr) == m_size) return strncmp(ptr, m_ptr, m_size);
    return false;
    }
    constexpr bool operator==(const string_view other) const {
    if (other.size() == m_size) return strncmp(other.data(), m_ptr, m_size);
    return false;
    }
    constexpr bool operator!=(const char* ptr) const { return !(*this == ptr); }
    constexpr bool operator!=(const string_view other) const { return !(*this == other); }
    constexpr const char* begin() const { return m_ptr; }
    constexpr const char* end() const { return m_ptr + m_size; }
    constexpr string_view substr(size_t pos = 0, size_t count = npos) const {
    const size_t rcount = min(count, size() - pos);
    return string_view{m_ptr + pos, rcount};
    }
    constexpr bool empty() const { return m_size == 0; }
    constexpr size_t find_first_of(char c, size_t off = 0) const {
    if (off > m_size) return npos;
    for (size_t i = off; i < m_size; i++) {
    if (m_ptr[i] == c) return i;
    }
    return npos;
    }
    constexpr size_t find_first_not_of(char c, size_t off = 0) const {
    if (off > m_size) return npos;
    for (size_t i = off; i < m_size; i++) {
    if (m_ptr[i] != c) return i;
    }
    return npos;
    constexpr bool operator==(const string_view other) const {
    if (other.size() == m_size) return strncmp(other.data(), m_ptr, m_size);
    return false;
    }
    constexpr bool operator!=(const char* ptr) const { return !(*this == ptr); }
    constexpr bool operator!=(const string_view other) const { return !(*this == other); }
    constexpr const char* begin() const { return m_ptr; }
    constexpr const char* end() const { return m_ptr + m_size; }
    constexpr string_view substr(size_t pos = 0, size_t count = npos) const {
    const size_t rcount = min(count, size() - pos);
    return string_view{ m_ptr + pos, rcount };
    }
    constexpr bool empty() const { return m_size == 0; }
    constexpr size_t find_first_of(char c, size_t off = 0) const {
    if (off > m_size) return npos;
    for (size_t i = off; i < m_size; i++) {
    if (m_ptr[i] == c) return i;
    }
    explicit operator std::string() const { return std::string{m_ptr, m_size}; }
    constexpr operator std::string_view() const { return std::string_view{m_ptr, m_size}; }
    friend std::ostream& operator<<(std::ostream& stream, const string_view view) {
    return stream << std::string_view{view.data(), view.size()};
    return npos;
    }
    constexpr size_t find_first_not_of(char c, size_t off = 0) const {
    if (off > m_size) return npos;
    for (size_t i = off; i < m_size; i++) {
    if (m_ptr[i] != c) return i;
    }
    };
    } // namespace cxpr

    return npos;
    }
    explicit operator std::string() const { return std::string{ m_ptr, m_size }; }
    constexpr operator std::string_view() const { return std::string_view{ m_ptr, m_size }; }
    friend std::ostream& operator<<(std::ostream& stream, const string_view view) {
    return stream << std::string_view{ view.data(), view.size() };
    }
    };
    } // namespace cxpr
    #if _MSC_VER
    using _string_view = std::string_view;
    #else
    using _string_view = cxpr::string_view;
    #endif

    // constexpr string->integer conversion
    namespace __internal {
    template <bool Signed = true>
    constexpr auto StrViewTo64Trimmed(const _string_view str) {
    constexpr std::array values_table_i64 = {1_i64,
    10_i64,
    100_i64,
    1000_i64,
    10000_i64,
    100000_i64,
    1000000_i64,
    10000000_i64,
    100000000_i64,
    1000000000_i64,
    10000000000_i64,
    100000000000_i64,
    1000000000000_i64,
    10000000000000_i64,
    100000000000000_i64,
    1000000000000000_i64,
    10000000000000000_i64,
    100000000000000000_i64,
    1000000000000000000_i64};
    constexpr std::array value_table_u64 = {1_u64,
    10_u64,
    100_u64,
    1000_u64,
    10000_u64,
    100000_u64,
    1000000_u64,
    10000000_u64,
    100000000_u64,
    1000000000_u64,
    10000000000_u64,
    100000000000_u64,
    1000000000000_u64,
    10000000000000_u64,
    100000000000000_u64,
    1000000000000000_u64,
    10000000000000000_u64,
    100000000000000000_u64,
    1000000000000000000_u64,
    10000000000000000000_u64};

    using RetType = std::conditional_t<Signed, int64_t, uint64_t>;
    size_t start_idx = 0;
    size_t end_idx = str.size();

    bool neg = false;
    if constexpr (Signed) {
    char maybe_sign = str[0];
    neg = maybe_sign == '-';
    start_idx += (maybe_sign == '-' || maybe_sign == '+');
    }

    RetType result = 0;

    // skip leading zeros
    while (start_idx < end_idx) {
    if (str[start_idx] != '0') break;
    start_idx++;
    }
    template <bool Signed = true>
    constexpr auto StrViewTo64Trimmed(const _string_view str) {
    constexpr std::array values_table_i64 = { 1_i64,
    10_i64,
    100_i64,
    1000_i64,
    10000_i64,
    100000_i64,
    1000000_i64,
    10000000_i64,
    100000000_i64,
    1000000000_i64,
    10000000000_i64,
    100000000000_i64,
    1000000000000_i64,
    10000000000000_i64,
    100000000000000_i64,
    1000000000000000_i64,
    10000000000000000_i64,
    100000000000000000_i64,
    1000000000000000000_i64 };
    constexpr std::array value_table_u64 = { 1_u64,
    10_u64,
    100_u64,
    1000_u64,
    10000_u64,
    100000_u64,
    1000000_u64,
    10000000_u64,
    100000000_u64,
    1000000000_u64,
    10000000000_u64,
    100000000000_u64,
    1000000000000_u64,
    10000000000000_u64,
    100000000000000_u64,
    1000000000000000_u64,
    10000000000000000_u64,
    100000000000000000_u64,
    1000000000000000000_u64,
    10000000000000000000_u64 };

    using RetType = std::conditional_t<Signed, int64_t, uint64_t>;
    size_t start_idx = 0;
    size_t end_idx = str.size();

    bool neg = false;
    if constexpr (Signed) {
    char maybe_sign = str[0];
    neg = maybe_sign == '-';
    start_idx += (maybe_sign == '-' || maybe_sign == '+');
    }

    if (start_idx == end_idx) return RetType{0};
    constexpr size_t max_uint64_size = cxpr::strlen("18446744073709551615");
    constexpr size_t max_int64_size = cxpr::strlen("9223372036854775807");
    RetType result = 0;

    constexpr auto max_size = Signed ? max_int64_size : max_uint64_size;
    // skip leading zeros
    while (start_idx < end_idx) {
    if (str[start_idx] != '0') break;
    start_idx++;
    }

    if (end_idx - start_idx > max_size) return RetType{0};
    if (start_idx == end_idx) return RetType{ 0 };
    constexpr size_t max_uint64_size = cxpr::strlen("18446744073709551615");
    constexpr size_t max_int64_size = cxpr::strlen("9223372036854775807");

    constexpr auto get_values_table = [values_table_i64, value_table_u64]() {
    if constexpr (Signed)
    return values_table_i64;
    else
    return value_table_u64;
    };
    constexpr auto max_size = Signed ? max_int64_size : max_uint64_size;

    constexpr const auto values_table = get_values_table();
    if (end_idx - start_idx > max_size) return RetType{ 0 };

    // 0-9 => 48-57
    for (size_t idx = end_idx - 1, tbl_idx = 0; idx >= start_idx; idx--, tbl_idx++) {
    result += static_cast<RetType>(str[idx] - '0') * values_table[tbl_idx];
    if (idx == 0) break;
    }
    constexpr auto get_values_table = [values_table_i64, value_table_u64]() {
    if constexpr (Signed)
    return result * (neg ? -1 : 1);
    return values_table_i64;
    else
    return result;
    }
    } // namespace __internal
    return value_table_u64;
    };

    constexpr const auto values_table = get_values_table();

    // 0-9 => 48-57
    for (size_t idx = end_idx - 1, tbl_idx = 0; idx >= start_idx; idx--, tbl_idx++) {
    result += static_cast<RetType>(str[idx] - '0') * values_table[tbl_idx];
    if (idx == 0) break;
    }
    if constexpr (Signed)
    return result * (neg ? -1 : 1);
    else
    return result;
    }
    } // namespace __internal
    template <bool Signed>
    constexpr int64_t StrViewTo64(const _string_view view) {
    size_t cur_index = 0;
    @@ -388,172 +381,155 @@ constexpr int64_t StrViewTo64(const _string_view view) {
    if (cur_index == max_index) return 0;
    return __internal::StrViewTo64Trimmed<Signed>(view.substr(cur_index, max_index));
    }

    constexpr inline auto StrViewToU64 = StrViewTo64<false>;
    constexpr inline auto StrViewToI64 = StrViewTo64<true>;

    namespace EnumHelpers {
    template <EnumT V, size_t N>
    class EnumStrHashMap {
    // round up to power of 2 to avoid modulos and just use bitwise ops
    constexpr static size_t ACTUAL_SIZE = std::bit_ceil(N);
    constexpr static size_t FOR_MOD_OPS = ACTUAL_SIZE - 1;
    struct KeyBkt {
    V key;
    bool used;
    };
    std::array<std::pair<KeyBkt, _string_view>, ACTUAL_SIZE> m_internal_map;
    size_t m_size = 0;

    public:
    constexpr void insert(V key, _string_view val) {
    if (m_size == m_internal_map.size()) throw std::runtime_error("This map is full");
    size_t idx = from_enum(key) & FOR_MOD_OPS;
    while (m_internal_map[idx].first.used) {
    idx = (idx + 1) & FOR_MOD_OPS;
    }
    m_internal_map[idx] = std::make_pair(KeyBkt{std::move(key), true}, val);
    m_size++;
    }
    constexpr _string_view operator[](V key) const {
    size_t idx = from_enum(key) & FOR_MOD_OPS;
    size_t n_tries = 0;
    while (m_internal_map[idx].first.key != key) {
    idx = (idx + 1) & FOR_MOD_OPS;
    if (n_tries++ == m_size) throw std::runtime_error("This enum value is not valid");
    }
    return m_internal_map[idx].second;
    }
    template <EnumT V, size_t N>
    class EnumStrHashMap {
    // round up to power of 2 to avoid modulos and just use bitwise ops
    constexpr static size_t ACTUAL_SIZE = std::bit_ceil(N);
    constexpr static size_t FOR_MOD_OPS = ACTUAL_SIZE - 1;
    struct KeyBkt {
    V key;
    bool used;
    };
    std::array<std::pair<KeyBkt, _string_view>, ACTUAL_SIZE> m_internal_map;
    size_t m_size = 0;

    constexpr size_t count_enum_values(_string_view view) {
    size_t count = 1;
    for (char c : view)
    count += (c == ',');
    return count;
    }

    template <EnumT T>
    constexpr _string_view get_enum_full_string(TagType<T>) {
    return "";
    }

    template <EnumT T>
    requires(!get_enum_full_string<T>({}).empty()) constexpr auto construct_enum_array(TagType<T>) {
    constexpr _string_view view = get_enum_full_string<T>({});
    std::array<std::pair<_string_view, T>, count_enum_values(view)> enum_map_l;
    std::underlying_type_t<T> current_val{};
    auto get_pair = [&view, &current_val](size_t first_idx, size_t second_idx) {
    constexpr bool Signed = std::is_signed_v<std::underlying_type_t<T>>;
    auto sub = view.substr(first_idx, second_idx - first_idx);
    auto equal_idx = sub.find_first_of('=');
    if (equal_idx == std::string_view::npos) {
    // no equal, get next value
    auto first_nospace_idx = sub.find_first_not_of(' ');
    auto last_nospace_idx = sub.find_first_of(' ', first_nospace_idx);
    return std::make_pair(
    sub.substr(first_nospace_idx, last_nospace_idx),
    to_enum<T>(current_val++));
    } else {
    auto first_nospace_idx = sub.find_first_not_of(' ');
    auto last_nospace_idx = sub.find_first_of(' ', first_nospace_idx);
    return std::make_pair(
    sub.substr(first_nospace_idx,
    (last_nospace_idx < equal_idx ? last_nospace_idx : equal_idx) - first_nospace_idx),
    to_enum<T>(StrViewTo64<Signed>(sub.substr(equal_idx + 1))));
    }
    };
    size_t first_idx = 0;
    size_t second_idx = view.find_first_of(',');
    size_t i = 0;
    while (second_idx != _string_view::npos) {
    enum_map_l[i++] = get_pair(first_idx, second_idx);
    first_idx = second_idx + 1;
    second_idx = view.find_first_of(',', first_idx);
    }
    enum_map_l[i] = get_pair(first_idx, view.size());
    return enum_map_l;
    public:
    constexpr void insert(V key, _string_view val) {
    if (m_size == m_internal_map.size()) throw std::runtime_error("This map is full");
    size_t idx = from_enum(key) & FOR_MOD_OPS;
    while (m_internal_map[idx].first.used) { idx = (idx + 1) & FOR_MOD_OPS; }
    m_internal_map[idx] = std::make_pair(KeyBkt{ std::move(key), true }, val);
    m_size++;
    }

    template <EnumT T>
    constexpr auto construct_enum_map(
    const std::array<std::pair<_string_view, T>, count_enum_values(get_enum_full_string<T>({}))>& enum_array) {
    constexpr size_t sz = count_enum_values(get_enum_full_string<T>({}));
    EnumStrHashMap<T, sz> map;
    for (const auto& [k, v] : enum_array) {
    map.insert(v, k);
    constexpr _string_view operator[](V key) const {
    size_t idx = from_enum(key) & FOR_MOD_OPS;
    size_t n_tries = 0;
    while (m_internal_map[idx].first.key != key) {
    idx = (idx + 1) & FOR_MOD_OPS;
    if (n_tries++ == m_size) throw std::runtime_error("This enum value is not valid");
    }
    return map;
    return m_internal_map[idx].second;
    }

    template <EnumT T>
    requires(requires { construct_enum_array<T>({}); }) struct EnumMapProvider {
    static constexpr auto enum_array = construct_enum_array<T>({});
    static constexpr auto map = construct_enum_map<T>(enum_array);
    };

    template <typename T>
    concept EnumSupportsMap = EnumT<T> && requires {
    {EnumMapProvider<T>{}};
    };

    template <EnumSupportsMap T>
    class EnumIterator {
    size_t index = 0;
    constexpr static const auto& s_enum_map = EnumMapProvider<T>::enum_array;

    public:
    using iterator_category = std::input_iterator_tag;
    using value_type = T;
    using reference = T&;

    constexpr EnumIterator() = default;
    constexpr EnumIterator(size_t idx) : index(idx) {}
    constexpr const T& operator*() const { return s_enum_map[index].second; }
    constexpr const T& operator->() const { return s_enum_map[index].second; }

    constexpr bool operator==(const EnumIterator& other) const { return index == other.index; }
    constexpr bool operator!=(const EnumIterator& other) const { return index != other.index; }

    constexpr EnumIterator& operator++() {
    index++;
    return *this;
    }
    constexpr EnumIterator operator++(int) {
    EnumIterator iter = *this;
    index++;
    return iter;
    }
    constexpr EnumIterator& operator--() {
    index--;
    return *this;
    }
    constexpr EnumIterator operator--(int) {
    EnumIterator iter = *this;
    index--;
    return iter;
    };
    constexpr size_t count_enum_values(_string_view view) {
    size_t count = 1;
    for (char c : view) count += (c == ',');
    return count;
    }
    template <EnumT T>
    constexpr _string_view get_enum_full_string(TagType<T>) {
    return "";
    }
    template <EnumT T>
    requires(!get_enum_full_string<T>({}).empty()) constexpr auto construct_enum_array(TagType<T>) {
    constexpr _string_view view = get_enum_full_string<T>({});
    std::array<std::pair<_string_view, T>, count_enum_values(view)> enum_map_l;
    std::underlying_type_t<T> current_val{};
    auto get_pair = [&view, &current_val](size_t first_idx, size_t second_idx) {
    constexpr bool Signed = std::is_signed_v<std::underlying_type_t<T>>;
    auto sub = view.substr(first_idx, second_idx - first_idx);
    auto equal_idx = sub.find_first_of('=');
    if (equal_idx == std::string_view::npos) {
    // no equal, get next value
    auto first_nospace_idx = sub.find_first_not_of(' ');
    auto last_nospace_idx = sub.find_first_of(' ', first_nospace_idx);
    return std::make_pair(sub.substr(first_nospace_idx, last_nospace_idx), to_enum<T>(current_val++));
    } else {
    auto first_nospace_idx = sub.find_first_not_of(' ');
    auto last_nospace_idx = sub.find_first_of(' ', first_nospace_idx);
    return std::make_pair(
    sub.substr(
    first_nospace_idx, (last_nospace_idx < equal_idx ? last_nospace_idx : equal_idx) - first_nospace_idx
    ),
    to_enum<T>(StrViewTo64<Signed>(sub.substr(equal_idx + 1)))
    );
    }
    };
    } // namespace EnumHelpers
    size_t first_idx = 0;
    size_t second_idx = view.find_first_of(',');
    size_t i = 0;
    while (second_idx != _string_view::npos) {
    enum_map_l[i++] = get_pair(first_idx, second_idx);
    first_idx = second_idx + 1;
    second_idx = view.find_first_of(',', first_idx);
    }
    enum_map_l[i] = get_pair(first_idx, view.size());
    return enum_map_l;
    }
    template <EnumT T>
    constexpr auto construct_enum_map(
    const std::array<std::pair<_string_view, T>, count_enum_values(get_enum_full_string<T>({}))>& enum_array
    ) {
    constexpr size_t sz = count_enum_values(get_enum_full_string<T>({}));
    EnumStrHashMap<T, sz> map;
    for (const auto& [k, v] : enum_array) { map.insert(v, k); }
    return map;
    }
    template <EnumT T>
    requires(requires { construct_enum_array<T>({}); }) struct EnumMapProvider {
    constexpr static auto enum_array = construct_enum_array<T>({});
    constexpr static auto map = construct_enum_map<T>(enum_array);
    };
    template <typename T>
    concept EnumSupportsMap = EnumT<T> && requires {
    { EnumMapProvider<T>{} };
    };
    template <EnumSupportsMap T>
    class EnumIterator {
    size_t index = 0;
    constexpr static const auto& s_enum_map = EnumMapProvider<T>::enum_array;

    public:
    using iterator_category = std::input_iterator_tag;
    using value_type = T;
    using reference = T&;

    constexpr EnumIterator() = default;
    constexpr EnumIterator(size_t idx) : index(idx) {}
    constexpr const T& operator*() const { return s_enum_map[index].second; }
    constexpr const T& operator->() const { return s_enum_map[index].second; }
    constexpr bool operator==(const EnumIterator& other) const { return index == other.index; }
    constexpr bool operator!=(const EnumIterator& other) const { return index != other.index; }
    constexpr EnumIterator& operator++() {
    index++;
    return *this;
    }
    constexpr EnumIterator operator++(int) {
    EnumIterator iter = *this;
    index++;
    return iter;
    }
    constexpr EnumIterator& operator--() {
    index--;
    return *this;
    }
    constexpr EnumIterator operator--(int) {
    EnumIterator iter = *this;
    index--;
    return iter;
    }
    };
    } // namespace EnumHelpers
    template <EnumT E>
    class std::iterator_traits<EnumHelpers::EnumIterator<E>> {
    public:
    using Iter = EnumHelpers::EnumIterator<E>;
    using difference_type = void;
    using value_type = E;
    using pointer = void;
    using reference = E&;
    using Iter = EnumHelpers::EnumIterator<E>;
    using difference_type = void;
    using value_type = E;
    using pointer = void;
    using reference = E&;
    using iterator_category = std::input_iterator_tag;
    };

    enum class EnumStrSearchType { HashMap, Linear };

    template <EnumStrSearchType SearchType = EnumStrSearchType::HashMap, EnumHelpers::EnumSupportsMap T>
    constexpr _string_view enum_to_str_view(T e) {
    if constexpr (SearchType == EnumStrSearchType::Linear) {
    constexpr const auto& enum_map = EnumHelpers::EnumMapProvider<T>::enum_array;
    auto it = std::find_if(enum_map.begin(), enum_map.end(), [&e](const auto& p) {
    auto it = std::find_if(enum_map.begin(), enum_map.end(), [&e](const auto& p) {
    const auto& [name, val] = p;
    return val == e;
    });
    @@ -577,48 +553,38 @@ constexpr _string_view enum_to_str_view(T e) {
    return enum_map[e];
    }
    }

    template <EnumHelpers::EnumSupportsMap T>
    constexpr size_t enum_size() {
    constexpr const auto& enum_array = EnumHelpers::EnumMapProvider<T>::enum_array;
    return enum_array.size();
    }

    template <EnumStrSearchType SearchType = EnumStrSearchType::HashMap, EnumHelpers::EnumSupportsMap T>
    std::string enum_to_str(T e) {
    return std::string{enum_to_str_view<SearchType, T>(e)};
    return std::string{ enum_to_str_view<SearchType, T>(e) };
    }

    template <EnumHelpers::EnumSupportsMap T>
    struct ForEachEnum {
    constexpr auto begin() const { return EnumHelpers::EnumIterator<T>{0}; }
    constexpr auto begin() const { return EnumHelpers::EnumIterator<T>{ 0 }; }
    constexpr auto end() const {
    return EnumHelpers::EnumIterator<T>{EnumHelpers::EnumMapProvider<T>::enum_array.size()};
    return EnumHelpers::EnumIterator<T>{ EnumHelpers::EnumMapProvider<T>::enum_array.size() };
    }
    };

    template <EnumHelpers::EnumSupportsMap T>
    constexpr auto for_each_enum() {
    return ForEachEnum<T>{};
    }

    template <EnumHelpers::EnumSupportsMap T, typename Functor>
    requires(requires { std::declval<Functor>()(std::declval<T>()); }) constexpr auto for_each_enum(Functor func) {
    using Res = std::invoke_result_t<Functor, T>;
    if constexpr (std::is_void_v<Res>) {
    for (auto val : ForEachEnum<T>{}) {
    func(val);
    }
    for (auto val : ForEachEnum<T>{}) { func(val); }
    } else {
    std::array<Res, EnumHelpers::EnumMapProvider<T>::enum_array.size()> result_array;
    size_t i = 0;
    for (auto val : ForEachEnum<T>{}) {
    result_array[i++] = func(val);
    }
    for (auto val : ForEachEnum<T>{}) { result_array[i++] = func(val); }
    return result_array;
    }
    }

    #define ENUM_TO_STR(en, ...) \
    namespace EnumHelpers { \
    template <> \
    @@ -632,31 +598,54 @@ requires(requires { std::declval<Functor>()(std::declval<T>()); }) constexpr aut
    ENUM_TO_STR(en, __VA_ARGS__)

    #define BITMASK_ENUM(en) \
    inline constexpr auto operator&(en lhs, en rhs) { return to_enum<en>(from_enum(lhs) & from_enum(rhs)); } \
    inline constexpr auto operator|(en lhs, en rhs) { return to_enum<en>(from_enum(lhs) | from_enum(rhs)); } \
    inline constexpr auto operator^(en lhs, en rhs) { return to_enum<en>(from_enum(lhs) ^ from_enum(rhs)); } \
    inline constexpr auto operator~(en val) { return to_enum<en>(~from_enum(val)); } \
    inline constexpr auto& operator&=(en& lhs, en rhs) { \
    constexpr inline auto operator&(en lhs, en rhs) { \
    return to_enum<en>(from_enum(lhs) & from_enum(rhs)); \
    } \
    constexpr inline auto operator|(en lhs, en rhs) { \
    return to_enum<en>(from_enum(lhs) | from_enum(rhs)); \
    } \
    constexpr inline auto operator^(en lhs, en rhs) { \
    return to_enum<en>(from_enum(lhs) ^ from_enum(rhs)); \
    } \
    constexpr inline auto operator~(en val) { \
    return to_enum<en>(~from_enum(val)); \
    } \
    constexpr inline auto& operator&=(en& lhs, en rhs) { \
    lhs = lhs & rhs; \
    return lhs; \
    } \
    inline constexpr auto& operator|=(en& lhs, en rhs) { \
    constexpr inline auto& operator|=(en& lhs, en rhs) { \
    lhs = lhs | rhs; \
    return lhs; \
    } \
    inline constexpr auto& operator^=(en& lhs, en rhs) { \
    constexpr inline auto& operator^=(en& lhs, en rhs) { \
    lhs = lhs ^ rhs; \
    return lhs; \
    }

    [[noreturn]] inline void fatalfail() {
    abort();
    unreachable;
    }

    inline void assert_expr(bool expr, const char* msg = nullptr) {
    if (!expr) {
    if (msg) puts(msg);
    #ifdef BACKTRACE_AVAILABLE
    BackTrace::print_backtrace();
    #endif
    fatalfail();
    }
    }
    }
    template <typename T, typename Tp>
    concept SameAsConstPtr =
    std::same_as<std::add_pointer_t<Tp>, T> || std::same_as<std::add_pointer_t<std::add_const_t<Tp>>, T>;

    template <typename T, typename Tp>
    concept SameAsConstRef =
    std::same_as<std::add_lvalue_reference_t<Tp>, T> || std::same_as<std::add_lvalue_reference_t<std::add_const_t<Tp>>, T>;
    template <typename Iter, typename Tp>
    concept Iterator = requires(Iter it) {
    { it.operator->() } -> SameAsConstPtr<Tp>;
    { *it } -> SameAsConstRef<Tp>;
    { ++it };
    { it++ };
    };
  2. Atari2 created this gist May 4, 2022.
    662 changes: 662 additions & 0 deletions Common.h
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,662 @@
    #pragma once
    #include <array>
    #include <bit>
    #include <concepts>
    #include <cstdint>
    #include <optional>
    #include <stdexcept>
    #include <string>
    #include <string_view>

    // common and useful macros / functions
    #define STRIMPL(x) #x
    #define STR(x) STRIMPL(x)
    // defines a literal with the format "DEBUG [file:line]: <info>"
    #define DEBUGINFO(info) "DEBUG [" __FILE__ ":" STR(__LINE__) "]: " STR(info)
    #define WIDEIMPL(str) L##str
    #define WIDE(str) WIDEIMPL(str)

    // A catch-all tag type.
    template <typename T>
    struct TagType {};

    // Concept for enum template parameters
    template <typename T>
    concept EnumT = std::is_enum_v<T>;

    // Simple choice support
    template <typename T>
    constexpr auto choice(bool t, T ret_true, T ret_false) {
    return (t ? ret_true : ret_false);
    }

    template <typename T>
    constexpr auto triple_choice(bool a, bool b, T reta, T retb, T retc) {
    return (a ? reta : (b ? retb : retc));
    }

    // enum conversions
    template <EnumT T>
    constexpr auto from_enum(T val) {
    return static_cast<std::underlying_type_t<T>>(val);
    }

    template <EnumT T>
    constexpr auto to_enum(std::integral auto val) {
    return static_cast<T>(static_cast<std::underlying_type_t<T>>(val));
    }

    // an always_false template dependant bool for static_asserts in if constexpr code
    template <typename T>
    inline constexpr bool always_false_v = false;

    // size explicit integer shorthands and operators
    using u8 = uint8_t;
    using i8 = int8_t;
    using u16 = uint16_t;
    using i16 = int16_t;
    using u32 = uint32_t;
    using i32 = int32_t;
    using u64 = uint64_t;
    using i64 = int64_t;
    using c = char;
    using uc = unsigned char;

    constexpr u8 operator""_u8(unsigned long long val) {
    return static_cast<u8>(val);
    }
    constexpr u16 operator""_u16(unsigned long long val) {
    return static_cast<u16>(val);
    }
    constexpr u32 operator""_u32(unsigned long long val) {
    return static_cast<u32>(val);
    }
    constexpr u64 operator""_u64(unsigned long long val) {
    return static_cast<u64>(val);
    }
    constexpr i8 operator""_i8(unsigned long long val) {
    return static_cast<i8>(val);
    }
    constexpr i16 operator""_i16(unsigned long long val) {
    return static_cast<i16>(val);
    }
    constexpr i32 operator""_i32(unsigned long long val) {
    return static_cast<i32>(val);
    }
    constexpr i64 operator""_i64(unsigned long long val) {
    return static_cast<i64>(val);
    }
    constexpr size_t operator""_sz(unsigned long long val) {
    return static_cast<size_t>(val);
    }
    constexpr intptr_t operator""_iptr(unsigned long long val) {
    return static_cast<intptr_t>(val);
    }
    constexpr uintptr_t operator""_uptr(unsigned long long val) {
    return static_cast<uintptr_t>(val);
    }
    constexpr c operator""_c(char val) {
    return static_cast<c>(val);
    }
    constexpr uc operator""_uc(char val) {
    return static_cast<uc>(val);
    }

    // platform information
    enum class PlatformType { Windows = 0, Apple = 1, Unix = 2 };
    enum class PlatformWidth { x64 = 0, x86 = 1 };
    namespace __internal {
    template <PlatformType TType, PlatformWidth TWidth>
    struct PlatformInfoImpl {
    static_assert(TType == PlatformType::Windows || TType == PlatformType::Apple || TType == PlatformType::Unix,
    "Invalid platform type");
    static_assert(TWidth == PlatformWidth::x64 || TWidth == PlatformWidth::x86, "Invalid platform width");
    static constexpr PlatformType Type = TType;
    static constexpr bool WINDOWS = (TType == PlatformType::Windows);
    static constexpr bool UNIX = (TType == PlatformType::Unix);
    static constexpr bool APPLE = (TType == PlatformType::Apple);
    static constexpr PlatformWidth Width = TWidth;
    static constexpr bool X64 = (TWidth == PlatformWidth::x64);
    static constexpr bool X86 = (TWidth == PlatformWidth::x86);
    static constexpr const char* Name = triple_choice(WINDOWS, UNIX, "Windows", "Unix", "Apple");
    static constexpr const char* StrWidth = choice(X64, "x64", "x86");
    constexpr static auto type() { return Type; }
    constexpr static bool is_windows() { return WINDOWS; }
    constexpr static bool is_unix() { return UNIX; }
    constexpr static bool is_apple() { return APPLE; }
    template <typename T = PlatformWidth>
    constexpr static auto width() {
    if constexpr (std::same_as<T, PlatformWidth>) {
    return Width;
    } else if constexpr (std::same_as<T, char*>) {
    return StrWidth;
    } else {
    static_assert(always_false_v<T>,
    "width() call is only valid with PlatformWidth or char* as template parameters");
    return nullptr;
    }
    }
    constexpr static bool x64() { return X64; }
    constexpr static bool x86() { return X86; }
    constexpr static auto name() { return Name; }
    };
    } // namespace __internal

    #ifdef _WIN32
    // Windows
    #ifdef _WIN64
    using PlatformInfo = __internal::PlatformInfoImpl<PlatformType::Windows, PlatformWidth::x64>;
    #else
    using PlatformInfo = __internal::PlatformInfoImpl<PlatformType::Windows, PlatformWidth::x86>;
    #endif

    #define unreachable __assume(0)
    #define forceinline __forceinline
    #define noop __noop
    #define NEWLINE "\r\n"

    #elif __APPLE__
    // Apple
    #if defined(__LP64__) || defined(__x86_64__)
    using PlatformInfo = __internal::PlatformInfoImpl<PlatformType::Apple, PlatformWidth::x64>;
    #else
    using PlatformInfo = __internal::PlatformInfoImpl<PlatformType::Apple, PlatformWidth::x86>;
    #endif

    #define unreachable __builtin_unreachable();
    #define forceinline __attribute__((always_inline))
    #define noop ((void)0)
    #define NEWLINE "\n"

    #elif __unix__
    // Unix
    #if defined(__LP64__) || defined(__x86_64__)
    using PlatformInfo = __internal::PlatformInfoImpl<PlatformType::Unix, PlatformWidth::x64>;
    #else
    using PlatformInfo = __internal::PlatformInfoImpl<PlatformType::Unix, PlatformWidth::x86>;
    #endif

    #define unreachable __builtin_unreachable();
    #define forceinline __attribute__((always_inline))
    #define noop ((void)0)
    #define NEWLINE "\n"

    #else
    #error "Unknown platform"
    #endif

    /* Constexpr support for various utilities */
    namespace cxpr {
    constexpr size_t strlen(const char* ptr) {
    if (!ptr) return 0;
    size_t len = 0;
    while (*(ptr++))
    len++;
    return len;
    }

    constexpr bool isspace(const unsigned char c) {
    constexpr const std::array whitespaces{'\t'_uc, '\n'_uc, '\v'_uc, '\f'_uc, '\r'_uc};

    constexpr unsigned char begin_ws_range = whitespaces.front();
    constexpr unsigned char end_ws_range = whitespaces.back();

    return c == ' ' || (c >= begin_ws_range && c <= end_ws_range);
    }

    constexpr bool strncmp(const char* lhs, const char* rhs, size_t size) {
    for (size_t i = 0; i < size; i++) {
    if (lhs[i] != rhs[i]) return false;
    }
    return true;
    }

    constexpr size_t min(size_t lhs, size_t rhs) { return (lhs < rhs) ? lhs : rhs; }

    // minimal string_view constexpr implementation
    // this exists only because std::string_view is constexpr-capable only on msvc
    // (as of 20 april 2022)
    class string_view {
    const char* m_ptr = nullptr;
    size_t m_size = 0;

    public:
    constexpr static size_t npos = static_cast<size_t>(-1);
    constexpr string_view(const char* ptr, size_t size) : m_ptr(ptr), m_size(size) {}
    constexpr string_view(const char* ptr) : m_ptr(ptr), m_size(strlen(ptr)) {}
    constexpr string_view() = default;

    constexpr const char* data() const { return m_ptr; }
    constexpr size_t size() const { return m_size; }
    constexpr size_t length() const { return m_size; }
    constexpr char operator[](size_t index) const { return m_ptr[index]; }
    constexpr bool operator==(const char* ptr) const {
    if (strlen(ptr) == m_size) return strncmp(ptr, m_ptr, m_size);
    return false;
    }
    constexpr bool operator==(const string_view other) const {
    if (other.size() == m_size) return strncmp(other.data(), m_ptr, m_size);
    return false;
    }
    constexpr bool operator!=(const char* ptr) const { return !(*this == ptr); }
    constexpr bool operator!=(const string_view other) const { return !(*this == other); }
    constexpr const char* begin() const { return m_ptr; }
    constexpr const char* end() const { return m_ptr + m_size; }
    constexpr string_view substr(size_t pos = 0, size_t count = npos) const {
    const size_t rcount = min(count, size() - pos);
    return string_view{m_ptr + pos, rcount};
    }
    constexpr bool empty() const { return m_size == 0; }
    constexpr size_t find_first_of(char c, size_t off = 0) const {
    if (off > m_size) return npos;
    for (size_t i = off; i < m_size; i++) {
    if (m_ptr[i] == c) return i;
    }
    return npos;
    }
    constexpr size_t find_first_not_of(char c, size_t off = 0) const {
    if (off > m_size) return npos;
    for (size_t i = off; i < m_size; i++) {
    if (m_ptr[i] != c) return i;
    }
    return npos;
    }
    explicit operator std::string() const { return std::string{m_ptr, m_size}; }
    constexpr operator std::string_view() const { return std::string_view{m_ptr, m_size}; }
    friend std::ostream& operator<<(std::ostream& stream, const string_view view) {
    return stream << std::string_view{view.data(), view.size()};
    }
    };
    } // namespace cxpr

    #if _MSC_VER
    using _string_view = std::string_view;
    #else
    using _string_view = cxpr::string_view;
    #endif

    // constexpr string->integer conversion
    namespace __internal {
    template <bool Signed = true>
    constexpr auto StrViewTo64Trimmed(const _string_view str) {
    constexpr std::array values_table_i64 = {1_i64,
    10_i64,
    100_i64,
    1000_i64,
    10000_i64,
    100000_i64,
    1000000_i64,
    10000000_i64,
    100000000_i64,
    1000000000_i64,
    10000000000_i64,
    100000000000_i64,
    1000000000000_i64,
    10000000000000_i64,
    100000000000000_i64,
    1000000000000000_i64,
    10000000000000000_i64,
    100000000000000000_i64,
    1000000000000000000_i64};
    constexpr std::array value_table_u64 = {1_u64,
    10_u64,
    100_u64,
    1000_u64,
    10000_u64,
    100000_u64,
    1000000_u64,
    10000000_u64,
    100000000_u64,
    1000000000_u64,
    10000000000_u64,
    100000000000_u64,
    1000000000000_u64,
    10000000000000_u64,
    100000000000000_u64,
    1000000000000000_u64,
    10000000000000000_u64,
    100000000000000000_u64,
    1000000000000000000_u64,
    10000000000000000000_u64};

    using RetType = std::conditional_t<Signed, int64_t, uint64_t>;
    size_t start_idx = 0;
    size_t end_idx = str.size();

    bool neg = false;
    if constexpr (Signed) {
    char maybe_sign = str[0];
    neg = maybe_sign == '-';
    start_idx += (maybe_sign == '-' || maybe_sign == '+');
    }

    RetType result = 0;

    // skip leading zeros
    while (start_idx < end_idx) {
    if (str[start_idx] != '0') break;
    start_idx++;
    }

    if (start_idx == end_idx) return RetType{0};
    constexpr size_t max_uint64_size = cxpr::strlen("18446744073709551615");
    constexpr size_t max_int64_size = cxpr::strlen("9223372036854775807");

    constexpr auto max_size = Signed ? max_int64_size : max_uint64_size;

    if (end_idx - start_idx > max_size) return RetType{0};

    constexpr auto get_values_table = [values_table_i64, value_table_u64]() {
    if constexpr (Signed)
    return values_table_i64;
    else
    return value_table_u64;
    };

    constexpr const auto values_table = get_values_table();

    // 0-9 => 48-57
    for (size_t idx = end_idx - 1, tbl_idx = 0; idx >= start_idx; idx--, tbl_idx++) {
    result += static_cast<RetType>(str[idx] - '0') * values_table[tbl_idx];
    if (idx == 0) break;
    }
    if constexpr (Signed)
    return result * (neg ? -1 : 1);
    else
    return result;
    }
    } // namespace __internal

    template <bool Signed>
    constexpr int64_t StrViewTo64(const _string_view view) {
    size_t cur_index = 0;
    size_t max_index = view.length();

    // skip leading and trailing whitespace
    if (max_index == 0) return 0;

    while (cxpr::isspace(view[cur_index])) {
    cur_index++;
    if (cur_index == max_index) return 0;
    }

    while (cxpr::isspace(view[max_index - 1])) {
    max_index--;
    if (max_index == _string_view::npos) return 0;
    }

    if (cur_index == max_index) return 0;
    return __internal::StrViewTo64Trimmed<Signed>(view.substr(cur_index, max_index));
    }

    constexpr inline auto StrViewToU64 = StrViewTo64<false>;
    constexpr inline auto StrViewToI64 = StrViewTo64<true>;

    namespace EnumHelpers {
    template <EnumT V, size_t N>
    class EnumStrHashMap {
    // round up to power of 2 to avoid modulos and just use bitwise ops
    constexpr static size_t ACTUAL_SIZE = std::bit_ceil(N);
    constexpr static size_t FOR_MOD_OPS = ACTUAL_SIZE - 1;
    struct KeyBkt {
    V key;
    bool used;
    };
    std::array<std::pair<KeyBkt, _string_view>, ACTUAL_SIZE> m_internal_map;
    size_t m_size = 0;

    public:
    constexpr void insert(V key, _string_view val) {
    if (m_size == m_internal_map.size()) throw std::runtime_error("This map is full");
    size_t idx = from_enum(key) & FOR_MOD_OPS;
    while (m_internal_map[idx].first.used) {
    idx = (idx + 1) & FOR_MOD_OPS;
    }
    m_internal_map[idx] = std::make_pair(KeyBkt{std::move(key), true}, val);
    m_size++;
    }
    constexpr _string_view operator[](V key) const {
    size_t idx = from_enum(key) & FOR_MOD_OPS;
    size_t n_tries = 0;
    while (m_internal_map[idx].first.key != key) {
    idx = (idx + 1) & FOR_MOD_OPS;
    if (n_tries++ == m_size) throw std::runtime_error("This enum value is not valid");
    }
    return m_internal_map[idx].second;
    }
    };

    constexpr size_t count_enum_values(_string_view view) {
    size_t count = 1;
    for (char c : view)
    count += (c == ',');
    return count;
    }

    template <EnumT T>
    constexpr _string_view get_enum_full_string(TagType<T>) {
    return "";
    }

    template <EnumT T>
    requires(!get_enum_full_string<T>({}).empty()) constexpr auto construct_enum_array(TagType<T>) {
    constexpr _string_view view = get_enum_full_string<T>({});
    std::array<std::pair<_string_view, T>, count_enum_values(view)> enum_map_l;
    std::underlying_type_t<T> current_val{};
    auto get_pair = [&view, &current_val](size_t first_idx, size_t second_idx) {
    constexpr bool Signed = std::is_signed_v<std::underlying_type_t<T>>;
    auto sub = view.substr(first_idx, second_idx - first_idx);
    auto equal_idx = sub.find_first_of('=');
    if (equal_idx == std::string_view::npos) {
    // no equal, get next value
    auto first_nospace_idx = sub.find_first_not_of(' ');
    auto last_nospace_idx = sub.find_first_of(' ', first_nospace_idx);
    return std::make_pair(
    sub.substr(first_nospace_idx, last_nospace_idx),
    to_enum<T>(current_val++));
    } else {
    auto first_nospace_idx = sub.find_first_not_of(' ');
    auto last_nospace_idx = sub.find_first_of(' ', first_nospace_idx);
    return std::make_pair(
    sub.substr(first_nospace_idx,
    (last_nospace_idx < equal_idx ? last_nospace_idx : equal_idx) - first_nospace_idx),
    to_enum<T>(StrViewTo64<Signed>(sub.substr(equal_idx + 1))));
    }
    };
    size_t first_idx = 0;
    size_t second_idx = view.find_first_of(',');
    size_t i = 0;
    while (second_idx != _string_view::npos) {
    enum_map_l[i++] = get_pair(first_idx, second_idx);
    first_idx = second_idx + 1;
    second_idx = view.find_first_of(',', first_idx);
    }
    enum_map_l[i] = get_pair(first_idx, view.size());
    return enum_map_l;
    }

    template <EnumT T>
    constexpr auto construct_enum_map(
    const std::array<std::pair<_string_view, T>, count_enum_values(get_enum_full_string<T>({}))>& enum_array) {
    constexpr size_t sz = count_enum_values(get_enum_full_string<T>({}));
    EnumStrHashMap<T, sz> map;
    for (const auto& [k, v] : enum_array) {
    map.insert(v, k);
    }
    return map;
    }

    template <EnumT T>
    requires(requires { construct_enum_array<T>({}); }) struct EnumMapProvider {
    static constexpr auto enum_array = construct_enum_array<T>({});
    static constexpr auto map = construct_enum_map<T>(enum_array);
    };

    template <typename T>
    concept EnumSupportsMap = EnumT<T> && requires {
    {EnumMapProvider<T>{}};
    };

    template <EnumSupportsMap T>
    class EnumIterator {
    size_t index = 0;
    constexpr static const auto& s_enum_map = EnumMapProvider<T>::enum_array;

    public:
    using iterator_category = std::input_iterator_tag;
    using value_type = T;
    using reference = T&;

    constexpr EnumIterator() = default;
    constexpr EnumIterator(size_t idx) : index(idx) {}
    constexpr const T& operator*() const { return s_enum_map[index].second; }
    constexpr const T& operator->() const { return s_enum_map[index].second; }

    constexpr bool operator==(const EnumIterator& other) const { return index == other.index; }
    constexpr bool operator!=(const EnumIterator& other) const { return index != other.index; }

    constexpr EnumIterator& operator++() {
    index++;
    return *this;
    }
    constexpr EnumIterator operator++(int) {
    EnumIterator iter = *this;
    index++;
    return iter;
    }
    constexpr EnumIterator& operator--() {
    index--;
    return *this;
    }
    constexpr EnumIterator operator--(int) {
    EnumIterator iter = *this;
    index--;
    return iter;
    }
    };
    } // namespace EnumHelpers

    template <EnumT E>
    class std::iterator_traits<EnumHelpers::EnumIterator<E>> {
    public:
    using Iter = EnumHelpers::EnumIterator<E>;
    using difference_type = void;
    using value_type = E;
    using pointer = void;
    using reference = E&;
    using iterator_category = std::input_iterator_tag;
    };

    enum class EnumStrSearchType { HashMap, Linear };

    template <EnumStrSearchType SearchType = EnumStrSearchType::HashMap, EnumHelpers::EnumSupportsMap T>
    constexpr _string_view enum_to_str_view(T e) {
    if constexpr (SearchType == EnumStrSearchType::Linear) {
    constexpr const auto& enum_map = EnumHelpers::EnumMapProvider<T>::enum_array;
    auto it = std::find_if(enum_map.begin(), enum_map.end(), [&e](const auto& p) {
    const auto& [name, val] = p;
    return val == e;
    });
    if (it != enum_map.end()) return it->first;
    if (std::is_constant_evaluated()) {
    // this allocation is here to stop compilation
    // if your code reached this allocation it means you passed an invalid value to enum_to_str()
    // this *does not* cause leaks because it only gets executed during constexpr evaluation
    // and during constexpr evaluation allocations which are not freed in the same scope cause a compilation
    // failure because the expression is not constant anymore for example, the error msvc gives you is:
    // `error C2131: expression did not evaluate to a constant`
    // `Common.h(341): note: failure was caused by allocated storage not being deallocated`
    new int[from_enum(e)];
    }
    return "invalid enum value";
    } else {
    // I'm not sure if this is better than linear search, it's really just a poor's man linear probing
    // hash map with O(1) access time (if no collisions)
    // and O(N) max round trip. It will throw if the enum isn't in the map
    constexpr const auto& enum_map = EnumHelpers::EnumMapProvider<T>::map;
    return enum_map[e];
    }
    }

    template <EnumHelpers::EnumSupportsMap T>
    constexpr size_t enum_size() {
    constexpr const auto& enum_array = EnumHelpers::EnumMapProvider<T>::enum_array;
    return enum_array.size();
    }

    template <EnumStrSearchType SearchType = EnumStrSearchType::HashMap, EnumHelpers::EnumSupportsMap T>
    std::string enum_to_str(T e) {
    return std::string{enum_to_str_view<SearchType, T>(e)};
    }

    template <EnumHelpers::EnumSupportsMap T>
    struct ForEachEnum {
    constexpr auto begin() const { return EnumHelpers::EnumIterator<T>{0}; }
    constexpr auto end() const {
    return EnumHelpers::EnumIterator<T>{EnumHelpers::EnumMapProvider<T>::enum_array.size()};
    }
    };

    template <EnumHelpers::EnumSupportsMap T>
    constexpr auto for_each_enum() {
    return ForEachEnum<T>{};
    }

    template <EnumHelpers::EnumSupportsMap T, typename Functor>
    requires(requires { std::declval<Functor>()(std::declval<T>()); }) constexpr auto for_each_enum(Functor func) {
    using Res = std::invoke_result_t<Functor, T>;
    if constexpr (std::is_void_v<Res>) {
    for (auto val : ForEachEnum<T>{}) {
    func(val);
    }
    } else {
    std::array<Res, EnumHelpers::EnumMapProvider<T>::enum_array.size()> result_array;
    size_t i = 0;
    for (auto val : ForEachEnum<T>{}) {
    result_array[i++] = func(val);
    }
    return result_array;
    }
    }

    #define ENUM_TO_STR(en, ...) \
    namespace EnumHelpers { \
    template <> \
    constexpr _string_view get_enum_full_string(TagType<en>) { \
    return #__VA_ARGS__; \
    } \
    }

    #define MAKE_FANCY_ENUM(en, ...) \
    enum class en { __VA_ARGS__ }; \
    ENUM_TO_STR(en, __VA_ARGS__)

    #define BITMASK_ENUM(en) \
    inline constexpr auto operator&(en lhs, en rhs) { return to_enum<en>(from_enum(lhs) & from_enum(rhs)); } \
    inline constexpr auto operator|(en lhs, en rhs) { return to_enum<en>(from_enum(lhs) | from_enum(rhs)); } \
    inline constexpr auto operator^(en lhs, en rhs) { return to_enum<en>(from_enum(lhs) ^ from_enum(rhs)); } \
    inline constexpr auto operator~(en val) { return to_enum<en>(~from_enum(val)); } \
    inline constexpr auto& operator&=(en& lhs, en rhs) { \
    lhs = lhs & rhs; \
    return lhs; \
    } \
    inline constexpr auto& operator|=(en& lhs, en rhs) { \
    lhs = lhs | rhs; \
    return lhs; \
    } \
    inline constexpr auto& operator^=(en& lhs, en rhs) { \
    lhs = lhs ^ rhs; \
    return lhs; \
    }

    [[noreturn]] inline void fatalfail() {
    abort();
    unreachable;
    }

    inline void assert_expr(bool expr, const char* msg = nullptr) {
    if (!expr) {
    if (msg) puts(msg);
    fatalfail();
    }
    }