fixup compiler errors & finalize json (de-)serialization for values

Signed-off-by: Folling <mail@folling.io>
This commit is contained in:
Folling 2023-12-09 14:02:05 +01:00 committed by Folling
parent a934564afc
commit 785e43d9e6
Signed by: folling
SSH key fingerprint: SHA256:S9qEx5WCFFLK49tE/LKnKuJYM5sw+++Dn6qJbbyxnCY
13 changed files with 116 additions and 58 deletions

View file

@ -112,7 +112,7 @@ IKA_API void ikarus_entity_get_properties(
); );
/// \brief Gets the value of a property of an entity. /// \brief Gets the value of a property of an entity.
/// \details If the entity has never set the value of the property, the default value is returned (which may be indeterminate). /// \details If the entity has never set the value of the property, the default value is returned (which may be undefined).
/// \param entity The entity to get the value of. /// \param entity The entity to get the value of.
/// \pre \li Must not be null. /// \pre \li Must not be null.
/// \pre \li Must exist. /// \pre \li Must exist.

View file

@ -25,7 +25,7 @@ IKA_API IkarusNumberValue * ikarus_number_value_create();
/// \param idx The index of the data to fetch. /// \param idx The index of the data to fetch.
/// \pre \li Must be less than the size of the value. /// \pre \li Must be less than the size of the value.
/// \return The underlying data or null if an error occurs or the value is undefined. /// \return The underlying data or null if an error occurs or the value is undefined.
IKA_API long double const * ikarus_number_value_get(IkarusNumberValue * value, size_t idx); IKA_API double const * ikarus_number_value_get(IkarusNumberValue * value, size_t idx);
/// \brief Fetches the size of the underlying data of a number value. /// \brief Fetches the size of the underlying data of a number value.
/// \param value The number value. /// \param value The number value.
@ -39,7 +39,7 @@ IKA_API size_t ikarus_number_value_get_size(IkarusNumberValue const * value);
/// \param idx The index of the data to set. /// \param idx The index of the data to set.
/// \pre \li Must be less than the size of the value. /// \pre \li Must be less than the size of the value.
/// \param new_data The new data. /// \param new_data The new data.
IKA_API void ikarus_number_value_set(IkarusNumberValue * value, size_t idx, long double const * new_data); IKA_API void ikarus_number_value_set(IkarusNumberValue * value, size_t idx, double const * new_data);
/// \brief Removes a data from a number value. /// \brief Removes a data from a number value.
/// \param value The number value. /// \param value The number value.
@ -54,7 +54,7 @@ IKA_API void ikarus_number_value_remove(IkarusNumberValue * value, size_t idx);
/// \param idx The index of the data to insert. /// \param idx The index of the data to insert.
/// \pre \li Must be less than or equal to the size of the value. /// \pre \li Must be less than or equal to the size of the value.
/// \param new_data The new data. /// \param new_data The new data.
IKA_API void ikarus_number_value_insert(IkarusNumberValue * value, size_t idx, long double const * new_data); IKA_API void ikarus_number_value_insert(IkarusNumberValue * value, size_t idx, double const * new_data);
/// \brief Clears a number value. /// \brief Clears a number value.
/// \param value The number value. /// \param value The number value.

View file

