diff --git a/include/ikarus/errors.h b/include/ikarus/errors.h index f501c22..ce2f31d 100644 --- a/include/ikarus/errors.h +++ b/include/ikarus/errors.h @@ -33,28 +33,28 @@ enum IkarusErrorInfo { /// \brief No error occurred. IkarusErrorInfo_Type_None = 0x0002000000000000, /// \brief The user misused the API. - /// \example Accessing a resource that does not exist. + /// Example: Accessing a resource that does not exist. IkarusErrorInfo_Type_Client_Misuse = 0x0002000100000001, /// \brief The user provided invalid input. - /// \example Passing null for a pointer that must not be null. + /// Example: Passing null for a pointer that must not be null. IkarusErrorInfo_Type_Client_Input = 0x0002000100000002, /// \brief An error occurred while interacting with a dependency from ikarus. - /// \example An error occurred in the underlying OS library. + /// Example: An error occurred in the underlying OS library. IkarusErrorInfo_Type_SubSystem_Dependency = 0x0002000200000001, /// \brief An error occurred while interacting with the database. - /// \example An error occurred while executing a query. + /// Example: An error occurred while executing a query. IkarusErrorInfo_Type_SubSystem_Database = 0x0002000200000002, /// \brief An error occurred while interacting with the filesystem. - /// \example An error occurred while reading a file. + /// Example: An error occurred while reading a file. IkarusErrorInfo_Type_SubSystem_Filesystem = 0x0002000200000003, /// \brief A datapoint within ikarus is invalid for the current state of the system. - /// \example The name of an object is found to be invalid UTF8. + /// Example: The name of an object is found to be invalid UTF8. IkarusErrorInfo_Type_LibIkarus_InvalidState = 0x0002000300000001, /// \brief LibIkarus is unable to perform a certain operation that should succeed. - /// \example Migrating a project fails + /// Example: Migrating a project fails IkarusErrorInfo_Type_LibIkarus_CannotPerformOperation = 0x0002000300000002, /// \brief LibIkarus is unable to perform a certain operation within a given timeframe. - /// \example A query takes longer than the timeout. + /// Example: A query takes longer than the timeout. IkarusErrorInfo_Type_LibIkarus_Timeout = 0x0002000300000003, /// \brief The type of error is unknown. IkarusErrorInfo_Type_Unknown = 0xFFFFFFFF, diff --git a/include/ikarus/values/number_value.h b/include/ikarus/values/number_value.h index 2c054f8..a489cd6 100644 --- a/include/ikarus/values/number_value.h +++ b/include/ikarus/values/number_value.h @@ -24,21 +24,21 @@ IKA_API IkarusNumberValue * ikarus_number_value_create(long double 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. /// \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); -/// \brief Fetches the underlying value of a number value. -/// \param value The number value. -/// \return The underlying value. -/// \warning If the value is indeterminate, false is returned. -IKA_API long double ikarus_number_value_get_underlying(IkarusNumberValue const * value); - /// \brief Converts a number value to an entity value. /// \param number_value The number value to convert. /// \return The converted entity value. -IKA_API struct IkarusEntityValue * ikarus_number_value_to_entity_value(IkarusNumberValue * number_value); +IKA_API struct IkarusValue * ikarus_number_value_to_value(IkarusNumberValue * number_value); IKARUS_END_HEADER diff --git a/include/ikarus/values/text_value.h b/include/ikarus/values/text_value.h index 867a638..b9ea9c9 100644 --- a/include/ikarus/values/text_value.h +++ b/include/ikarus/values/text_value.h @@ -24,21 +24,22 @@ IKA_API IkarusTextValue * ikarus_text_value_create(char const * 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. /// \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); -/// \brief Fetches the underlying value of a text value. -/// \param value The text value. -/// \return The underlying value. -/// \warning If the value is indeterminate, false is returned. -IKA_API char const * ikarus_text_value_get_underlying(IkarusTextValue const * value); - /// \brief Converts a text value to an entity value. /// \param text_value The text value to convert. /// \return The converted entity value. -IKA_API struct IkarusEntityValue * ikarus_text_value_to_entity_value(IkarusTextValue * text_value); +IKA_API struct IkarusValue * ikarus_text_value_to_value(IkarusTextValue * text_value); IKARUS_END_HEADER diff --git a/include/ikarus/values/toggle_value.h b/include/ikarus/values/toggle_value.h index 7c77870..e653482 100644 --- a/include/ikarus/values/toggle_value.h +++ b/include/ikarus/values/toggle_value.h @@ -24,21 +24,21 @@ IKA_API IkarusToggleValue * ikarus_toggle_value_create(bool 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. /// \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); -/// \brief Fetches the underlying value of a toggle value. -/// \param value The toggle value. -/// \return The underlying value. -/// \warning If the value is indeterminate, false is returned. -IKA_API bool ikarus_toggle_value_get_underlying(IkarusToggleValue const * value); - /// \brief Converts a toggle value to an entity value. /// \param toggle_value The toggle value to convert. /// \return The converted entity value. -IKA_API struct IkarusEntityValue * ikarus_toggle_value_to_entity_value(IkarusToggleValue * toggle_value); +IKA_API struct IkarusValue * ikarus_toggle_value_to_value(IkarusToggleValue * toggle_value); IKARUS_END_HEADER diff --git a/include/ikarus/values/value.h b/include/ikarus/values/value.h index fd17f5b..b8b95fe 100644 --- a/include/ikarus/values/value.h +++ b/include/ikarus/values/value.h @@ -4,7 +4,6 @@ /// \author Folling #include -#include /// \defgroup entity_value Entity Values /// \brief The values stored in entities. @@ -25,15 +24,22 @@ struct IkarusValue; /// \return True if the value is indeterminate, false otherwise. IKA_API bool ikarus_value_is_indeterminate(IkarusValue const * value); -// \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 a copy and owned by the caller. +/// \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. /// \param toggle_visitor The function to call if the value is a toggle value. Skipped if null. /// \param number_visitor The function to call if the value is a number value. Skipped if null. /// \param text_visitor The function to call if the value is a text value. Skipped if null. diff --git a/src/values/number_value.cpp b/src/values/number_value.cpp new file mode 100644 index 0000000..b4d3413 --- /dev/null +++ b/src/values/number_value.cpp @@ -0,0 +1,26 @@ +#include "ikarus/values/number_value.h" + +#include + +IkarusNumberValue * ikarus_number_value_create(long double value) { + return new IkarusNumberValue{value}; +} + +IkarusNumberValue * ikarus_number_value_create_indeterminate() { + auto * ret = new IkarusNumberValue{0.0}; + ret->set_intermediate(true); + + return ret; +} + +long double ikarus_number_value_get(IkarusNumberValue const * value) { + return value->get_value(); +} + +void ikarus_number_value_set(IkarusNumberValue * value, long double new_value) { + value->set_value(new_value); +} + +struct IkarusValue * ikarus_number_value_to_value(IkarusNumberValue * number_value) { + return static_cast(number_value); +} diff --git a/src/values/number_value.hpp b/src/values/number_value.hpp index 51020fc..e495be5 100644 --- a/src/values/number_value.hpp +++ b/src/values/number_value.hpp @@ -1,5 +1,31 @@ #pragma once -struct IkarusNumberValue { - long double value; +#include + +/// \private +struct IkarusNumberValue final : IkarusValue { +public: + explicit IkarusNumberValue(long double value): + IkarusValue{this}, + _value{value} {} + + IkarusNumberValue(IkarusNumberValue const&) = default; + IkarusNumberValue(IkarusNumberValue&&) = default; + + IkarusNumberValue& operator=(IkarusNumberValue const&) = default; + IkarusNumberValue& operator=(IkarusNumberValue&&) = default; + + ~IkarusNumberValue() override = default; + +public: + [[nodiscard]] long double get_value() const { + return _value; + } + + void set_value(long double value) { + _value = value; + } + +private: + long double _value; }; diff --git a/src/values/text_value.cpp b/src/values/text_value.cpp new file mode 100644 index 0000000..6eb839c --- /dev/null +++ b/src/values/text_value.cpp @@ -0,0 +1,26 @@ +#include "ikarus/values/text_value.h" + +#include "text_value.hpp" + +IkarusTextValue * ikarus_text_value_create(char const * value) { + return new IkarusTextValue{value}; +} + +IkarusTextValue * ikarus_text_value_create_indeterminate() { + auto * ret = new IkarusTextValue{""}; + ret->set_intermediate(true); + + return ret; +} + +char const * ikarus_text_value_get(IkarusTextValue const * value) { + return value->get_value().data(); +} + +void ikarus_text_value_set(IkarusTextValue * value, char const * new_value) { + value->set_value(new_value); +} + +struct IkarusValue * ikarus_text_value_to_value(IkarusTextValue * text_value) { + return static_cast(text_value); +} diff --git a/src/values/text_value.hpp b/src/values/text_value.hpp index 20880c4..3766513 100644 --- a/src/values/text_value.hpp +++ b/src/values/text_value.hpp @@ -2,7 +2,32 @@ #include +#include + /// \private -struct IkarusTextValue { - std::string value; +struct IkarusTextValue final : IkarusValue { +public: + explicit IkarusTextValue(std::string value): + IkarusValue{this}, + _value(std::move(value)) {} + + IkarusTextValue(IkarusTextValue const&) = default; + IkarusTextValue(IkarusTextValue&&) noexcept = default; + + IkarusTextValue& operator=(IkarusTextValue const&) = default; + IkarusTextValue& operator=(IkarusTextValue&&) noexcept = default; + + ~IkarusTextValue() override = default; + +public: + [[nodiscard]] std::string_view get_value() const noexcept { + return _value; + } + + void set_value(std::string_view value) { + _value = value; + } + +private: + std::string _value; }; diff --git a/src/values/toggle_value.cpp b/src/values/toggle_value.cpp new file mode 100644 index 0000000..30e64c8 --- /dev/null +++ b/src/values/toggle_value.cpp @@ -0,0 +1,26 @@ +#include "ikarus/values/toggle_value.h" + +#include "toggle_value.hpp" + +IkarusToggleValue * ikarus_toggle_value_create(bool value) { + return new IkarusToggleValue{value}; +} + +IkarusToggleValue * ikarus_toggle_value_create_indeterminate() { + auto * ret = new IkarusToggleValue{false}; + ret->set_intermediate(true); + + return ret; +} + +bool ikarus_toggle_value_get(IkarusToggleValue const * value) { + return value->get_value(); +} + +void ikarus_toggle_value_set(IkarusToggleValue * value, bool new_value) { + value->set_value(new_value); +} + +struct IkarusValue * ikarus_toggle_value_to_value(IkarusToggleValue * toggle_value) { + return static_cast(toggle_value); +} diff --git a/src/values/toggle_value.hpp b/src/values/toggle_value.hpp index a2f2d70..b526476 100644 --- a/src/values/toggle_value.hpp +++ b/src/values/toggle_value.hpp @@ -1,6 +1,31 @@ #pragma once +#include + /// \private -struct IkarusToggleValue { - bool value; +struct IkarusToggleValue final : IkarusValue { +public: + explicit IkarusToggleValue(bool value): + IkarusValue{this}, + _value{value} {} + + IkarusToggleValue(IkarusToggleValue const&) = default; + IkarusToggleValue(IkarusToggleValue&&) = default; + + IkarusToggleValue& operator=(IkarusToggleValue const&) = default; + IkarusToggleValue& operator=(IkarusToggleValue&&) = default; + + ~IkarusToggleValue() override = default; + +public: + [[nodiscard]] bool get_value() const { + return _value; + } + + void set_value(bool value) { + _value = value; + } + +private: + bool _value; }; diff --git a/src/values/value.cpp b/src/values/value.cpp index 52b4d18..f61f2bb 100644 --- a/src/values/value.cpp +++ b/src/values/value.cpp @@ -10,22 +10,60 @@ #include bool ikarus_value_is_indeterminate(IkarusValue const * value) { - return value->indeterminate; + return value->is_interminate(); +} + +void ikarus_value_set_indeterminate(IkarusValue * value, bool indeterminate) { + value->set_intermediate(indeterminate); } char const * ikarus_value_to_string(IkarusValue const * value) { - auto str = std::visit( + auto const str = std::visit( cppbase::overloaded{ [](IkarusToggleValue const * toggle_value) -> std::string { return toggle_value->value ? "true" : "false"; }, [](IkarusNumberValue const * number_value) -> std::string { return fmt::format("{}", number_value->value); }, [](IkarusTextValue const * text_value) -> std::string { return fmt::format("{}", text_value->value); }, }, - value->data + value->get_data() ); - char * ret = new char[str.size() + 1]; + auto * const ret = new char[str.size() + 1]; std::strncpy(ret, str.data(), str.size() + 1); return ret; } + +void ikarus_value_visit( + IkarusValue * value, + void (*toggle_visitor)(IkarusToggleValue *, void *), + void (*number_visitor)(IkarusNumberValue *, void *), + void (*text_visitor)(IkarusTextValue *, void *), + void * data +) { + std::visit( + cppbase::overloaded{ + [toggle_visitor, data](IkarusToggleValue * toggle_value) { toggle_visitor(toggle_value, data); }, + [number_visitor, data](IkarusNumberValue * number_value) { number_visitor(number_value, data); }, + [text_visitor, data](IkarusTextValue * text_value) { text_visitor(text_value, data); }, + }, + value->get_data() + ); +} + +void ikarus_value_visit_const( + IkarusValue const * value, + void (*toggle_visitor)(IkarusToggleValue const *, void *), + void (*number_visitor)(IkarusNumberValue const *, void *), + void (*text_visitor)(IkarusTextValue const *, void *), + void * data +) { + std::visit( + cppbase::overloaded{ + [toggle_visitor, data](IkarusToggleValue const * toggle_value) { toggle_visitor(toggle_value, data); }, + [number_visitor, data](IkarusNumberValue const * number_value) { number_visitor(number_value, data); }, + [text_visitor, data](IkarusTextValue const * text_value) { text_visitor(text_value, data); }, + }, + value->get_data() + ); +} diff --git a/src/values/value.hpp b/src/values/value.hpp index 1d53154..0adc61c 100644 --- a/src/values/value.hpp +++ b/src/values/value.hpp @@ -3,6 +3,39 @@ #include struct IkarusValue { - bool indeterminate; - std::variant data; +public: + using Data = std::variant::variant; + +public: + explicit IkarusValue(Data data): + _data(data) {} + + IkarusValue(IkarusValue const&) = default; + IkarusValue(IkarusValue&&) noexcept = default; + + IkarusValue& operator=(IkarusValue const&) = default; + IkarusValue& operator=(IkarusValue&&) noexcept = default; + + virtual ~IkarusValue(); + +public: + [[nodiscard]] inline bool is_interminate() const { + return _indeterminate; + } + + void set_intermediate(bool value) { + _indeterminate = value; + } + + [[nodiscard]] inline Data& get_data() { + return _data; + } + + [[nodiscard]] inline Data const& get_data() const { + return _data; + } + +private: + bool _indeterminate{false}; + Data _data; }; diff --git a/vendor/sqlitecpp b/vendor/sqlitecpp index 538616d..3057656 160000 --- a/vendor/sqlitecpp +++ b/vendor/sqlitecpp @@ -1 +1 @@ -Subproject commit 538616d8ced2d3f04659261ccae3b039d65da004 +Subproject commit 3057656ff277294ab424af90e553e630c2a5e8f7