20 class STORMBYTE_DATABASE_PUBLIC
Value {
26 enum class Type:
unsigned short {
44 m_value(std::monostate{}), m_type(Type::Null) {}
46 Value(
int value)
noexcept:
47 m_value(value), m_type(Type::Integer) {}
49 Value(
unsigned int value)
noexcept:
50 m_value(value), m_type(Type::UnsignedInteger) {}
52 Value(
long int value)
noexcept:
53 m_value(value), m_type(Type::LongInteger) {}
55 Value(
unsigned long int value)
noexcept:
56 m_value(value), m_type(Type::UnsignedLongInteger) {}
58 Value(
double value)
noexcept:
59 m_value(value), m_type(Type::Double) {}
61 Value(
const std::string& value)
noexcept:
62 m_value(value), m_type(Type::Text) {}
64 Value(std::string&& value)
noexcept:
65 m_value(std::move(value)), m_type(Type::Text) {}
67 Value(
const char* value)
noexcept:
68 Value(std::string(value)) {}
70 Value(
const std::vector<std::byte>& value)
noexcept:
71 m_value(value), m_type(Type::Blob) {}
73 Value(std::vector<std::byte>&& value)
noexcept:
74 m_value(std::move(value)), m_type(Type::Blob) {}
76 Value(
bool value)
noexcept:
77 m_value(value), m_type(Type::Boolean) {}
106 requires StormByte::
Type::VariantHasType<ValuesVariant, std::decay_t<T>>
107 std::decay_t<T> Get()
const {
108 using To = std::decay_t<T>;
110 return std::visit([](
auto&& val) -> To {
111 using From = std::decay_t<
decltype(val)>;
112 if constexpr (std::is_same_v<From, std::monostate>) {
113 throw WrongValueType(
"Requested type does not match stored type (null).");
114 }
else if constexpr (std::is_same_v<From, To>) {
116 }
else if constexpr (std::is_arithmetic_v<From> && std::is_arithmetic_v<To>) {
117 return convert_numeric<To, From>(val);
119 throw WrongValueType(
"Requested type does not match stored type.");
137 return m_type == Type::Null;
142 template<
typename To,
typename From>
143 requires (std::is_arithmetic_v<To> && std::is_arithmetic_v<From>)
144 static To convert_numeric(
const From& val) {
145 if constexpr (std::is_integral_v<From> && std::is_integral_v<To>) {
146 if constexpr (std::is_signed_v<From>) {
147 std::intmax_t from =
static_cast<std::intmax_t
>(val);
148 if constexpr (std::is_signed_v<To>) {
149 if (from <
static_cast<std::intmax_t
>(std::numeric_limits<To>::lowest()) || from >
static_cast<std::intmax_t
>(std::numeric_limits<To>::max()))
150 throw WrongValueType(
"Integer conversion would overflow/narrow.");
151 return static_cast<To
>(from);
154 if (from < 0)
throw WrongValueType(
"Negative value cannot be converted to unsigned.");
155 if (
static_cast<std::uintmax_t
>(from) >
static_cast<std::uintmax_t
>(std::numeric_limits<To>::max()))
156 throw WrongValueType(
"Integer conversion would overflow/narrow.");
157 return static_cast<To
>(from);
161 std::uintmax_t from =
static_cast<std::uintmax_t
>(val);
162 if constexpr (std::is_signed_v<To>) {
163 if (from >
static_cast<std::uintmax_t
>(std::numeric_limits<To>::max()))
164 throw WrongValueType(
"Integer conversion would overflow/narrow.");
165 return static_cast<To
>(from);
168 if (from >
static_cast<std::uintmax_t
>(std::numeric_limits<To>::max()))
169 throw WrongValueType(
"Integer conversion would overflow/narrow.");
170 return static_cast<To
>(from);
173 }
else if constexpr (std::is_integral_v<From> && std::is_floating_point_v<To>) {
174 return static_cast<To
>(val);
175 }
else if constexpr (std::is_floating_point_v<From> && std::is_integral_v<To>) {
176 long double d =
static_cast<long double>(val);
177 if (!std::isfinite(d))
throw WrongValueType(
"Non-finite floating conversion to integer.");
178 if (std::trunc(d) != d)
throw WrongValueType(
"Floating value has fractional part; would lose data.");
179 std::intmax_t tmp =
static_cast<std::intmax_t
>(d);
180 if constexpr (std::is_signed_v<To>) {
181 if (tmp <
static_cast<std::intmax_t
>(std::numeric_limits<To>::lowest()) || tmp >
static_cast<std::intmax_t
>(std::numeric_limits<To>::max()))
182 throw WrongValueType(
"Floating to integer conversion would overflow/narrow.");
183 return static_cast<To
>(tmp);
186 if (tmp < 0)
throw WrongValueType(
"Negative value cannot be converted to unsigned.");
187 if (
static_cast<std::uintmax_t
>(tmp) >
static_cast<std::uintmax_t
>(std::numeric_limits<To>::max()))
188 throw WrongValueType(
"Floating to integer conversion would overflow/narrow.");
189 return static_cast<To
>(tmp);
191 }
else if constexpr (std::is_floating_point_v<From> && std::is_floating_point_v<To>) {
192 return static_cast<To
>(val);
194 throw WrongValueType(
"Unsupported numeric conversion.");
197 ValuesVariant m_value;