@ -91,8 +91,9 @@ IkarusPropertySource const * ikarus_property_get_source(IkarusProperty const * p
auto * ctx = property->get_project()->get_function_context(); auto * ctx = property->get_project()->get_function_context();
VTRY( VTRYRV(
auto const source, auto const source,
nullptr,
property->get_project() property->get_project()
->get_db() ->get_db()
->query_one<int>("SELECT `source` FROM `properties` WHERE `id` = ?", property->get_id()) ->query_one<int>("SELECT `source` FROM `properties` WHERE `id` = ?", property->get_id())
@ -129,8 +130,9 @@ IkarusValue * ikarus_property_get_default_value(IkarusProperty const * property)
auto * ctx = property->get_project()->get_function_context(); auto * ctx = property->get_project()->get_function_context();
VTRY( VTRYRV(
auto const value, auto const value,
nullptr,
property->get_project() property->get_project()
->get_db() ->get_db()
->query_one<int>("SELECT `default_value` FROM `properties` WHERE `id` = ?", property->get_id()) ->query_one<int>("SELECT `default_value` FROM `properties` WHERE `id` = ?", property->get_id())
@ -144,7 +146,7 @@ IkarusValue * ikarus_property_get_default_value(IkarusProperty const * property)
}) })
); );
return new IkarusValue(property->get_project(), value); return IkarusValue::from_json(value).unwrap_value_or(nullptr);
} }
void ikarus_property_visit( void ikarus_property_visit(

3
src/redirect/json.hpp Normal file
View file

@ -0,0 +1,3 @@
#pragma once
#include <boost/json/src.hpp>

View file

@ -12,7 +12,7 @@ IkarusNumberValue * ikarus_number_value_create() {
return new IkarusNumberValue{}; return new IkarusNumberValue{};
} }
long double const * ikarus_number_value_get(IkarusNumberValue * value, size_t idx) { double const * ikarus_number_value_get(IkarusNumberValue * value, size_t idx) {
return ikarus_value_base_get(value, idx); return ikarus_value_base_get(value, idx);
} }
@ -20,7 +20,7 @@ size_t ikarus_number_value_get_size(IkarusNumberValue const * value) {
return ikarus_value_base_get_size(value); return ikarus_value_base_get_size(value);
} }
void ikarus_number_value_set(IkarusNumberValue * value, size_t idx, long double new_data) { void ikarus_number_value_set(IkarusNumberValue * value, size_t idx, double new_data) {
return ikarus_value_base_set(value, idx, new_data); return ikarus_value_base_set(value, idx, new_data);
} }
@ -45,12 +45,7 @@ void ikarus_number_value_set_undefined(IkarusNumberValue * value, bool undefined
} }
char const * ikarus_number_value_to_string(IkarusNumberValue const * value) { char const * ikarus_number_value_to_string(IkarusNumberValue const * value) {
return boost::variant2::visit( return ikarus_value_base_to_string(value, [](auto const& value) { return value; });
boost::make_overloaded_function(
[](boost::variant2::monostate const&) { return nullptr; }, [](auto const& data) { return fmt::join(data, ", "); }
),
value->data
);
} }
bool ikarus_number_value_is_equal(IkarusNumberValue const * lhs, IkarusNumberValue const * rhs) { bool ikarus_number_value_is_equal(IkarusNumberValue const * lhs, IkarusNumberValue const * rhs) {

View file

@ -1,13 +1,13 @@
#pragma once #pragma once
#include <boost/container/vector.hpp> #include <boost/container/small_vector.hpp>
#include <boost/variant2.hpp> #include <boost/variant2.hpp>
#include <values/value.hpp> #include <values/value.hpp>
struct IkarusNumberValue final : IkarusValue { struct IkarusNumberValue final : IkarusValue {
public: public:
using data_type = long double; using data_type = double;
public: public:
explicit IkarusNumberValue(); explicit IkarusNumberValue();
@ -21,7 +21,6 @@ public:
~IkarusNumberValue() override = default; ~IkarusNumberValue() override = default;
public: public:
boost::variant2:: boost::variant2::variant<boost::variant2::monostate, boost::container::small_vector<data_type, SMALL_VEC_VALUE_SIZE>> data{
variant<boost::variant2::monostate, boost::container::small_vector<data_type, SMALL_VEC_VALUE_SIZE>> };
data{};
}; };

View file

@ -1,5 +1,6 @@
#include "ikarus/values/text_value.h" #include "ikarus/values/text_value.h"
#include <boost/bind/bind.hpp>
#include <boost/functional/overloaded_function.hpp> #include <boost/functional/overloaded_function.hpp>
#include <values/text_value.hpp> #include <values/text_value.hpp>
@ -45,12 +46,7 @@ void ikarus_text_value_set_undefined(IkarusTextValue * value, bool undefined) {
} }
char const * ikarus_text_value_to_string(IkarusTextValue const * value) { char const * ikarus_text_value_to_string(IkarusTextValue const * value) {
return boost::variant2::visit( return ikarus_value_base_to_string(value, [](auto const& value) { return value; });
boost::make_overloaded_function(
[](boost::variant2::monostate const&) { return nullptr; }, [](auto const& data) { return fmt::join(data, ", "); }
),
value->data
);
} }
bool ikarus_text_value_is_equal(IkarusTextValue const * lhs, IkarusTextValue const * rhs) { bool ikarus_text_value_is_equal(IkarusTextValue const * lhs, IkarusTextValue const * rhs) {

View file

@ -1,6 +1,6 @@
#pragma once #pragma once
#include <boost/container/vector.hpp> #include <boost/container/small_vector.hpp>
#include <values/value.hpp> #include <values/value.hpp>

View file

@ -46,17 +46,7 @@ void ikarus_toggle_value_set_undefined(IkarusToggleValue * value, bool undefined
} }
char const * ikarus_toggle_value_to_string(IkarusToggleValue const * value) { char const * ikarus_toggle_value_to_string(IkarusToggleValue const * value) {
return boost::variant2::visit( return ikarus_value_base_to_string(value, [](auto const& value) { return value ? "" : ""; });
boost::make_overloaded_function(
[](boost::variant2::monostate const&) { return nullptr; },
[](auto const& data) {
return fmt::join(
data | boost::adaptors::transformed([](auto const& bool_value) { return bool_value ? "" : ""; }), ", "
);
}
),
value->data
);
} }
bool ikarus_toggle_value_is_equal(IkarusToggleValue const * lhs, IkarusToggleValue const * rhs) { bool ikarus_toggle_value_is_equal(IkarusToggleValue const * lhs, IkarusToggleValue const * rhs) {

View file

@ -1,6 +1,6 @@
#pragma once #pragma once
#include <boost/container/vector.hpp> #include <boost/container/small_vector.hpp>
#include <values/value.hpp> #include <values/value.hpp>

View file

@ -2,10 +2,11 @@
#include <string> #include <string>
#include <boost/container/small_vector.hpp>
#include <boost/functional/overloaded_function.hpp> #include <boost/functional/overloaded_function.hpp>
#include <boost/type_traits.hpp>
#include <fmt/format.h> // required for header-only inclusion
#include <boost/json/src.hpp>
#include <ikarus/objects/properties/property_type.h> #include <ikarus/objects/properties/property_type.h>
@ -17,7 +18,7 @@
IkarusValue::IkarusValue(Data data): IkarusValue::IkarusValue(Data data):
data(data) {} data(data) {}
cppbase::Result<IkarusValue, IkarusValue::FromJsonError> IkarusValue::from_json(boost::json::value const& json) { cppbase::Result<IkarusValue *, IkarusValue::FromJsonError> IkarusValue::from_json(boost::json::value const& json) {
if (auto const * obj = json.if_object(); obj == nullptr) { if (auto const * obj = json.if_object(); obj == nullptr) {
return cppbase::err(FromJsonError{}); return cppbase::err(FromJsonError{});
} else { } else {
@ -35,15 +36,23 @@ cppbase::Result<IkarusValue, IkarusValue::FromJsonError> IkarusValue::from_json(
} }
auto create_value = [data]<typename T>() -> cppbase::Result<IkarusValue *, FromJsonError> { auto create_value = [data]<typename T>() -> cppbase::Result<IkarusValue *, FromJsonError> {
auto * ret = new T{}; T * ret = nullptr;
auto res = boost::json::try_value_to<boost::container::vector<typename T::data_type>>(*data);
if (res.has_error()) { if (data->is_null()) {
return cppbase::err(FromJsonError{}); ret = new T{};
ret->data = boost::variant2::monostate{};
} else {
auto res = boost::json::try_value_to<
boost::container::small_vector<typename T::data_type, IkarusValue::SMALL_VEC_VALUE_SIZE>>(*data);
if (res.has_error()) {
return cppbase::err(FromJsonError{});
}
ret = new T{};
ret->data = std::move(res.value());
} }
ret->data = std::move(res.value());
return cppbase::ok(ret); return cppbase::ok(ret);
}; };
@ -74,7 +83,18 @@ boost::json::value IkarusValue::to_json() const {
data data
); );
auto data_json = boost::variant2::visit([](auto const * value) { return boost::json::value_from(value->data); }, data); auto data_json = boost::variant2::visit(
[]<typename T>(T const * value) -> boost::json::value {
return boost::variant2::visit(
boost::make_overloaded_function(
[]([[maybe_unused]] boost::variant2::monostate const& data) -> boost::json::value { return nullptr; },
[](auto const& data) -> boost::json::value { return boost::json::value_from(data); }
),
value->data
);
},
data
);
return { return {
{"type", type}, {"type", type},

View file

@ -8,7 +8,7 @@
struct IkarusValue { struct IkarusValue {
public: public:
using Data = boost::variant2::variant<struct IkarusToggleValue *, struct IkarusNumberValue *, struct IkarusTextValue *>; using Data = boost::variant2::variant<struct IkarusToggleValue *, struct IkarusNumberValue *, struct IkarusTextValue *>;
constexpr auto SMALL_VEC_VALUE_SIZE = 8; constexpr static auto SMALL_VEC_VALUE_SIZE = 8;
public: public:
explicit IkarusValue(Data data); explicit IkarusValue(Data data);
@ -24,7 +24,7 @@ public:
public: public:
struct FromJsonError {}; struct FromJsonError {};
[[nodiscard]] static cppbase::Result<IkarusValue, FromJsonError> from_json(boost::json::value const& json); [[nodiscard]] static cppbase::Result<IkarusValue *, FromJsonError> from_json(boost::json::value const& json);
[[nodiscard]] boost::json::value to_json() const; [[nodiscard]] boost::json::value to_json() const;
public: public:

View file

@ -1,8 +1,19 @@
#pragma once #pragma once
#include <concepts>
#include <ranges>
#include <boost/bind/bind.hpp>
#include <boost/container/small_vector.hpp>
#include <boost/functional/overloaded_function.hpp>
template<typename V> template<typename V>
typename V::data_type const * ikarus_value_base_get(V * value, size_t idx) { typename V::data_type const * ikarus_value_base_get(V * value, size_t idx) {
if (auto * data = value->data.template get_if<std::vector<typename V::data_type>>(); data != nullptr) { if (auto * data =
boost::variant2::get_if<boost::container::small_vector<typename V::data_type, IkarusValue::SMALL_VEC_VALUE_SIZE>>(
&value->data
);
data != nullptr) {
return &(*data)[idx]; return &(*data)[idx];
} }
@ -11,7 +22,11 @@ typename V::data_type const * ikarus_value_base_get(V * value, size_t idx) {
template<typename V> template<typename V>
size_t ikarus_value_base_get_size(V const * value) { size_t ikarus_value_base_get_size(V const * value) {
if (auto * data = value->data.template get_if<std::vector<typename V::data_type>>(); data != nullptr) { if (auto * data =
boost::variant2::get_if<boost::container::small_vector<typename V::data_type, IkarusValue::SMALL_VEC_VALUE_SIZE>>(
&value->data
);
data != nullptr) {
return data->size(); return data->size();
} }
@ -20,28 +35,44 @@ size_t ikarus_value_base_get_size(V const * value) {
template<typename V> template<typename V>
void ikarus_value_base_set(V * value, size_t idx, typename V::data_type new_data) { void ikarus_value_base_set(V * value, size_t idx, typename V::data_type new_data) {
if (auto * data = value->data.template get_if<std::vector<typename V::data_type>>(); data != nullptr) { if (auto * data =
boost::variant2::get_if<boost::container::small_vector<typename V::data_type, IkarusValue::SMALL_VEC_VALUE_SIZE>>(
&value->data
);
data != nullptr) {
(*data)[idx] = new_data; (*data)[idx] = new_data;
} }
} }
template<typename V> template<typename V>
void ikarus_value_base_remove(V * value, size_t idx) { void ikarus_value_base_remove(V * value, size_t idx) {
if (auto * data = value->data.template get_if<std::vector<typename V::data_type>>(); data != nullptr) { if (auto * data =
boost::variant2::get_if<boost::container::small_vector<typename V::data_type, IkarusValue::SMALL_VEC_VALUE_SIZE>>(
&value->data
);
data != nullptr) {
data->erase(data->begin() + idx); data->erase(data->begin() + idx);
} }
} }
template<typename V> template<typename V>
void ikarus_value_base_insert(V * value, size_t idx, typename V::data_type new_data) { void ikarus_value_base_insert(V * value, size_t idx, typename V::data_type new_data) {
if (auto * data = value->data.template get_if<std::vector<typename V::data_type>>(); data != nullptr) { if (auto * data =
boost::variant2::get_if<boost::container::small_vector<typename V::data_type, IkarusValue::SMALL_VEC_VALUE_SIZE>>(
&value->data
);
data != nullptr) {
data->insert(data->begin() + idx, new_data); data->insert(data->begin() + idx, new_data);
} }
} }
template<typename V> template<typename V>
void ikarus_value_base_clear(V * value) { void ikarus_value_base_clear(V * value) {
if (auto * data = value->data.template get_if<std::vector<typename V::data_type>>(); data != nullptr) { if (auto * data =
boost::variant2::get_if<boost::container::small_vector<typename V::data_type, IkarusValue::SMALL_VEC_VALUE_SIZE>>(
&value->data
);
data != nullptr) {
data->clear(); data->clear();
} }
} }
@ -56,10 +87,32 @@ void ikarus_value_base_set_undefined(V * value, bool undefined) {
if (undefined) { if (undefined) {
value->data = boost::variant2::monostate{}; value->data = boost::variant2::monostate{};
} else { } else {
value->data = typename V::data_type{}; value->data = boost::container::small_vector<typename V::data_type, IkarusValue::SMALL_VEC_VALUE_SIZE>{};
} }
} }
template<typename V, std::invocable<typename V::data_type> F>
char const * ikarus_value_base_to_string(V const * value, F transformer) {
return boost::variant2::visit(
boost::make_overloaded_function(
[](boost::variant2::monostate const&) -> char const * { return nullptr; },
[&transformer](boost::container::small_vector<typename V::data_type, IkarusValue::SMALL_VEC_VALUE_SIZE> const& data
) -> char const * {
auto buffer = fmt::memory_buffer{};
fmt::format_to(
std::back_inserter(buffer),
"{}",
fmt::join(data | std::views::transform(std::forward<F>(transformer)), ", ")
);
return buffer.data();
}
),
value->data
);
}
template<typename V> template<typename V>
bool ikarus_value_base_is_equal(V const * lhs, V const * rhs) { bool ikarus_value_base_is_equal(V const * lhs, V const * rhs) {
return lhs->data == rhs->data; return lhs->data == rhs->data;