diff --git a/.clang-format b/.clang-format index 513423e..23c71e6 100644 --- a/.clang-format +++ b/.clang-format @@ -87,24 +87,26 @@ IncludeCategories: Priority: 2 - Regex: '^<[a-z0-9_]+>$' Priority: 3 - - Regex: '^$' + - Regex: '^$' Priority: 4 - - Regex: '^$' + - Regex: '^$' Priority: 5 - - Regex: '^$' + - Regex: '^$' Priority: 6 - - Regex: '^$' + - Regex: '^$' Priority: 7 - - Regex: '^$' + - Regex: '^$' Priority: 8 - - Regex: '^$' + - Regex: '^$' Priority: 9 - - Regex: '^$' + - Regex: '^$' Priority: 10 - - Regex: '^$' + - Regex: '^$' Priority: 11 - - Regex: '^$' + - Regex: '^$' Priority: 12 + - Regex: '^$' + Priority: 13 IndentAccessModifiers: false IndentCaseBlocks: false diff --git a/CMakeLists.txt b/CMakeLists.txt index 1bbb826..ae81667 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -14,6 +14,8 @@ add_subdirectory(vendor) add_subdirectory(include) add_subdirectory(src) +find_package(Boost REQUIRED) + add_library( libikarus SHARED ${INCLUDE_FILES} @@ -34,6 +36,12 @@ target_link_libraries( libikarus PRIVATE cppbase sqlitecpp + ${Boost_LIBRARIES} +) + +target_include_directories( + libikarus PRIVATE + ${Boost_INCLUDE_DIRS} ) if (LIBIKARUS_ENABLE_LINTS) diff --git a/include/ikarus/objects/properties/property.h b/include/ikarus/objects/properties/property.h index a6ebad8..7aa6a2a 100644 --- a/include/ikarus/objects/properties/property.h +++ b/include/ikarus/objects/properties/property.h @@ -78,6 +78,14 @@ IKA_API IkarusPropertyType ikarus_property_get_type(IkarusProperty const * prope /// \remark Must be freed using #ikarus_free. IKA_API struct IkarusPropertySource const * ikarus_property_get_source(IkarusProperty const * property); +/// \brief Gets the default value of a property. +/// \param property The property to get the type info of. +/// \pre \li Must not be null. +/// \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); + /// \brief Visits a property. Calling the appropriate function for the property's type. /// \param property The property to visit. /// \pre \li Must not be null. diff --git a/include/ikarus/values/number_value.h b/include/ikarus/values/number_value.h index d4b6446..2edb69b 100644 --- a/include/ikarus/values/number_value.h +++ b/include/ikarus/values/number_value.h @@ -4,42 +4,57 @@ /// \author Folling #include +#include /// \addtogroup values Values /// @{ IKARUS_BEGIN_HEADER -/// \brief A true/false boolean-like value. For example "IsDead". +/// \brief A true/false long doubleean-esque value. For example "Is Dead". struct IkarusNumberValue; -/// \brief Creates a number value from a long double. -/// \param value The numeric value. -/// \return The entity value. +/// \brief Creates a number value from doubles. +/// \param data The number data or null if you wish to clear the data. +/// \details LibIkarus does not take ownership of this array. +/// \param data_size The size of the data array or 0 if you wish to clear the data. +/// \return The value. /// \remark Must be freed with #ikarus_free. -IKA_API IkarusNumberValue * ikarus_number_value_create(long double value); +IKA_API IkarusNumberValue * ikarus_number_value_create(long double * data, size_t data_size); /// \brief Creates an indeterminate number value. -/// \return The entity value. +/// \return The value. /// \remark Must be freed with #ikarus_free. IKA_API IkarusNumberValue * ikarus_number_value_create_indeterminate(); -/// \brief Fetches the underlying value of a number value. -/// \param value The number value. -/// \return The underlying value. -/// \warning Undefined if the value is indeterminate. -IKA_API long double ikarus_number_value_get(IkarusNumberValue const * value); - -/// \brief Sets the value of a number value. +/// \brief Fetches the underlying data of a number value. +/// \details You may adjust the returned data as per your hearts desire. +/// If you need to grow the data, use #ikarus_number_value_set with a new array. +/// Just remember that IkarusValues are plain objects, so changing them won't affect any state. +/// They will need to be submitted to other functions such as #ikarus_entity_set_value to have any effect. /// \param value The number value. /// \pre \li Must not be null. -/// \param new_value The new value. -IKA_API void ikarus_number_value_set(IkarusNumberValue * value, bool new_value); +/// \param data_size_out An out-parameter for the size of the returned array. +/// \remark Ignored if null. +/// \return The underlying data. Owned by LibIkarus, most not be freed. +/// \warning Undefined if the value is indeterminate. +IKA_API long double * ikarus_number_value_get(IkarusNumberValue * value, size_t * data_size_out); + +/// \see ikarus_number_value_get +long double const * ikarus_number_value_get_const(IkarusNumberValue const * value, size_t * data_size_out); + +/// \brief Sets the data of a number value. +/// \param value The number value. +/// \pre \li Must not be null. +/// \param new_data The new data or null if you wish to clear the data. +/// \details LibIkarus does not take ownership of this array. +/// \param new_data_size The size of the new data array or 0 if you wish to clear the data. +IKA_API void ikarus_number_value_set(IkarusNumberValue * value, long double * new_data, size_t new_data_size); /// \brief Converts a number value to an entity value. -/// \param number_value The number value to convert. +/// \param value The number value to convert. /// \return The converted entity value. -IKA_API struct IkarusValue * ikarus_number_value_to_value(IkarusNumberValue * number_value); +IKA_API struct IkarusValue * ikarus_number_value_to_value(IkarusNumberValue * value); IKARUS_END_HEADER diff --git a/include/ikarus/values/text_value.h b/include/ikarus/values/text_value.h index 8562ab5..3f1f682 100644 --- a/include/ikarus/values/text_value.h +++ b/include/ikarus/values/text_value.h @@ -4,43 +4,57 @@ /// \author Folling #include +#include /// \addtogroup values Values /// @{ IKARUS_BEGIN_HEADER -/// \brief A true/false boolean-like value. For example "IsDead". +/// \brief A true/false char const*ean-esque value. For example "Is Dead". struct IkarusTextValue; -/// \brief Creates a text value from a boolean. -/// \param value The text value. -/// \return The entity value. +/// \brief Creates a text value from doubles. +/// \param data The text data or null if you wish to clear the data. +/// \details LibIkarus does not take ownership of this array. +/// \param data_size The size of the data array or 0 if you wish to clear the data. +/// \return The value. /// \remark Must be freed with #ikarus_free. -IKA_API IkarusTextValue * ikarus_text_value_create(char const * value); +IKA_API IkarusTextValue * ikarus_text_value_create(char const ** data, size_t data_size); /// \brief Creates an indeterminate text value. -/// \return The entity value. +/// \return The value. /// \remark Must be freed with #ikarus_free. IKA_API IkarusTextValue * ikarus_text_value_create_indeterminate(); -/// \brief Fetches the underlying value of a text value. -/// \param value The text value. -/// \return The underlying value. -/// \warning Undefined if the value is indeterminate. -/// \remark The value is owned by libikarus and must not be freed. -IKA_API char const * ikarus_text_value_get_underlying(IkarusTextValue const * value); - -/// \brief Sets the value of a text value. +/// \brief Fetches the underlying data of a text value. +/// \details You may adjust the returned data as per your hearts desire. +/// If you need to grow the data, use #ikarus_text_value_set with a new array. +/// Just remember that IkarusValues are plain objects, so changing them won't affect any state. +/// They will need to be submitted to other functions such as #ikarus_entity_set_value to have any effect. /// \param value The text value. /// \pre \li Must not be null. -/// \param new_value The new value. -IKA_API void ikarus_text_value_set(IkarusTextValue * value, bool new_value); +/// \param data_size_out An out-parameter for the size of the returned array. +/// \remark Ignored if null. +/// \return The underlying data. Owned by LibIkarus, most not be freed. +/// \warning Undefined if the value is indeterminate. +IKA_API char ** ikarus_text_value_get(IkarusTextValue * value, size_t * data_size_out); + +/// \see ikarus_text_value_get +char const * const * ikarus_text_value_get_const(IkarusTextValue const * value, size_t * data_size_out); + +/// \brief Sets the data of a text value. +/// \param value The text value. +/// \pre \li Must not be null. +/// \param new_data The new data or null if you wish to clear the data. +/// \details LibIkarus does not take ownership of this array. +/// \param new_data_size The size of the new data array or 0 if you wish to clear the data. +IKA_API void ikarus_text_value_set(IkarusTextValue * value, char const ** new_data, size_t new_data_size); /// \brief Converts a text value to an entity value. -/// \param text_value The text value to convert. +/// \param value The text value to convert. /// \return The converted entity value. -IKA_API struct IkarusValue * ikarus_text_value_to_value(IkarusTextValue * text_value); +IKA_API struct IkarusValue * ikarus_text_value_to_value(IkarusTextValue * value); IKARUS_END_HEADER diff --git a/include/ikarus/values/toggle_value.h b/include/ikarus/values/toggle_value.h index fed97d2..89d5678 100644 --- a/include/ikarus/values/toggle_value.h +++ b/include/ikarus/values/toggle_value.h @@ -4,42 +4,57 @@ /// \author Folling #include +#include /// \addtogroup values Values /// @{ IKARUS_BEGIN_HEADER -/// \brief A true/false boolean-like value. For example "IsDead". +/// \brief A true/false boolean-esque value. For example "Is Dead". struct IkarusToggleValue; -/// \brief Creates a toggle value from a boolean. -/// \param value The toggle value. -/// \return The entity value. +/// \brief Creates a toggle value from doubles. +/// \param data The toggle data or null if you wish to clear the data. +/// \details LibIkarus does not take ownership of this array. +/// \param data_size The size of the data array or 0 if you wish to clear the data. +/// \return The value. /// \remark Must be freed with #ikarus_free. -IKA_API IkarusToggleValue * ikarus_toggle_value_create(bool value); +IKA_API IkarusToggleValue * ikarus_toggle_value_create(bool * data, size_t data_size); /// \brief Creates an indeterminate toggle value. -/// \return The entity value. +/// \return The value. /// \remark Must be freed with #ikarus_free. IKA_API IkarusToggleValue * ikarus_toggle_value_create_indeterminate(); -/// \brief Fetches the underlying value of a toggle value. -/// \param value The toggle value. -/// \return The underlying value. -/// \warning Undefined if the value is indeterminate. -IKA_API bool ikarus_toggle_value_get(IkarusToggleValue const * value); - -/// \brief Sets the value of a toggle value. +/// \brief Fetches the underlying data of a toggle value. +/// \details You may adjust the returned data as per your hearts desire. +/// If you need to grow the data, use #ikarus_toggle_value_set with a new array. +/// Just remember that IkarusValues are plain objects, so changing them won't affect any state. +/// They will need to be submitted to other functions such as #ikarus_entity_set_value to have any effect. /// \param value The toggle value. /// \pre \li Must not be null. -/// \param new_value The new value. -IKA_API void ikarus_toggle_value_set(IkarusToggleValue * value, bool new_value); +/// \param data_size_out An out-parameter for the size of the returned array. +/// \remark Ignored if null. +/// \return The underlying data. Owned by LibIkarus, most not be freed. +/// \warning Undefined if the value is indeterminate. +IKA_API bool * ikarus_toggle_value_get(IkarusToggleValue * value, size_t * data_size_out); + +/// \see ikarus_toggle_value_get +bool const * ikarus_toggle_value_get_const(IkarusToggleValue const * value, size_t * data_size_out); + +/// \brief Sets the data of a toggle value. +/// \param value The toggle value. +/// \pre \li Must not be null. +/// \param new_data The new data or null if you wish to clear the data. +/// \details LibIkarus does not take ownership of this array. +/// \param new_data_size The size of the new data array or 0 if you wish to clear the data. +IKA_API void ikarus_toggle_value_set(IkarusToggleValue * value, bool * new_data, size_t new_data_size); /// \brief Converts a toggle value to an entity value. -/// \param toggle_value The toggle value to convert. +/// \param value The toggle value to convert. /// \return The converted entity value. -IKA_API struct IkarusValue * ikarus_toggle_value_to_value(IkarusToggleValue * toggle_value); +IKA_API struct IkarusValue * ikarus_toggle_value_to_value(IkarusToggleValue * value); IKARUS_END_HEADER diff --git a/include/ikarus/values/value.h b/include/ikarus/values/value.h index 1cf1fd0..b894701 100644 --- a/include/ikarus/values/value.h +++ b/include/ikarus/values/value.h @@ -6,11 +6,14 @@ #include /// \defgroup values Values -/// \brief The values stored in entities. +/// \brief The values of properties. /// \details Each entity has a value for each property it is associated with. -/// The value is of the type specified by the property and constrained by the property's settings. -/// A value may be indeterminate which means it is unknown or not specified. -/// \see PropertyType PropertySettings +/// These value classes represent plain objects. They are not associated with any entity. +/// Each value may be indeterminate. \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 +/// settings. \see PropertyType /// @{ IKARUS_BEGIN_HEADER diff --git a/src/objects/properties/property.cpp b/src/objects/properties/property.cpp index cda8434..d1eb94a 100644 --- a/src/objects/properties/property.cpp +++ b/src/objects/properties/property.cpp @@ -8,6 +8,7 @@ #include #include #include +#include IkarusProperty::IkarusProperty(IkarusProject * project, IkarusId id, Data data): IkarusObject{project, id}, @@ -121,6 +122,31 @@ IkarusPropertySource const * ikarus_property_get_source(IkarusProperty const * p } } +IkarusValue * ikarus_property_get_default_value(IkarusProperty const * property) { + LOG_VERBOSE("fetching property default value"); + + LOG_VERBOSE("project={};property={}", property->get_project()->get_path().c_str(), property->get_id()); + + auto * ctx = property->get_project()->get_function_context(); + + VTRY( + auto const value, + property->get_project() + ->get_db() + ->query_one("SELECT `default_value` FROM `properties` WHERE `id` = ?", property->get_id()) + .on_error([ctx](auto const& err) { + ctx->set_error( + fmt::format("failed to fetch property's default value: {}", err), + true, + IkarusErrorInfo_Source_SubSystem, + IkarusErrorInfo_Type_SubSystem_Database + ); + }) + ); + + return new IkarusValue(property->get_project(), value); +} + void ikarus_property_visit( IkarusProperty * property, void (*toggle_property_visitor)(struct IkarusToggleProperty *, void *), diff --git a/src/objects/properties/toggle_property.cpp b/src/objects/properties/toggle_property.cpp index d2fb82d..70ec934 100644 --- a/src/objects/properties/toggle_property.cpp +++ b/src/objects/properties/toggle_property.cpp @@ -1,6 +1,10 @@ #include "toggle_property.hpp" IkarusToggleProperty::IkarusToggleProperty(IkarusProject * project, IkarusId id): - IkarusProperty{project, id, this} { + IkarusProperty{project, id, this} {} + +IkarusToggleProperty * ikarus_toggle_property_create( + struct IkarusProject * project, char const * name, struct IkarusPropertySource * property_source +) { } diff --git a/src/persistence/migrations/m1_initial_layout.sql b/src/persistence/migrations/m1_initial_layout.sql index d94fa10..ea24c56 100644 --- a/src/persistence/migrations/m1_initial_layout.sql +++ b/src/persistence/migrations/m1_initial_layout.sql @@ -1,8 +1,9 @@ CREATE TABLE `objects` ( `do_not_access_rowid_alias` INTEGER PRIMARY KEY, - `object_type` INT NOT NULL, - `id` INT GENERATED ALWAYS AS (`do_not_access_rowid_alias` | (`object_type` << 56)) VIRTUAL, + `object_type` INT NOT NULL, + `id` INT GENERATED ALWAYS AS (`do_not_access_rowid_alias` | (`object_type` << 56) +) VIRTUAL, `name` TEXT NOT NULL, `information` TEXT NOT NULL ) STRICT; @@ -11,7 +12,7 @@ CREATE UNIQUE INDEX `object_id` ON `objects` (`id`); CREATE INDEX `object_type` ON `objects` (`object_type`); CREATE - VIRTUAL TABLE `objects_fts` USING fts5 +VIRTUAL TABLE `objects_fts` USING fts5 ( `name`, `information`, @@ -23,7 +24,7 @@ CREATE "unicode61 remove_diacritics 2 tokenchars '-_'" ); -CREATE TABLE `blueprints` +CREATE TABLE `entities` ( `id` INT, @@ -31,7 +32,7 @@ CREATE TABLE `blueprints` FOREIGN KEY (`id`) REFERENCES `objects` (`id`) ON DELETE CASCADE ) WITHOUT ROWID, STRICT; -CREATE TABLE `entities` +CREATE TABLE `blueprints` ( `id` INT, @@ -69,7 +70,7 @@ CREATE INDEX `properties_type` ON `properties` (`type`); CREATE INDEX `properties_source` ON `properties` (`source`); CREATE - VIRTUAL TABLE `property_default_value_fts` USING fts5 +VIRTUAL TABLE `property_default_value_fts` USING fts5 ( `default_value`, content= @@ -81,7 +82,7 @@ CREATE ); CREATE - VIRTUAL TABLE `property_settings_fts` USING fts5 +VIRTUAL TABLE `property_settings_fts` USING fts5 ( `settings`, content= @@ -104,7 +105,7 @@ CREATE TABLE `values` ) WITHOUT ROWID, STRICT; CREATE - VIRTUAL TABLE `values_fts` USING fts5 +VIRTUAL TABLE `values_fts` USING fts5 ( `value`, content= diff --git a/src/values/number_value.cpp b/src/values/number_value.cpp index b4d3413..4a450e3 100644 --- a/src/values/number_value.cpp +++ b/src/values/number_value.cpp @@ -2,25 +2,54 @@ #include -IkarusNumberValue * ikarus_number_value_create(long double value) { - return new IkarusNumberValue{value}; +IkarusNumberValue::IkarusNumberValue(): + IkarusValue{this} {} + +boost::container::vector& IkarusNumberValue::get_value() { + return _value; +} + +boost::container::vector const& IkarusNumberValue::get_value() const { + return _value; +} + +IkarusNumberValue * ikarus_number_value_create(long double * data, size_t data_size) { + auto * ret = new IkarusNumberValue{}; + + ikarus_number_value_set(ret, data, data_size); + + return ret; } IkarusNumberValue * ikarus_number_value_create_indeterminate() { - auto * ret = new IkarusNumberValue{0.0}; + auto * ret = new IkarusNumberValue{}; ret->set_intermediate(true); return ret; } -long double ikarus_number_value_get(IkarusNumberValue const * value) { - return value->get_value(); +long double * ikarus_number_value_get(IkarusNumberValue * value, size_t * data_size_out) { + // NOLINTNEXTLINE(*-pro-type-const-cast) + return const_cast(ikarus_number_value_get_const(value, data_size_out)); } -void ikarus_number_value_set(IkarusNumberValue * value, long double new_value) { - value->set_value(new_value); +long double const * ikarus_number_value_get_const(IkarusNumberValue const * value, size_t * data_size_out) { + if (data_size_out != nullptr) { + *data_size_out = value->get_value().size(); + } + + return value->get_value().data(); } -struct IkarusValue * ikarus_number_value_to_value(IkarusNumberValue * number_value) { - return static_cast(number_value); +void ikarus_number_value_set(IkarusNumberValue * value, long double * new_data, size_t new_data_size) { + value->get_value().reserve(new_data_size); + + for (auto i = 0; i < new_data_size; ++i) { + // NOLINTNEXTLINE(*-pro-bounds-pointer-arithmetic) + value->get_value().emplace_back(new_data[i]); + } +} + +struct IkarusValue * ikarus_number_value_to_value(IkarusNumberValue * value) { + return static_cast(value); } diff --git a/src/values/number_value.hpp b/src/values/number_value.hpp index e495be5..f6befe1 100644 --- a/src/values/number_value.hpp +++ b/src/values/number_value.hpp @@ -1,13 +1,14 @@ #pragma once +#include + +#include + #include -/// \private struct IkarusNumberValue final : IkarusValue { public: - explicit IkarusNumberValue(long double value): - IkarusValue{this}, - _value{value} {} + explicit IkarusNumberValue(); IkarusNumberValue(IkarusNumberValue const&) = default; IkarusNumberValue(IkarusNumberValue&&) = default; @@ -18,14 +19,9 @@ public: ~IkarusNumberValue() override = default; public: - [[nodiscard]] long double get_value() const { - return _value; - } - - void set_value(long double value) { - _value = value; - } + [[nodiscard]] boost::container::vector& get_value(); + [[nodiscard]] boost::container::vector const& get_value() const; private: - long double _value; + boost::container::vector _value{}; }; diff --git a/src/values/text_value.cpp b/src/values/text_value.cpp index 6eb839c..ba30eb8 100644 --- a/src/values/text_value.cpp +++ b/src/values/text_value.cpp @@ -1,26 +1,55 @@ #include "ikarus/values/text_value.h" -#include "text_value.hpp" +#include -IkarusTextValue * ikarus_text_value_create(char const * value) { - return new IkarusTextValue{value}; +IkarusTextValue::IkarusTextValue(): + IkarusValue{this} {} + +boost::container::vector& IkarusTextValue::get_value() { + return _value; +} + +boost::container::vector const& IkarusTextValue::get_value() const { + return _value; +} + +IkarusTextValue * ikarus_text_value_create(char const ** data, size_t data_size) { + auto * ret = new IkarusTextValue{}; + + ikarus_text_value_set(ret, data, data_size); + + return ret; } IkarusTextValue * ikarus_text_value_create_indeterminate() { - auto * ret = new IkarusTextValue{""}; + auto * ret = new IkarusTextValue{}; ret->set_intermediate(true); return ret; } -char const * ikarus_text_value_get(IkarusTextValue const * value) { +char ** ikarus_text_value_get(IkarusTextValue * value, size_t * data_size_out) { + // NOLINTNEXTLINE(*-pro-type-const-cast) + return const_cast(ikarus_text_value_get_const(value, data_size_out)); +} + +char const * const * ikarus_text_value_get_const(IkarusTextValue const * value, size_t * data_size_out) { + if (data_size_out != nullptr) { + *data_size_out = value->get_value().size(); + } + return value->get_value().data(); } -void ikarus_text_value_set(IkarusTextValue * value, char const * new_value) { - value->set_value(new_value); +void ikarus_text_value_set(IkarusTextValue * value, char const ** new_data, size_t new_data_size) { + value->get_value().reserve(new_data_size); + + for (auto i = 0; i < new_data_size; ++i) { + // NOLINTNEXTLINE(*-pro-bounds-pointer-arithmetic) + value->get_value().emplace_back(new_data[i]); + } } -struct IkarusValue * ikarus_text_value_to_value(IkarusTextValue * text_value) { - return static_cast(text_value); +struct IkarusValue * ikarus_text_value_to_value(IkarusTextValue * value) { + return static_cast(value); } diff --git a/src/values/text_value.hpp b/src/values/text_value.hpp index 3766513..42484a2 100644 --- a/src/values/text_value.hpp +++ b/src/values/text_value.hpp @@ -1,33 +1,28 @@ #pragma once #include +#include + +#include #include -/// \private struct IkarusTextValue final : IkarusValue { public: - explicit IkarusTextValue(std::string value): - IkarusValue{this}, - _value(std::move(value)) {} + explicit IkarusTextValue(); IkarusTextValue(IkarusTextValue const&) = default; - IkarusTextValue(IkarusTextValue&&) noexcept = default; + IkarusTextValue(IkarusTextValue&&) = default; IkarusTextValue& operator=(IkarusTextValue const&) = default; - IkarusTextValue& operator=(IkarusTextValue&&) noexcept = default; + IkarusTextValue& operator=(IkarusTextValue&&) = default; ~IkarusTextValue() override = default; public: - [[nodiscard]] std::string_view get_value() const noexcept { - return _value; - } - - void set_value(std::string_view value) { - _value = value; - } + [[nodiscard]] boost::container::vector& get_value(); + [[nodiscard]] boost::container::vector const& get_value() const; private: - std::string _value; + boost::container::vector _value{}; }; diff --git a/src/values/toggle_value.cpp b/src/values/toggle_value.cpp index 30e64c8..c03f71b 100644 --- a/src/values/toggle_value.cpp +++ b/src/values/toggle_value.cpp @@ -1,26 +1,60 @@ #include "ikarus/values/toggle_value.h" -#include "toggle_value.hpp" +#include -IkarusToggleValue * ikarus_toggle_value_create(bool value) { - return new IkarusToggleValue{value}; +IkarusToggleValue::IkarusToggleValue(): + IkarusValue{this} {} + +boost::container::vector& IkarusToggleValue::get_value() { + return _value; +} + +boost::container::vector const& IkarusToggleValue::get_value() const { + return _value; +} + +IkarusToggleValue * ikarus_toggle_value_create(bool * data, size_t data_size) { + auto * ret = new IkarusToggleValue{}; + + ikarus_toggle_value_set(ret, data, data_size); + + return ret; } IkarusToggleValue * ikarus_toggle_value_create_indeterminate() { - auto * ret = new IkarusToggleValue{false}; + auto * ret = new IkarusToggleValue{}; ret->set_intermediate(true); return ret; } -bool ikarus_toggle_value_get(IkarusToggleValue const * value) { - return value->get_value(); +bool * ikarus_toggle_value_get(IkarusToggleValue * value, size_t * data_size_out) { + // NOLINTNEXTLINE(*-pro-type-const-cast) + return const_cast(ikarus_toggle_value_get_const(value, data_size_out)); } -void ikarus_toggle_value_set(IkarusToggleValue * value, bool new_value) { - value->set_value(new_value); +bool const * ikarus_toggle_value_get_const(IkarusToggleValue const * value, size_t * data_size_out) { + if (data_size_out != nullptr) { + *data_size_out = value->get_value().size(); + } + + return value->get_value().data(); } -struct IkarusValue * ikarus_toggle_value_to_value(IkarusToggleValue * toggle_value) { - return static_cast(toggle_value); +void ikarus_toggle_value_set(IkarusToggleValue * value, bool * new_data, size_t new_data_size) { + if (new_data == nullptr || new_data_size == 0) { + value->get_value().clear(); + return; + } + + value->get_value().reserve(new_data_size); + + for (auto i = 0; i < new_data_size; ++i) { + // NOLINTNEXTLINE(*-pro-bounds-pointer-arithmetic) + value->get_value().emplace_back(new_data[i]); + } +} + +struct IkarusValue * ikarus_toggle_value_to_value(IkarusToggleValue * value) { + return static_cast(value); } diff --git a/src/values/toggle_value.hpp b/src/values/toggle_value.hpp index b526476..81386a2 100644 --- a/src/values/toggle_value.hpp +++ b/src/values/toggle_value.hpp @@ -1,13 +1,14 @@ #pragma once +#include + +#include + #include -/// \private struct IkarusToggleValue final : IkarusValue { public: - explicit IkarusToggleValue(bool value): - IkarusValue{this}, - _value{value} {} + explicit IkarusToggleValue(); IkarusToggleValue(IkarusToggleValue const&) = default; IkarusToggleValue(IkarusToggleValue&&) = default; @@ -18,14 +19,9 @@ public: ~IkarusToggleValue() override = default; public: - [[nodiscard]] bool get_value() const { - return _value; - } - - void set_value(bool value) { - _value = value; - } + [[nodiscard]] boost::container::vector& get_value(); + [[nodiscard]] boost::container::vector const& get_value() const; private: - bool _value; + boost::container::vector _value{}; };