From 7f24d3d064f159281938c7525a523a12b09f16a6 Mon Sep 17 00:00:00 2001 From: folling Date: Sun, 3 Dec 2023 18:44:09 +0100 Subject: [PATCH] move sub-functions of value impls to concrete types Signed-off-by: Folling --- include/ikarus/objects/properties/property.h | 2 +- include/ikarus/values/number_value.h | 70 +++++++++++++---- include/ikarus/values/text_value.h | 80 +++++++++++++++----- include/ikarus/values/toggle_value.h | 51 ++++++++++++- include/ikarus/values/value.h | 21 +---- src/values/number_value.cpp | 35 +++++++++ src/values/number_value.hpp | 4 +- src/values/text_value.cpp | 35 +++++++++ src/values/text_value.hpp | 3 +- src/values/toggle_value.cpp | 41 ++++++++++ src/values/toggle_value.hpp | 3 +- src/values/value.cpp | 76 +++++-------------- src/values/value.hpp | 1 + src/values/value_base.hpp | 36 +++++++++ 14 files changed, 339 insertions(+), 119 deletions(-) diff --git a/include/ikarus/objects/properties/property.h b/include/ikarus/objects/properties/property.h index 7aa6a2a..c0f37fa 100644 --- a/include/ikarus/objects/properties/property.h +++ b/include/ikarus/objects/properties/property.h @@ -84,7 +84,7 @@ IKA_API struct IkarusPropertySource const * ikarus_property_get_source(IkarusPro /// \pre \li Must exist. /// \return The default value of the property or null if an error occurs. /// \remark Must be freed using #ikarus_free. -IKA_API struct IkarusValue * ikarus_property_get_default_value(IkarusProperty const * property); +IKA_API struct IkarusValue const * ikarus_property_get_default_value(IkarusProperty const * property); /// \brief Visits a property. Calling the appropriate function for the property's type. /// \param property The property to visit. diff --git a/include/ikarus/values/number_value.h b/include/ikarus/values/number_value.h index 2bdeb85..7049af8 100644 --- a/include/ikarus/values/number_value.h +++ b/include/ikarus/values/number_value.h @@ -14,31 +14,23 @@ IKARUS_BEGIN_HEADER /// \brief A numeric value. For example "Age" or "Height". struct IkarusNumberValue; -/// \brief Creates a number value from long doubles. -/// \param data The number data or null if you wish to create an empty value. -/// \details LibIkarus does not take ownership of this array. -/// \param data_size The size of the data array. +/// \brief Creates a number value. /// \return The value or null if an error occurs. /// \remark Must be freed with #ikarus_free. -IKA_API IkarusNumberValue * ikarus_number_value_create(long double * data, size_t data_size); - -/// \brief Creates an indeterminate number value. -/// \return The value. -/// \remark Must be freed with #ikarus_free. -IKA_API IkarusNumberValue * ikarus_number_value_create_indeterminate(); +IKA_API IkarusNumberValue * ikarus_number_value_create(); /// \brief Fetches the underlying data of a number value at a specific index. /// \param value The number value. /// \pre \li Must not be null. /// \param idx The index of the data to fetch. /// \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 indeterminate. +/// \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); /// \brief Fetches the size of the underlying data of a number value. /// \param value The number value. /// \pre \li Must not be null. -/// \return The size of the underlying data or 0 if an error occurs or the value is indeterminate. +/// \return The size of the underlying data or 0 if an error occurs or the value is undefined. IKA_API size_t ikarus_number_value_get_size(IkarusNumberValue const * value); /// \brief Sets the data of a number value at a specific index. @@ -47,14 +39,13 @@ IKA_API size_t ikarus_number_value_get_size(IkarusNumberValue const * value); /// \param idx The index of the data to set. /// \pre \li Must be less than the size of the value. /// \param new_data The new data. -IKA_API void ikarus_number_value_set(IkarusNumberValue * value, size_t idx, long double new_data); +IKA_API void ikarus_number_value_set(IkarusNumberValue * value, size_t idx, long double const * new_data); /// \brief Removes a data from a number value. /// \param value The number value. /// \pre \li Must not be null. /// \param idx The index of the data to remove. /// \pre \li Must be less than the size of the value. -/// \remark This will shift all data after the index by one to the left. IKA_API void ikarus_number_value_remove(IkarusNumberValue * value, size_t idx); /// \brief Inserts a data into a number value. @@ -63,14 +54,61 @@ IKA_API void ikarus_number_value_remove(IkarusNumberValue * value, size_t idx); /// \param idx The index of the data to insert. /// \pre \li Must be less than or equal to the size of the value. /// \param new_data The new data. -/// \remark This will shift all data after the index by one to the right. -IKA_API void ikarus_number_insert(IkarusNumberValue * value, size_t idx, long double new_data); +IKA_API void ikarus_number_value_insert(IkarusNumberValue * value, size_t idx, long double const * new_data); + +/// \brief Clears a number value. +/// \param value The number value. +/// \remark Noop if the value is undefined. +IKA_API void ikarus_number_value_clear(IkarusNumberValue * value); + +/// \brief Checks if a number value is undefined. +/// \param value The number value. +/// \pre \li Must not be null. +/// \return True if the value is undefined, false otherwise. +IKA_API bool ikarus_number_value_is_undefined(IkarusNumberValue const * value); + +/// \brief Changes a number value's undefined state. +/// \param value The number value. +/// \pre \li Must not be null. +/// \param undefined The new undefined state. +/// \remark Noop if the value is already undefined. +/// \remark If the value is set to undefined, all data will be cleared. +/// \remark If the value is set to not undefined, the value is as if newly created. +IKA_API void ikarus_number_value_set_undefined(IkarusNumberValue * value, bool undefined); + +/// \brief Converts a number value to a string. +/// \param value The number value to convert. +/// \pre \li Must not be null. +/// \return The converted string. +/// \remark Must be freed with #ikarus_free. +/// \remark Undefined if the value is undefined. +IKA_API char const * ikarus_number_value_to_string(IkarusNumberValue const * value); + +/// \brief Checks if two values are equal. +/// \param lhs The left hand side value. +/// \pre \li Must not be null. +/// \param rhs The right hand side value. +/// \pre \li Must not be null. +/// \return True if the values' data are equal, false otherwise. +IKA_API bool ikarus_number_value_is_equal(IkarusNumberValue const * lhs, IkarusNumberValue const * rhs); + +/// \brief Creates a copy of a number value. +/// \param value The value to copy. +/// \pre \li Must not be null. +/// \return The copied value. +/// \remark Must be freed with #ikarus_free. +IKA_API IkarusNumberValue * ikarus_number_value_copy(IkarusNumberValue const * value); /// \brief Converts a number value to an entity value. /// \param value The number value to convert. +/// \pre \li Must not be null. /// \return The converted entity value. +/// \remark This is the same pointer, so freeing it implies freeing the original value. IKA_API struct IkarusValue * ikarus_number_value_to_value(IkarusNumberValue * value); +/// \see ikarus_toggle_value_to_value +IKA_API struct IkarusValue const * ikarus_number_value_to_value_const(IkarusNumberValue const * value); + IKARUS_END_HEADER /// @} diff --git a/include/ikarus/values/text_value.h b/include/ikarus/values/text_value.h index 08a37c8..b40a7f6 100644 --- a/include/ikarus/values/text_value.h +++ b/include/ikarus/values/text_value.h @@ -11,29 +11,27 @@ IKARUS_BEGIN_HEADER -/// \brief A textual value. For example "Surname" or "Description". +/// \brief A textual value. For example "Surname" or "Description" struct IkarusTextValue; -/// \brief Creates a text value from strings. -/// \param data The text data or null if you wish to create an empty value. -/// \details LibIkarus does not take ownership of this array. -/// \param data_size The size of the data array. +/// \brief Creates a text value. /// \return The value or null if an error occurs. /// \remark Must be freed with #ikarus_free. -IKA_API IkarusTextValue * ikarus_text_value_create(char const ** data, size_t data_size); +IKA_API IkarusTextValue * ikarus_text_value_create(); -/// \brief Creates an indeterminate text value. -/// \return The value. -/// \remark Must be freed with #ikarus_free. -IKA_API IkarusTextValue * ikarus_text_value_create_indeterminate(); - -/// \see ikarus_number_value_get -IKA_API char const * const * ikarus_text_value_get(IkarusTextValue const * value, size_t idx); +/// \brief Fetches the underlying data of a number value at a specific index. +/// \param value The number value. +/// \pre \li Must not be null. +/// \param idx The index of the data to fetch. +/// \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. +/// \remark This value is owned by LibIkarus and must not be freed. +IKA_API char const * ikarus_text_value_get(IkarusTextValue * value, size_t idx); /// \brief Fetches the size of the underlying data of a text value. /// \param value The text value. /// \pre \li Must not be null. -/// \return The size of the underlying data or 0 if an error occurs or the value is indeterminate. +/// \return The size of the underlying data or 0 if an error occurs or the value is undefined. IKA_API size_t ikarus_text_value_get_size(IkarusTextValue const * value); /// \brief Sets the data of a text value at a specific index. @@ -41,7 +39,7 @@ IKA_API size_t ikarus_text_value_get_size(IkarusTextValue const * value); /// \pre \li Must not be null. /// \param idx The index of the data to set. /// \pre \li Must be less than the size of the value. -/// \param new_data The new data. +/// \param new_data The new data. LibIkarus assumes ownership of this pointer. IKA_API void ikarus_text_value_set(IkarusTextValue * value, size_t idx, char const * new_data); /// \brief Removes a data from a text value. @@ -49,7 +47,6 @@ IKA_API void ikarus_text_value_set(IkarusTextValue * value, size_t idx, char con /// \pre \li Must not be null. /// \param idx The index of the data to remove. /// \pre \li Must be less than the size of the value. -/// \remark This will shift all data after the index by one to the left. IKA_API void ikarus_text_value_remove(IkarusTextValue * value, size_t idx); /// \brief Inserts a data into a text value. @@ -58,14 +55,61 @@ IKA_API void ikarus_text_value_remove(IkarusTextValue * value, size_t idx); /// \param idx The index of the data to insert. /// \pre \li Must be less than or equal to the size of the value. /// \param new_data The new data. -/// \remark This will shift all data after the index by one to the right. -IKA_API void ikarus_text_insert(IkarusTextValue * value, size_t idx, char const * new_data); +IKA_API void ikarus_text_value_insert(IkarusTextValue * value, size_t idx, char const * new_data); + +/// \brief Clears a text value. +/// \param value The text value. +/// \remark Noop if the value is undefined. +IKA_API void ikarus_text_value_clear(IkarusTextValue * value); + +/// \brief Checks if a text value is undefined. +/// \param value The text value. +/// \pre \li Must not be null. +/// \return True if the value is undefined, false otherwise. +IKA_API bool ikarus_text_value_is_undefined(IkarusTextValue const * value); + +/// \brief Changes a text value's undefined state. +/// \param value The text value. +/// \pre \li Must not be null. +/// \param undefined The new undefined state. +/// \remark Noop if the value is already undefined. +/// \remark If the value is set to undefined, all data will be cleared. +/// \remark If the value is set to not undefined, the value is as if newly created. +IKA_API void ikarus_text_value_set_undefined(IkarusTextValue * value, bool undefined); + +/// \brief Converts a text value to a string. +/// \param value The text value to convert. +/// \pre \li Must not be null. +/// \return The converted string. +/// \remark Must be freed with #ikarus_free. +/// \remark Undefined if the value is undefined. +IKA_API char const * ikarus_text_value_to_string(IkarusTextValue const * value); + +/// \brief Checks if two values are equal. +/// \param lhs The left hand side value. +/// \pre \li Must not be null. +/// \param rhs The right hand side value. +/// \pre \li Must not be null. +/// \return True if the values' data are equal, false otherwise. +IKA_API bool ikarus_text_value_is_equal(IkarusTextValue const * lhs, IkarusTextValue const * rhs); + +/// \brief Creates a copy of a text value. +/// \param value The value to copy. +/// \pre \li Must not be null. +/// \return The copied value. +/// \remark Must be freed with #ikarus_free. +IKA_API IkarusTextValue * ikarus_text_value_copy(IkarusTextValue const * value); /// \brief Converts a text value to an entity value. /// \param value The text value to convert. +/// \pre \li Must not be null. /// \return The converted entity value. +/// \remark This is the same pointer, so freeing it implies freeing the original value. IKA_API struct IkarusValue * ikarus_text_value_to_value(IkarusTextValue * value); +/// \see ikarus_toggle_value_to_value +IKA_API struct IkarusValue const * ikarus_text_value_to_value_const(IkarusTextValue const * value); + IKARUS_END_HEADER /// @} diff --git a/include/ikarus/values/toggle_value.h b/include/ikarus/values/toggle_value.h index 2fe45d3..2bb84c7 100644 --- a/include/ikarus/values/toggle_value.h +++ b/include/ikarus/values/toggle_value.h @@ -14,7 +14,7 @@ IKARUS_BEGIN_HEADER /// \brief A true/false boolean-esque value. For example "Is Dead". struct IkarusToggleValue; -/// \brief Creates a toggle value from booleans. +/// \brief Creates a toggle. /// \return The value or null if an error occurs. /// \remark Must be freed with #ikarus_free. IKA_API IkarusToggleValue * ikarus_toggle_value_create(); @@ -24,13 +24,13 @@ IKA_API IkarusToggleValue * ikarus_toggle_value_create(); /// \pre \li Must not be null. /// \param idx The index of the data to fetch. /// \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 indeterminate. +/// \return The underlying data or null if an error occurs or the value is undefined. IKA_API bool const * ikarus_toggle_value_get(IkarusToggleValue * value, size_t idx); /// \brief Fetches the size of the underlying data of a toggle value. /// \param value The toggle value. /// \pre \li Must not be null. -/// \return The size of the underlying data or 0 if an error occurs or the value is indeterminate. +/// \return The size of the underlying data or 0 if an error occurs or the value is undefined. IKA_API size_t ikarus_toggle_value_get_size(IkarusToggleValue const * value); /// \brief Sets the data of a toggle value at a specific index. @@ -58,14 +58,57 @@ IKA_API void ikarus_toggle_value_insert(IkarusToggleValue * value, size_t idx, b /// \brief Clears a toggle value. /// \param value The toggle value. -/// \remark Noop if the value is indeterminate. +/// \remark Noop if the value is undefined. IKA_API void ikarus_toggle_value_clear(IkarusToggleValue * value); +/// \brief Checks if a toggle value is undefined. +/// \param value The toggle value. +/// \pre \li Must not be null. +/// \return True if the value is undefined, false otherwise. +IKA_API bool ikarus_toggle_value_is_undefined(IkarusToggleValue const * value); + +/// \brief Changes a toggle value's undefined state. +/// \param value The toggle value. +/// \pre \li Must not be null. +/// \param undefined The new undefined state. +/// \remark Noop if the value is already undefined. +/// \remark If the value is set to undefined, all data will be cleared. +/// \remark If the value is set to not undefined, the value is as if newly created. +IKA_API void ikarus_toggle_value_set_undefined(IkarusToggleValue * value, bool undefined); + +/// \brief Converts a toggle value to a string. +/// \param value The toggle value to convert. +/// \pre \li Must not be null. +/// \return The converted string. +/// \remark Must be freed with #ikarus_free. +/// \remark Undefined if the value is undefined. +IKA_API char const * ikarus_toggle_value_to_string(IkarusToggleValue const * value); + +/// \brief Checks if two values are equal. +/// \param lhs The left hand side value. +/// \pre \li Must not be null. +/// \param rhs The right hand side value. +/// \pre \li Must not be null. +/// \return True if the values' data are equal, false otherwise. +IKA_API bool ikarus_toggle_value_is_equal(IkarusToggleValue const * lhs, IkarusToggleValue const * rhs); + +/// \brief Creates a copy of a toggle value. +/// \param value The value to copy. +/// \pre \li Must not be null. +/// \return The copied value. +/// \remark Must be freed with #ikarus_free. +IKA_API IkarusToggleValue * ikarus_toggle_value_copy(IkarusToggleValue const * value); + /// \brief Converts a toggle value to an entity value. /// \param value The toggle value to convert. +/// \pre \li Must not be null. /// \return The converted entity value. +/// \remark This is the same pointer, so freeing it implies freeing the original value. IKA_API struct IkarusValue * ikarus_toggle_value_to_value(IkarusToggleValue * value); +/// \see ikarus_toggle_value_to_value +IKA_API struct IkarusValue const * ikarus_toggle_value_to_value_const(IkarusToggleValue const * value); + IKARUS_END_HEADER /// @} diff --git a/include/ikarus/values/value.h b/include/ikarus/values/value.h index b894701..d33f87a 100644 --- a/include/ikarus/values/value.h +++ b/include/ikarus/values/value.h @@ -9,7 +9,7 @@ /// \brief The values of properties. /// \details Each entity has a value for each property it is associated with. /// These value classes represent plain objects. They are not associated with any entity. -/// Each value may be indeterminate. \see IkarusProperty +/// Each value may be undefined. \see IkarusProperty /// Values are stored as lists. If a property is "singular" then its value is a list of size 1. /// Values are typed, with types existing for each of the corresponding property types. /// When setting values for a property the type must match the property type and the value must be valid under the property's @@ -21,25 +21,6 @@ IKARUS_BEGIN_HEADER /// \brief The common type for all values. struct IkarusValue; -/// \brief Checks if a value is indeterminate. -/// \param value The value. -/// \pre \li Must not be null. -/// \return True if the value is indeterminate, false otherwise. -IKA_API bool ikarus_value_is_indeterminate(IkarusValue const * value); - -/// \brief Sets the indeterminate state of a value. -/// \param value The value. -/// \pre \li Must not be null. -/// \param indeterminate The new indeterminate state. -IKA_API void ikarus_value_set_indeterminate(IkarusValue * value, bool indeterminate); - -/// \brief Converts an entity value to a string. -/// \pre \li Must not be null. -/// \param value The entity value. -/// \return A string representation of the value or null if an error occurred. -/// \remark The returned value is owned by the caller. -IKA_API char const * ikarus_value_to_string(IkarusValue const * value); - /// \brief Visits an entity value, calling the appropriate function for the value's type. /// \param value The entity value to visit. /// \pre \li Must not be null. diff --git a/src/values/number_value.cpp b/src/values/number_value.cpp index c928b10..cef3508 100644 --- a/src/values/number_value.cpp +++ b/src/values/number_value.cpp @@ -1,5 +1,7 @@ #include "ikarus/values/number_value.h" +#include + #include #include @@ -30,6 +32,39 @@ void ikarus_number_value_insert(IkarusNumberValue * value, size_t idx, long doub return ikarus_value_base_insert(value, idx, new_data); } +void ikarus_number_value_clear(IkarusNumberValue * value) { + return ikarus_value_base_clear(value); +} + +bool ikarus_number_value_is_undefined(IkarusNumberValue const * value) { + return ikarus_value_base_is_undefined(value); +} + +void ikarus_number_value_set_undefined(IkarusNumberValue * value, bool undefined) { + return ikarus_value_base_set_undefined(value, undefined); +} + +char const * ikarus_number_value_to_string(IkarusNumberValue const * value) { + return boost::variant2::visit( + 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) { + return ikarus_value_base_is_equal(lhs, rhs); +} + +IkarusNumberValue * ikarus_number_value_copy(IkarusNumberValue const * value) { + return ikarus_value_base_copy(value); +} + struct IkarusValue * ikarus_number_value_to_value(IkarusNumberValue * value) { return ikarus_value_base_to_value(value); } + +struct IkarusValue const * ikarus_number_value_to_value_const(IkarusNumberValue const * value) { + return ikarus_value_base_to_value_const(value); +} diff --git a/src/values/number_value.hpp b/src/values/number_value.hpp index 359e5d2..6cad130 100644 --- a/src/values/number_value.hpp +++ b/src/values/number_value.hpp @@ -21,5 +21,7 @@ public: ~IkarusNumberValue() override = default; public: - boost::variant2::variant> data{}; + boost::variant2:: + variant> + data{}; }; diff --git a/src/values/text_value.cpp b/src/values/text_value.cpp index a382c0a..08ad03a 100644 --- a/src/values/text_value.cpp +++ b/src/values/text_value.cpp @@ -1,5 +1,7 @@ #include "ikarus/values/text_value.h" +#include + #include #include @@ -30,6 +32,39 @@ void ikarus_text_value_insert(IkarusTextValue * value, size_t idx, char const * return ikarus_value_base_insert(value, idx, new_data); } +void ikarus_text_value_clear(IkarusTextValue * value) { + return ikarus_value_base_clear(value); +} + +bool ikarus_text_value_is_undefined(IkarusTextValue const * value) { + return ikarus_value_base_is_undefined(value); +} + +void ikarus_text_value_set_undefined(IkarusTextValue * value, bool undefined) { + return ikarus_value_base_set_undefined(value, undefined); +} + +char const * ikarus_text_value_to_string(IkarusTextValue const * value) { + return boost::variant2::visit( + 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) { + return ikarus_value_base_is_equal(lhs, rhs); +} + +IkarusTextValue * ikarus_text_value_copy(IkarusTextValue const * value) { + return ikarus_value_base_copy(value); +} + struct IkarusValue * ikarus_text_value_to_value(IkarusTextValue * value) { return ikarus_value_base_to_value(value); } + +struct IkarusValue const * ikarus_text_value_to_value_const(IkarusTextValue const * value) { + return ikarus_value_base_to_value_const(value); +} diff --git a/src/values/text_value.hpp b/src/values/text_value.hpp index 191206e..8d063f2 100644 --- a/src/values/text_value.hpp +++ b/src/values/text_value.hpp @@ -20,5 +20,6 @@ public: ~IkarusTextValue() override = default; public: - boost::variant2::variant> data{}; + boost::variant2::variant> data{ + }; }; diff --git a/src/values/toggle_value.cpp b/src/values/toggle_value.cpp index 8d11e5a..37b2069 100644 --- a/src/values/toggle_value.cpp +++ b/src/values/toggle_value.cpp @@ -1,5 +1,8 @@ #include "ikarus/values/toggle_value.h" +#include +#include + #include #include @@ -30,6 +33,44 @@ void ikarus_toggle_value_insert(IkarusToggleValue * value, size_t idx, bool new_ return ikarus_value_base_insert(value, idx, new_data); } +void ikarus_toggle_value_clear(IkarusToggleValue * value) { + return ikarus_value_base_clear(value); +} + +bool ikarus_toggle_value_is_undefined(IkarusToggleValue const * value) { + return ikarus_value_base_is_undefined(value); +} + +void ikarus_toggle_value_set_undefined(IkarusToggleValue * value, bool undefined) { + return ikarus_value_base_set_undefined(value, undefined); +} + +char const * ikarus_toggle_value_to_string(IkarusToggleValue const * value) { + return boost::variant2::visit( + 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) { + return ikarus_value_base_is_equal(lhs, rhs); +} + +IkarusToggleValue * ikarus_toggle_value_copy(IkarusToggleValue const * value) { + return ikarus_value_base_copy(value); +} + struct IkarusValue * ikarus_toggle_value_to_value(IkarusToggleValue * value) { return ikarus_value_base_to_value(value); } + +struct IkarusValue const * ikarus_toggle_value_to_value_const(IkarusToggleValue const * value) { + return ikarus_value_base_to_value_const(value); +} diff --git a/src/values/toggle_value.hpp b/src/values/toggle_value.hpp index 750af25..6506dda 100644 --- a/src/values/toggle_value.hpp +++ b/src/values/toggle_value.hpp @@ -20,5 +20,6 @@ public: ~IkarusToggleValue() override = default; public: - boost::variant2::variant> data{}; + boost::variant2::variant> data{ + }; }; diff --git a/src/values/value.cpp b/src/values/value.cpp index dd1b60e..b9a53a7 100644 --- a/src/values/value.cpp +++ b/src/values/value.cpp @@ -18,12 +18,12 @@ IkarusValue::IkarusValue(Data data): data(data) {} cppbase::Result IkarusValue::from_json(boost::json::value const& json) { - boost::int64_t const * type = nullptr; - boost::json::value const * data = nullptr; - if (auto const * obj = json.if_object(); obj == nullptr) { return cppbase::err(FromJsonError{}); } else { + boost::int64_t const * type = nullptr; + boost::json::value const * data = nullptr; + if (auto const * type_value = obj->if_contains("type"); type_value == nullptr) { return cppbase::err(FromJsonError{}); } else if (type = type_value->if_int64(); type == nullptr) { @@ -34,36 +34,28 @@ cppbase::Result IkarusValue::from_json( return cppbase::err(FromJsonError{}); } + auto create_value = [data]() -> cppbase::Result { + auto * ret = new T{}; + auto res = boost::json::try_value_to>(*data); + + if (res.has_error()) { + return cppbase::err(FromJsonError{}); + } + + ret->data = std::move(res.value()); + + return cppbase::ok(ret); + }; + switch (*type) { case IkarusPropertyType_Toggle: { - auto * ret = new IkarusToggleValue{}; - auto res = boost::json::try_value_to>(*data); - - if (res.has_error()) { - return cppbase::err(FromJsonError{}); - } - - ret->data = std::move(res.value()); + return create_value.operator()(); } case IkarusPropertyType_Number: { - auto * ret = new IkarusNumberValue{}; - auto res = boost::json::try_value_to>(*data); - - if (res.has_error()) { - return cppbase::err(FromJsonError{}); - } - - ret->data = std::move(res.value()); + return create_value.operator()(); } case IkarusPropertyType_Text: { - auto * ret = new IkarusTextValue{}; - auto res = boost::json::try_value_to>(*data); - - if (res.has_error()) { - return cppbase::err(FromJsonError{}); - } - - ret->data = std::move(res.value()); + return create_value.operator()(); } default: { return cppbase::err(FromJsonError{}); @@ -90,36 +82,6 @@ boost::json::value IkarusValue::to_json() const { }; } -bool ikarus_value_is_indeterminate(IkarusValue const * value) { - return boost::variant2::visit( - [](auto const * value) { return boost::variant2::holds_alternative(value->data); }, - value->data - ); -} - -void ikarus_value_set_indeterminate(IkarusValue * value, bool indeterminate) { - if (indeterminate) { - return boost::variant2::visit([](auto const * value) { value->data = boost::variant2::monostate{}; }, value->data); - } - - return boost::variant2::visit( - [](auto const * value) { value->data = boost::remove_pointer_t::data_type{}; }, value->data - ); -} - -char const * ikarus_value_to_string(IkarusValue const * value) { - auto const str = boost::variant2::visit( - boost::make_overloaded_function( - [](IkarusToggleValue const * toggle_value) -> std::string { return toggle_value->data ? "true" : "false"; }, - [](IkarusNumberValue const * number_value) -> std::string { return fmt::format("{}", number_value->data); }, - [](IkarusTextValue const * text_value) -> std::string { return fmt::format("{}", text_value->data); } - ), - value->data - ); - - return strdup(str.data()); -} - void ikarus_value_visit( IkarusValue * value, void (*toggle_visitor)(IkarusToggleValue *, void *), diff --git a/src/values/value.hpp b/src/values/value.hpp index 3fbfad9..14c2a73 100644 --- a/src/values/value.hpp +++ b/src/values/value.hpp @@ -8,6 +8,7 @@ struct IkarusValue { public: using Data = boost::variant2::variant; + constexpr auto SMALL_VEC_VALUE_SIZE = 8; public: explicit IkarusValue(Data data); diff --git a/src/values/value_base.hpp b/src/values/value_base.hpp index bad1b91..04bad48 100644 --- a/src/values/value_base.hpp +++ b/src/values/value_base.hpp @@ -39,7 +39,43 @@ void ikarus_value_base_insert(V * value, size_t idx, typename V::data_type new_d } } +template +void ikarus_value_base_clear(V * value) { + if (auto * data = value->data.template get_if>(); data != nullptr) { + data->clear(); + } +} + +template +bool ikarus_value_base_is_undefined(V const * value) { + return boost::variant2::holds_alternative(value->data); +} + +template +void ikarus_value_base_set_undefined(V * value, bool undefined) { + if (undefined) { + value->data = boost::variant2::monostate{}; + } else { + value->data = typename V::data_type{}; + } +} + +template +bool ikarus_value_base_is_equal(V const * lhs, V const * rhs) { + return lhs->data == rhs->data; +} + +template +V * ikarus_value_base_copy(V const * value) { + return new V{*value}; +} + template struct IkarusValue * ikarus_value_base_to_value(V * value) { return static_cast(value); } + +template +struct IkarusValue const * ikarus_value_base_to_value_const(V const * value) { + return static_cast(value); +}