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) {}
105 inline
bool operator==(const
Value& other) const noexcept {
106 return m_value == other.m_value;
115 return !(*
this == other);
124 requires StormByte::
Type::VariantHasType<ValuesVariant, std::decay_t<T>>
125 std::decay_t<T> Get()
const {
126 using To = std::decay_t<T>;
128 return std::visit([](
auto&& val) -> To {
129 using From = std::decay_t<
decltype(val)>;
130 if constexpr (std::is_same_v<From, std::monostate>) {
131 throw WrongValueType(
"Requested type does not match stored type (null).");
132 }
else if constexpr (std::is_same_v<From, To>) {
134 }
else if constexpr (std::is_arithmetic_v<From> && std::is_arithmetic_v<To>) {
135 return convert_numeric<To, From>(val);
137 throw WrongValueType(
"Requested type does not match stored type.");
155 return m_type == Type::Null;
160 template<
typename To,
typename From>
161 requires (std::is_arithmetic_v<To> && std::is_arithmetic_v<From>)
162 static To convert_numeric(
const From& val) {
163 if constexpr (std::is_integral_v<From> && std::is_integral_v<To>) {
164 if constexpr (std::is_signed_v<From>) {
165 std::intmax_t from =
static_cast<std::intmax_t
>(val);
166 if constexpr (std::is_signed_v<To>) {
167 if (from <
static_cast<std::intmax_t
>(std::numeric_limits<To>::lowest()) || from >
static_cast<std::intmax_t
>(std::numeric_limits<To>::max()))
168 throw WrongValueType(
"Integer conversion would overflow/narrow.");
169 return static_cast<To
>(from);
172 if (from < 0)
throw WrongValueType(
"Negative value cannot be converted to unsigned.");
173 if (
static_cast<std::uintmax_t
>(from) >
static_cast<std::uintmax_t
>(std::numeric_limits<To>::max()))
174 throw WrongValueType(
"Integer conversion would overflow/narrow.");
175 return static_cast<To
>(from);
179 std::uintmax_t from =
static_cast<std::uintmax_t
>(val);
180 if constexpr (std::is_signed_v<To>) {
181 if (from >
static_cast<std::uintmax_t
>(std::numeric_limits<To>::max()))
182 throw WrongValueType(
"Integer conversion would overflow/narrow.");
183 return static_cast<To
>(from);
186 if (from >
static_cast<std::uintmax_t
>(std::numeric_limits<To>::max()))
187 throw WrongValueType(
"Integer conversion would overflow/narrow.");
188 return static_cast<To
>(from);
191 }
else if constexpr (std::is_integral_v<From> && std::is_floating_point_v<To>) {
192 return static_cast<To
>(val);
193 }
else if constexpr (std::is_floating_point_v<From> && std::is_integral_v<To>) {
194 long double d =
static_cast<long double>(val);
195 if (!std::isfinite(d))
throw WrongValueType(
"Non-finite floating conversion to integer.");
196 if (std::trunc(d) != d)
throw WrongValueType(
"Floating value has fractional part; would lose data.");
197 std::intmax_t tmp =
static_cast<std::intmax_t
>(d);
198 if constexpr (std::is_signed_v<To>) {
199 if (tmp <
static_cast<std::intmax_t
>(std::numeric_limits<To>::lowest()) || tmp >
static_cast<std::intmax_t
>(std::numeric_limits<To>::max()))
200 throw WrongValueType(
"Floating to integer conversion would overflow/narrow.");
201 return static_cast<To
>(tmp);
204 if (tmp < 0)
throw WrongValueType(
"Negative value cannot be converted to unsigned.");
205 if (
static_cast<std::uintmax_t
>(tmp) >
static_cast<std::uintmax_t
>(std::numeric_limits<To>::max()))
206 throw WrongValueType(
"Floating to integer conversion would overflow/narrow.");
207 return static_cast<To
>(tmp);
209 }
else if constexpr (std::is_floating_point_v<From> && std::is_floating_point_v<To>) {
210 return static_cast<To
>(val);
212 throw WrongValueType(
"Unsupported numeric conversion.");
215 ValuesVariant m_value;