2023-07-21 20:24:23 +02:00
|
|
|
#pragma once
|
|
|
|
|
2023-12-12 16:33:50 +01:00
|
|
|
#include <cstdint>
|
2023-07-21 20:24:23 +02:00
|
|
|
#include <string>
|
|
|
|
#include <string_view>
|
|
|
|
#include <optional>
|
|
|
|
#include <type_traits>
|
|
|
|
#include <cassert>
|
|
|
|
|
2024-10-18 19:24:46 +02:00
|
|
|
// TODO: use pack(16) instead to guarantie same size on 32bit and 64bit?
|
|
|
|
#pragma pack(1)
|
2023-12-01 19:21:09 +01:00
|
|
|
struct CM_InternalStringView final {
|
2023-07-21 20:24:23 +02:00
|
|
|
const char* start {nullptr};
|
|
|
|
uint64_t extend {0};
|
|
|
|
|
|
|
|
// conversion helpers
|
|
|
|
CM_InternalStringView(const std::string_view sv) : start(sv.data()), extend(sv.size()) {}
|
|
|
|
template<std::size_t N>
|
2023-12-01 19:21:09 +01:00
|
|
|
CM_InternalStringView(const char (&str)[N]) : start(str), extend(N-1u) {}
|
2023-07-21 20:24:23 +02:00
|
|
|
CM_InternalStringView(const std::string& str) : start(str.data()), extend(str.size()) {}
|
|
|
|
operator std::string() { return {start, start+extend}; }
|
2024-10-18 23:18:28 +02:00
|
|
|
operator std::string_view() { return {start, size_t(extend)}; }
|
2023-07-21 20:24:23 +02:00
|
|
|
};
|
|
|
|
static_assert(sizeof(CM_InternalStringView) == sizeof(const char*) + sizeof(uint64_t), "guarantee abi (hope)");
|
|
|
|
|
|
|
|
using CM_ISV = CM_InternalStringView;
|
2024-10-18 19:24:46 +02:00
|
|
|
#pragma pack() // undo pack(1)
|
2023-07-21 20:24:23 +02:00
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
struct CM_InternalOptional {
|
|
|
|
bool has_value {false};
|
|
|
|
union {
|
|
|
|
bool b;
|
|
|
|
int64_t i;
|
|
|
|
double d;
|
|
|
|
CM_InternalStringView s;
|
|
|
|
};
|
|
|
|
|
|
|
|
void set(bool v) { has_value = true; b = v; }
|
|
|
|
void set(int64_t v) { has_value = true; i = v; }
|
|
|
|
void set(double v) { has_value = true; d = v; }
|
|
|
|
void set(CM_InternalStringView v) { has_value = true; s = v; }
|
|
|
|
|
|
|
|
CM_InternalOptional(T v) : CM_InternalOptional(std::optional<T>{v}) {} // HACK: route through conv
|
|
|
|
|
|
|
|
// conversion helpers
|
|
|
|
CM_InternalOptional(std::nullopt_t) : has_value(false) {}
|
|
|
|
|
|
|
|
CM_InternalOptional(std::optional<bool> opt) : has_value(opt.has_value()) { if (opt.has_value()) set(opt.value()); }
|
|
|
|
CM_InternalOptional(std::optional<int64_t> opt) : has_value(opt.has_value()) { if (opt.has_value()) set(opt.value()); }
|
|
|
|
CM_InternalOptional(std::optional<double> opt) : has_value(opt.has_value()) { if (opt.has_value()) set(opt.value()); }
|
|
|
|
CM_InternalOptional(std::optional<CM_InternalStringView> opt) : has_value(opt.has_value()) { if (opt.has_value()) set(opt.value()); }
|
|
|
|
|
|
|
|
//operator std::optional<T>(void) const = delete;
|
|
|
|
|
|
|
|
operator auto() const {
|
|
|
|
if (has_value) {
|
|
|
|
if constexpr (std::is_same_v<T, bool>) {
|
|
|
|
return std::optional{b};
|
|
|
|
} else if constexpr (std::is_same_v<T, int64_t>) {
|
|
|
|
return std::optional{i};
|
|
|
|
} else if constexpr (std::is_same_v<T, double>) {
|
|
|
|
return std::optional{d};
|
|
|
|
} else if constexpr (std::is_same_v<T, CM_InternalStringView>) {
|
|
|
|
return std::optional{s};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return std::optional<T>{};
|
|
|
|
}
|
|
|
|
|
|
|
|
T value(void) {
|
|
|
|
assert(has_value); // use exceptions instead?
|
|
|
|
if constexpr (std::is_same_v<T, bool>) {
|
|
|
|
return b;
|
|
|
|
} else if constexpr (std::is_same_v<T, int64_t>) {
|
|
|
|
return i;
|
|
|
|
} else if constexpr (std::is_same_v<T, double>) {
|
|
|
|
return d;
|
|
|
|
} else if constexpr (std::is_same_v<T, CM_InternalStringView>) {
|
|
|
|
return s;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-02-04 15:10:34 +01:00
|
|
|
T& value_or(T& other) {
|
|
|
|
if (has_value) {
|
|
|
|
if constexpr (std::is_same_v<T, bool>) {
|
|
|
|
return b;
|
|
|
|
} else if constexpr (std::is_same_v<T, int64_t>) {
|
|
|
|
return i;
|
|
|
|
} else if constexpr (std::is_same_v<T, double>) {
|
|
|
|
return d;
|
|
|
|
} else if constexpr (std::is_same_v<T, CM_InternalStringView>) {
|
|
|
|
return s;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
return other;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
const T& value_or(const T& other) const {
|
|
|
|
if (has_value) {
|
|
|
|
if constexpr (std::is_same_v<T, bool>) {
|
|
|
|
return b;
|
|
|
|
} else if constexpr (std::is_same_v<T, int64_t>) {
|
|
|
|
return i;
|
|
|
|
} else if constexpr (std::is_same_v<T, double>) {
|
|
|
|
return d;
|
|
|
|
} else if constexpr (std::is_same_v<T, CM_InternalStringView>) {
|
|
|
|
return s;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
return other;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-07-21 20:24:23 +02:00
|
|
|
T value_or(T&& other) {
|
|
|
|
if (has_value) {
|
|
|
|
if constexpr (std::is_same_v<T, bool>) {
|
|
|
|
return b;
|
|
|
|
} else if constexpr (std::is_same_v<T, int64_t>) {
|
|
|
|
return i;
|
|
|
|
} else if constexpr (std::is_same_v<T, double>) {
|
|
|
|
return d;
|
|
|
|
} else if constexpr (std::is_same_v<T, CM_InternalStringView>) {
|
|
|
|
return s;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
return other;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|