diff --git a/.clang-format b/.clang-format index 85337cc..6d3560a 100644 --- a/.clang-format +++ b/.clang-format @@ -109,7 +109,9 @@ IncludeCategories: Priority: 11 - Regex: '^$' Priority: 12 - - Regex: '^$' + - Regex: '^$' + Priority: 13 + - Regex: '^$' Priority: 13 IndentAccessModifiers: false @@ -189,4 +191,4 @@ SpacesInSquareBrackets: false Standard: c++20 TabWidth: 4 -UseTab: Never +UseTab: Always diff --git a/.gitmodules b/.gitmodules index 933638b..94e3d41 100644 --- a/.gitmodules +++ b/.gitmodules @@ -10,3 +10,6 @@ [submodule "vendor/cppbase"] path = vendor/cppbase url = ssh://git@git.rewritesarebliss.com:16658/Folling/cppbase.git +[submodule "vendor/json"] + path = vendor/json + url = git@github.com:nlohmann/json.git diff --git a/CMakeLists.txt b/CMakeLists.txt index 8a16b08..63b949c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.18) +cmake_minimum_required(VERSION 3.31) project(ikarus) option(LIBIKARUS_ENABLE_TESTS "Enable tests" OFF) @@ -9,7 +9,7 @@ add_subdirectory(vendor) add_subdirectory(include) add_subdirectory(src) -find_package(Boost COMPONENTS system filesystem REQUIRED) +find_package(Boost CONFIG COMPONENTS system filesystem REQUIRED) add_library( ikarus SHARED @@ -17,40 +17,31 @@ add_library( ${SOURCE_FILES} ) -add_dependencies( - ikarus - flatbuffer_headers -) - set_target_properties( ikarus PROPERTIES CXX_STANDARD 23 CXX_STANDARD_REQUIRED ON + LINKER_LANGUAGE CXX POSITION_INDEPENDENT_CODE TRUE ) target_include_directories( - ikarus PUBLIC + ikarus + PUBLIC ${CMAKE_CURRENT_LIST_DIR}/include -) - -target_include_directories( - ikarus PRIVATE + PRIVATE ${CMAKE_CURRENT_LIST_DIR}/src + ${Boost_INCLUDE_DIR} ) target_link_libraries( ikarus PRIVATE cppbase sqlitecpp + nlohmann_json::nlohmann_json ${Boost_LIBRARIES} ) -target_include_directories( - ikarus PRIVATE - ${Boost_INCLUDE_DIR} -) - if (LIBIKARUS_ENABLE_LINTS) find_program(IWYU_PATH NAMES include-what-you-use iwyu REQUIRED) find_program(CLANG_TIDY_PATH NAMES clang-tidy REQUIRED) @@ -66,7 +57,7 @@ if (LIBIKARUS_BUILD_DOCS) find_program(DOXYGEN_PATH NAMES doxygen REQUIRED) add_custom_target( libikarus_docs - WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}/docs + WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}/docs/doxygen COMMAND ${DOXYGEN_PATH} DoxyFile COMMENT "Generating documentation with Doxygen" VERBATIM diff --git a/CMakePresets.json b/CMakePresets.json new file mode 100644 index 0000000..0772ba0 --- /dev/null +++ b/CMakePresets.json @@ -0,0 +1,35 @@ +{ + "version": 6, + "cmakeMinimumRequired": { + "major": 3, + "minor": 23, + "patch": 0 + }, + "configurePresets": [ + { + "name": "default-mac", + "displayName": "Default Config for MacOS", + "description": "Default MacOS build using Ninja generator", + "generator": "Ninja", + "binaryDir": "${sourceDir}/build/default", + "cacheVariables": { + "CMAKE_COLOR_DIAGNOSTICS": "ON", + "CMAKE_EXPORT_COMPILE_COMMANDS": "ON" + }, + "toolchainFile": "tools/cmake/toolchains/mac.cmake" + }, + { + "name": "test-mac", + "displayName": "Test Config MacOS", + "description": "Test MacOS build using Ninja generator", + "generator": "Ninja", + "binaryDir": "${sourceDir}/build/test", + "cacheVariables": { + "CMAKE_COLOR_DIAGNOSTICS": "ON", + "LIBIKARUS_ENABLE_TESTS": "ON", + "CMAKE_EXPORT_COMPILE_COMMANDS": "ON" + }, + "toolchainFile": "tools/cmake/toolchains/mac.cmake" + } + ] +} diff --git a/LICENSE.md b/LICENSE.md index 5f2c6f6..41924e1 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -1,4 +1,4 @@ -Copyright 2019-2023 Folling (folling@ikarus.world) +Copyright 2019-2024 Folling (mail@folling.io) Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: diff --git a/docs/Flags.md b/docs/Flags.md new file mode 100644 index 0000000..6f54cdc --- /dev/null +++ b/docs/Flags.md @@ -0,0 +1,5 @@ +All mutating functions take a flag argument that can be used to control the behavior of the function. The flags are +defined in a corresponding enum. The flags are passed as a bitset, so multiple flags can be passed at once by using the +bitwise OR operator `|`. + +The reason for this feature is ABI stability. \ No newline at end of file diff --git a/docs/Ownership.md b/docs/Ownership.md new file mode 100644 index 0000000..9827299 --- /dev/null +++ b/docs/Ownership.md @@ -0,0 +1,7 @@ +### Getters + +Returned data remains owned by libikarus, the exception are Entity(Property)Values. + +### Setters + +libikarus assumes ownership of any data passed into it, the exception are Entity(Property)Values. \ No newline at end of file diff --git a/docs/DoxyFile b/docs/doxygen/DoxyFile similarity index 100% rename from docs/DoxyFile rename to docs/doxygen/DoxyFile diff --git a/docs/format_fix.js b/docs/doxygen/format_fix.js similarity index 100% rename from docs/format_fix.js rename to docs/doxygen/format_fix.js diff --git a/docs/header.html b/docs/doxygen/header.html similarity index 100% rename from docs/header.html rename to docs/doxygen/header.html diff --git a/docs/internal/Caching.md b/docs/internal/Caching.md new file mode 100644 index 0000000..cd4e262 --- /dev/null +++ b/docs/internal/Caching.md @@ -0,0 +1,2 @@ +libikarus doesn't perform any caching as the filesystem & SQLite already cache quite well. +Until we can see that there's a performance overhead no caching will be implemented. diff --git a/include/CMakeLists.txt b/include/CMakeLists.txt index e3043c7..d5a0a7a 100644 --- a/include/CMakeLists.txt +++ b/include/CMakeLists.txt @@ -5,5 +5,3 @@ file( ) set(INCLUDE_FILES ${FILES} PARENT_SCOPE) - -add_subdirectory(ikarus) \ No newline at end of file diff --git a/include/ikarus/CMakeLists.txt b/include/ikarus/CMakeLists.txt deleted file mode 100644 index cd981b8..0000000 --- a/include/ikarus/CMakeLists.txt +++ /dev/null @@ -1 +0,0 @@ -add_subdirectory(models) \ No newline at end of file diff --git a/include/ikarus/errors.h b/include/ikarus/errors.h index 926f07d..a41c291 100644 --- a/include/ikarus/errors.h +++ b/include/ikarus/errors.h @@ -1,19 +1,17 @@ #pragma once /// \file errors.h -/// \author Folling +/// \author Folling #include /// \addtogroup errors Errors /// \brief Error handling within libikarus /// \details Functions in Ikarus may fail. To report the type of failure all functions have an out parameter for the error. -/// Upon erring the function will store relevant information about the error in the out parameter. -/// If the out parameter is null nothing will be stored. This is not recommended as it essentially ignores errors. -/// For the sake of simplicity we have avoided mechanisms that "force" clients to handle errors. -/// Note that Ikarus does not check for null pointers. Passing null pointers to functions that do not explicitly state that they accept null -/// pointers is undefined behaviour. This decision is done for the sake of brevity and readability. `project_get_name(project)` is also -/// synonymous to `project->get_name()` in OOP languages, which shares the same semantics. +/// Upon erring the function will store relevant information about the error in +/// the out parameter. If the out parameter is null nothing will be stored. This +/// is not recommended as it essentially ignores errors. For the sake of +/// simplicity we have avoided mechanisms that "force" clients to handle errors. /// @{ IKARUS_BEGIN_HEADER @@ -22,73 +20,77 @@ IKARUS_BEGIN_HEADER /// \remark Note that this doesn't show responsibility. An error with source "SubSystem" could still be the /// fault of libikarus, it just indicates where the error occurred. enum IkarusErrorInfo { - /// \brief No error occurred. - IkarusErrorInfo_None = 0x0, - /// \brief The client misused the API. - /// Example: Accessing a resource that does not exist. - IkarusErrorInfo_Client_Misuse = 0x01000001, - /// \brief The client provided a null value for a parameter that must not be null. - /// Example: Passing null for `ikarus_project_get_name` - IkarusErrorInfo_Client_InvalidNull = 0x01000002, - /// \brief The client provided an index that was out of bounds for some array. - /// Example: Passing the index 3 for an `IkarusToggleValue` with size 3. - IkarusErrorInfo_Client_IndexOutOfBounds = 0x01000003, - /// \brief The client provided a numeric value that was out of bounds - /// Example: Passing the value 2^32 to an i32 (might be passed as a string). - IkarusErrorInfo_Client_ValueOutOfBounds = 0x01000004, - /// \brief The client provided invalid input that doesn't fit in any of the other categories. - /// Example: Passing an empty/blank string for a string that must be non-empty/-blank. - IkarusErrorInfo_Client_InvalidInput = 0x01000005, - /// \brief The client provided valid data in an invalid format. - /// Example: Passing a malformed JSON string. - IkarusErrorInfo_Client_InvalidFormat = 0x01000006, - /// \brief The client violated a constraint. - /// \details This error is most likely caused by endusers. - /// Example: A user tries to set the age of a character to an value outside of their specified range. - IkarusErrorInfo_Client_ConstraintViolated = 0x10000007, + /// \brief No error occurred. + IkarusErrorInfo_None = 0x0, + /// \brief The client misused the API. + /// Example: Accessing a resource that does not exist. + IkarusErrorInfo_Client_Misuse = 0x01000001, + /// \brief The client provided a null value for a parameter that must not be null. + /// Example: Passing null for `ikarus_project_get_name` + IkarusErrorInfo_Client_InvalidNull = 0x01000002, + /// \brief The client provided a non-existent resource. + /// Example: Passing an entity to a function after it has been deleted. + IkarusErrorInfo_Client_NonExistent = 0x01000003, + /// \brief The client provided an index that was out of bounds for some array. + /// Example: Passing the index 3 for an `IkarusToggleValue` with size 3. + IkarusErrorInfo_Client_IndexOutOfBounds = 0x01000004, + /// \brief The client provided a numeric value that was out of bounds + /// Example: Passing the value 2^32 to an i32 (might be passed as a string). + IkarusErrorInfo_Client_ValueOutOfBounds = 0x01000005, + /// \brief The client provided invalid input that doesn't fit in any of the other categories. + /// Example: Passing an empty/blank string for a string that must be + /// non-empty/-blank. + IkarusErrorInfo_Client_InvalidInput = 0x01000006, + /// \brief The client provided valid data in an invalid format. + /// Example: Passing a malformed JSON string. + IkarusErrorInfo_Client_InvalidFormat = 0x01000007, + /// \brief The client violated a constraint. + /// \details This error is most likely caused by clients. + /// Example: A user tries to set the age of a character to a value outside + /// its specified range. + IkarusErrorInfo_Client_ConstraintViolated = 0x10000008, - // 0x02 reserved for dependency errors + // 0x02 reserved for dependency errors - /// \brief A file or directory already exists. - IkarusErrorInfo_Filesystem_AccessIssue = 0x03000001, - /// \brief A file was not found. - IkarusErrorInfo_Filesystem_NotFound = 0x03000002, - /// \brief A file or directory already exists. - IkarusErrorInfo_Filesystem_AlreadyExists = 0x03000003, - /// \brief Missing permissions to access a file or directory. - IkarusErrorInfo_Filesystem_MissingPermissions = 0x03000004, - /// \brief Insufficient space to perform an operation. - IkarusErrorInfo_Filesystem_InsufficientSpace = 0x03000005, - /// \brief A path is invalid. - IkarusErrorInfo_Filesystem_InvalidPath = 0x03000006, + /// \brief A file was not found. + IkarusErrorInfo_Filesystem_NotFound = 0x03000001, + /// \brief A file or directory already exists. + IkarusErrorInfo_Filesystem_AlreadyExists = 0x03000002, + /// \brief Missing permissions to access a file or directory. + IkarusErrorInfo_Filesystem_MissingPermissions = 0x03000003, + /// \brief Insufficient space to perform an operation. + IkarusErrorInfo_Filesystem_InsufficientSpace = 0x03000004, + /// \brief A path is invalid. + IkarusErrorInfo_Filesystem_InvalidPath = 0x03000005, - /// \brief A database connection failed. - IkarusErrorInfo_Database_ConnectionFailed = 0x04000001, - /// \brief A database query failed. - IkarusErrorInfo_Database_QueryFailed = 0x04000002, - /// \brief A database migration failed. - IkarusErrorInfo_Database_MigrationFailed = 0x04000003, - /// \brief A database is in an invalid state. This indicates a corrupt project. - /// Example: An entity is linked to a non-existant blueprint. - IkarusErrorInfo_Database_InvalidState = 0x04000004, + /// \brief A database connection failed. + IkarusErrorInfo_Database_ConnectionFailed = 0x04000001, + /// \brief A database query failed. + IkarusErrorInfo_Database_QueryFailed = 0x04000002, + /// \brief A database migration failed. + IkarusErrorInfo_Database_MigrationFailed = 0x04000003, + /// \brief A database is in an invalid state. This indicates a corrupt project. + /// Example: An entity is linked to a non-existent blueprint. + IkarusErrorInfo_Database_InvalidState = 0x04000004, - /// \brief A system call failed. - IkarusErrorInfo_OS_SystemCallFailed = 0x05000001, - /// \brief A system call returned an invalid value. - IkarusErrorInfo_OS_InvalidReturnValue = 0x05000002, - /// \brief An OOM error occurred. - IkarusErrorInfo_OS_InsufficientMemory = 0x05000003, + /// \brief A system call failed. + IkarusErrorInfo_OS_SystemCallFailed = 0x05000001, + /// \brief A system call returned an invalid value. + IkarusErrorInfo_OS_InvalidReturnValue = 0x05000002, + /// \brief An OOM error occurred. + IkarusErrorInfo_OS_InsufficientMemory = 0x05000003, - /// \brief A datapoint within ikarus is invalid for the current state of the system. - /// \details This differs from IkarusErrorInfo_Database_InvalidState in that the latter implies the database itself holds invalid state, - /// whereas the former may imply that the state is ephemeral, e.g. data within a function. - /// Example: The name of an object is found to be invalid UTF8. - IkarusErrorInfo_LibIkarus_InvalidState = 0x06000001, - /// \brief libikarus is unable to perform a certain operation that should succeed. - IkarusErrorInfo_LibIkarus_CannotPerformOperation = 0x06000002, - /// \brief libikarus is unable to perform a certain operation within a given timeframe. - /// Example: A query takes longer than the timeout. - IkarusErrorInfo_LibIkarus_Timeout = 0x06000003, + /// \brief A datapoint within ikarus is invalid for the current state of the system. + /// \details This differs from IkarusErrorInfo_Database_InvalidState in that the latter implies the database itself holds invalid state, + /// whereas the former may imply that the state is ephemeral, e.g. data + /// within a function. + /// Example: The name of an object is found to be invalid UTF8. + IkarusErrorInfo_LibIkarus_InvalidState = 0x06000001, + /// \brief libikarus is unable to perform a certain operation that should succeed. + IkarusErrorInfo_LibIkarus_CannotPerformOperation = 0x06000002, + /// \brief libikarus is unable to perform a certain operation within a given timeframe. + /// Example: A query takes longer than the timeout. + IkarusErrorInfo_LibIkarus_Timeout = 0x06000003, }; /// \brief The maximum length of an error message. @@ -96,17 +98,17 @@ enum IkarusErrorInfo { /// \brief The data stored for an error struct IkarusErrorData { - /// \brief The error type - IkarusErrorInfo info; + /// \brief The error type + enum IkarusErrorInfo info; - char message[IKARUS_ERROR_DATA_MAX_MESSAGE_LIMIT]; + char message[IKARUS_ERROR_DATA_MAX_MESSAGE_LIMIT]; }; /// \brief Gets the name of an error info. /// \param info The error info to get the name of. /// \return The name of the error info. /// \remark The returned pointer is valid for the lifetime of the program and must not be freed. -IKA_API char const * ikarus_get_error_info_name(IkarusErrorInfo info); +IKA_API char const * ikarus_error_info_get_name(enum IkarusErrorInfo info); /// \brief Checks if an error data is a success. /// \param data The error data to check. diff --git a/include/ikarus/models/CMakeLists.txt b/include/ikarus/models/CMakeLists.txt deleted file mode 100644 index e3d8758..0000000 --- a/include/ikarus/models/CMakeLists.txt +++ /dev/null @@ -1,41 +0,0 @@ -file( - GLOB_RECURSE - FLATBUFFER_SOURCES - "*.fbs" -) - -foreach (FLATBUFFER_SOURCE IN LISTS ${FLATBUFFER_SOURCES}) - cmake_path( - GET - ${FLATBUFFER_SOURCE} - FILENAME - FLATBUFFER_SOURCE_NAME - ) - - string( - CONCAT - FLATBUFFER_GENERATED_SOURCE_NAME - ${FLATBUFFER_SOURCE_NAME} - "_generated" - ) - - cmake_path( - REPLACE_EXTENSION - ${FLATBUFFER_GENERATED_SOURCE_NAME} - ".h" - OUTPUT_VARIABLE - FLATBUFFER_GENERATED_HEADER - ) - - list(APPEND FLATBUFFER_GENERATED_HEADERS ${FLATBUFFER_GENERATED_HEADER}) -endforeach () - -add_custom_target( - flatbuffer_headers - COMMENT "Generating flatbuffer headers" - DEPENDS ${FLATBUFFER_SOURCES} - BYPRODUCTS ${FLATBUFFER_GENERATED_HEADERS} - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} - COMMAND flatc --cpp --cpp-std "c++17" ${FLATBUFFER_SOURCES} - VERBATIM -) diff --git a/include/ikarus/models/blueprint.fbs b/include/ikarus/models/blueprint.fbs deleted file mode 100644 index fb782d8..0000000 --- a/include/ikarus/models/blueprint.fbs +++ /dev/null @@ -1,12 +0,0 @@ -include "property.fbs"; - -namespace Ikarus; - -table Blueprint { - id: int64; - name: string; - description: string; - tags: [string]; -} - -root_type Blueprint; diff --git a/include/ikarus/models/blueprint_generated.h b/include/ikarus/models/blueprint_generated.h deleted file mode 100644 index b70924b..0000000 --- a/include/ikarus/models/blueprint_generated.h +++ /dev/null @@ -1,153 +0,0 @@ -// automatically generated by the FlatBuffers compiler, do not modify - - -#ifndef FLATBUFFERS_GENERATED_BLUEPRINT_IKARUS_H_ -#define FLATBUFFERS_GENERATED_BLUEPRINT_IKARUS_H_ - -#include "flatbuffers/flatbuffers.h" - -// Ensure the included flatbuffers.h is the same version as when this file was -// generated, otherwise it may not be compatible. -static_assert(FLATBUFFERS_VERSION_MAJOR == 24 && - FLATBUFFERS_VERSION_MINOR == 3 && - FLATBUFFERS_VERSION_REVISION == 25, - "Non-compatible flatbuffers version included"); - -#include "property_generated.h" - -namespace Ikarus { - -struct Blueprint; -struct BlueprintBuilder; - -struct Blueprint FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table { - typedef BlueprintBuilder Builder; - struct Traits; - enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { - VT_ID = 4, - VT_NAME = 6, - VT_DESCRIPTION = 8, - VT_TAGS = 10 - }; - int64_t id() const { - return GetField(VT_ID, 0); - } - const ::flatbuffers::String *name() const { - return GetPointer(VT_NAME); - } - const ::flatbuffers::String *description() const { - return GetPointer(VT_DESCRIPTION); - } - const ::flatbuffers::Vector<::flatbuffers::Offset<::flatbuffers::String>> *tags() const { - return GetPointer> *>(VT_TAGS); - } - bool Verify(::flatbuffers::Verifier &verifier) const { - return VerifyTableStart(verifier) && - VerifyField(verifier, VT_ID, 8) && - VerifyOffset(verifier, VT_NAME) && - verifier.VerifyString(name()) && - VerifyOffset(verifier, VT_DESCRIPTION) && - verifier.VerifyString(description()) && - VerifyOffset(verifier, VT_TAGS) && - verifier.VerifyVector(tags()) && - verifier.VerifyVectorOfStrings(tags()) && - verifier.EndTable(); - } -}; - -struct BlueprintBuilder { - typedef Blueprint Table; - ::flatbuffers::FlatBufferBuilder &fbb_; - ::flatbuffers::uoffset_t start_; - void add_id(int64_t id) { - fbb_.AddElement(Blueprint::VT_ID, id, 0); - } - void add_name(::flatbuffers::Offset<::flatbuffers::String> name) { - fbb_.AddOffset(Blueprint::VT_NAME, name); - } - void add_description(::flatbuffers::Offset<::flatbuffers::String> description) { - fbb_.AddOffset(Blueprint::VT_DESCRIPTION, description); - } - void add_tags(::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset<::flatbuffers::String>>> tags) { - fbb_.AddOffset(Blueprint::VT_TAGS, tags); - } - explicit BlueprintBuilder(::flatbuffers::FlatBufferBuilder &_fbb) - : fbb_(_fbb) { - start_ = fbb_.StartTable(); - } - ::flatbuffers::Offset Finish() { - const auto end = fbb_.EndTable(start_); - auto o = ::flatbuffers::Offset(end); - return o; - } -}; - -inline ::flatbuffers::Offset CreateBlueprint( - ::flatbuffers::FlatBufferBuilder &_fbb, - int64_t id = 0, - ::flatbuffers::Offset<::flatbuffers::String> name = 0, - ::flatbuffers::Offset<::flatbuffers::String> description = 0, - ::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset<::flatbuffers::String>>> tags = 0) { - BlueprintBuilder builder_(_fbb); - builder_.add_id(id); - builder_.add_tags(tags); - builder_.add_description(description); - builder_.add_name(name); - return builder_.Finish(); -} - -struct Blueprint::Traits { - using type = Blueprint; - static auto constexpr Create = CreateBlueprint; -}; - -inline ::flatbuffers::Offset CreateBlueprintDirect( - ::flatbuffers::FlatBufferBuilder &_fbb, - int64_t id = 0, - const char *name = nullptr, - const char *description = nullptr, - const std::vector<::flatbuffers::Offset<::flatbuffers::String>> *tags = nullptr) { - auto name__ = name ? _fbb.CreateString(name) : 0; - auto description__ = description ? _fbb.CreateString(description) : 0; - auto tags__ = tags ? _fbb.CreateVector<::flatbuffers::Offset<::flatbuffers::String>>(*tags) : 0; - return Ikarus::CreateBlueprint( - _fbb, - id, - name__, - description__, - tags__); -} - -inline const Ikarus::Blueprint *GetBlueprint(const void *buf) { - return ::flatbuffers::GetRoot(buf); -} - -inline const Ikarus::Blueprint *GetSizePrefixedBlueprint(const void *buf) { - return ::flatbuffers::GetSizePrefixedRoot(buf); -} - -inline bool VerifyBlueprintBuffer( - ::flatbuffers::Verifier &verifier) { - return verifier.VerifyBuffer(nullptr); -} - -inline bool VerifySizePrefixedBlueprintBuffer( - ::flatbuffers::Verifier &verifier) { - return verifier.VerifySizePrefixedBuffer(nullptr); -} - -inline void FinishBlueprintBuffer( - ::flatbuffers::FlatBufferBuilder &fbb, - ::flatbuffers::Offset root) { - fbb.Finish(root); -} - -inline void FinishSizePrefixedBlueprintBuffer( - ::flatbuffers::FlatBufferBuilder &fbb, - ::flatbuffers::Offset root) { - fbb.FinishSizePrefixed(root); -} - -} // namespace Ikarus - -#endif // FLATBUFFERS_GENERATED_BLUEPRINT_IKARUS_H_ diff --git a/include/ikarus/models/entity.fbs b/include/ikarus/models/entity.fbs deleted file mode 100644 index bce2ff5..0000000 --- a/include/ikarus/models/entity.fbs +++ /dev/null @@ -1,26 +0,0 @@ -include "value.fbs"; -include "property.fbs"; -include "blueprint.fbs"; - -namespace Ikarus; - -table NamedValue { - name: string (key); - value: Ikarus.Value.Value; -} - -table PropertyValue { - property_id: int64 (key); - data: Ikarus.Value.Data; -} - -table Entity { - id: int64; - name: string; - description: string; - tags: [string]; - values: [NamedValue]; - property_values: [PropertyValue]; -} - -root_type Entity; diff --git a/include/ikarus/models/entity_generated.h b/include/ikarus/models/entity_generated.h deleted file mode 100644 index e253038..0000000 --- a/include/ikarus/models/entity_generated.h +++ /dev/null @@ -1,398 +0,0 @@ -// automatically generated by the FlatBuffers compiler, do not modify - - -#ifndef FLATBUFFERS_GENERATED_ENTITY_IKARUS_H_ -#define FLATBUFFERS_GENERATED_ENTITY_IKARUS_H_ - -#include "flatbuffers/flatbuffers.h" - -// Ensure the included flatbuffers.h is the same version as when this file was -// generated, otherwise it may not be compatible. -static_assert(FLATBUFFERS_VERSION_MAJOR == 24 && - FLATBUFFERS_VERSION_MINOR == 3 && - FLATBUFFERS_VERSION_REVISION == 25, - "Non-compatible flatbuffers version included"); - -#include "blueprint_generated.h" -#include "property_generated.h" -#include "value_generated.h" - -namespace Ikarus { - -struct NamedValue; -struct NamedValueBuilder; - -struct PropertyValue; -struct PropertyValueBuilder; - -struct Entity; -struct EntityBuilder; - -struct NamedValue FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table { - typedef NamedValueBuilder Builder; - struct Traits; - enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { - VT_NAME = 4, - VT_VALUE = 6 - }; - const ::flatbuffers::String *name() const { - return GetPointer(VT_NAME); - } - bool KeyCompareLessThan(const NamedValue * const o) const { - return *name() < *o->name(); - } - int KeyCompareWithValue(const char *_name) const { - return strcmp(name()->c_str(), _name); - } - template - int KeyCompareWithValue(const StringType& _name) const { - if (name()->c_str() < _name) return -1; - if (_name < name()->c_str()) return 1; - return 0; - } - const Ikarus::Value::Value *value() const { - return GetPointer(VT_VALUE); - } - bool Verify(::flatbuffers::Verifier &verifier) const { - return VerifyTableStart(verifier) && - VerifyOffsetRequired(verifier, VT_NAME) && - verifier.VerifyString(name()) && - VerifyOffset(verifier, VT_VALUE) && - verifier.VerifyTable(value()) && - verifier.EndTable(); - } -}; - -struct NamedValueBuilder { - typedef NamedValue Table; - ::flatbuffers::FlatBufferBuilder &fbb_; - ::flatbuffers::uoffset_t start_; - void add_name(::flatbuffers::Offset<::flatbuffers::String> name) { - fbb_.AddOffset(NamedValue::VT_NAME, name); - } - void add_value(::flatbuffers::Offset value) { - fbb_.AddOffset(NamedValue::VT_VALUE, value); - } - explicit NamedValueBuilder(::flatbuffers::FlatBufferBuilder &_fbb) - : fbb_(_fbb) { - start_ = fbb_.StartTable(); - } - ::flatbuffers::Offset Finish() { - const auto end = fbb_.EndTable(start_); - auto o = ::flatbuffers::Offset(end); - fbb_.Required(o, NamedValue::VT_NAME); - return o; - } -}; - -inline ::flatbuffers::Offset CreateNamedValue( - ::flatbuffers::FlatBufferBuilder &_fbb, - ::flatbuffers::Offset<::flatbuffers::String> name = 0, - ::flatbuffers::Offset value = 0) { - NamedValueBuilder builder_(_fbb); - builder_.add_value(value); - builder_.add_name(name); - return builder_.Finish(); -} - -struct NamedValue::Traits { - using type = NamedValue; - static auto constexpr Create = CreateNamedValue; -}; - -inline ::flatbuffers::Offset CreateNamedValueDirect( - ::flatbuffers::FlatBufferBuilder &_fbb, - const char *name = nullptr, - ::flatbuffers::Offset value = 0) { - auto name__ = name ? _fbb.CreateString(name) : 0; - return Ikarus::CreateNamedValue( - _fbb, - name__, - value); -} - -struct PropertyValue FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table { - typedef PropertyValueBuilder Builder; - struct Traits; - enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { - VT_PROPERTY_ID = 4, - VT_DATA_TYPE = 6, - VT_DATA = 8 - }; - int64_t property_id() const { - return GetField(VT_PROPERTY_ID, 0); - } - bool KeyCompareLessThan(const PropertyValue * const o) const { - return property_id() < o->property_id(); - } - int KeyCompareWithValue(int64_t _property_id) const { - return static_cast(property_id() > _property_id) - static_cast(property_id() < _property_id); - } - Ikarus::Value::Data data_type() const { - return static_cast(GetField(VT_DATA_TYPE, 0)); - } - const void *data() const { - return GetPointer(VT_DATA); - } - template const T *data_as() const; - const Ikarus::Value::ToggleDataPoint *data_as_ToggleDataPoint() const { - return data_type() == Ikarus::Value::Data::ToggleDataPoint ? static_cast(data()) : nullptr; - } - const Ikarus::Value::NumberDataPoint *data_as_NumberDataPoint() const { - return data_type() == Ikarus::Value::Data::NumberDataPoint ? static_cast(data()) : nullptr; - } - const Ikarus::Value::TextDataPoint *data_as_TextDataPoint() const { - return data_type() == Ikarus::Value::Data::TextDataPoint ? static_cast(data()) : nullptr; - } - const Ikarus::Value::SimpleData *data_as_SimpleData() const { - return data_type() == Ikarus::Value::Data::SimpleData ? static_cast(data()) : nullptr; - } - const Ikarus::Value::CombinedData *data_as_CombinedData() const { - return data_type() == Ikarus::Value::Data::CombinedData ? static_cast(data()) : nullptr; - } - const Ikarus::Value::ListData *data_as_ListData() const { - return data_type() == Ikarus::Value::Data::ListData ? static_cast(data()) : nullptr; - } - const Ikarus::Value::ComplexData *data_as_ComplexData() const { - return data_type() == Ikarus::Value::Data::ComplexData ? static_cast(data()) : nullptr; - } - bool Verify(::flatbuffers::Verifier &verifier) const { - return VerifyTableStart(verifier) && - VerifyField(verifier, VT_PROPERTY_ID, 8) && - VerifyField(verifier, VT_DATA_TYPE, 1) && - VerifyOffset(verifier, VT_DATA) && - VerifyData(verifier, data(), data_type()) && - verifier.EndTable(); - } -}; - -template<> inline const Ikarus::Value::ToggleDataPoint *PropertyValue::data_as() const { - return data_as_ToggleDataPoint(); -} - -template<> inline const Ikarus::Value::NumberDataPoint *PropertyValue::data_as() const { - return data_as_NumberDataPoint(); -} - -template<> inline const Ikarus::Value::TextDataPoint *PropertyValue::data_as() const { - return data_as_TextDataPoint(); -} - -template<> inline const Ikarus::Value::SimpleData *PropertyValue::data_as() const { - return data_as_SimpleData(); -} - -template<> inline const Ikarus::Value::CombinedData *PropertyValue::data_as() const { - return data_as_CombinedData(); -} - -template<> inline const Ikarus::Value::ListData *PropertyValue::data_as() const { - return data_as_ListData(); -} - -template<> inline const Ikarus::Value::ComplexData *PropertyValue::data_as() const { - return data_as_ComplexData(); -} - -struct PropertyValueBuilder { - typedef PropertyValue Table; - ::flatbuffers::FlatBufferBuilder &fbb_; - ::flatbuffers::uoffset_t start_; - void add_property_id(int64_t property_id) { - fbb_.AddElement(PropertyValue::VT_PROPERTY_ID, property_id, 0); - } - void add_data_type(Ikarus::Value::Data data_type) { - fbb_.AddElement(PropertyValue::VT_DATA_TYPE, static_cast(data_type), 0); - } - void add_data(::flatbuffers::Offset data) { - fbb_.AddOffset(PropertyValue::VT_DATA, data); - } - explicit PropertyValueBuilder(::flatbuffers::FlatBufferBuilder &_fbb) - : fbb_(_fbb) { - start_ = fbb_.StartTable(); - } - ::flatbuffers::Offset Finish() { - const auto end = fbb_.EndTable(start_); - auto o = ::flatbuffers::Offset(end); - return o; - } -}; - -inline ::flatbuffers::Offset CreatePropertyValue( - ::flatbuffers::FlatBufferBuilder &_fbb, - int64_t property_id = 0, - Ikarus::Value::Data data_type = Ikarus::Value::Data::NONE, - ::flatbuffers::Offset data = 0) { - PropertyValueBuilder builder_(_fbb); - builder_.add_property_id(property_id); - builder_.add_data(data); - builder_.add_data_type(data_type); - return builder_.Finish(); -} - -struct PropertyValue::Traits { - using type = PropertyValue; - static auto constexpr Create = CreatePropertyValue; -}; - -struct Entity FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table { - typedef EntityBuilder Builder; - struct Traits; - enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { - VT_ID = 4, - VT_NAME = 6, - VT_DESCRIPTION = 8, - VT_TAGS = 10, - VT_VALUES = 12, - VT_PROPERTY_VALUES = 14 - }; - int64_t id() const { - return GetField(VT_ID, 0); - } - const ::flatbuffers::String *name() const { - return GetPointer(VT_NAME); - } - const ::flatbuffers::String *description() const { - return GetPointer(VT_DESCRIPTION); - } - const ::flatbuffers::Vector<::flatbuffers::Offset<::flatbuffers::String>> *tags() const { - return GetPointer> *>(VT_TAGS); - } - const ::flatbuffers::Vector<::flatbuffers::Offset> *values() const { - return GetPointer> *>(VT_VALUES); - } - const ::flatbuffers::Vector<::flatbuffers::Offset> *property_values() const { - return GetPointer> *>(VT_PROPERTY_VALUES); - } - bool Verify(::flatbuffers::Verifier &verifier) const { - return VerifyTableStart(verifier) && - VerifyField(verifier, VT_ID, 8) && - VerifyOffset(verifier, VT_NAME) && - verifier.VerifyString(name()) && - VerifyOffset(verifier, VT_DESCRIPTION) && - verifier.VerifyString(description()) && - VerifyOffset(verifier, VT_TAGS) && - verifier.VerifyVector(tags()) && - verifier.VerifyVectorOfStrings(tags()) && - VerifyOffset(verifier, VT_VALUES) && - verifier.VerifyVector(values()) && - verifier.VerifyVectorOfTables(values()) && - VerifyOffset(verifier, VT_PROPERTY_VALUES) && - verifier.VerifyVector(property_values()) && - verifier.VerifyVectorOfTables(property_values()) && - verifier.EndTable(); - } -}; - -struct EntityBuilder { - typedef Entity Table; - ::flatbuffers::FlatBufferBuilder &fbb_; - ::flatbuffers::uoffset_t start_; - void add_id(int64_t id) { - fbb_.AddElement(Entity::VT_ID, id, 0); - } - void add_name(::flatbuffers::Offset<::flatbuffers::String> name) { - fbb_.AddOffset(Entity::VT_NAME, name); - } - void add_description(::flatbuffers::Offset<::flatbuffers::String> description) { - fbb_.AddOffset(Entity::VT_DESCRIPTION, description); - } - void add_tags(::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset<::flatbuffers::String>>> tags) { - fbb_.AddOffset(Entity::VT_TAGS, tags); - } - void add_values(::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset>> values) { - fbb_.AddOffset(Entity::VT_VALUES, values); - } - void add_property_values(::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset>> property_values) { - fbb_.AddOffset(Entity::VT_PROPERTY_VALUES, property_values); - } - explicit EntityBuilder(::flatbuffers::FlatBufferBuilder &_fbb) - : fbb_(_fbb) { - start_ = fbb_.StartTable(); - } - ::flatbuffers::Offset Finish() { - const auto end = fbb_.EndTable(start_); - auto o = ::flatbuffers::Offset(end); - return o; - } -}; - -inline ::flatbuffers::Offset CreateEntity( - ::flatbuffers::FlatBufferBuilder &_fbb, - int64_t id = 0, - ::flatbuffers::Offset<::flatbuffers::String> name = 0, - ::flatbuffers::Offset<::flatbuffers::String> description = 0, - ::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset<::flatbuffers::String>>> tags = 0, - ::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset>> values = 0, - ::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset>> property_values = 0) { - EntityBuilder builder_(_fbb); - builder_.add_id(id); - builder_.add_property_values(property_values); - builder_.add_values(values); - builder_.add_tags(tags); - builder_.add_description(description); - builder_.add_name(name); - return builder_.Finish(); -} - -struct Entity::Traits { - using type = Entity; - static auto constexpr Create = CreateEntity; -}; - -inline ::flatbuffers::Offset CreateEntityDirect( - ::flatbuffers::FlatBufferBuilder &_fbb, - int64_t id = 0, - const char *name = nullptr, - const char *description = nullptr, - const std::vector<::flatbuffers::Offset<::flatbuffers::String>> *tags = nullptr, - std::vector<::flatbuffers::Offset> *values = nullptr, - std::vector<::flatbuffers::Offset> *property_values = nullptr) { - auto name__ = name ? _fbb.CreateString(name) : 0; - auto description__ = description ? _fbb.CreateString(description) : 0; - auto tags__ = tags ? _fbb.CreateVector<::flatbuffers::Offset<::flatbuffers::String>>(*tags) : 0; - auto values__ = values ? _fbb.CreateVectorOfSortedTables(values) : 0; - auto property_values__ = property_values ? _fbb.CreateVectorOfSortedTables(property_values) : 0; - return Ikarus::CreateEntity( - _fbb, - id, - name__, - description__, - tags__, - values__, - property_values__); -} - -inline const Ikarus::Entity *GetEntity(const void *buf) { - return ::flatbuffers::GetRoot(buf); -} - -inline const Ikarus::Entity *GetSizePrefixedEntity(const void *buf) { - return ::flatbuffers::GetSizePrefixedRoot(buf); -} - -inline bool VerifyEntityBuffer( - ::flatbuffers::Verifier &verifier) { - return verifier.VerifyBuffer(nullptr); -} - -inline bool VerifySizePrefixedEntityBuffer( - ::flatbuffers::Verifier &verifier) { - return verifier.VerifySizePrefixedBuffer(nullptr); -} - -inline void FinishEntityBuffer( - ::flatbuffers::FlatBufferBuilder &fbb, - ::flatbuffers::Offset root) { - fbb.Finish(root); -} - -inline void FinishSizePrefixedEntityBuffer( - ::flatbuffers::FlatBufferBuilder &fbb, - ::flatbuffers::Offset root) { - fbb.FinishSizePrefixed(root); -} - -} // namespace Ikarus - -#endif // FLATBUFFERS_GENERATED_ENTITY_IKARUS_H_ diff --git a/include/ikarus/models/property.fbs b/include/ikarus/models/property.fbs deleted file mode 100644 index 8a96bb2..0000000 --- a/include/ikarus/models/property.fbs +++ /dev/null @@ -1,14 +0,0 @@ -include "value.fbs"; - -namespace Ikarus; - -table Property { - id: int64; - name: string; - description: string; - tags: [string]; - value_schema: Ikarus.Value.Schema; - default_value: Ikarus.Value.Data; -} - -root_type Property; diff --git a/include/ikarus/models/property_generated.h b/include/ikarus/models/property_generated.h deleted file mode 100644 index 1111bee..0000000 --- a/include/ikarus/models/property_generated.h +++ /dev/null @@ -1,289 +0,0 @@ -// automatically generated by the FlatBuffers compiler, do not modify - - -#ifndef FLATBUFFERS_GENERATED_PROPERTY_IKARUS_H_ -#define FLATBUFFERS_GENERATED_PROPERTY_IKARUS_H_ - -#include "flatbuffers/flatbuffers.h" - -// Ensure the included flatbuffers.h is the same version as when this file was -// generated, otherwise it may not be compatible. -static_assert(FLATBUFFERS_VERSION_MAJOR == 24 && - FLATBUFFERS_VERSION_MINOR == 3 && - FLATBUFFERS_VERSION_REVISION == 25, - "Non-compatible flatbuffers version included"); - -#include "value_generated.h" - -namespace Ikarus { - -struct Property; -struct PropertyBuilder; - -struct Property FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table { - typedef PropertyBuilder Builder; - struct Traits; - enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { - VT_ID = 4, - VT_NAME = 6, - VT_DESCRIPTION = 8, - VT_TAGS = 10, - VT_VALUE_SCHEMA_TYPE = 12, - VT_VALUE_SCHEMA = 14, - VT_DEFAULT_VALUE_TYPE = 16, - VT_DEFAULT_VALUE = 18 - }; - int64_t id() const { - return GetField(VT_ID, 0); - } - const ::flatbuffers::String *name() const { - return GetPointer(VT_NAME); - } - const ::flatbuffers::String *description() const { - return GetPointer(VT_DESCRIPTION); - } - const ::flatbuffers::Vector<::flatbuffers::Offset<::flatbuffers::String>> *tags() const { - return GetPointer> *>(VT_TAGS); - } - Ikarus::Value::Schema value_schema_type() const { - return static_cast(GetField(VT_VALUE_SCHEMA_TYPE, 0)); - } - const void *value_schema() const { - return GetPointer(VT_VALUE_SCHEMA); - } - template const T *value_schema_as() const; - const Ikarus::Value::ConstantSchema *value_schema_as_ConstantSchema() const { - return value_schema_type() == Ikarus::Value::Schema::ConstantSchema ? static_cast(value_schema()) : nullptr; - } - const Ikarus::Value::SimpleSchema *value_schema_as_SimpleSchema() const { - return value_schema_type() == Ikarus::Value::Schema::SimpleSchema ? static_cast(value_schema()) : nullptr; - } - const Ikarus::Value::CombinedSchema *value_schema_as_CombinedSchema() const { - return value_schema_type() == Ikarus::Value::Schema::CombinedSchema ? static_cast(value_schema()) : nullptr; - } - const Ikarus::Value::ListSchema *value_schema_as_ListSchema() const { - return value_schema_type() == Ikarus::Value::Schema::ListSchema ? static_cast(value_schema()) : nullptr; - } - const Ikarus::Value::ComplexSchema *value_schema_as_ComplexSchema() const { - return value_schema_type() == Ikarus::Value::Schema::ComplexSchema ? static_cast(value_schema()) : nullptr; - } - Ikarus::Value::Data default_value_type() const { - return static_cast(GetField(VT_DEFAULT_VALUE_TYPE, 0)); - } - const void *default_value() const { - return GetPointer(VT_DEFAULT_VALUE); - } - template const T *default_value_as() const; - const Ikarus::Value::ToggleDataPoint *default_value_as_ToggleDataPoint() const { - return default_value_type() == Ikarus::Value::Data::ToggleDataPoint ? static_cast(default_value()) : nullptr; - } - const Ikarus::Value::NumberDataPoint *default_value_as_NumberDataPoint() const { - return default_value_type() == Ikarus::Value::Data::NumberDataPoint ? static_cast(default_value()) : nullptr; - } - const Ikarus::Value::TextDataPoint *default_value_as_TextDataPoint() const { - return default_value_type() == Ikarus::Value::Data::TextDataPoint ? static_cast(default_value()) : nullptr; - } - const Ikarus::Value::SimpleData *default_value_as_SimpleData() const { - return default_value_type() == Ikarus::Value::Data::SimpleData ? static_cast(default_value()) : nullptr; - } - const Ikarus::Value::CombinedData *default_value_as_CombinedData() const { - return default_value_type() == Ikarus::Value::Data::CombinedData ? static_cast(default_value()) : nullptr; - } - const Ikarus::Value::ListData *default_value_as_ListData() const { - return default_value_type() == Ikarus::Value::Data::ListData ? static_cast(default_value()) : nullptr; - } - const Ikarus::Value::ComplexData *default_value_as_ComplexData() const { - return default_value_type() == Ikarus::Value::Data::ComplexData ? static_cast(default_value()) : nullptr; - } - bool Verify(::flatbuffers::Verifier &verifier) const { - return VerifyTableStart(verifier) && - VerifyField(verifier, VT_ID, 8) && - VerifyOffset(verifier, VT_NAME) && - verifier.VerifyString(name()) && - VerifyOffset(verifier, VT_DESCRIPTION) && - verifier.VerifyString(description()) && - VerifyOffset(verifier, VT_TAGS) && - verifier.VerifyVector(tags()) && - verifier.VerifyVectorOfStrings(tags()) && - VerifyField(verifier, VT_VALUE_SCHEMA_TYPE, 1) && - VerifyOffset(verifier, VT_VALUE_SCHEMA) && - VerifySchema(verifier, value_schema(), value_schema_type()) && - VerifyField(verifier, VT_DEFAULT_VALUE_TYPE, 1) && - VerifyOffset(verifier, VT_DEFAULT_VALUE) && - VerifyData(verifier, default_value(), default_value_type()) && - verifier.EndTable(); - } -}; - -template<> inline const Ikarus::Value::ConstantSchema *Property::value_schema_as() const { - return value_schema_as_ConstantSchema(); -} - -template<> inline const Ikarus::Value::SimpleSchema *Property::value_schema_as() const { - return value_schema_as_SimpleSchema(); -} - -template<> inline const Ikarus::Value::CombinedSchema *Property::value_schema_as() const { - return value_schema_as_CombinedSchema(); -} - -template<> inline const Ikarus::Value::ListSchema *Property::value_schema_as() const { - return value_schema_as_ListSchema(); -} - -template<> inline const Ikarus::Value::ComplexSchema *Property::value_schema_as() const { - return value_schema_as_ComplexSchema(); -} - -template<> inline const Ikarus::Value::ToggleDataPoint *Property::default_value_as() const { - return default_value_as_ToggleDataPoint(); -} - -template<> inline const Ikarus::Value::NumberDataPoint *Property::default_value_as() const { - return default_value_as_NumberDataPoint(); -} - -template<> inline const Ikarus::Value::TextDataPoint *Property::default_value_as() const { - return default_value_as_TextDataPoint(); -} - -template<> inline const Ikarus::Value::SimpleData *Property::default_value_as() const { - return default_value_as_SimpleData(); -} - -template<> inline const Ikarus::Value::CombinedData *Property::default_value_as() const { - return default_value_as_CombinedData(); -} - -template<> inline const Ikarus::Value::ListData *Property::default_value_as() const { - return default_value_as_ListData(); -} - -template<> inline const Ikarus::Value::ComplexData *Property::default_value_as() const { - return default_value_as_ComplexData(); -} - -struct PropertyBuilder { - typedef Property Table; - ::flatbuffers::FlatBufferBuilder &fbb_; - ::flatbuffers::uoffset_t start_; - void add_id(int64_t id) { - fbb_.AddElement(Property::VT_ID, id, 0); - } - void add_name(::flatbuffers::Offset<::flatbuffers::String> name) { - fbb_.AddOffset(Property::VT_NAME, name); - } - void add_description(::flatbuffers::Offset<::flatbuffers::String> description) { - fbb_.AddOffset(Property::VT_DESCRIPTION, description); - } - void add_tags(::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset<::flatbuffers::String>>> tags) { - fbb_.AddOffset(Property::VT_TAGS, tags); - } - void add_value_schema_type(Ikarus::Value::Schema value_schema_type) { - fbb_.AddElement(Property::VT_VALUE_SCHEMA_TYPE, static_cast(value_schema_type), 0); - } - void add_value_schema(::flatbuffers::Offset value_schema) { - fbb_.AddOffset(Property::VT_VALUE_SCHEMA, value_schema); - } - void add_default_value_type(Ikarus::Value::Data default_value_type) { - fbb_.AddElement(Property::VT_DEFAULT_VALUE_TYPE, static_cast(default_value_type), 0); - } - void add_default_value(::flatbuffers::Offset default_value) { - fbb_.AddOffset(Property::VT_DEFAULT_VALUE, default_value); - } - explicit PropertyBuilder(::flatbuffers::FlatBufferBuilder &_fbb) - : fbb_(_fbb) { - start_ = fbb_.StartTable(); - } - ::flatbuffers::Offset Finish() { - const auto end = fbb_.EndTable(start_); - auto o = ::flatbuffers::Offset(end); - return o; - } -}; - -inline ::flatbuffers::Offset CreateProperty( - ::flatbuffers::FlatBufferBuilder &_fbb, - int64_t id = 0, - ::flatbuffers::Offset<::flatbuffers::String> name = 0, - ::flatbuffers::Offset<::flatbuffers::String> description = 0, - ::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset<::flatbuffers::String>>> tags = 0, - Ikarus::Value::Schema value_schema_type = Ikarus::Value::Schema::NONE, - ::flatbuffers::Offset value_schema = 0, - Ikarus::Value::Data default_value_type = Ikarus::Value::Data::NONE, - ::flatbuffers::Offset default_value = 0) { - PropertyBuilder builder_(_fbb); - builder_.add_id(id); - builder_.add_default_value(default_value); - builder_.add_value_schema(value_schema); - builder_.add_tags(tags); - builder_.add_description(description); - builder_.add_name(name); - builder_.add_default_value_type(default_value_type); - builder_.add_value_schema_type(value_schema_type); - return builder_.Finish(); -} - -struct Property::Traits { - using type = Property; - static auto constexpr Create = CreateProperty; -}; - -inline ::flatbuffers::Offset CreatePropertyDirect( - ::flatbuffers::FlatBufferBuilder &_fbb, - int64_t id = 0, - const char *name = nullptr, - const char *description = nullptr, - const std::vector<::flatbuffers::Offset<::flatbuffers::String>> *tags = nullptr, - Ikarus::Value::Schema value_schema_type = Ikarus::Value::Schema::NONE, - ::flatbuffers::Offset value_schema = 0, - Ikarus::Value::Data default_value_type = Ikarus::Value::Data::NONE, - ::flatbuffers::Offset default_value = 0) { - auto name__ = name ? _fbb.CreateString(name) : 0; - auto description__ = description ? _fbb.CreateString(description) : 0; - auto tags__ = tags ? _fbb.CreateVector<::flatbuffers::Offset<::flatbuffers::String>>(*tags) : 0; - return Ikarus::CreateProperty( - _fbb, - id, - name__, - description__, - tags__, - value_schema_type, - value_schema, - default_value_type, - default_value); -} - -inline const Ikarus::Property *GetProperty(const void *buf) { - return ::flatbuffers::GetRoot(buf); -} - -inline const Ikarus::Property *GetSizePrefixedProperty(const void *buf) { - return ::flatbuffers::GetSizePrefixedRoot(buf); -} - -inline bool VerifyPropertyBuffer( - ::flatbuffers::Verifier &verifier) { - return verifier.VerifyBuffer(nullptr); -} - -inline bool VerifySizePrefixedPropertyBuffer( - ::flatbuffers::Verifier &verifier) { - return verifier.VerifySizePrefixedBuffer(nullptr); -} - -inline void FinishPropertyBuffer( - ::flatbuffers::FlatBufferBuilder &fbb, - ::flatbuffers::Offset root) { - fbb.Finish(root); -} - -inline void FinishSizePrefixedPropertyBuffer( - ::flatbuffers::FlatBufferBuilder &fbb, - ::flatbuffers::Offset root) { - fbb.FinishSizePrefixed(root); -} - -} // namespace Ikarus - -#endif // FLATBUFFERS_GENERATED_PROPERTY_IKARUS_H_ diff --git a/include/ikarus/models/value.fbs b/include/ikarus/models/value.fbs deleted file mode 100644 index 27a27e9..0000000 --- a/include/ikarus/models/value.fbs +++ /dev/null @@ -1,85 +0,0 @@ -namespace Ikarus.Value; - -table ToggleDataPoint { - data: [bool]; -} - -table NumberDataPoint { - data: [double]; -} - -table TextDataPoint { - data: [string]; -} - -union Data { - ToggleDataPoint, - NumberDataPoint, - TextDataPoint, - SimpleData, - CombinedData, - ListData, - ComplexData -} - -union Schema { - ConstantSchema, - SimpleSchema, - CombinedSchema, - ListSchema, - ComplexSchema -} - -table ConstantSchema { - sub_schema: Schema; - data: Data; -} - -table SimpleSchema { - sub_schema: Schema; -} - -table SimpleData { - data: Data; -} - -table CombinedSchema { - schemas: [Schema]; -} - -table CombinedData { - data: [Data]; -} - -table ListSchema { - schema: Schema; -} - -table ListData { - data: [Data]; -} - -table NamedSchema { - name: string; - schema: Schema; -} - -table ComplexSchema { - schemas: [NamedSchema]; -} - -table NamedData { - name: string; - data: Data; -} - -table ComplexData { - data: [NamedData]; -} - -table Value { - schema: Schema; - data: Data; -} - -root_type Value; diff --git a/include/ikarus/models/value_generated.h b/include/ikarus/models/value_generated.h deleted file mode 100644 index c9da9e3..0000000 --- a/include/ikarus/models/value_generated.h +++ /dev/null @@ -1,1719 +0,0 @@ -// automatically generated by the FlatBuffers compiler, do not modify - - -#ifndef FLATBUFFERS_GENERATED_VALUE_IKARUS_VALUE_H_ -#define FLATBUFFERS_GENERATED_VALUE_IKARUS_VALUE_H_ - -#include "flatbuffers/flatbuffers.h" - -// Ensure the included flatbuffers.h is the same version as when this file was -// generated, otherwise it may not be compatible. -static_assert(FLATBUFFERS_VERSION_MAJOR == 24 && - FLATBUFFERS_VERSION_MINOR == 3 && - FLATBUFFERS_VERSION_REVISION == 25, - "Non-compatible flatbuffers version included"); - -namespace Ikarus { -namespace Value { - -struct ToggleDataPoint; -struct ToggleDataPointBuilder; - -struct NumberDataPoint; -struct NumberDataPointBuilder; - -struct TextDataPoint; -struct TextDataPointBuilder; - -struct ConstantSchema; -struct ConstantSchemaBuilder; - -struct SimpleSchema; -struct SimpleSchemaBuilder; - -struct SimpleData; -struct SimpleDataBuilder; - -struct CombinedSchema; -struct CombinedSchemaBuilder; - -struct CombinedData; -struct CombinedDataBuilder; - -struct ListSchema; -struct ListSchemaBuilder; - -struct ListData; -struct ListDataBuilder; - -struct NamedSchema; -struct NamedSchemaBuilder; - -struct ComplexSchema; -struct ComplexSchemaBuilder; - -struct NamedData; -struct NamedDataBuilder; - -struct ComplexData; -struct ComplexDataBuilder; - -struct Value; -struct ValueBuilder; - -enum class Data : uint8_t { - NONE = 0, - ToggleDataPoint = 1, - NumberDataPoint = 2, - TextDataPoint = 3, - SimpleData = 4, - CombinedData = 5, - ListData = 6, - ComplexData = 7, - MIN = NONE, - MAX = ComplexData -}; - -inline const Data (&EnumValuesData())[8] { - static const Data values[] = { - Data::NONE, - Data::ToggleDataPoint, - Data::NumberDataPoint, - Data::TextDataPoint, - Data::SimpleData, - Data::CombinedData, - Data::ListData, - Data::ComplexData - }; - return values; -} - -inline const char * const *EnumNamesData() { - static const char * const names[9] = { - "NONE", - "ToggleDataPoint", - "NumberDataPoint", - "TextDataPoint", - "SimpleData", - "CombinedData", - "ListData", - "ComplexData", - nullptr - }; - return names; -} - -inline const char *EnumNameData(Data e) { - if (::flatbuffers::IsOutRange(e, Data::NONE, Data::ComplexData)) return ""; - const size_t index = static_cast(e); - return EnumNamesData()[index]; -} - -template struct DataTraits { - static const Data enum_value = Data::NONE; -}; - -template<> struct DataTraits { - static const Data enum_value = Data::ToggleDataPoint; -}; - -template<> struct DataTraits { - static const Data enum_value = Data::NumberDataPoint; -}; - -template<> struct DataTraits { - static const Data enum_value = Data::TextDataPoint; -}; - -template<> struct DataTraits { - static const Data enum_value = Data::SimpleData; -}; - -template<> struct DataTraits { - static const Data enum_value = Data::CombinedData; -}; - -template<> struct DataTraits { - static const Data enum_value = Data::ListData; -}; - -template<> struct DataTraits { - static const Data enum_value = Data::ComplexData; -}; - -bool VerifyData(::flatbuffers::Verifier &verifier, const void *obj, Data type); -bool VerifyDataVector(::flatbuffers::Verifier &verifier, const ::flatbuffers::Vector<::flatbuffers::Offset> *values, const ::flatbuffers::Vector *types); - -enum class Schema : uint8_t { - NONE = 0, - ConstantSchema = 1, - SimpleSchema = 2, - CombinedSchema = 3, - ListSchema = 4, - ComplexSchema = 5, - MIN = NONE, - MAX = ComplexSchema -}; - -inline const Schema (&EnumValuesSchema())[6] { - static const Schema values[] = { - Schema::NONE, - Schema::ConstantSchema, - Schema::SimpleSchema, - Schema::CombinedSchema, - Schema::ListSchema, - Schema::ComplexSchema - }; - return values; -} - -inline const char * const *EnumNamesSchema() { - static const char * const names[7] = { - "NONE", - "ConstantSchema", - "SimpleSchema", - "CombinedSchema", - "ListSchema", - "ComplexSchema", - nullptr - }; - return names; -} - -inline const char *EnumNameSchema(Schema e) { - if (::flatbuffers::IsOutRange(e, Schema::NONE, Schema::ComplexSchema)) return ""; - const size_t index = static_cast(e); - return EnumNamesSchema()[index]; -} - -template struct SchemaTraits { - static const Schema enum_value = Schema::NONE; -}; - -template<> struct SchemaTraits { - static const Schema enum_value = Schema::ConstantSchema; -}; - -template<> struct SchemaTraits { - static const Schema enum_value = Schema::SimpleSchema; -}; - -template<> struct SchemaTraits { - static const Schema enum_value = Schema::CombinedSchema; -}; - -template<> struct SchemaTraits { - static const Schema enum_value = Schema::ListSchema; -}; - -template<> struct SchemaTraits { - static const Schema enum_value = Schema::ComplexSchema; -}; - -bool VerifySchema(::flatbuffers::Verifier &verifier, const void *obj, Schema type); -bool VerifySchemaVector(::flatbuffers::Verifier &verifier, const ::flatbuffers::Vector<::flatbuffers::Offset> *values, const ::flatbuffers::Vector *types); - -struct ToggleDataPoint FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table { - typedef ToggleDataPointBuilder Builder; - struct Traits; - enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { - VT_DATA = 4 - }; - const ::flatbuffers::Vector *data() const { - return GetPointer *>(VT_DATA); - } - bool Verify(::flatbuffers::Verifier &verifier) const { - return VerifyTableStart(verifier) && - VerifyOffset(verifier, VT_DATA) && - verifier.VerifyVector(data()) && - verifier.EndTable(); - } -}; - -struct ToggleDataPointBuilder { - typedef ToggleDataPoint Table; - ::flatbuffers::FlatBufferBuilder &fbb_; - ::flatbuffers::uoffset_t start_; - void add_data(::flatbuffers::Offset<::flatbuffers::Vector> data) { - fbb_.AddOffset(ToggleDataPoint::VT_DATA, data); - } - explicit ToggleDataPointBuilder(::flatbuffers::FlatBufferBuilder &_fbb) - : fbb_(_fbb) { - start_ = fbb_.StartTable(); - } - ::flatbuffers::Offset Finish() { - const auto end = fbb_.EndTable(start_); - auto o = ::flatbuffers::Offset(end); - return o; - } -}; - -inline ::flatbuffers::Offset CreateToggleDataPoint( - ::flatbuffers::FlatBufferBuilder &_fbb, - ::flatbuffers::Offset<::flatbuffers::Vector> data = 0) { - ToggleDataPointBuilder builder_(_fbb); - builder_.add_data(data); - return builder_.Finish(); -} - -struct ToggleDataPoint::Traits { - using type = ToggleDataPoint; - static auto constexpr Create = CreateToggleDataPoint; -}; - -inline ::flatbuffers::Offset CreateToggleDataPointDirect( - ::flatbuffers::FlatBufferBuilder &_fbb, - const std::vector *data = nullptr) { - auto data__ = data ? _fbb.CreateVector(*data) : 0; - return Ikarus::Value::CreateToggleDataPoint( - _fbb, - data__); -} - -struct NumberDataPoint FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table { - typedef NumberDataPointBuilder Builder; - struct Traits; - enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { - VT_DATA = 4 - }; - const ::flatbuffers::Vector *data() const { - return GetPointer *>(VT_DATA); - } - bool Verify(::flatbuffers::Verifier &verifier) const { - return VerifyTableStart(verifier) && - VerifyOffset(verifier, VT_DATA) && - verifier.VerifyVector(data()) && - verifier.EndTable(); - } -}; - -struct NumberDataPointBuilder { - typedef NumberDataPoint Table; - ::flatbuffers::FlatBufferBuilder &fbb_; - ::flatbuffers::uoffset_t start_; - void add_data(::flatbuffers::Offset<::flatbuffers::Vector> data) { - fbb_.AddOffset(NumberDataPoint::VT_DATA, data); - } - explicit NumberDataPointBuilder(::flatbuffers::FlatBufferBuilder &_fbb) - : fbb_(_fbb) { - start_ = fbb_.StartTable(); - } - ::flatbuffers::Offset Finish() { - const auto end = fbb_.EndTable(start_); - auto o = ::flatbuffers::Offset(end); - return o; - } -}; - -inline ::flatbuffers::Offset CreateNumberDataPoint( - ::flatbuffers::FlatBufferBuilder &_fbb, - ::flatbuffers::Offset<::flatbuffers::Vector> data = 0) { - NumberDataPointBuilder builder_(_fbb); - builder_.add_data(data); - return builder_.Finish(); -} - -struct NumberDataPoint::Traits { - using type = NumberDataPoint; - static auto constexpr Create = CreateNumberDataPoint; -}; - -inline ::flatbuffers::Offset CreateNumberDataPointDirect( - ::flatbuffers::FlatBufferBuilder &_fbb, - const std::vector *data = nullptr) { - auto data__ = data ? _fbb.CreateVector(*data) : 0; - return Ikarus::Value::CreateNumberDataPoint( - _fbb, - data__); -} - -struct TextDataPoint FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table { - typedef TextDataPointBuilder Builder; - struct Traits; - enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { - VT_DATA = 4 - }; - const ::flatbuffers::Vector<::flatbuffers::Offset<::flatbuffers::String>> *data() const { - return GetPointer> *>(VT_DATA); - } - bool Verify(::flatbuffers::Verifier &verifier) const { - return VerifyTableStart(verifier) && - VerifyOffset(verifier, VT_DATA) && - verifier.VerifyVector(data()) && - verifier.VerifyVectorOfStrings(data()) && - verifier.EndTable(); - } -}; - -struct TextDataPointBuilder { - typedef TextDataPoint Table; - ::flatbuffers::FlatBufferBuilder &fbb_; - ::flatbuffers::uoffset_t start_; - void add_data(::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset<::flatbuffers::String>>> data) { - fbb_.AddOffset(TextDataPoint::VT_DATA, data); - } - explicit TextDataPointBuilder(::flatbuffers::FlatBufferBuilder &_fbb) - : fbb_(_fbb) { - start_ = fbb_.StartTable(); - } - ::flatbuffers::Offset Finish() { - const auto end = fbb_.EndTable(start_); - auto o = ::flatbuffers::Offset(end); - return o; - } -}; - -inline ::flatbuffers::Offset CreateTextDataPoint( - ::flatbuffers::FlatBufferBuilder &_fbb, - ::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset<::flatbuffers::String>>> data = 0) { - TextDataPointBuilder builder_(_fbb); - builder_.add_data(data); - return builder_.Finish(); -} - -struct TextDataPoint::Traits { - using type = TextDataPoint; - static auto constexpr Create = CreateTextDataPoint; -}; - -inline ::flatbuffers::Offset CreateTextDataPointDirect( - ::flatbuffers::FlatBufferBuilder &_fbb, - const std::vector<::flatbuffers::Offset<::flatbuffers::String>> *data = nullptr) { - auto data__ = data ? _fbb.CreateVector<::flatbuffers::Offset<::flatbuffers::String>>(*data) : 0; - return Ikarus::Value::CreateTextDataPoint( - _fbb, - data__); -} - -struct ConstantSchema FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table { - typedef ConstantSchemaBuilder Builder; - struct Traits; - enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { - VT_SUB_SCHEMA_TYPE = 4, - VT_SUB_SCHEMA = 6, - VT_DATA_TYPE = 8, - VT_DATA = 10 - }; - Ikarus::Value::Schema sub_schema_type() const { - return static_cast(GetField(VT_SUB_SCHEMA_TYPE, 0)); - } - const void *sub_schema() const { - return GetPointer(VT_SUB_SCHEMA); - } - template const T *sub_schema_as() const; - const Ikarus::Value::ConstantSchema *sub_schema_as_ConstantSchema() const { - return sub_schema_type() == Ikarus::Value::Schema::ConstantSchema ? static_cast(sub_schema()) : nullptr; - } - const Ikarus::Value::SimpleSchema *sub_schema_as_SimpleSchema() const { - return sub_schema_type() == Ikarus::Value::Schema::SimpleSchema ? static_cast(sub_schema()) : nullptr; - } - const Ikarus::Value::CombinedSchema *sub_schema_as_CombinedSchema() const { - return sub_schema_type() == Ikarus::Value::Schema::CombinedSchema ? static_cast(sub_schema()) : nullptr; - } - const Ikarus::Value::ListSchema *sub_schema_as_ListSchema() const { - return sub_schema_type() == Ikarus::Value::Schema::ListSchema ? static_cast(sub_schema()) : nullptr; - } - const Ikarus::Value::ComplexSchema *sub_schema_as_ComplexSchema() const { - return sub_schema_type() == Ikarus::Value::Schema::ComplexSchema ? static_cast(sub_schema()) : nullptr; - } - Ikarus::Value::Data data_type() const { - return static_cast(GetField(VT_DATA_TYPE, 0)); - } - const void *data() const { - return GetPointer(VT_DATA); - } - template const T *data_as() const; - const Ikarus::Value::ToggleDataPoint *data_as_ToggleDataPoint() const { - return data_type() == Ikarus::Value::Data::ToggleDataPoint ? static_cast(data()) : nullptr; - } - const Ikarus::Value::NumberDataPoint *data_as_NumberDataPoint() const { - return data_type() == Ikarus::Value::Data::NumberDataPoint ? static_cast(data()) : nullptr; - } - const Ikarus::Value::TextDataPoint *data_as_TextDataPoint() const { - return data_type() == Ikarus::Value::Data::TextDataPoint ? static_cast(data()) : nullptr; - } - const Ikarus::Value::SimpleData *data_as_SimpleData() const { - return data_type() == Ikarus::Value::Data::SimpleData ? static_cast(data()) : nullptr; - } - const Ikarus::Value::CombinedData *data_as_CombinedData() const { - return data_type() == Ikarus::Value::Data::CombinedData ? static_cast(data()) : nullptr; - } - const Ikarus::Value::ListData *data_as_ListData() const { - return data_type() == Ikarus::Value::Data::ListData ? static_cast(data()) : nullptr; - } - const Ikarus::Value::ComplexData *data_as_ComplexData() const { - return data_type() == Ikarus::Value::Data::ComplexData ? static_cast(data()) : nullptr; - } - bool Verify(::flatbuffers::Verifier &verifier) const { - return VerifyTableStart(verifier) && - VerifyField(verifier, VT_SUB_SCHEMA_TYPE, 1) && - VerifyOffset(verifier, VT_SUB_SCHEMA) && - VerifySchema(verifier, sub_schema(), sub_schema_type()) && - VerifyField(verifier, VT_DATA_TYPE, 1) && - VerifyOffset(verifier, VT_DATA) && - VerifyData(verifier, data(), data_type()) && - verifier.EndTable(); - } -}; - -template<> inline const Ikarus::Value::ConstantSchema *ConstantSchema::sub_schema_as() const { - return sub_schema_as_ConstantSchema(); -} - -template<> inline const Ikarus::Value::SimpleSchema *ConstantSchema::sub_schema_as() const { - return sub_schema_as_SimpleSchema(); -} - -template<> inline const Ikarus::Value::CombinedSchema *ConstantSchema::sub_schema_as() const { - return sub_schema_as_CombinedSchema(); -} - -template<> inline const Ikarus::Value::ListSchema *ConstantSchema::sub_schema_as() const { - return sub_schema_as_ListSchema(); -} - -template<> inline const Ikarus::Value::ComplexSchema *ConstantSchema::sub_schema_as() const { - return sub_schema_as_ComplexSchema(); -} - -template<> inline const Ikarus::Value::ToggleDataPoint *ConstantSchema::data_as() const { - return data_as_ToggleDataPoint(); -} - -template<> inline const Ikarus::Value::NumberDataPoint *ConstantSchema::data_as() const { - return data_as_NumberDataPoint(); -} - -template<> inline const Ikarus::Value::TextDataPoint *ConstantSchema::data_as() const { - return data_as_TextDataPoint(); -} - -template<> inline const Ikarus::Value::SimpleData *ConstantSchema::data_as() const { - return data_as_SimpleData(); -} - -template<> inline const Ikarus::Value::CombinedData *ConstantSchema::data_as() const { - return data_as_CombinedData(); -} - -template<> inline const Ikarus::Value::ListData *ConstantSchema::data_as() const { - return data_as_ListData(); -} - -template<> inline const Ikarus::Value::ComplexData *ConstantSchema::data_as() const { - return data_as_ComplexData(); -} - -struct ConstantSchemaBuilder { - typedef ConstantSchema Table; - ::flatbuffers::FlatBufferBuilder &fbb_; - ::flatbuffers::uoffset_t start_; - void add_sub_schema_type(Ikarus::Value::Schema sub_schema_type) { - fbb_.AddElement(ConstantSchema::VT_SUB_SCHEMA_TYPE, static_cast(sub_schema_type), 0); - } - void add_sub_schema(::flatbuffers::Offset sub_schema) { - fbb_.AddOffset(ConstantSchema::VT_SUB_SCHEMA, sub_schema); - } - void add_data_type(Ikarus::Value::Data data_type) { - fbb_.AddElement(ConstantSchema::VT_DATA_TYPE, static_cast(data_type), 0); - } - void add_data(::flatbuffers::Offset data) { - fbb_.AddOffset(ConstantSchema::VT_DATA, data); - } - explicit ConstantSchemaBuilder(::flatbuffers::FlatBufferBuilder &_fbb) - : fbb_(_fbb) { - start_ = fbb_.StartTable(); - } - ::flatbuffers::Offset Finish() { - const auto end = fbb_.EndTable(start_); - auto o = ::flatbuffers::Offset(end); - return o; - } -}; - -inline ::flatbuffers::Offset CreateConstantSchema( - ::flatbuffers::FlatBufferBuilder &_fbb, - Ikarus::Value::Schema sub_schema_type = Ikarus::Value::Schema::NONE, - ::flatbuffers::Offset sub_schema = 0, - Ikarus::Value::Data data_type = Ikarus::Value::Data::NONE, - ::flatbuffers::Offset data = 0) { - ConstantSchemaBuilder builder_(_fbb); - builder_.add_data(data); - builder_.add_sub_schema(sub_schema); - builder_.add_data_type(data_type); - builder_.add_sub_schema_type(sub_schema_type); - return builder_.Finish(); -} - -struct ConstantSchema::Traits { - using type = ConstantSchema; - static auto constexpr Create = CreateConstantSchema; -}; - -struct SimpleSchema FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table { - typedef SimpleSchemaBuilder Builder; - struct Traits; - enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { - VT_SUB_SCHEMA_TYPE = 4, - VT_SUB_SCHEMA = 6 - }; - Ikarus::Value::Schema sub_schema_type() const { - return static_cast(GetField(VT_SUB_SCHEMA_TYPE, 0)); - } - const void *sub_schema() const { - return GetPointer(VT_SUB_SCHEMA); - } - template const T *sub_schema_as() const; - const Ikarus::Value::ConstantSchema *sub_schema_as_ConstantSchema() const { - return sub_schema_type() == Ikarus::Value::Schema::ConstantSchema ? static_cast(sub_schema()) : nullptr; - } - const Ikarus::Value::SimpleSchema *sub_schema_as_SimpleSchema() const { - return sub_schema_type() == Ikarus::Value::Schema::SimpleSchema ? static_cast(sub_schema()) : nullptr; - } - const Ikarus::Value::CombinedSchema *sub_schema_as_CombinedSchema() const { - return sub_schema_type() == Ikarus::Value::Schema::CombinedSchema ? static_cast(sub_schema()) : nullptr; - } - const Ikarus::Value::ListSchema *sub_schema_as_ListSchema() const { - return sub_schema_type() == Ikarus::Value::Schema::ListSchema ? static_cast(sub_schema()) : nullptr; - } - const Ikarus::Value::ComplexSchema *sub_schema_as_ComplexSchema() const { - return sub_schema_type() == Ikarus::Value::Schema::ComplexSchema ? static_cast(sub_schema()) : nullptr; - } - bool Verify(::flatbuffers::Verifier &verifier) const { - return VerifyTableStart(verifier) && - VerifyField(verifier, VT_SUB_SCHEMA_TYPE, 1) && - VerifyOffset(verifier, VT_SUB_SCHEMA) && - VerifySchema(verifier, sub_schema(), sub_schema_type()) && - verifier.EndTable(); - } -}; - -template<> inline const Ikarus::Value::ConstantSchema *SimpleSchema::sub_schema_as() const { - return sub_schema_as_ConstantSchema(); -} - -template<> inline const Ikarus::Value::SimpleSchema *SimpleSchema::sub_schema_as() const { - return sub_schema_as_SimpleSchema(); -} - -template<> inline const Ikarus::Value::CombinedSchema *SimpleSchema::sub_schema_as() const { - return sub_schema_as_CombinedSchema(); -} - -template<> inline const Ikarus::Value::ListSchema *SimpleSchema::sub_schema_as() const { - return sub_schema_as_ListSchema(); -} - -template<> inline const Ikarus::Value::ComplexSchema *SimpleSchema::sub_schema_as() const { - return sub_schema_as_ComplexSchema(); -} - -struct SimpleSchemaBuilder { - typedef SimpleSchema Table; - ::flatbuffers::FlatBufferBuilder &fbb_; - ::flatbuffers::uoffset_t start_; - void add_sub_schema_type(Ikarus::Value::Schema sub_schema_type) { - fbb_.AddElement(SimpleSchema::VT_SUB_SCHEMA_TYPE, static_cast(sub_schema_type), 0); - } - void add_sub_schema(::flatbuffers::Offset sub_schema) { - fbb_.AddOffset(SimpleSchema::VT_SUB_SCHEMA, sub_schema); - } - explicit SimpleSchemaBuilder(::flatbuffers::FlatBufferBuilder &_fbb) - : fbb_(_fbb) { - start_ = fbb_.StartTable(); - } - ::flatbuffers::Offset Finish() { - const auto end = fbb_.EndTable(start_); - auto o = ::flatbuffers::Offset(end); - return o; - } -}; - -inline ::flatbuffers::Offset CreateSimpleSchema( - ::flatbuffers::FlatBufferBuilder &_fbb, - Ikarus::Value::Schema sub_schema_type = Ikarus::Value::Schema::NONE, - ::flatbuffers::Offset sub_schema = 0) { - SimpleSchemaBuilder builder_(_fbb); - builder_.add_sub_schema(sub_schema); - builder_.add_sub_schema_type(sub_schema_type); - return builder_.Finish(); -} - -struct SimpleSchema::Traits { - using type = SimpleSchema; - static auto constexpr Create = CreateSimpleSchema; -}; - -struct SimpleData FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table { - typedef SimpleDataBuilder Builder; - struct Traits; - enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { - VT_DATA_TYPE = 4, - VT_DATA = 6 - }; - Ikarus::Value::Data data_type() const { - return static_cast(GetField(VT_DATA_TYPE, 0)); - } - const void *data() const { - return GetPointer(VT_DATA); - } - template const T *data_as() const; - const Ikarus::Value::ToggleDataPoint *data_as_ToggleDataPoint() const { - return data_type() == Ikarus::Value::Data::ToggleDataPoint ? static_cast(data()) : nullptr; - } - const Ikarus::Value::NumberDataPoint *data_as_NumberDataPoint() const { - return data_type() == Ikarus::Value::Data::NumberDataPoint ? static_cast(data()) : nullptr; - } - const Ikarus::Value::TextDataPoint *data_as_TextDataPoint() const { - return data_type() == Ikarus::Value::Data::TextDataPoint ? static_cast(data()) : nullptr; - } - const Ikarus::Value::SimpleData *data_as_SimpleData() const { - return data_type() == Ikarus::Value::Data::SimpleData ? static_cast(data()) : nullptr; - } - const Ikarus::Value::CombinedData *data_as_CombinedData() const { - return data_type() == Ikarus::Value::Data::CombinedData ? static_cast(data()) : nullptr; - } - const Ikarus::Value::ListData *data_as_ListData() const { - return data_type() == Ikarus::Value::Data::ListData ? static_cast(data()) : nullptr; - } - const Ikarus::Value::ComplexData *data_as_ComplexData() const { - return data_type() == Ikarus::Value::Data::ComplexData ? static_cast(data()) : nullptr; - } - bool Verify(::flatbuffers::Verifier &verifier) const { - return VerifyTableStart(verifier) && - VerifyField(verifier, VT_DATA_TYPE, 1) && - VerifyOffset(verifier, VT_DATA) && - VerifyData(verifier, data(), data_type()) && - verifier.EndTable(); - } -}; - -template<> inline const Ikarus::Value::ToggleDataPoint *SimpleData::data_as() const { - return data_as_ToggleDataPoint(); -} - -template<> inline const Ikarus::Value::NumberDataPoint *SimpleData::data_as() const { - return data_as_NumberDataPoint(); -} - -template<> inline const Ikarus::Value::TextDataPoint *SimpleData::data_as() const { - return data_as_TextDataPoint(); -} - -template<> inline const Ikarus::Value::SimpleData *SimpleData::data_as() const { - return data_as_SimpleData(); -} - -template<> inline const Ikarus::Value::CombinedData *SimpleData::data_as() const { - return data_as_CombinedData(); -} - -template<> inline const Ikarus::Value::ListData *SimpleData::data_as() const { - return data_as_ListData(); -} - -template<> inline const Ikarus::Value::ComplexData *SimpleData::data_as() const { - return data_as_ComplexData(); -} - -struct SimpleDataBuilder { - typedef SimpleData Table; - ::flatbuffers::FlatBufferBuilder &fbb_; - ::flatbuffers::uoffset_t start_; - void add_data_type(Ikarus::Value::Data data_type) { - fbb_.AddElement(SimpleData::VT_DATA_TYPE, static_cast(data_type), 0); - } - void add_data(::flatbuffers::Offset data) { - fbb_.AddOffset(SimpleData::VT_DATA, data); - } - explicit SimpleDataBuilder(::flatbuffers::FlatBufferBuilder &_fbb) - : fbb_(_fbb) { - start_ = fbb_.StartTable(); - } - ::flatbuffers::Offset Finish() { - const auto end = fbb_.EndTable(start_); - auto o = ::flatbuffers::Offset(end); - return o; - } -}; - -inline ::flatbuffers::Offset CreateSimpleData( - ::flatbuffers::FlatBufferBuilder &_fbb, - Ikarus::Value::Data data_type = Ikarus::Value::Data::NONE, - ::flatbuffers::Offset data = 0) { - SimpleDataBuilder builder_(_fbb); - builder_.add_data(data); - builder_.add_data_type(data_type); - return builder_.Finish(); -} - -struct SimpleData::Traits { - using type = SimpleData; - static auto constexpr Create = CreateSimpleData; -}; - -struct CombinedSchema FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table { - typedef CombinedSchemaBuilder Builder; - struct Traits; - enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { - VT_SCHEMAS_TYPE = 4, - VT_SCHEMAS = 6 - }; - const ::flatbuffers::Vector *schemas_type() const { - return GetPointer *>(VT_SCHEMAS_TYPE); - } - const ::flatbuffers::Vector<::flatbuffers::Offset> *schemas() const { - return GetPointer> *>(VT_SCHEMAS); - } - bool Verify(::flatbuffers::Verifier &verifier) const { - return VerifyTableStart(verifier) && - VerifyOffset(verifier, VT_SCHEMAS_TYPE) && - verifier.VerifyVector(schemas_type()) && - VerifyOffset(verifier, VT_SCHEMAS) && - verifier.VerifyVector(schemas()) && - VerifySchemaVector(verifier, schemas(), schemas_type()) && - verifier.EndTable(); - } -}; - -struct CombinedSchemaBuilder { - typedef CombinedSchema Table; - ::flatbuffers::FlatBufferBuilder &fbb_; - ::flatbuffers::uoffset_t start_; - void add_schemas_type(::flatbuffers::Offset<::flatbuffers::Vector> schemas_type) { - fbb_.AddOffset(CombinedSchema::VT_SCHEMAS_TYPE, schemas_type); - } - void add_schemas(::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset>> schemas) { - fbb_.AddOffset(CombinedSchema::VT_SCHEMAS, schemas); - } - explicit CombinedSchemaBuilder(::flatbuffers::FlatBufferBuilder &_fbb) - : fbb_(_fbb) { - start_ = fbb_.StartTable(); - } - ::flatbuffers::Offset Finish() { - const auto end = fbb_.EndTable(start_); - auto o = ::flatbuffers::Offset(end); - return o; - } -}; - -inline ::flatbuffers::Offset CreateCombinedSchema( - ::flatbuffers::FlatBufferBuilder &_fbb, - ::flatbuffers::Offset<::flatbuffers::Vector> schemas_type = 0, - ::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset>> schemas = 0) { - CombinedSchemaBuilder builder_(_fbb); - builder_.add_schemas(schemas); - builder_.add_schemas_type(schemas_type); - return builder_.Finish(); -} - -struct CombinedSchema::Traits { - using type = CombinedSchema; - static auto constexpr Create = CreateCombinedSchema; -}; - -inline ::flatbuffers::Offset CreateCombinedSchemaDirect( - ::flatbuffers::FlatBufferBuilder &_fbb, - const std::vector *schemas_type = nullptr, - const std::vector<::flatbuffers::Offset> *schemas = nullptr) { - auto schemas_type__ = schemas_type ? _fbb.CreateVector(*schemas_type) : 0; - auto schemas__ = schemas ? _fbb.CreateVector<::flatbuffers::Offset>(*schemas) : 0; - return Ikarus::Value::CreateCombinedSchema( - _fbb, - schemas_type__, - schemas__); -} - -struct CombinedData FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table { - typedef CombinedDataBuilder Builder; - struct Traits; - enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { - VT_DATA_TYPE = 4, - VT_DATA = 6 - }; - const ::flatbuffers::Vector *data_type() const { - return GetPointer *>(VT_DATA_TYPE); - } - const ::flatbuffers::Vector<::flatbuffers::Offset> *data() const { - return GetPointer> *>(VT_DATA); - } - bool Verify(::flatbuffers::Verifier &verifier) const { - return VerifyTableStart(verifier) && - VerifyOffset(verifier, VT_DATA_TYPE) && - verifier.VerifyVector(data_type()) && - VerifyOffset(verifier, VT_DATA) && - verifier.VerifyVector(data()) && - VerifyDataVector(verifier, data(), data_type()) && - verifier.EndTable(); - } -}; - -struct CombinedDataBuilder { - typedef CombinedData Table; - ::flatbuffers::FlatBufferBuilder &fbb_; - ::flatbuffers::uoffset_t start_; - void add_data_type(::flatbuffers::Offset<::flatbuffers::Vector> data_type) { - fbb_.AddOffset(CombinedData::VT_DATA_TYPE, data_type); - } - void add_data(::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset>> data) { - fbb_.AddOffset(CombinedData::VT_DATA, data); - } - explicit CombinedDataBuilder(::flatbuffers::FlatBufferBuilder &_fbb) - : fbb_(_fbb) { - start_ = fbb_.StartTable(); - } - ::flatbuffers::Offset Finish() { - const auto end = fbb_.EndTable(start_); - auto o = ::flatbuffers::Offset(end); - return o; - } -}; - -inline ::flatbuffers::Offset CreateCombinedData( - ::flatbuffers::FlatBufferBuilder &_fbb, - ::flatbuffers::Offset<::flatbuffers::Vector> data_type = 0, - ::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset>> data = 0) { - CombinedDataBuilder builder_(_fbb); - builder_.add_data(data); - builder_.add_data_type(data_type); - return builder_.Finish(); -} - -struct CombinedData::Traits { - using type = CombinedData; - static auto constexpr Create = CreateCombinedData; -}; - -inline ::flatbuffers::Offset CreateCombinedDataDirect( - ::flatbuffers::FlatBufferBuilder &_fbb, - const std::vector *data_type = nullptr, - const std::vector<::flatbuffers::Offset> *data = nullptr) { - auto data_type__ = data_type ? _fbb.CreateVector(*data_type) : 0; - auto data__ = data ? _fbb.CreateVector<::flatbuffers::Offset>(*data) : 0; - return Ikarus::Value::CreateCombinedData( - _fbb, - data_type__, - data__); -} - -struct ListSchema FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table { - typedef ListSchemaBuilder Builder; - struct Traits; - enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { - VT_SCHEMA_TYPE = 4, - VT_SCHEMA = 6 - }; - Ikarus::Value::Schema schema_type() const { - return static_cast(GetField(VT_SCHEMA_TYPE, 0)); - } - const void *schema() const { - return GetPointer(VT_SCHEMA); - } - template const T *schema_as() const; - const Ikarus::Value::ConstantSchema *schema_as_ConstantSchema() const { - return schema_type() == Ikarus::Value::Schema::ConstantSchema ? static_cast(schema()) : nullptr; - } - const Ikarus::Value::SimpleSchema *schema_as_SimpleSchema() const { - return schema_type() == Ikarus::Value::Schema::SimpleSchema ? static_cast(schema()) : nullptr; - } - const Ikarus::Value::CombinedSchema *schema_as_CombinedSchema() const { - return schema_type() == Ikarus::Value::Schema::CombinedSchema ? static_cast(schema()) : nullptr; - } - const Ikarus::Value::ListSchema *schema_as_ListSchema() const { - return schema_type() == Ikarus::Value::Schema::ListSchema ? static_cast(schema()) : nullptr; - } - const Ikarus::Value::ComplexSchema *schema_as_ComplexSchema() const { - return schema_type() == Ikarus::Value::Schema::ComplexSchema ? static_cast(schema()) : nullptr; - } - bool Verify(::flatbuffers::Verifier &verifier) const { - return VerifyTableStart(verifier) && - VerifyField(verifier, VT_SCHEMA_TYPE, 1) && - VerifyOffset(verifier, VT_SCHEMA) && - VerifySchema(verifier, schema(), schema_type()) && - verifier.EndTable(); - } -}; - -template<> inline const Ikarus::Value::ConstantSchema *ListSchema::schema_as() const { - return schema_as_ConstantSchema(); -} - -template<> inline const Ikarus::Value::SimpleSchema *ListSchema::schema_as() const { - return schema_as_SimpleSchema(); -} - -template<> inline const Ikarus::Value::CombinedSchema *ListSchema::schema_as() const { - return schema_as_CombinedSchema(); -} - -template<> inline const Ikarus::Value::ListSchema *ListSchema::schema_as() const { - return schema_as_ListSchema(); -} - -template<> inline const Ikarus::Value::ComplexSchema *ListSchema::schema_as() const { - return schema_as_ComplexSchema(); -} - -struct ListSchemaBuilder { - typedef ListSchema Table; - ::flatbuffers::FlatBufferBuilder &fbb_; - ::flatbuffers::uoffset_t start_; - void add_schema_type(Ikarus::Value::Schema schema_type) { - fbb_.AddElement(ListSchema::VT_SCHEMA_TYPE, static_cast(schema_type), 0); - } - void add_schema(::flatbuffers::Offset schema) { - fbb_.AddOffset(ListSchema::VT_SCHEMA, schema); - } - explicit ListSchemaBuilder(::flatbuffers::FlatBufferBuilder &_fbb) - : fbb_(_fbb) { - start_ = fbb_.StartTable(); - } - ::flatbuffers::Offset Finish() { - const auto end = fbb_.EndTable(start_); - auto o = ::flatbuffers::Offset(end); - return o; - } -}; - -inline ::flatbuffers::Offset CreateListSchema( - ::flatbuffers::FlatBufferBuilder &_fbb, - Ikarus::Value::Schema schema_type = Ikarus::Value::Schema::NONE, - ::flatbuffers::Offset schema = 0) { - ListSchemaBuilder builder_(_fbb); - builder_.add_schema(schema); - builder_.add_schema_type(schema_type); - return builder_.Finish(); -} - -struct ListSchema::Traits { - using type = ListSchema; - static auto constexpr Create = CreateListSchema; -}; - -struct ListData FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table { - typedef ListDataBuilder Builder; - struct Traits; - enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { - VT_DATA_TYPE = 4, - VT_DATA = 6 - }; - const ::flatbuffers::Vector *data_type() const { - return GetPointer *>(VT_DATA_TYPE); - } - const ::flatbuffers::Vector<::flatbuffers::Offset> *data() const { - return GetPointer> *>(VT_DATA); - } - bool Verify(::flatbuffers::Verifier &verifier) const { - return VerifyTableStart(verifier) && - VerifyOffset(verifier, VT_DATA_TYPE) && - verifier.VerifyVector(data_type()) && - VerifyOffset(verifier, VT_DATA) && - verifier.VerifyVector(data()) && - VerifyDataVector(verifier, data(), data_type()) && - verifier.EndTable(); - } -}; - -struct ListDataBuilder { - typedef ListData Table; - ::flatbuffers::FlatBufferBuilder &fbb_; - ::flatbuffers::uoffset_t start_; - void add_data_type(::flatbuffers::Offset<::flatbuffers::Vector> data_type) { - fbb_.AddOffset(ListData::VT_DATA_TYPE, data_type); - } - void add_data(::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset>> data) { - fbb_.AddOffset(ListData::VT_DATA, data); - } - explicit ListDataBuilder(::flatbuffers::FlatBufferBuilder &_fbb) - : fbb_(_fbb) { - start_ = fbb_.StartTable(); - } - ::flatbuffers::Offset Finish() { - const auto end = fbb_.EndTable(start_); - auto o = ::flatbuffers::Offset(end); - return o; - } -}; - -inline ::flatbuffers::Offset CreateListData( - ::flatbuffers::FlatBufferBuilder &_fbb, - ::flatbuffers::Offset<::flatbuffers::Vector> data_type = 0, - ::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset>> data = 0) { - ListDataBuilder builder_(_fbb); - builder_.add_data(data); - builder_.add_data_type(data_type); - return builder_.Finish(); -} - -struct ListData::Traits { - using type = ListData; - static auto constexpr Create = CreateListData; -}; - -inline ::flatbuffers::Offset CreateListDataDirect( - ::flatbuffers::FlatBufferBuilder &_fbb, - const std::vector *data_type = nullptr, - const std::vector<::flatbuffers::Offset> *data = nullptr) { - auto data_type__ = data_type ? _fbb.CreateVector(*data_type) : 0; - auto data__ = data ? _fbb.CreateVector<::flatbuffers::Offset>(*data) : 0; - return Ikarus::Value::CreateListData( - _fbb, - data_type__, - data__); -} - -struct NamedSchema FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table { - typedef NamedSchemaBuilder Builder; - struct Traits; - enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { - VT_NAME = 4, - VT_SCHEMA_TYPE = 6, - VT_SCHEMA = 8 - }; - const ::flatbuffers::String *name() const { - return GetPointer(VT_NAME); - } - Ikarus::Value::Schema schema_type() const { - return static_cast(GetField(VT_SCHEMA_TYPE, 0)); - } - const void *schema() const { - return GetPointer(VT_SCHEMA); - } - template const T *schema_as() const; - const Ikarus::Value::ConstantSchema *schema_as_ConstantSchema() const { - return schema_type() == Ikarus::Value::Schema::ConstantSchema ? static_cast(schema()) : nullptr; - } - const Ikarus::Value::SimpleSchema *schema_as_SimpleSchema() const { - return schema_type() == Ikarus::Value::Schema::SimpleSchema ? static_cast(schema()) : nullptr; - } - const Ikarus::Value::CombinedSchema *schema_as_CombinedSchema() const { - return schema_type() == Ikarus::Value::Schema::CombinedSchema ? static_cast(schema()) : nullptr; - } - const Ikarus::Value::ListSchema *schema_as_ListSchema() const { - return schema_type() == Ikarus::Value::Schema::ListSchema ? static_cast(schema()) : nullptr; - } - const Ikarus::Value::ComplexSchema *schema_as_ComplexSchema() const { - return schema_type() == Ikarus::Value::Schema::ComplexSchema ? static_cast(schema()) : nullptr; - } - bool Verify(::flatbuffers::Verifier &verifier) const { - return VerifyTableStart(verifier) && - VerifyOffset(verifier, VT_NAME) && - verifier.VerifyString(name()) && - VerifyField(verifier, VT_SCHEMA_TYPE, 1) && - VerifyOffset(verifier, VT_SCHEMA) && - VerifySchema(verifier, schema(), schema_type()) && - verifier.EndTable(); - } -}; - -template<> inline const Ikarus::Value::ConstantSchema *NamedSchema::schema_as() const { - return schema_as_ConstantSchema(); -} - -template<> inline const Ikarus::Value::SimpleSchema *NamedSchema::schema_as() const { - return schema_as_SimpleSchema(); -} - -template<> inline const Ikarus::Value::CombinedSchema *NamedSchema::schema_as() const { - return schema_as_CombinedSchema(); -} - -template<> inline const Ikarus::Value::ListSchema *NamedSchema::schema_as() const { - return schema_as_ListSchema(); -} - -template<> inline const Ikarus::Value::ComplexSchema *NamedSchema::schema_as() const { - return schema_as_ComplexSchema(); -} - -struct NamedSchemaBuilder { - typedef NamedSchema Table; - ::flatbuffers::FlatBufferBuilder &fbb_; - ::flatbuffers::uoffset_t start_; - void add_name(::flatbuffers::Offset<::flatbuffers::String> name) { - fbb_.AddOffset(NamedSchema::VT_NAME, name); - } - void add_schema_type(Ikarus::Value::Schema schema_type) { - fbb_.AddElement(NamedSchema::VT_SCHEMA_TYPE, static_cast(schema_type), 0); - } - void add_schema(::flatbuffers::Offset schema) { - fbb_.AddOffset(NamedSchema::VT_SCHEMA, schema); - } - explicit NamedSchemaBuilder(::flatbuffers::FlatBufferBuilder &_fbb) - : fbb_(_fbb) { - start_ = fbb_.StartTable(); - } - ::flatbuffers::Offset Finish() { - const auto end = fbb_.EndTable(start_); - auto o = ::flatbuffers::Offset(end); - return o; - } -}; - -inline ::flatbuffers::Offset CreateNamedSchema( - ::flatbuffers::FlatBufferBuilder &_fbb, - ::flatbuffers::Offset<::flatbuffers::String> name = 0, - Ikarus::Value::Schema schema_type = Ikarus::Value::Schema::NONE, - ::flatbuffers::Offset schema = 0) { - NamedSchemaBuilder builder_(_fbb); - builder_.add_schema(schema); - builder_.add_name(name); - builder_.add_schema_type(schema_type); - return builder_.Finish(); -} - -struct NamedSchema::Traits { - using type = NamedSchema; - static auto constexpr Create = CreateNamedSchema; -}; - -inline ::flatbuffers::Offset CreateNamedSchemaDirect( - ::flatbuffers::FlatBufferBuilder &_fbb, - const char *name = nullptr, - Ikarus::Value::Schema schema_type = Ikarus::Value::Schema::NONE, - ::flatbuffers::Offset schema = 0) { - auto name__ = name ? _fbb.CreateString(name) : 0; - return Ikarus::Value::CreateNamedSchema( - _fbb, - name__, - schema_type, - schema); -} - -struct ComplexSchema FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table { - typedef ComplexSchemaBuilder Builder; - struct Traits; - enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { - VT_SCHEMAS = 4 - }; - const ::flatbuffers::Vector<::flatbuffers::Offset> *schemas() const { - return GetPointer> *>(VT_SCHEMAS); - } - bool Verify(::flatbuffers::Verifier &verifier) const { - return VerifyTableStart(verifier) && - VerifyOffset(verifier, VT_SCHEMAS) && - verifier.VerifyVector(schemas()) && - verifier.VerifyVectorOfTables(schemas()) && - verifier.EndTable(); - } -}; - -struct ComplexSchemaBuilder { - typedef ComplexSchema Table; - ::flatbuffers::FlatBufferBuilder &fbb_; - ::flatbuffers::uoffset_t start_; - void add_schemas(::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset>> schemas) { - fbb_.AddOffset(ComplexSchema::VT_SCHEMAS, schemas); - } - explicit ComplexSchemaBuilder(::flatbuffers::FlatBufferBuilder &_fbb) - : fbb_(_fbb) { - start_ = fbb_.StartTable(); - } - ::flatbuffers::Offset Finish() { - const auto end = fbb_.EndTable(start_); - auto o = ::flatbuffers::Offset(end); - return o; - } -}; - -inline ::flatbuffers::Offset CreateComplexSchema( - ::flatbuffers::FlatBufferBuilder &_fbb, - ::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset>> schemas = 0) { - ComplexSchemaBuilder builder_(_fbb); - builder_.add_schemas(schemas); - return builder_.Finish(); -} - -struct ComplexSchema::Traits { - using type = ComplexSchema; - static auto constexpr Create = CreateComplexSchema; -}; - -inline ::flatbuffers::Offset CreateComplexSchemaDirect( - ::flatbuffers::FlatBufferBuilder &_fbb, - const std::vector<::flatbuffers::Offset> *schemas = nullptr) { - auto schemas__ = schemas ? _fbb.CreateVector<::flatbuffers::Offset>(*schemas) : 0; - return Ikarus::Value::CreateComplexSchema( - _fbb, - schemas__); -} - -struct NamedData FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table { - typedef NamedDataBuilder Builder; - struct Traits; - enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { - VT_NAME = 4, - VT_DATA_TYPE = 6, - VT_DATA = 8 - }; - const ::flatbuffers::String *name() const { - return GetPointer(VT_NAME); - } - Ikarus::Value::Data data_type() const { - return static_cast(GetField(VT_DATA_TYPE, 0)); - } - const void *data() const { - return GetPointer(VT_DATA); - } - template const T *data_as() const; - const Ikarus::Value::ToggleDataPoint *data_as_ToggleDataPoint() const { - return data_type() == Ikarus::Value::Data::ToggleDataPoint ? static_cast(data()) : nullptr; - } - const Ikarus::Value::NumberDataPoint *data_as_NumberDataPoint() const { - return data_type() == Ikarus::Value::Data::NumberDataPoint ? static_cast(data()) : nullptr; - } - const Ikarus::Value::TextDataPoint *data_as_TextDataPoint() const { - return data_type() == Ikarus::Value::Data::TextDataPoint ? static_cast(data()) : nullptr; - } - const Ikarus::Value::SimpleData *data_as_SimpleData() const { - return data_type() == Ikarus::Value::Data::SimpleData ? static_cast(data()) : nullptr; - } - const Ikarus::Value::CombinedData *data_as_CombinedData() const { - return data_type() == Ikarus::Value::Data::CombinedData ? static_cast(data()) : nullptr; - } - const Ikarus::Value::ListData *data_as_ListData() const { - return data_type() == Ikarus::Value::Data::ListData ? static_cast(data()) : nullptr; - } - const Ikarus::Value::ComplexData *data_as_ComplexData() const { - return data_type() == Ikarus::Value::Data::ComplexData ? static_cast(data()) : nullptr; - } - bool Verify(::flatbuffers::Verifier &verifier) const { - return VerifyTableStart(verifier) && - VerifyOffset(verifier, VT_NAME) && - verifier.VerifyString(name()) && - VerifyField(verifier, VT_DATA_TYPE, 1) && - VerifyOffset(verifier, VT_DATA) && - VerifyData(verifier, data(), data_type()) && - verifier.EndTable(); - } -}; - -template<> inline const Ikarus::Value::ToggleDataPoint *NamedData::data_as() const { - return data_as_ToggleDataPoint(); -} - -template<> inline const Ikarus::Value::NumberDataPoint *NamedData::data_as() const { - return data_as_NumberDataPoint(); -} - -template<> inline const Ikarus::Value::TextDataPoint *NamedData::data_as() const { - return data_as_TextDataPoint(); -} - -template<> inline const Ikarus::Value::SimpleData *NamedData::data_as() const { - return data_as_SimpleData(); -} - -template<> inline const Ikarus::Value::CombinedData *NamedData::data_as() const { - return data_as_CombinedData(); -} - -template<> inline const Ikarus::Value::ListData *NamedData::data_as() const { - return data_as_ListData(); -} - -template<> inline const Ikarus::Value::ComplexData *NamedData::data_as() const { - return data_as_ComplexData(); -} - -struct NamedDataBuilder { - typedef NamedData Table; - ::flatbuffers::FlatBufferBuilder &fbb_; - ::flatbuffers::uoffset_t start_; - void add_name(::flatbuffers::Offset<::flatbuffers::String> name) { - fbb_.AddOffset(NamedData::VT_NAME, name); - } - void add_data_type(Ikarus::Value::Data data_type) { - fbb_.AddElement(NamedData::VT_DATA_TYPE, static_cast(data_type), 0); - } - void add_data(::flatbuffers::Offset data) { - fbb_.AddOffset(NamedData::VT_DATA, data); - } - explicit NamedDataBuilder(::flatbuffers::FlatBufferBuilder &_fbb) - : fbb_(_fbb) { - start_ = fbb_.StartTable(); - } - ::flatbuffers::Offset Finish() { - const auto end = fbb_.EndTable(start_); - auto o = ::flatbuffers::Offset(end); - return o; - } -}; - -inline ::flatbuffers::Offset CreateNamedData( - ::flatbuffers::FlatBufferBuilder &_fbb, - ::flatbuffers::Offset<::flatbuffers::String> name = 0, - Ikarus::Value::Data data_type = Ikarus::Value::Data::NONE, - ::flatbuffers::Offset data = 0) { - NamedDataBuilder builder_(_fbb); - builder_.add_data(data); - builder_.add_name(name); - builder_.add_data_type(data_type); - return builder_.Finish(); -} - -struct NamedData::Traits { - using type = NamedData; - static auto constexpr Create = CreateNamedData; -}; - -inline ::flatbuffers::Offset CreateNamedDataDirect( - ::flatbuffers::FlatBufferBuilder &_fbb, - const char *name = nullptr, - Ikarus::Value::Data data_type = Ikarus::Value::Data::NONE, - ::flatbuffers::Offset data = 0) { - auto name__ = name ? _fbb.CreateString(name) : 0; - return Ikarus::Value::CreateNamedData( - _fbb, - name__, - data_type, - data); -} - -struct ComplexData FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table { - typedef ComplexDataBuilder Builder; - struct Traits; - enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { - VT_DATA = 4 - }; - const ::flatbuffers::Vector<::flatbuffers::Offset> *data() const { - return GetPointer> *>(VT_DATA); - } - bool Verify(::flatbuffers::Verifier &verifier) const { - return VerifyTableStart(verifier) && - VerifyOffset(verifier, VT_DATA) && - verifier.VerifyVector(data()) && - verifier.VerifyVectorOfTables(data()) && - verifier.EndTable(); - } -}; - -struct ComplexDataBuilder { - typedef ComplexData Table; - ::flatbuffers::FlatBufferBuilder &fbb_; - ::flatbuffers::uoffset_t start_; - void add_data(::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset>> data) { - fbb_.AddOffset(ComplexData::VT_DATA, data); - } - explicit ComplexDataBuilder(::flatbuffers::FlatBufferBuilder &_fbb) - : fbb_(_fbb) { - start_ = fbb_.StartTable(); - } - ::flatbuffers::Offset Finish() { - const auto end = fbb_.EndTable(start_); - auto o = ::flatbuffers::Offset(end); - return o; - } -}; - -inline ::flatbuffers::Offset CreateComplexData( - ::flatbuffers::FlatBufferBuilder &_fbb, - ::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset>> data = 0) { - ComplexDataBuilder builder_(_fbb); - builder_.add_data(data); - return builder_.Finish(); -} - -struct ComplexData::Traits { - using type = ComplexData; - static auto constexpr Create = CreateComplexData; -}; - -inline ::flatbuffers::Offset CreateComplexDataDirect( - ::flatbuffers::FlatBufferBuilder &_fbb, - const std::vector<::flatbuffers::Offset> *data = nullptr) { - auto data__ = data ? _fbb.CreateVector<::flatbuffers::Offset>(*data) : 0; - return Ikarus::Value::CreateComplexData( - _fbb, - data__); -} - -struct Value FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table { - typedef ValueBuilder Builder; - struct Traits; - enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { - VT_SCHEMA_TYPE = 4, - VT_SCHEMA = 6, - VT_DATA_TYPE = 8, - VT_DATA = 10 - }; - Ikarus::Value::Schema schema_type() const { - return static_cast(GetField(VT_SCHEMA_TYPE, 0)); - } - const void *schema() const { - return GetPointer(VT_SCHEMA); - } - template const T *schema_as() const; - const Ikarus::Value::ConstantSchema *schema_as_ConstantSchema() const { - return schema_type() == Ikarus::Value::Schema::ConstantSchema ? static_cast(schema()) : nullptr; - } - const Ikarus::Value::SimpleSchema *schema_as_SimpleSchema() const { - return schema_type() == Ikarus::Value::Schema::SimpleSchema ? static_cast(schema()) : nullptr; - } - const Ikarus::Value::CombinedSchema *schema_as_CombinedSchema() const { - return schema_type() == Ikarus::Value::Schema::CombinedSchema ? static_cast(schema()) : nullptr; - } - const Ikarus::Value::ListSchema *schema_as_ListSchema() const { - return schema_type() == Ikarus::Value::Schema::ListSchema ? static_cast(schema()) : nullptr; - } - const Ikarus::Value::ComplexSchema *schema_as_ComplexSchema() const { - return schema_type() == Ikarus::Value::Schema::ComplexSchema ? static_cast(schema()) : nullptr; - } - Ikarus::Value::Data data_type() const { - return static_cast(GetField(VT_DATA_TYPE, 0)); - } - const void *data() const { - return GetPointer(VT_DATA); - } - template const T *data_as() const; - const Ikarus::Value::ToggleDataPoint *data_as_ToggleDataPoint() const { - return data_type() == Ikarus::Value::Data::ToggleDataPoint ? static_cast(data()) : nullptr; - } - const Ikarus::Value::NumberDataPoint *data_as_NumberDataPoint() const { - return data_type() == Ikarus::Value::Data::NumberDataPoint ? static_cast(data()) : nullptr; - } - const Ikarus::Value::TextDataPoint *data_as_TextDataPoint() const { - return data_type() == Ikarus::Value::Data::TextDataPoint ? static_cast(data()) : nullptr; - } - const Ikarus::Value::SimpleData *data_as_SimpleData() const { - return data_type() == Ikarus::Value::Data::SimpleData ? static_cast(data()) : nullptr; - } - const Ikarus::Value::CombinedData *data_as_CombinedData() const { - return data_type() == Ikarus::Value::Data::CombinedData ? static_cast(data()) : nullptr; - } - const Ikarus::Value::ListData *data_as_ListData() const { - return data_type() == Ikarus::Value::Data::ListData ? static_cast(data()) : nullptr; - } - const Ikarus::Value::ComplexData *data_as_ComplexData() const { - return data_type() == Ikarus::Value::Data::ComplexData ? static_cast(data()) : nullptr; - } - bool Verify(::flatbuffers::Verifier &verifier) const { - return VerifyTableStart(verifier) && - VerifyField(verifier, VT_SCHEMA_TYPE, 1) && - VerifyOffset(verifier, VT_SCHEMA) && - VerifySchema(verifier, schema(), schema_type()) && - VerifyField(verifier, VT_DATA_TYPE, 1) && - VerifyOffset(verifier, VT_DATA) && - VerifyData(verifier, data(), data_type()) && - verifier.EndTable(); - } -}; - -template<> inline const Ikarus::Value::ConstantSchema *Value::schema_as() const { - return schema_as_ConstantSchema(); -} - -template<> inline const Ikarus::Value::SimpleSchema *Value::schema_as() const { - return schema_as_SimpleSchema(); -} - -template<> inline const Ikarus::Value::CombinedSchema *Value::schema_as() const { - return schema_as_CombinedSchema(); -} - -template<> inline const Ikarus::Value::ListSchema *Value::schema_as() const { - return schema_as_ListSchema(); -} - -template<> inline const Ikarus::Value::ComplexSchema *Value::schema_as() const { - return schema_as_ComplexSchema(); -} - -template<> inline const Ikarus::Value::ToggleDataPoint *Value::data_as() const { - return data_as_ToggleDataPoint(); -} - -template<> inline const Ikarus::Value::NumberDataPoint *Value::data_as() const { - return data_as_NumberDataPoint(); -} - -template<> inline const Ikarus::Value::TextDataPoint *Value::data_as() const { - return data_as_TextDataPoint(); -} - -template<> inline const Ikarus::Value::SimpleData *Value::data_as() const { - return data_as_SimpleData(); -} - -template<> inline const Ikarus::Value::CombinedData *Value::data_as() const { - return data_as_CombinedData(); -} - -template<> inline const Ikarus::Value::ListData *Value::data_as() const { - return data_as_ListData(); -} - -template<> inline const Ikarus::Value::ComplexData *Value::data_as() const { - return data_as_ComplexData(); -} - -struct ValueBuilder { - typedef Value Table; - ::flatbuffers::FlatBufferBuilder &fbb_; - ::flatbuffers::uoffset_t start_; - void add_schema_type(Ikarus::Value::Schema schema_type) { - fbb_.AddElement(Value::VT_SCHEMA_TYPE, static_cast(schema_type), 0); - } - void add_schema(::flatbuffers::Offset schema) { - fbb_.AddOffset(Value::VT_SCHEMA, schema); - } - void add_data_type(Ikarus::Value::Data data_type) { - fbb_.AddElement(Value::VT_DATA_TYPE, static_cast(data_type), 0); - } - void add_data(::flatbuffers::Offset data) { - fbb_.AddOffset(Value::VT_DATA, data); - } - explicit ValueBuilder(::flatbuffers::FlatBufferBuilder &_fbb) - : fbb_(_fbb) { - start_ = fbb_.StartTable(); - } - ::flatbuffers::Offset Finish() { - const auto end = fbb_.EndTable(start_); - auto o = ::flatbuffers::Offset(end); - return o; - } -}; - -inline ::flatbuffers::Offset CreateValue( - ::flatbuffers::FlatBufferBuilder &_fbb, - Ikarus::Value::Schema schema_type = Ikarus::Value::Schema::NONE, - ::flatbuffers::Offset schema = 0, - Ikarus::Value::Data data_type = Ikarus::Value::Data::NONE, - ::flatbuffers::Offset data = 0) { - ValueBuilder builder_(_fbb); - builder_.add_data(data); - builder_.add_schema(schema); - builder_.add_data_type(data_type); - builder_.add_schema_type(schema_type); - return builder_.Finish(); -} - -struct Value::Traits { - using type = Value; - static auto constexpr Create = CreateValue; -}; - -inline bool VerifyData(::flatbuffers::Verifier &verifier, const void *obj, Data type) { - switch (type) { - case Data::NONE: { - return true; - } - case Data::ToggleDataPoint: { - auto ptr = reinterpret_cast(obj); - return verifier.VerifyTable(ptr); - } - case Data::NumberDataPoint: { - auto ptr = reinterpret_cast(obj); - return verifier.VerifyTable(ptr); - } - case Data::TextDataPoint: { - auto ptr = reinterpret_cast(obj); - return verifier.VerifyTable(ptr); - } - case Data::SimpleData: { - auto ptr = reinterpret_cast(obj); - return verifier.VerifyTable(ptr); - } - case Data::CombinedData: { - auto ptr = reinterpret_cast(obj); - return verifier.VerifyTable(ptr); - } - case Data::ListData: { - auto ptr = reinterpret_cast(obj); - return verifier.VerifyTable(ptr); - } - case Data::ComplexData: { - auto ptr = reinterpret_cast(obj); - return verifier.VerifyTable(ptr); - } - default: return true; - } -} - -inline bool VerifyDataVector(::flatbuffers::Verifier &verifier, const ::flatbuffers::Vector<::flatbuffers::Offset> *values, const ::flatbuffers::Vector *types) { - if (!values || !types) return !values && !types; - if (values->size() != types->size()) return false; - for (::flatbuffers::uoffset_t i = 0; i < values->size(); ++i) { - if (!VerifyData( - verifier, values->Get(i), types->GetEnum(i))) { - return false; - } - } - return true; -} - -inline bool VerifySchema(::flatbuffers::Verifier &verifier, const void *obj, Schema type) { - switch (type) { - case Schema::NONE: { - return true; - } - case Schema::ConstantSchema: { - auto ptr = reinterpret_cast(obj); - return verifier.VerifyTable(ptr); - } - case Schema::SimpleSchema: { - auto ptr = reinterpret_cast(obj); - return verifier.VerifyTable(ptr); - } - case Schema::CombinedSchema: { - auto ptr = reinterpret_cast(obj); - return verifier.VerifyTable(ptr); - } - case Schema::ListSchema: { - auto ptr = reinterpret_cast(obj); - return verifier.VerifyTable(ptr); - } - case Schema::ComplexSchema: { - auto ptr = reinterpret_cast(obj); - return verifier.VerifyTable(ptr); - } - default: return true; - } -} - -inline bool VerifySchemaVector(::flatbuffers::Verifier &verifier, const ::flatbuffers::Vector<::flatbuffers::Offset> *values, const ::flatbuffers::Vector *types) { - if (!values || !types) return !values && !types; - if (values->size() != types->size()) return false; - for (::flatbuffers::uoffset_t i = 0; i < values->size(); ++i) { - if (!VerifySchema( - verifier, values->Get(i), types->GetEnum(i))) { - return false; - } - } - return true; -} - -inline const Ikarus::Value::Value *GetValue(const void *buf) { - return ::flatbuffers::GetRoot(buf); -} - -inline const Ikarus::Value::Value *GetSizePrefixedValue(const void *buf) { - return ::flatbuffers::GetSizePrefixedRoot(buf); -} - -inline bool VerifyValueBuffer( - ::flatbuffers::Verifier &verifier) { - return verifier.VerifyBuffer(nullptr); -} - -inline bool VerifySizePrefixedValueBuffer( - ::flatbuffers::Verifier &verifier) { - return verifier.VerifySizePrefixedBuffer(nullptr); -} - -inline void FinishValueBuffer( - ::flatbuffers::FlatBufferBuilder &fbb, - ::flatbuffers::Offset root) { - fbb.Finish(root); -} - -inline void FinishSizePrefixedValueBuffer( - ::flatbuffers::FlatBufferBuilder &fbb, - ::flatbuffers::Offset root) { - fbb.FinishSizePrefixed(root); -} - -} // namespace Value -} // namespace Ikarus - -#endif // FLATBUFFERS_GENERATED_VALUE_IKARUS_VALUE_H_ diff --git a/include/ikarus/objects/blueprint.h b/include/ikarus/objects/blueprint.h index 9ad444e..adc97e9 100644 --- a/include/ikarus/objects/blueprint.h +++ b/include/ikarus/objects/blueprint.h @@ -1,7 +1,7 @@ #pragma once /// \file blueprint.h -/// \author Folling +/// \author Folling #include #include @@ -13,57 +13,113 @@ IKARUS_BEGIN_HEADER -/// \brief Blueprints are templates for managing common properties of entities. -/// \details A blueprint is a collection of properties which can be linked to entities. -/// Each entity the blueprint is linked to will have values for the blueprints -/// properties. Changes in blueprints will be reflected in all linked entities. +/// \brief Templates for sharing common properties between entities. +/// \details A blueprint allows sharing properties between entities. +/// Each entity the blueprint is linked to will have a corresponding value for +/// each of the blueprint's properties. Changes in blueprints will be reflected +/// in all linked entities. struct IkarusBlueprint; -/// \brief Creates a blueprint. -/// \param project The project the blueprint is part of. +/// \brief Flags for creating a blueprint. +enum IkarusBlueprintCreateFlags { + /// \brief No flags. + IkarusBlueprintCreateFlags_None = 0, +}; + +/// \brief Creates a new blueprint. +/// \param project The project to create the blueprint in. /// \pre \li Must not be null. /// \pre \li Must exist. /// \param name The name of the blueprint. /// \pre \li Must not be null. -/// \param error_out \see errors.h +/// \pre \li Must not be empty. +/// \param flags Flags for creating the blueprint. /// \return The created blueprint or null if an error occurs. +/// \param error_out \see errors.h +/// \remark Ownership remains with libikarus. IKA_API IkarusBlueprint * ikarus_blueprint_create( - struct IkarusProject * project, - char const * name, - IkarusErrorData * error_out + struct IkarusProject * project, + char const * name, + IkarusBlueprintCreateFlags flags, + struct IkarusErrorData * error_out ); -/// \brief Deletes a blueprint. +/// \brief Flags for creating a blueprint from an entity. +enum IkarusBlueprintCreateFromEntityFlags { + /// \brief No flags. + IkarusBlueprintCreateFromEntityFlags_None = 0, + /// \brief The default values of the properties will be set to the values of the source entity. + IkarusBlueprintCreateFromEntityFlags_AdoptDefaultValues = 1 << 0, + /// \brief The entity will be linked to the blueprint, and all values will be turned into properties. + IkarusBlueprintCreateFromEntityFlags_LinkEntity = 1 << 1, +}; + +/// \brief Creates a new blueprint from an entity. +/// \details Each value of the entity will be copied into the blueprint as a property. +/// \param entity The entity to create the blueprint from. +/// \pre \li Must not be null. +/// \pre \li Must exist. +/// \param name The name of the blueprint. +/// \pre \li Must not be null. +/// \pre \li Must not be empty. +/// \param flags Flags for creating the blueprint. +/// \param error_out \see errors.h +/// \return The created blueprint or null if an error occurs. +IKA_API IkarusBlueprint * ikarus_blueprint_create_from_entity( + struct IkarusEntity * entity, + char const * name, + IkarusBlueprintCreateFromEntityFlags flags, + struct IkarusErrorData * error_out +); + +/// \brief Flags for copying a blueprint. +enum IkarusBlueprintCopyFlags { + /// \brief No flags. + IkarusBlueprintCopyFlags_None = 0, +}; + +/// \brief Copies a blueprint. +/// \param blueprint The blueprint to copy. +/// \pre \li Must not be null. +/// \pre \li Must exist. +/// \param flags Flags for copying the blueprint. +/// \param error_out \see errors.h +/// \return The copied blueprint or null if an error occurs. +IKA_API struct IkarusBlueprint * ikarus_blueprint_copy( + struct IkarusBlueprint * blueprint, + IkarusBlueprintCopyFlags flags, + struct IkarusErrorData * error_out +); + +/// \brief Flags for deleting a blueprint. +enum IkarusBlueprintDeleteFlags { + /// \brief No flags. + IkarusBlueprintDeleteFlags_None = 0, +}; + +/// \brief Deletes a blueprint, all associated properties, and their values. /// \param blueprint The blueprint to delete. /// \pre \li Must not be null. /// \pre \li Must exist. +/// \param flags Flags for deleting the blueprint. +/// \remark Must not be used after deletion. /// \param error_out \see errors.h -/// \remark The blueprint must not be accessed after deletion. IKA_API void ikarus_blueprint_delete( - IkarusBlueprint * blueprint, - IkarusErrorData * error_out + struct IkarusBlueprint * blueprint, + IkarusBlueprintDeleteFlags flags, + IkarusErrorData * error_out ); -/// \brief Gets the ID of a blueprint. -/// \param blueprint The blueprint to get the ID of. -/// \pre \li Must not be null. -/// \pre \li Must exist. -/// \param error_out \see errors.h -/// \return The ID of the blueprint or 0 if an error occurs. -IKA_API int64_t ikarus_blueprint_get_id( - IkarusBlueprint const * blueprint, - IkarusErrorData * error_out -); - -/// \brief Gets the project a blueprint is part of. +/// \brief Gets the project a blueprint belongs to. /// \param blueprint The blueprint to get the project of. /// \pre \li Must not be null. /// \pre \li Must exist. /// \param error_out \see errors.h -/// \return The project or null if an error occurs. -IKA_API IkarusProject * ikarus_blueprint_get_project( - IkarusBlueprint const * blueprint, - IkarusErrorData * error_out +/// \return The project the blueprint belongs to. +/// \remark Ownership remains with libikarus. +IKA_API struct IkarusProject * ikarus_blueprint_get_project( + struct IkarusBlueprint * blueprint, + struct IkarusErrorData * error_out ); /// \brief Gets the name of a blueprint. @@ -71,79 +127,84 @@ IKA_API IkarusProject * ikarus_blueprint_get_project( /// \pre \li Must not be null. /// \pre \li Must exist. /// \param error_out \see errors.h -/// \return The name or null if an error occurs. +/// \return The name of the blueprint. +/// \remark Ownership remains with libikarus. IKA_API char const * ikarus_blueprint_get_name( - IkarusBlueprint const * blueprint, - IkarusErrorData * error_out + struct IkarusBlueprint * blueprint, + struct IkarusErrorData * error_out ); +/// \brief Flags for setting the name of a blueprint. +enum IkarusBlueprintSetNameFlags { + /// \brief No flags. + IkarusBlueprintSetNameFlags_None = 0, +}; + /// \brief Sets the name of a blueprint. /// \param blueprint The blueprint to set the name of. /// \pre \li Must not be null. /// \pre \li Must exist. /// \param name The new name of the blueprint. /// \pre \li Must not be null. +/// \pre \li Must not be empty. +/// \param flags Flags for setting the name of the blueprint. /// \param error_out \see errors.h IKA_API void ikarus_blueprint_set_name( - IkarusBlueprint * blueprint, - char const * name, - IkarusErrorData * error_out + struct IkarusBlueprint * blueprint, + char const * name, + IkarusBlueprintSetNameFlags flags, + struct IkarusErrorData * error_out ); /// \brief Gets the properties of a blueprint. /// \param blueprint The blueprint to get the properties of. /// \pre \li Must not be null. /// \pre \li Must exist. -/// \param properties_out The buffer to write the properties to. -/// \pre \li Must not be null. -/// \param properties_out_size The size of the buffer. +/// \param size_out An out parameter for the number of items in the returned array or undefined if an error occurs. /// \param error_out \see errors.h -/// \see ikarus_blueprint_get_property_count -IKA_API void ikarus_blueprint_get_properties( - IkarusBlueprint const * blueprint, - struct IkarusProperty ** properties_out, - size_t properties_out_size, - IkarusErrorData * error_out +/// \return The properties of the blueprint or null if an error occurs. +IKA_API struct IkarusProperty ** ikarus_blueprint_get_properties( + struct IkarusBlueprint * blueprint, + size_t * size_out, + struct IkarusErrorData * error_out ); /// \brief Gets the number of properties of a blueprint. -/// \param blueprint The blueprint to get the number of properties of. +/// \param blueprint The blueprint to get the properties count of. /// \pre \li Must not be null. /// \pre \li Must exist. /// \param error_out \see errors.h -/// \return The number of properties or undefined if an error occurs. -IKA_API size_t ikarus_blueprint_get_property_count( - IkarusBlueprint const * blueprint, - IkarusErrorData * error_out +/// \return The number of properties of the blueprint or 0 if an error occurs. +IKA_API size_t ikarus_blueprint_get_properties_count( + struct IkarusBlueprint * blueprint, + struct IkarusErrorData * error_out ); -/// \brief Gets the entities linked to a blueprint. -/// \param blueprint The blueprint to get the linked entities of. +/// \brief Gets all entities linked to a blueprint. +/// \param blueprint The blueprint to get the entities of. /// \pre \li Must not be null. /// \pre \li Must exist. -/// \param entities_out The buffer to write the entities to. -/// \pre \li Must not be null. -/// \param entities_out_size The size of the buffer. +/// \param size_out An out parameter for the number of items in the returned array or undefined if an error occurs. +/// \remark Ignore if null. /// \param error_out \see errors.h -/// \see ikarus_blueprint_get_linked_entity_count -IKA_API void ikarus_blueprint_get_linked_entities( - IkarusBlueprint const * blueprint, - struct IkarusEntity ** entities_out, - size_t entities_out_size, - IkarusErrorData * error_out +/// \return The entities linked to the blueprint or null if an error occurs. +IKA_API struct IkarusEntity ** ikarus_blueprint_get_entities( + struct IkarusBlueprint * blueprint, + size_t * size_out, + struct IkarusErrorData * error_out ); /// \brief Gets the number of entities linked to a blueprint. -/// \param blueprint The blueprint to get the number of linked entities of. +/// \param blueprint The blueprint to get the entities count of. /// \pre \li Must not be null. /// \pre \li Must exist. /// \param error_out \see errors.h -/// \return The number of linked entities or undefined if an error occurs. -IKA_API size_t ikarus_blueprint_get_linked_entity_count( - IkarusBlueprint const * blueprint, - IkarusErrorData * error_out +/// \return The number of entities linked to the blueprint or 0 if an error occurs. +IKA_API size_t ikarus_blueprint_get_entities_count( + struct IkarusBlueprint * blueprint, + struct IkarusErrorData * error_out ); IKARUS_END_HEADER -// @} +/// @} diff --git a/include/ikarus/objects/entity.h b/include/ikarus/objects/entity.h index 28cebf8..0481da7 100644 --- a/include/ikarus/objects/entity.h +++ b/include/ikarus/objects/entity.h @@ -5,7 +5,7 @@ #include /// \file entity.h -/// \author Folling +/// \author Folling /// \defgroup entities Entities /// \brief Entities are the core building blocks of Ikarus. @@ -13,15 +13,13 @@ IKARUS_BEGIN_HEADER /// \brief Entities are the core building blocks of Ikarus. -/// \details Entities store two data: A name and a set of values. -/// The name identifies the entity but does not have to be unique. The values -/// are the actual information of the entity. +/// \details Entities store a number of values associated with a name or property. /// -/// For documentation on the types and layout of values \see Values.h. +/// For documentation on the types and layout of values \see values.h. /// /// Entities can be linked to blueprints. /// The entity has a (possibly uninitialized) value for each property of all -/// blueprints it is linked to. \see Property.h \see Blueprint.h. +/// blueprints it is linked to. \see property.h \see blueprint.h. /// /// We distinguish between `EntityValues` and `EntityPropertyValues`. /// `EntityValues` are a direct part of the entity. @@ -29,59 +27,89 @@ IKARUS_BEGIN_HEADER /// via a blueprint. struct IkarusEntity; -/// \brief Creates an entity. -/// \param project The project the entity is part of. +/// \brief Flags for creating an entity. +enum IkarusEntityCreateFlags { + /// \brief No flags. + IkarusEntityCreateFlags_None = 0, +}; + +/// \brief Creates a new entity. +/// \param project The project to create the entity in. /// \pre \li Must not be null. /// \pre \li Must exist. /// \param name The name of the entity. /// \pre \li Must not be null. +/// \pre \li Must not be empty. +/// \param flags Flags for creating the entity. /// \param error_out \see errors.h /// \return The created entity or null if an error occurs. IKA_API IkarusEntity * ikarus_entity_create( - struct IkarusProject * project, - char const * name, - IkarusErrorData * error_out + struct IkarusProject * project, + char const * name, + IkarusEntityCreateFlags flags, + IkarusErrorData * error_out ); -/// \brief Deletes an entity. +/// \brief Flags for deleting an entity. +enum IkarusEntityDeleteFlags { + /// \brief No flags. + IkarusEntityDeleteFlags_None = 0, +}; + +/// \brief Deletes an entity and its values. /// \param entity The entity to delete. /// \pre \li Must not be null. /// \pre \li Must exist. +/// \param flags Flags for deleting the entity. /// \param error_out \see errors.h -/// \remark The entity must not be accessed after deletion. -IKA_API void -ikarus_entity_delete(IkarusEntity * entity, IkarusErrorData * error_out); +IKA_API void ikarus_entity_delete( + IkarusEntity * entity, + IkarusEntityDeleteFlags flags, + IkarusErrorData * error_out +); -/// \brief Gets the id of an entity. -/// \param entity The entity to get the id of. +/// \brief Flags for copying an entity. +enum IkarusEntityCopyFlags { + /// \brief No flags. + IkarusEntityCopyFlags_None = 0, +}; + +/// \brief Copies an entity. +/// \param entity The entity to copy. /// \pre \li Must not be null. /// \pre \li Must exist. +/// \param flags Flags for copying the entity. /// \param error_out \see errors.h -/// \return The id of the entity or 0 if an error occurs. -IKA_API int64_t -ikarus_entity_get_id(IkarusEntity const * entity, IkarusErrorData * error_out); +/// \return The copied entity or null if an error occurs. +IKA_API IkarusEntity * ikarus_entity_copy( + IkarusEntity * entity, + IkarusEntityCopyFlags flags, + IkarusErrorData * error_out +); -/// \brief Gets the project an entity is part of. +/// \brief Gets the project an entity belongs to. /// \param entity The entity to get the project of. /// \pre \li Must not be null. /// \pre \li Must exist. /// \param error_out \see errors.h -/// \return The project the entity is part of or null if an error occurs. -IKA_API IkarusProject * ikarus_entity_get_project( - IkarusEntity const * entity, - IkarusErrorData * error_out -); +/// \return The project the entity belongs to. +IKA_API struct IkarusProject * +ikarus_entity_get_project(IkarusEntity * entity, IkarusErrorData * error_out); /// \brief Gets the name of an entity. /// \param entity The entity to get the name of. /// \pre \li Must not be null. /// \pre \li Must exist. /// \param error_out \see errors.h -/// \return The name of the entity or null if an error occurs. -IKA_API char const * ikarus_entity_get_name( - IkarusEntity const * entity, - IkarusErrorData * error_out -); +/// \return The name of the entity. +IKA_API char const * +ikarus_entity_get_name(IkarusEntity * entity, IkarusErrorData * error_out); + +/// \brief Flags for setting the name of an entity. +enum IkarusEntitySetNameFlags { + /// \brief No flags. + IkarusEntitySetNameFlags_None = 0, +}; /// \brief Sets the name of an entity. /// \param entity The entity to set the name of. @@ -89,73 +117,27 @@ IKA_API char const * ikarus_entity_get_name( /// \pre \li Must exist. /// \param name The new name of the entity. /// \pre \li Must not be null. +/// \pre \li Must not be empty. +/// \param flags Flags for setting the name of the entity. /// \param error_out \see errors.h IKA_API void ikarus_entity_set_name( - IkarusEntity * entity, - char const * name, - IkarusErrorData * error_out + IkarusEntity * entity, + char const * name, + IkarusEntitySetNameFlags flags, + IkarusErrorData * error_out ); -/// \brief Checks if an entity is linked to a blueprint. -/// \param entity The entity to check. -/// \pre \li Must not be null. -/// \pre \li Must exist. -/// \param blueprint The blueprint to check. -/// \pre \li Must not be null. -/// \pre \li Must exist. -/// \param error_out \see errors.h -/// \return True if the entity is linked to the blueprint, false otherwise. -IKA_API bool ikarus_entity_is_linked_to_blueprint( - IkarusEntity const * entity, - struct IkarusBlueprint const * blueprint, - IkarusErrorData * error_out -); - -/// \brief Links an entity to a blueprint. -/// \param entity The entity to link. -/// \pre \li Must not be null. -/// \pre \li Must exist. -/// \param blueprint The blueprint to link the entity to. -/// \pre \li Must not be null. -/// \pre \li Must exist. -/// \param error_out \see errors.h -/// \remark No-op if the entity is already linked to the blueprint. -IKA_API void ikarus_entity_link_to_blueprint( - IkarusEntity * entity, - struct IkarusBlueprint * blueprint, - IkarusErrorData * error_out -); - -/// \brief Unlinks an entity from a blueprint. -/// All values of the blueprints' properties will be deleted. -/// \param entity The entity to unlink. -/// \pre \li Must not be null. -/// \pre \li Must exist. -/// \param blueprint The blueprint to unlink the entity from. -/// \pre \li Must not be null. -/// \pre \li Must exist. -/// \param error_out \see errors.h -/// \remark No-op if the entity is not linked to the blueprint. -IKA_API void ikarus_entity_unlink_from_blueprint( - IkarusEntity * entity, - struct IkarusBlueprint * blueprint, - IkarusErrorData * error_out -); - -/// \brief Gets all blueprints an entity is linked to. +/// \brief Gets the blueprints an entity is linked to. /// \param entity The entity to get the blueprints of. /// \pre \li Must not be null. /// \pre \li Must exist. -/// \param blueprints_out The buffer to write the blueprints to. -/// \pre \li Must not be null. -/// \param blueprints_out_size The size of the buffer. +/// \param size_out An out parameter for the number of blueprints in the returned array +/// or undefined if an error occurs. /// \param error_out \see errors.h -/// \see ikarus_entity_get_linked_blueprint_count -IKA_API void ikarus_entity_get_linked_blueprints( - IkarusEntity const * entity, - struct IkarusBlueprint ** blueprints_out, - size_t blueprints_out_size, - IkarusErrorData * error_out +IKA_API struct IkarusBlueprint ** ikarus_entity_get_linked_blueprints( + IkarusEntity * entity, + size_t * size_out, + IkarusErrorData * error_out ); /// \brief Gets the number of blueprints an entity is linked to. @@ -163,156 +145,199 @@ IKA_API void ikarus_entity_get_linked_blueprints( /// \pre \li Must not be null. /// \pre \li Must exist. /// \param error_out \see errors.h -/// \return The number of blueprints or undefined if an error occurs. -IKA_API size_t ikarus_entity_get_linked_blueprint_count( - IkarusEntity const * entity, - IkarusErrorData * error_out +/// \return The number of linked blueprints or 0 if an error occurs. +IKA_API size_t ikarus_entity_get_linked_blueprints_count( + IkarusEntity * entity, + IkarusErrorData * error_out ); -/// \brief Checks if an entity has a value with a given name. -/// \param entity The entity to check. +/// \brief Flags for linking an entity to a blueprint. +enum IkarusEntityLinkBlueprintFlags { + /// \brief No flags. + IkarusEntityLinkBlueprintFlags_None = 0, +}; + +/// \brief Links an entity to a blueprint. +/// \details An uninitialized (default) value is created for each property of the +/// blueprint. +/// \param entity The entity to link the blueprint to. /// \pre \li Must not be null. /// \pre \li Must exist. -/// \param name The name of the value to check. +/// \param blueprint The blueprint to link to. /// \pre \li Must not be null. +/// \pre \li Must exist. +/// \pre \li Must be in the same project as the entity. +/// \remark If the entity is already linked to the blueprint, nothing happens. +/// \param flags Flags for linking the entity to the blueprint. /// \param error_out \see errors.h -/// \return False if the entity does not have a value associated with -/// the name or if an error occurs, true otherwise. -IKA_API bool ikarus_entity_has_value( - IkarusEntity const * entity, - char const * name, - IkarusErrorData * error_out +IKA_API void ikarus_entity_link_blueprint( + IkarusEntity * entity, + struct IkarusBlueprint * blueprint, + IkarusEntityLinkBlueprintFlags flags, + IkarusErrorData * error_out ); -/// \brief Gets the value of an entity. +/// \brief Flags for unlinking an entity from a blueprint. +enum IkarusEntityUnlinkBlueprintFlags { + /// \brief No flags. + IkarusEntityUnlinkBlueprintFlags_None = 0, + /// \brief Keep the values associated with the blueprint, transforming them into entity values. + IkarusEntityUnlinkBlueprintFlags_KeepValues = 1, +}; + +/// \brief Unlinks an entity from a blueprint. +/// \details All values associated with the blueprint are deleted. +/// \param entity The entity to unlink the blueprint from. +/// \pre \li Must not be null. +/// \pre \li Must exist. +/// \param blueprint The blueprint to unlink from. +/// \pre \li Must not be null. +/// \pre \li Must exist. +/// \remark If the entity is not linked to the blueprint, nothing happens. +/// \param flags Flags for unlinking the entity from the blueprint. +/// \param error_out \see errors.h +IKA_API void ikarus_entity_unlink_blueprint( + IkarusEntity * entity, + struct IkarusBlueprint * blueprint, + IkarusEntityUnlinkBlueprintFlags flags, + IkarusErrorData * error_out +); + +/// \brief Gets the values of an entity. +/// \param entity The entity to get the values of. +/// \pre \li Must not be null. +/// \pre \li Must exist. +/// \param error_out \see errors.h +/// \return The values, in json format of or null if an error occurs. +/// The json representation is an array of objects with the following keys: +/// - `name`: The name of the value. +/// - `value`: The value itself. \see value.h +IKA_API char const * +ikarus_entity_get_values(IkarusEntity * entity, IkarusErrorData * error_out); + +/// \brief Gets a value of an entity. /// \param entity The entity to get the value of. -/// \pre \li Must not be null. -/// \pre \li Must exist. -/// \param name The name of the value to get. -/// \pre \li Must not be null. -/// \pre \li Must be an existing value of the entity. +/// \pre \li Must not be null. +/// \pre \li Must exist. +/// \param name The value's name. +/// \pre \li Must not be null. +/// \remark Ownership remains with the client. /// \param error_out \see errors.h -/// \return The value of the entity or null if an error occurs. -IKA_API struct IkarusValue * ikarus_entity_get_value( - IkarusEntity const * entity, - char const * name, - IkarusErrorData * error_out +/// \return The value, in json format of or null if an error occurs. \see value.h +IKA_API char const * ikarus_entity_get_value( + IkarusEntity * entity, + char const * name, + IkarusErrorData * error_out ); -/// \brief Sets the value of an entity. -/// If the entity does not have a value associated with the name, it is created. -/// \remark Types are overwritten if the value already exists. +/// \brief Flags for setting a value of an entity. +enum IkarusEntitySetValueFlags { + /// \brief No flags. + IkarusEntitySetValueFlags_None = 0, +}; + +/// \brief Sets a value of an entity. +/// \details If no value exists for the name, a new one is created. +/// Any previous value is overwritten. /// \param entity The entity to set the value of. /// \pre \li Must not be null. /// \pre \li Must exist. -/// \param name The name of the value to set. +/// \param name The value's name. /// \pre \li Must not be null. -/// \pre \li Must exist. -/// \param value The new value of the entity. +/// \param value The value to set. /// \pre \li Must not be null. +/// \pre \li Must be a valid json representation of a value. \see value.h +/// \param flags Flags for setting the value. /// \param error_out \see errors.h IKA_API void ikarus_entity_set_value( - IkarusEntity * entity, - char const * name, - struct IkarusValue const * value, - IkarusErrorData * error_out + IkarusEntity * entity, + char const * name, + char const * value, + IkarusEntitySetValueFlags flags, + IkarusErrorData * error_out ); -/// \brief Removes a value from an entity. -/// \pre \li The value must exist. +/// \brief Flags for deleting a value of an entity. +enum IkarusEntityDeleteValueFlags { + /// \brief No flags. + IkarusEntityDeleteValueFlags_None = 0, +}; + +/// \brief Deletes a value of an entity. /// \param entity The entity to delete the value of. /// \pre \li Must not be null. /// \pre \li Must exist. -/// \param name The name of the value to delete. +/// \param name The property's name to delete the value of. /// \pre \li Must not be null. +/// \pre \li Must be the name of a value which exists within the property. +/// \param flags Flags for deleting the value. /// \param error_out \see errors.h -IKA_API void ikarus_entity_remove_value( - IkarusEntity * entity, - char const * name, - IkarusErrorData * error_out +IKA_API void ikarus_entity_delete_value( + IkarusEntity * entity, + char const * name, + IkarusEntityDeleteValueFlags flags, + IkarusErrorData * error_out ); -/// \brief Checks if a property is linked to an entity. -/// \param entity The entity to check. -/// \pre \li Must not be null. -/// \pre \li Must exist. -/// \param property The property to check. +/// \brief Gets the property values of an entity. +/// \param entity The entity to get the property values of. /// \pre \li Must not be null. /// \pre \li Must exist. /// \param error_out \see errors.h -/// \return False if an error occurs or the entity does not have the property, -/// true otherwise. -IKA_API bool ikarus_entity_has_property( - IkarusEntity const * entity, - struct IkarusProperty const * property, - IkarusErrorData * error_out -); - -/// \brief Gets the properties an entity is linked to. -/// \param entity The entity to get the linked properties of. -/// \pre \li Must not be null. -/// \pre \li Must exist. -/// \param properties_out The buffer to write the linked properties to. -/// \pre \li Must not be null. -/// \param error_out \see errors.h -/// \param properties_out_size The size of the buffer. -/// \see ikarus_entity_get_property_count -IKA_API void ikarus_entity_get_properties( - IkarusEntity const * entity, - struct IkarusProperty ** properties_out, - size_t properties_out_size, - IkarusErrorData * error_out -); - -/// \brief Gets the number of properties an entity is linked to. -/// \param entity The entity to get the number of linked properties of. -/// \pre \li Must not be null. -/// \pre \li Must exist. -/// \param error_out \see errors.h -/// \return The number of properties or undefined if an error occurs. -IKA_API size_t ikarus_entity_get_property_count( - IkarusEntity const * entity, - IkarusErrorData * error_out +/// \return The property values, in msgpack format of or null if an error occurs. +/// The format is a map of property pointers (as integers) to values. \see +/// value.h +IKA_API char const * ikarus_entity_get_property_values( + IkarusEntity * entity, + IkarusErrorData * error_out ); /// \brief Gets the value of a property of an entity. -/// \details If the entity has never set the value of the property, -/// the property's default value is returned. -/// \param entity The entity to get the value of. -/// \pre \li Must not be null. -/// \pre \li Must exist. -/// \param property The property to get the value of. -/// \pre \li Must not be null. -/// \pre \li Must exist. -/// \pre \li Must be linked to the entity. -/// \param error_out \see errors.h -/// \return The value of the property or null if an error occurs. -IKA_API struct IkarusValue * ikarus_entity_get_property_value( - IkarusEntity const * entity, - struct IkarusProperty const * property, - IkarusErrorData * error_out +/// \param entity The entity to get the value of. +/// \pre \li Must not be null. +/// \pre \li Must exist. +/// \param property The property to get the value of. +/// \pre \li Must not be null. +/// \pre \li Must exist. +/// \pre \li Must be linked to the entity. +/// \param error_out \see errors.h +/// \return The value, in json format of or null if an error occurs. \see +/// value.h +IKA_API char const * ikarus_entity_get_property_value( + IkarusEntity * entity, + struct IkarusProperty * property, + IkarusErrorData * error_out ); +/// \brief Flags for setting the value of a property of an entity. +enum IkarusEntitySetPropertyValueFlags { + /// \brief No flags. + IkarusEntitySetPropertyValueFlags_None = 0, +}; + /// \brief Sets the value of a property of an entity. -/// \param entity The entity to set the property value of. +/// \details Any previous value is overwritten. +/// \param entity The entity to set the value of. /// \pre \li Must not be null. /// \pre \li Must exist. /// \param property The property to set the value of. /// \pre \li Must not be null. /// \pre \li Must exist. -/// \param value The new value of the property. +/// \pre \li Must be linked to the entity. +/// \param value The value to set. /// \pre \li Must not be null. -/// \pre \li Must be of the same type as the property. -/// \pre \li Must be valid for the property's settings. +/// \pre \li Must be a valid json representation of a value. \see value.h +/// \pre \li Must be valid for the property's schema. \see schema.h +/// \param flags Flags for setting the property value. /// \param error_out \see errors.h -/// \remark If the entity does not have the property, this function fails. IKA_API void ikarus_entity_set_property_value( - IkarusEntity * entity, - struct IkarusProperty const * property, - struct IkarusValue const * value, - IkarusErrorData * error_out + IkarusEntity * entity, + struct IkarusProperty * property, + char const * value, + IkarusEntitySetPropertyValueFlags flags, + IkarusErrorData * error_out ); IKARUS_END_HEADER -// @} +/// @} diff --git a/include/ikarus/objects/properties/number_property.h b/include/ikarus/objects/properties/number_property.h deleted file mode 100644 index d989ec2..0000000 --- a/include/ikarus/objects/properties/number_property.h +++ /dev/null @@ -1,40 +0,0 @@ -#pragma once - -/// \file number_property.h -/// \author Folling - -#include -#include - -/// \addtogroup properties Properties -/// \brief Number properties store a value that can be either true or false. (e.g. "Is the character dead?") -/// @{ - -IKARUS_BEGIN_HEADER - -struct IkarusNumberProperty; - -/// \brief Creates a number property. -/// \param project The project to create the property in. -/// \pre \li Must not be null. -/// \pre \li Must exist. -/// \param name The name of the property. -/// \pre \li Must not be null. -/// \param property_source The property source to create the property for. -/// \pre \li Must not be null. -/// \pre \li Must exist. -/// \param default_value The default value for the property. -/// \pre \li Must not be null. -/// \param error_out \see errors.h -/// \return The created property or null if an error occurs. -IKA_API IkarusNumberProperty * ikarus_number_property_create( - struct IkarusProject * project, - char const * name, - struct IkarusPropertySource * property_source, - struct IkarusNumberValue * default_value, - IkarusErrorData * error_out -); - -IKARUS_END_HEADER - -/// @} diff --git a/include/ikarus/objects/properties/property.h b/include/ikarus/objects/properties/property.h deleted file mode 100644 index c7ba19b..0000000 --- a/include/ikarus/objects/properties/property.h +++ /dev/null @@ -1,144 +0,0 @@ -#pragma once - -/// \file property.h -/// \author Folling - -#include -#include -#include -#include -#include - -/// \defgroup properties Properties -/// \brief Properties define the structure and types of data. -/// @{ - -IKARUS_BEGIN_HEADER - -/// \brief Properties define the structure of blueprints. -/// \details Each blueprint can have any number of properties. -/// Every property has a type that identifies the kind of data that can be put in. -/// This is the "base class" of properties. See the derived types (e.g. IkarusToggleProperty) for more information. -/// -/// The following types currently exist: -/// - Toggle: A true/false boolean-like value -/// - Number: An arbitrary numeric value -/// - Text: An arbitrary textual value -/// -/// Property Examples: -/// - Is Dead (Toggle) -/// - Age (Number) -/// - ISBN (Text) -/// -/// Each entity associated with the property has a value for it. -/// -/// \remark Values for properties are lazily created to save space. -/// Fetching the value for some property of some entity will return the property's default value if none is specified. -struct IkarusProperty; - -/// \brief Deletes a property. -/// \param property The property to delete. -/// \pre \li Must not be null. -/// \pre \li Must exist. -/// \param error_out \see errors.h -/// \remark The property must not be accessed after deletion. -IKA_API void ikarus_property_delete(IkarusProperty * property, IkarusErrorData * error_out); - -/// \brief Gets the ID of a property. -/// \param property The property to get the ID of. -/// \pre \li Must not be null. -/// \pre \li Must exist. -/// \param error_out \see errors.h -/// \return The ID of the property or 0 if an error occurs. -IKA_API int64_t ikarus_property_get_id(IkarusProperty const * property, IkarusErrorData * error_out); - -/// \brief Gets the project of a property. -/// \param property The property to get the project of. -/// \pre \li Must not be null. -/// \pre \li Must exist. -/// \param error_out \see errors.h -/// \return The project of the property or null if an error occurs. -IKA_API struct IkarusProject * ikarus_property_get_project(IkarusProperty const * property, IkarusErrorData * error_out); - -/// \brief Gets the name of an property. -/// \param entity The property to get the name of. -/// \pre \li Must not be null. -/// \pre \li Must exist. -/// \param error_out \see errors.h -/// \return The name of the property or null if an error occurs. -IKA_API char const * ikarus_property_get_name(IkarusProperty const * entity, IkarusErrorData * error_out); - -/// \brief Sets the name of an property. -/// \param entity The property to set the name of. -/// \pre \li Must not be null. -/// \pre \li Must exist. -/// \param name The new name of the property. -/// \pre \li Must not be null. -/// \param error_out \see errors.h -IKA_API void ikarus_property_set_name(IkarusProperty * entity, char const * name, IkarusErrorData * error_out); - -/// \brief Gets the type info of a property. -/// \param property The property to get the type info of. -/// \pre \li Must not be null. -/// \pre \li Must exist. -/// \param error_out \see errors.h -/// \return The type info of the property or null if an error occurs. -/// \remark Changing the type of a property is not supported. This is because the property would need to change -IKA_API IkarusValueType ikarus_property_get_type(IkarusProperty const * property, IkarusErrorData * error_out); - -// there is no `set_type` as we encode type information in the underlying datatype - -/// \briefs Gets a property's cardinality. -/// \param property The property to get the cardinality of. -/// \pre \li Must not be null. -/// \pre \li Must exist. -/// \param error_out \see errors.h -/// \return The cardinality of the property or false if an error occurs. -IKA_API IkarusValueCardinality ikarus_property_get_cardinality(IkarusProperty const * property, IkarusErrorData * error_out); - -/// \briefs Sets a property's default value. -/// \param property The property to set the cardinality of. -/// \pre \li Must not be null. -/// \pre \li Must exist. -/// \\param cardinality The new cardinality of the property. -/// \param error_out \see errors.h -IKA_API void -ikarus_property_set_cardinality(IkarusProperty * property, IkarusValueCardinality cardinality, IkarusErrorData * error_out); - -/// \briefs Gets a property's default value. -/// \param property The property to get the default value of. -/// \pre \li Must not be null. -/// \pre \li Must exist. -/// \param error_out \see errors.h -/// \return The default value of the property or null if an error occurs. -IKA_API struct IkarusValue * ikarus_property_get_default_value(IkarusProperty const * property, IkarusErrorData * error_out); - -/// \brief Gets the source blueprint of a property. -/// \param property The property to get the source of. -/// \pre \li Must not be null. -/// \pre \li Must exist. -/// \param error_out \see errors.h -/// \return The source of the property or null if an error occurs. -IKA_API struct IkarusBlueprint * ikarus_property_get_blueprint(IkarusProperty const * property, IkarusErrorData * error_out); - -/// \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. -/// \pre \li Must exist. -/// \param toggle_property_visitor The function to call if the property is a toggle property. Skipped if null. -/// \param number_property_visitor The function to call if the property is a number property. Skipped if null. -/// \param text_property_visitor The function to call if the property is a text property. Skipped if null. -/// \param data The data to pass to the functions. -/// \param error_out \see errors.h -IKA_API void ikarus_property_visit( - IkarusProperty * property, - void (*toggle_property_visitor)(struct IkarusToggleProperty *, void *), - void (*number_property_visitor)(struct IkarusNumberProperty *, void *), - void (*text_property_visitor)(struct IkarusTextProperty *, void *), - void * data, - IkarusErrorData * error_out -); - -IKARUS_END_HEADER - -// @} diff --git a/include/ikarus/objects/properties/text_property.h b/include/ikarus/objects/properties/text_property.h deleted file mode 100644 index a0c0a9d..0000000 --- a/include/ikarus/objects/properties/text_property.h +++ /dev/null @@ -1,40 +0,0 @@ -#pragma once - -/// \file text_property.h -/// \author Folling - -#include -#include - -/// \addtogroup properties Properties -/// \brief Text properties store a value that can be either true or false. (e.g. "Is the character dead?") -/// @{ - -IKARUS_BEGIN_HEADER - -struct IkarusTextProperty; - -/// \brief Creates a text property. -/// \param project The project to create the property in. -/// \pre \li Must not be null. -/// \pre \li Must exist. -/// \param name The name of the property. -/// \pre \li Must not be null. -/// \param property_source The property source to create the property for. -/// \pre \li Must not be null. -/// \pre \li Must exist. -/// \param default_value The default value for the property. -/// \pre \li Must not be null. -/// \param error_out \see errors.h -/// \return The created property or null if an error occurs. -IKA_API IkarusTextProperty * ikarus_text_property_create( - struct IkarusProject * project, - char const * name, - struct IkarusPropertySource * property_source, - struct IkarusTextValue * default_value, - IkarusErrorData * error_out -); - -IKARUS_END_HEADER - -/// @} diff --git a/include/ikarus/objects/properties/toggle_property.h b/include/ikarus/objects/properties/toggle_property.h deleted file mode 100644 index bfec311..0000000 --- a/include/ikarus/objects/properties/toggle_property.h +++ /dev/null @@ -1,37 +0,0 @@ -#pragma once - -/// \file toggle_property.h -/// \author Folling - -#include -#include - -/// \addtogroup properties Properties -/// @{ - -IKARUS_BEGIN_HEADER - -/// \brief Toggle properties store a value that can be either true or false. (e.g. "Is the character dead?") -struct IkarusToggleProperty; - -/// \brief Creates a toggle property. -/// \param project The project to create the property in. -/// \pre \li Must not be null. -/// \pre \li Must exist. -/// \param name The name of the property. -/// \pre \li Must not be null. -/// \param property_source The property source to create the property for. -/// \pre \li Must not be null. -/// \pre \li Must exist. -/// \param error_out \see errors.h -/// \return The created property or null if an error occurs. -IKA_API IkarusToggleProperty * ikarus_toggle_property_create( - struct IkarusProject * project, - char const * name, - struct IkarusPropertySource * property_source, - IkarusErrorData * error_out -); - -IKARUS_END_HEADER - -/// @} diff --git a/include/ikarus/objects/property.h b/include/ikarus/objects/property.h new file mode 100644 index 0000000..5bff42c --- /dev/null +++ b/include/ikarus/objects/property.h @@ -0,0 +1,143 @@ +#pragma once + +/// \file property.h +/// \author Folling + +#include +#include +#include + +/// \defgroup properties Properties +/// \brief Properties define the structure and types of data. +/// @{ + +IKARUS_BEGIN_HEADER + +/// \brief Properties define the structure of blueprints. +/// \details Each blueprint can have any number of properties. +/// Every property has a type that identifies the kind of data that can be put +/// in. This is the "base class" of properties. See the derived types (e.g. +/// IkarusToggleProperty) for more information. +/// +/// The following types currently exist: +/// - Toggle: A true/false boolean-like value +/// - Number: An arbitrary numeric value +/// - Text: An arbitrary textual value +/// +/// Property Examples: +/// - Is Dead (Toggle) +/// - Age (Number) +/// - ISBN (Text) +/// +/// Each entity associated with the property has a value for it. +/// +/// \remark Values for properties are lazily created to save space. +/// Fetching the value for some property of some entity will return the +/// property's default value if none is specified. +struct IkarusProperty; + +/// \brief Flags for creating a property. +enum IkarusPropertyCreateFlags { + /// \brief No flags. + IkarusPropertyCreateFlags_None = 0, +}; + +/// \brief Create a new property. +/// \param project The project to create the property in. +/// \pre \li Must not be null. +/// \pre \li Must exist. +/// \param name The name of the property. +/// \pre \li Must not be null. +/// \pre \li Must not be empty. +/// \param schema The schema of the property. +/// \pre \li Must not be null. +/// \param flags Flags for creating the property. +/// \param error_out \see errors.h +/// \return The created property or NULL if an error occurred. +/// \remark Must only be deleted with #ikarus_property_delete. +IKA_API IkarusProperty * ikarus_property_create( + struct IkarusProject * project, + char const * name, + struct IkarusValueSchema * schema, + IkarusPropertyCreateFlags flags, + IkarusErrorData * error_out +); + +/// \brief Flags for deleting a property. +enum IkarusPropertyDeleteFlags { + /// \brief No flags. + IkarusPropertyDeleteFlags_None = 0, +}; + +/// \brief Delete a property. +/// \param property The property to delete. +/// \param flags Flags for deleting the property. +/// \param error_out \see errors.h +IKA_API void ikarus_property_delete( + IkarusProperty * property, + IkarusPropertyDeleteFlags flags, + IkarusErrorData * error_out +); + +/// \brief Get the project a property belongs to. +/// \param property The property to get the project of. +/// \pre \li Must not be null. +/// \pre \li Must exist. +/// \param error_out \see errors.h +/// \return The project the property belongs to or null if an error occurred. +/// \remark Ownership remains with libikarus. +IKA_API struct IkarusProject * ikarus_property_get_project( + IkarusProperty * property, + IkarusErrorData * error_out +); + +/// \brief Get the name of a property. +/// \param property The property to get the name of. +/// \pre \li Must not be null. +/// \pre \li Must exist. +/// \param error_out \see errors.h +/// \return The name of the property or null if an error occurred. +/// \remark Ownership remains with libikarus. +IKA_API char const * ikarus_property_get_name( + IkarusProperty * property, + IkarusErrorData * error_out +); + +/// \brief Get the schema of a property. +/// \param property The property to get the schema of. +/// \pre \li Must not be null. +/// \pre \li Must exist. +/// \param error_out \see errors.h +/// \return The schema of the property or null if an error occurred. +/// \remark Ownership remains with libikarus. +IKA_API struct IkarusValueSchema * ikarus_property_get_schema( + IkarusProperty * property, + IkarusErrorData * error_out +); + +/// \brief Flags for setting the name of a property. +enum IkarusPropertySetNameFlags { + /// \brief No flags. + IkarusPropertySetNameFlags_None = 0, +}; + +/// \brief Set the name of a property. +/// \param property The property to set the name of. +/// \pre \li Must not be null. +/// \pre \li Must exist. +/// \param name The new name of the property. +/// \pre \li Must not be null. +/// \pre \li Must not be empty. +/// \param flags Flags for setting the name of the property. +/// \param error_out \see errors.h +/// \remark Ownership remains with the caller. +IKA_API void ikarus_property_set_name( + IkarusProperty * property, + char const * name, + IkarusPropertySetNameFlags flags, + IkarusErrorData * error_out +); + +IKARUS_END_HEADER + +/// @} diff --git a/include/ikarus/persistence/project.h b/include/ikarus/persistence/project.h index 74258a9..af40147 100644 --- a/include/ikarus/persistence/project.h +++ b/include/ikarus/persistence/project.h @@ -1,7 +1,9 @@ #pragma once /// \file project.h -/// \author Folling +/// \author Folling + +#include #include #include @@ -15,10 +17,19 @@ IKARUS_BEGIN_HEADER /// \brief An Ikarus project. -/// \details A project may only be open once at a time. Opening a project from two different locations Gets undefined +/// \details A project may only be open once at a time. +/// Opening a project from two different locations results in undefined /// behavior. struct IkarusProject; +/// \brief Flags for creating a project. +enum IkarusProjectCreateFlags { + /// \brief No flags. + IkarusProjectCreateFlags_None = 0, + /// \brief Allow overwriting existing files. + IkarusProjectCreateFlags_AllowOverwrite = 1 << 0, +}; + /// \brief Creates a persisted project on the filesystem. /// \param path The path to the project. /// \pre \li Must not be null. @@ -26,126 +37,168 @@ struct IkarusProject; /// \param name The name of the project. Must neither be null nor empty. /// \pre \li Must not be null. /// \pre \li Must not be empty. +/// \param flags Flags for creating the project. /// \param error_out \see errors.h /// \return The created project or null if an error occurs. -/// \remark Must be freed using #ikarus_free. Freeing does not delete the project from the filesystem. For that, use -/// ikarus_project_delete -IKA_API IkarusProject * ikarus_project_create( - char const * path, - char const * name, - IkarusErrorData * error_out +/// \remark Must be closed with #ikarus_project_close. +IKA_API struct IkarusProject * ikarus_project_create( + char const * path, + char const * name, + IkarusProjectCreateFlags flags, + IkarusErrorData * error_out ); -/// \brief Creates a project in memory. +/// \brief Flags for creating a project in memory. +enum IkarusProjectCreateInMemoryFlags { + /// \brief No flags. + IkarusProjectCreateInMemoryFlags_None = 0, +}; + +/// \brief Creates a project in memory. The project is not persisted. /// \param name The name of the project. Must neither be null nor empty. /// \pre \li Must not be null. /// \pre \li Must not be empty. +/// \param flags Flags for creating the project. /// \param error_out \see errors.h /// \return The created project or null if an error occurs. -/// \remark Must be freed using #ikarus_free. Freeing does not delete the project from the filesystem. For that, use -/// ikarus_project_delete -IKA_API IkarusProject * -ikarus_project_create_in_memory(char const * name, IkarusErrorData * error_out); +/// \remark Must be closed with #ikarus_project_close. +IKA_API struct IkarusProject * ikarus_project_create_in_memory( + char const * name, + IkarusProjectCreateInMemoryFlags flags, + IkarusErrorData * error_out +); + +/// \brief Flags for opening a project. +enum IkarusProjectOpenFlags { + /// \brief No flags. + IkarusProjectOpenFlags_None = 0, +}; /// \brief Opens an existing project. /// \param path The path to the project. /// \pre \li Must not be null. /// \pre \li Must point to an existing project on the system. +/// \param flags Flags for opening the project. /// \param error_out \see errors.h /// \return The opened project or null if an error occurs. -/// \remark Must be freed using ikarus_free. Freeing does not delete the project from the filesystem. For that, use -/// ikarus_project_delete -IKA_API IkarusProject * -ikarus_project_open(char const * path, IkarusErrorData * error_out); - -/// \brief Gets the name of a project. -/// \param project The project to get the name of. -/// \pre \li Must not be null. -/// \pre \li Must exist. -/// \param error_out \see errors.h -/// \return The name of the project. -/// \remark Ownership remains with libikarus, must not be freed. -IKA_API char const * ikarus_project_get_name( - IkarusProject const * project, - IkarusErrorData * error_out +/// \remark Must be closed with #ikarus_project_close. +IKA_API struct IkarusProject * ikarus_project_open( + char const * path, + IkarusProjectOpenFlags flags, + IkarusErrorData * error_out ); -/// \brief Sets the name of a project. -/// \param project The project to set the name of. +/// \brief Flags for closing a project in memory. +enum IkarusProjectCloseFlags { + /// \brief No flags. + IkarusProjectCloseFlags_None = 0, +}; + +/// \brief Closes a project. This function must be called to free resources. +/// \param project The project to close. +/// \pre \li Must not be null. +/// \pre \li Must be open. +/// \param flags Flags for closing the project. +/// \param error_out \see errors.h +/// \remark The project must not be used after closing. +/// \remark Does not delete the project from the filesystem. +/// \remark Mutually exclusive with #ikarus_project_delete. +IKA_API void ikarus_project_close( + struct IkarusProject * project, + IkarusProjectCloseFlags flags, + IkarusErrorData * error_out +); + +/// \brief Flags for deleting a project. +enum IkarusProjectDeleteFlags { + /// \brief No flags. + IkarusProjectDeleteFlags_None = 0, +}; + +/// \brief Deletes a project from the filesystem. +/// \param project The project to delete. /// \pre \li Must not be null. /// \pre \li Must exist. -/// \param new_name The new name of the project. -/// \pre \li Must not be null. -/// \pre \li Must not be empty. +/// \param flags Flags for deleting the project. /// \param error_out \see errors.h -IKA_API void ikarus_project_set_name( - IkarusProject * project, - char const * new_name, - IkarusErrorData * error_out +/// \remark The project must not be used after deletion. +/// \remark Mutually exclusive with #ikarus_project_close. +IKA_API void ikarus_project_delete( + struct IkarusProject * project, + IkarusProjectDeleteFlags flags, + IkarusErrorData * error_out +); + +/// \brief Gets the name of a project. +/// \param project The project to delete. +/// \pre \li Must not be null. +/// \pre \li Must exist. +/// \param error_out \see errors.h +/// \returns The name of the project or null if an error occurs. +IKA_API char const * ikarus_project_get_name( + struct IkarusProject const * project, + IkarusErrorData * error_out ); /// \brief Gets the path of a project. -/// \param project The project to get the path of. +/// \param project The project to delete. /// \pre \li Must not be null. /// \pre \li Must exist. /// \param error_out \see errors.h -/// \return The path of the project. -/// \remark Ownership remains with libikarus, must not be freed. +/// \returns The path of the project or null if an error occurs. IKA_API char const * ikarus_project_get_path( - IkarusProject const * project, - IkarusErrorData * error_out + struct IkarusProject const * project, + IkarusErrorData * error_out ); -/// \brief Gets the entities of a project. -/// \param project The project to get the entities of. +/// \brief Gets all entities in a project. +/// \param project The project from which to get the entities. /// \pre \li Must not be null. /// \pre \li Must exist. -/// \param entities_out The buffer to write the entities to. -/// \pre \li Must not be null. -/// \param entities_out_size The size of the buffer. +/// \param size_out An out parameter for the number of entities in the returned array +/// or undefined if an error occurs. /// \param error_out \see errors.h -IKA_API void ikarus_project_get_entities( - IkarusProject * project, - struct IkarusEntity ** entities_out, - size_t entities_out_size, - IkarusErrorData * error_out +/// \returns An array of entities or null if an error occurs. +IKA_API struct IkarusEntity ** ikarus_project_get_entities( + struct IkarusProject const * project, + size_t * size_out, + IkarusErrorData * error_out ); -/// \brief Gets the number of entities of a project. -/// \param project The project to get the number of entities of. +/// \brief Gets how many entities in a project there are. +/// \param project The project from which to get the count. /// \pre \li Must not be null. /// \pre \li Must exist. /// \param error_out \see errors.h -/// \return The number of entities or undefined if an error occurs. -IKA_API size_t ikarus_project_get_entity_count( - IkarusProject const * project, - IkarusErrorData * error_out +/// \return The count or 0 if an error occurs. +IKA_API size_t ikarus_project_get_entities_count( + IkarusProject const * project, + IkarusErrorData * error_out ); -/// \brief Gets the blueprints of a project. -/// \param project The project to get the blueprints of. +/// \brief Gets all blueprints from a project. +/// \param project The project from which to get the blueprints. /// \pre \li Must not be null. /// \pre \li Must exist. -/// \param blueprints_out The buffer to write the blueprints to. -/// \pre \li Must not be null. -/// \param blueprints_out_size The size of the buffer. +/// \param size_out An out parameter for the number of blueprints in the returned array +/// or undefined if an error occurs. /// \param error_out \see errors.h -IKA_API void ikarus_project_get_blueprints( - IkarusProject * project, - struct IkarusBlueprint ** blueprints_out, - size_t blueprints_out_size, - IkarusErrorData * error_out +/// \return An array of blueprints or null if an error occurs. +IKA_API struct IkarusBlueprint ** ikarus_project_get_blueprints( + struct IkarusProject const * project, + size_t * size_out, + IkarusErrorData * error_out ); -/// \brief Gets the number of blueprints of a project. -/// \param project The project to get the number of blueprints of. +/// \brief Gets how many blueprints in a project there are. +/// \param project The project from which to get the count. /// \pre \li Must not be null. /// \pre \li Must exist. /// \param error_out \see errors.h -/// \return The number of blueprints or undefined if an error occurs. -IKA_API size_t ikarus_project_get_blueprint_count( - IkarusProject const * project, - IkarusErrorData * error_out +/// \return The count or 0 if an error occurs. +IKA_API size_t ikarus_project_get_blueprints_count( + IkarusProject const * project, + IkarusErrorData * error_out ); IKARUS_END_HEADER diff --git a/include/ikarus/stdtypes.h b/include/ikarus/stdtypes.h index 4274e3f..71d07c2 100644 --- a/include/ikarus/stdtypes.h +++ b/include/ikarus/stdtypes.h @@ -1,10 +1,11 @@ #pragma once #ifdef __cplusplus -#include -#include + #include + #include using std::size_t; #else -#include -#include + #include + #include + #include #endif diff --git a/include/ikarus/values/data.h b/include/ikarus/values/data.h new file mode 100644 index 0000000..d4e2367 --- /dev/null +++ b/include/ikarus/values/data.h @@ -0,0 +1,48 @@ +#pragma once + +#include +#include +#include + +/// \file data.h +/// \author Folling + +/// \addtogroup values Values + +IKARUS_BEGIN_HEADER + +/// \brief Data stores the actual information of a value. +/// \details Data is schemaless and can store any kind of data. Only when the +/// data is combined with a schema does it become a value. \see value.h. +/// Given the complexity of data, they are transferred as json. +/// The json representation of a data is a map with the following keys: +/// - `type` The type of the data. \see IkarusValueDataType. Must be one of the +/// following: +/// - `Primitive` A primitive value. Has two additional key: +/// - `primitive` The type of the primitive. Must be one of the following: +/// - `data` The stored data. Must be either a bool, double, or string. +/// - `Constant` A constant value. Has no additional keys, as the constant +/// value is shared across all values. +/// - `List` A list of values. Has the following additional keys: +/// - `data` An array of stored data. +/// - `Map` A map of key-value pairs. Has the following additional keys: +/// - `data` An array of key-value pairs. +/// - `Tuple` A tuple of values. Has the following additional keys: +/// - `data` An array of stored data. +/// Note that each sub-data is also a data, allowing for arbitrarily nested data +/// structures. +struct IkarusValueData; + +/// \brief The type of data. +enum IkarusValueDataType { + /// \brief A primitive value. \see IkarusValuePrimitiveType. + IkarusValueDataType_Primitive = 1, + /// \brief A list of values. + IkarusValueDataType_List = 2, + /// \brief A map of key-value pairs. + IkarusValueDataType_Map = 3, + /// \brief A tuple of values. + IkarusValueDataType_Tuple = 4, +}; + +IKARUS_END_HEADER diff --git a/include/ikarus/values/number_value.h b/include/ikarus/values/number_value.h deleted file mode 100644 index 220a11c..0000000 --- a/include/ikarus/values/number_value.h +++ /dev/null @@ -1,109 +0,0 @@ -#pragma once - -/// \file number_value.h -/// \author Folling - -#include -#include -#include - -/// \addtogroup values Values -/// @{ - -IKARUS_BEGIN_HEADER - -/// \brief A numeric value. For example "Age" or "Height". -struct IkarusNumberValue; - -/// \brief Creates an empty number value. -/// \details If the cardinality is "Single", the value will be initialized with 0.0. -/// \param cardinality The cardinality of the value. -/// \param error_out \see errors.h -/// \return The value or null if an error occurs. -IKA_API IkarusNumberValue * ikarus_number_value_create(IkarusValueCardinality cardinality, IkarusErrorData * error_out); - -/// \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. -/// \param error_out \see errors.h -/// \return The underlying data or NaN if an error occurs. -IKA_API double ikarus_number_value_get(IkarusNumberValue const * value, size_t idx, IkarusErrorData * error_out); - -/// \brief Fetches the size of the underlying data of a number value. -/// \param value The number value. -/// \pre \li Must not be null. -/// \param error_out \see errors.h -/// \return The size of the underlying data or 0 if an error occurs. -IKA_API size_t ikarus_number_value_get_size(IkarusNumberValue const * value, IkarusErrorData * error_out); - -/// \brief Sets the 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 set. -/// \pre \li Must be less than the size of the value. -/// \param new_data The new data. -/// \param error_out \see errors.h -IKA_API void ikarus_number_value_set(IkarusNumberValue * value, size_t idx, double new_data, IkarusErrorData * error_out); - -/// \brief Inserts a data into a number value. -/// \param value The number value. -/// \pre \li Must not be null. -/// \pre \li Cardinality must be "Multiple". -/// \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. -/// \param error_out \see errors.h -IKA_API void ikarus_number_value_insert(IkarusNumberValue * value, size_t idx, double new_data, IkarusErrorData * error_out); - -/// \brief Removes a data from a number value. -/// \param value The number value. -/// \pre \li Must not be null. -/// \pre \li Cardinality must be "Multiple". -/// \param idx The index of the data to remove. -/// \pre \li Must be less than the size of the value. -/// \param error_out \see errors.h -IKA_API void ikarus_number_value_remove(IkarusNumberValue * value, size_t idx, IkarusErrorData * error_out); - -/// \brief Clears a number value. -/// \param value The number value. -/// \pre \li Cardinality must be "Multiple". -/// \param error_out \see errors.h -IKA_API void ikarus_number_value_clear(IkarusNumberValue * value, IkarusErrorData * error_out); - -/// \brief Converts a number value to a string. -/// \param value The number value to convert. -/// \pre \li Must not be null. -/// \param error_out \see errors.h -/// \return The converted string. -/// \remark Must be freed with #ikarus_free. -IKA_API char const * ikarus_number_value_to_string(IkarusNumberValue const * value, IkarusErrorData * error_out); - -/// \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. -/// \param error_out \see errors.h -/// \return True if the values' data are equal, false otherwise. -IKA_API bool ikarus_number_value_is_equal(IkarusNumberValue const * lhs, IkarusNumberValue const * rhs, IkarusErrorData * error_out); - -/// \brief Creates a copy of a number value. -/// \param value The value to copy. -/// \pre \li Must not be null. -/// \param error_out \see errors.h -/// \return The copied value. -IKA_API IkarusNumberValue * ikarus_number_value_copy(IkarusNumberValue const * value, IkarusErrorData * error_out); - -/// \brief Converts a number value to an entity value. -/// \param value The number value to convert. -/// \pre \li Must not be null. -/// \param error_out \see errors.h -/// \return The converted entity value. -/// \remark This is the same pointer, so freeing it implies freeing the original value. -IKA_API struct IkarusValueData * ikarus_number_value_to_value(IkarusNumberValue * value, IkarusErrorData * error_out); - -IKARUS_END_HEADER - -/// @} diff --git a/include/ikarus/values/schema.h b/include/ikarus/values/schema.h new file mode 100644 index 0000000..9e25e01 --- /dev/null +++ b/include/ikarus/values/schema.h @@ -0,0 +1,58 @@ +#pragma once + +#include +#include +#include + +/// \file schema.h +/// \author Folling + +/// \addtogroup values Values + +IKARUS_BEGIN_HEADER + +/// \brief Schemas define the type of value. +/// \details Schemas are used to define the type of value. They are akin to +/// classes in programming languages. +/// Schemas are used to validate values and structure data. +/// +/// Given the complexity of schemas, they are transferred as json. +/// The json representation of a schema is a map with the following keys: +/// - `type` The type of the schema. Must be one of the following: +/// - `Primitive` A primitive value. Has the following additional keys: +/// - `primitive` The type of the primitive value. \see IkarusPrimitiveType. +/// - `Constant` A constant value. Has the following additional keys: +/// - `value` The constant value, shared across all values of the schema. +/// \see value.h. \remark The schema is derived from the value. +/// - `List` A list of values. Has the following additional keys: +/// - `schema` The schema of the values in the list. +/// - `Map` A map of key-value pairs. Has the following additional keys: +/// - `key_schema` The schema of the keys. +/// - `value_schema` The schema of the values. +/// - `Tuple` A tuple of values. Has the following additional keys: +/// - `schemas` The schemas of the values in the tuple. +struct IkarusSchema; + +/// \brief The type of primitive data. +enum IkarusValuePrimitiveType { + /// \brief A boolean. + IkarusValuePrimitiveType_Toggle = 1, + /// \brief A 64-bit floating point number. + IkarusValuePrimitiveType_Number = 2, + /// \brief An arbitrary length string. + IkarusValuePrimitiveType_Text = 3 +}; + +/// \brief The type of schema. +enum IkarusValueSchemaType { + /// \brief A primitive value. \see IkarusPrimitiveType + IkarusValueSchemaType_Primitive = 1, + /// \brief A homogeneous list of values. + IkarusValueSchemaType_List = 2, + /// \brief A mapping from Value->Value. + IkarusValueSchemaType_Map = 3, + /// \brief A heterogeneous list of values. + IkarusValueSchemaType_Tuple = 4 +}; + +IKARUS_END_HEADER diff --git a/include/ikarus/values/text_value.h b/include/ikarus/values/text_value.h deleted file mode 100644 index 3b7d978..0000000 --- a/include/ikarus/values/text_value.h +++ /dev/null @@ -1,109 +0,0 @@ -#pragma once - -/// \file text_value.h -/// \author Folling - -#include -#include -#include - -/// \addtogroup values Values -/// @{ - -IKARUS_BEGIN_HEADER - -/// \brief A numeric value. For example "Age" or "Height". -struct IkarusTextValue; - -/// \brief Creates an empty text value. -/// \details If the cardinality is "Single", the value will be initialized with 0.0. -/// \param cardinality The cardinality of the value. -/// \param error_out \see errors.h -/// \return The value or null if an error occurs. -IKA_API IkarusTextValue * ikarus_text_value_create(IkarusValueCardinality cardinality, IkarusErrorData * error_out); - -/// \brief Fetches the underlying data of a text value at a specific index. -/// \param value The text 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. -/// \param error_out \see errors.h -/// \return The underlying data or NaN if an error occurs. -IKA_API char const * ikarus_text_value_get(IkarusTextValue const * value, size_t idx, IkarusErrorData * error_out); - -/// \brief Fetches the size of the underlying data of a text value. -/// \param value The text value. -/// \pre \li Must not be null. -/// \param error_out \see errors.h -/// \return The size of the underlying data or 0 if an error occurs. -IKA_API size_t ikarus_text_value_get_size(IkarusTextValue const * value, IkarusErrorData * error_out); - -/// \brief Sets the data of a text value at a specific index. -/// \param value The text 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 error_out \see errors.h -IKA_API void ikarus_text_value_set(IkarusTextValue * value, size_t idx, char const * new_data, IkarusErrorData * error_out); - -/// \brief Inserts a data into a text value. -/// \param value The text value. -/// \pre \li Must not be null. -/// \pre \li Cardinality must be "Multiple". -/// \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. -/// \param error_out \see errors.h -IKA_API void ikarus_text_value_insert(IkarusTextValue * value, size_t idx, char const * new_data, IkarusErrorData * error_out); - -/// \brief Removes a data from a text value. -/// \param value The text value. -/// \pre \li Must not be null. -/// \pre \li Cardinality must be "Multiple". -/// \param idx The index of the data to remove. -/// \pre \li Must be less than the size of the value. -/// \param error_out \see errors.h -IKA_API void ikarus_text_value_remove(IkarusTextValue * value, size_t idx, IkarusErrorData * error_out); - -/// \brief Clears a text value. -/// \param value The text value. -/// \pre \li Cardinality must be "Multiple". -/// \param error_out \see errors.h -IKA_API void ikarus_text_value_clear(IkarusTextValue * value, IkarusErrorData * error_out); - -/// \brief Converts a text value to a string. -/// \param value The text value to convert. -/// \pre \li Must not be null. -/// \param error_out \see errors.h -/// \return The converted string. -/// \remark Must be freed with #ikarus_free. -IKA_API char const * ikarus_text_value_to_string(IkarusTextValue const * value, IkarusErrorData * error_out); - -/// \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. -/// \param error_out \see errors.h -/// \return True if the values' data are equal, false otherwise. -IKA_API bool ikarus_text_value_is_equal(IkarusTextValue const * lhs, IkarusTextValue const * rhs, IkarusErrorData * error_out); - -/// \brief Creates a copy of a text value. -/// \param value The value to copy. -/// \pre \li Must not be null. -/// \param error_out \see errors.h -/// \return The copied value. -IKA_API IkarusTextValue * ikarus_text_value_copy(IkarusTextValue const * value, IkarusErrorData * error_out); - -/// \brief Converts a text value to an entity value. -/// \param value The text value to convert. -/// \pre \li Must not be null. -/// \param error_out \see errors.h -/// \return The converted entity value. -/// \remark This is the same pointer, so freeing it implies freeing the original value. -IKA_API struct IkarusValueData * ikarus_text_value_to_value(IkarusTextValue * value, IkarusErrorData * error_out); - -IKARUS_END_HEADER - -/// @} diff --git a/include/ikarus/values/toggle_value.h b/include/ikarus/values/toggle_value.h deleted file mode 100644 index 05c5ddc..0000000 --- a/include/ikarus/values/toggle_value.h +++ /dev/null @@ -1,109 +0,0 @@ -#pragma once - -/// \file toggle_value.h -/// \author Folling - -#include -#include -#include - -/// \addtogroup values Values -/// @{ - -IKARUS_BEGIN_HEADER - -/// \brief A numeric value. For example "Age" or "Height". -struct IkarusToggleValue; - -/// \brief Creates an empty toggle value. -/// \details If the cardinality is "Single", the value will be initialized with 0.0. -/// \param cardinality The cardinality of the value. -/// \param error_out \see errors.h -/// \return The value or null if an error occurs. -IKA_API IkarusToggleValue * ikarus_toggle_value_create(IkarusValueCardinality cardinality, IkarusErrorData * error_out); - -/// \brief Fetches the underlying data of a toggle value at a specific index. -/// \param value The toggle 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. -/// \param error_out \see errors.h -/// \return The underlying data or NaN if an error occurs. -IKA_API bool ikarus_toggle_value_get(IkarusToggleValue const * value, size_t idx, IkarusErrorData * error_out); - -/// \brief Fetches the size of the underlying data of a toggle value. -/// \param value The toggle value. -/// \pre \li Must not be null. -/// \param error_out \see errors.h -/// \return The size of the underlying data or 0 if an error occurs. -IKA_API size_t ikarus_toggle_value_get_size(IkarusToggleValue const * value, IkarusErrorData * error_out); - -/// \brief Sets the data of a toggle value at a specific index. -/// \param value The toggle 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 error_out \see errors.h -IKA_API void ikarus_toggle_value_set(IkarusToggleValue * value, size_t idx, bool new_data, IkarusErrorData * error_out); - -/// \brief Inserts a data into a toggle value. -/// \param value The toggle value. -/// \pre \li Must not be null. -/// \pre \li Cardinality must be "Multiple". -/// \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. -/// \param error_out \see errors.h -IKA_API void ikarus_toggle_value_insert(IkarusToggleValue * value, size_t idx, bool new_data, IkarusErrorData * error_out); - -/// \brief Removes a data from a toggle value. -/// \param value The toggle value. -/// \pre \li Must not be null. -/// \pre \li Cardinality must be "Multiple". -/// \param idx The index of the data to remove. -/// \pre \li Must be less than the size of the value. -/// \param error_out \see errors.h -IKA_API void ikarus_toggle_value_remove(IkarusToggleValue * value, size_t idx, IkarusErrorData * error_out); - -/// \brief Clears a toggle value. -/// \param value The toggle value. -/// \pre \li Cardinality must be "Multiple". -/// \param error_out \see errors.h -IKA_API void ikarus_toggle_value_clear(IkarusToggleValue * value, IkarusErrorData * error_out); - -/// \brief Converts a toggle value to a string. -/// \param value The toggle value to convert. -/// \pre \li Must not be null. -/// \param error_out \see errors.h -/// \return The converted string. -/// \remark Must be freed with #ikarus_free. -IKA_API char const * ikarus_toggle_value_to_string(IkarusToggleValue const * value, IkarusErrorData * error_out); - -/// \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. -/// \param error_out \see errors.h -/// \return True if the values' data are equal, false otherwise. -IKA_API bool ikarus_toggle_value_is_equal(IkarusToggleValue const * lhs, IkarusToggleValue const * rhs, IkarusErrorData * error_out); - -/// \brief Creates a copy of a toggle value. -/// \param value The value to copy. -/// \pre \li Must not be null. -/// \param error_out \see errors.h -/// \return The copied value. -IKA_API IkarusToggleValue * ikarus_toggle_value_copy(IkarusToggleValue const * value, IkarusErrorData * error_out); - -/// \brief Converts a toggle value to an entity value. -/// \param value The toggle value to convert. -/// \pre \li Must not be null. -/// \param error_out \see errors.h -/// \return The converted entity value. -/// \remark This is the same pointer, so freeing it implies freeing the original value. -IKA_API struct IkarusValueData * ikarus_toggle_value_to_value(IkarusToggleValue * value, IkarusErrorData * error_out); - -IKARUS_END_HEADER - -/// @} diff --git a/include/ikarus/values/value.h b/include/ikarus/values/value.h index aec86ac..870f551 100644 --- a/include/ikarus/values/value.h +++ b/include/ikarus/values/value.h @@ -1,61 +1,26 @@ #pragma once -/// \file value.h -/// \author Folling - -/// \defgroup values Values -/// \brief Values are data in entities. -/// \details An entity is made up of any number of values. -/// Each value defines a certain aspect of an entity. -/// Values have a name, a type, and some data. -/// Examples of values would be: -/// - Is Dead (Toggle) -/// - Age (Number) -/// - ISBN (Text) -/// -/// Values are either single or multiple. -/// We call this property "Cardinality" (\see IkarusValueCardinality) -/// because it's really hard to find a simpler name. -/// Each piece of data within a value is called a "datapoint". -/// Single values have exactly one datapoint, multiple values have any number of -/// datapoints. For example "Age" would be singular, while "Nicknames" would be -/// multiple. The type is unaffected by this. A pendant in programming languages -/// would be a List. Note that all values are stored as a list of items, -/// even if the value is singular. Single values effectively act as a list with -/// one element. This is enforced by the API at runtime. -/// -/// For a comprehensive list of value types, see \ref IkarusValueType. -/// @{ - #include #include +#include + +/// \file value.h +/// \author Folling + +/// \defgroup entities Entities +/// \brief Entities are the core building blocks of Ikarus. IKARUS_BEGIN_HEADER -/// \brief The common type for all value data. -struct IkarusValue; - -/// \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. -/// \remark Skipped if null. -/// \param number_visitor The function to call if the value is a number value. -/// \remark Skipped if null. -/// \param text_visitor The function to call if the value is a text value. -/// \remark Skipped if null. -/// \param data The data passed to the visitor functions. -/// \param error_out \see errors.h -IKA_API void ikarus_value_visit( - IkarusValue * value, - void (*toggle_visitor)(struct IkarusToggleValue *, void *), - void (*number_visitor)(struct IkarusNumberValue *, void *), - void (*text_visitor)(struct IkarusTextValue *, void *), - void * data, - IkarusErrorData * error_out -); +/// \brief Values are data containers for entities. +/// \details Values are flexible enough to store any kind of data. They are +/// akin to objects in programming languages. +/// Each value has a schema that defines the type of the value. \see schema.h +/// They also store data appropriate for the schema. +/// +/// Given the complexity of values, they are transferred as json. +/// The json representation of a value is a map with the following keys: +/// - `schema`: The schema of the value. \see schema.h. +/// - `data`: The data of the value. \see data.h. IKARUS_END_HEADER - -/// @} diff --git a/include/ikarus/values/value_cardinality.h b/include/ikarus/values/value_cardinality.h deleted file mode 100644 index 6d5526f..0000000 --- a/include/ikarus/values/value_cardinality.h +++ /dev/null @@ -1,23 +0,0 @@ -#pragma once - -/// \file value_cardinality.h -/// \author Folling - -/// \addtogroup values Values -/// @{ - -#include - -IKARUS_BEGIN_HEADER - -/// \brief The cardinality of a value. -enum IkarusValueCardinality { - /// \brief Only contains one datapoint - IkarusValueCardinality_Single, - /// \brief Contains any number of datapoints - IkarusValueCardinality_List -}; - -IKARUS_END_HEADER - -/// @} diff --git a/include/ikarus/values/value_type.h b/include/ikarus/values/value_type.h deleted file mode 100644 index caa6165..0000000 --- a/include/ikarus/values/value_type.h +++ /dev/null @@ -1,198 +0,0 @@ -#pragma once - -/// \file value_schema.h -/// \author Folling - -/// \addtogroup values Values -/// @{ - -#include -#include -#include - -IKARUS_BEGIN_HEADER - -/// \brief Layouts define the structure and constraints of values. -/// \details Ikarus lets you define any schema for values and add constraints to them. -/// These schemas are assembled hierarchical and are akin to JSON schemas. -/// Layouts may be arbitrarily nested and combined e.g.: -/// Combination, Number, Complex<"Foo":Toggle,"Bar":Text> -struct IkarusValueLayout; -/// \brief A fixed datapoint with a fixed layout. -/// Example: Age: Union> -struct IkarusValueLayoutConstant; -/// \brief A singular datapoint with one of a list of layouts. -/// Example: ChestReward: Combination -struct IkarusValueLayoutCombination; -/// \brief A collection of datapoints with a homogenous layout. -/// Example: Friends: List -struct IkarusValueLayoutList; -/// \brief A collection of nameable datapoints with heterogeneous layouts. -/// Example: GeoLocation: Complex<"Latitude":Number, "Longitude":Number> -struct IkarusValueLayoutComplex; - -/// \brief Defines the type of datapoints. -enum IkarusValueDataType { - /// \brief Boolean datapoints - /// Example: Is the character alive? Yes - Toggle, - /// \brief Numeric datapoints - /// Example: How much does the character weigh? 57kg - Number, - /// \brief Textual datapoints - /// Example: What is the character's maiden name? Sandra - Text, - /// \brief A colour datapoint - /// Example: What colours make up the nation's flag? White/Pink/Blue. - /// \remark Not yet implemented - Colour, - /// \brief A date/time datapoint, interfacing with the calendar and timeline feature. - /// Example: When was the city founded? 12th of January 233 at 2:11 - /// \remark Not yet implemented - Time, - /// \brief A location datapoint, interfacing with the map feature. - /// Example: Where is the city situated? 12.345, 67.890 - /// \remark Not yet implemented - Location, - /// \brief An enum-esque datapoint - /// Example: Of which rarity is the weapon? Normal/Rare/Legendary - /// \remark Not yet implemented - Choice, - /// \brief A datapoint linking to some other object in Ikarus - /// Example: Who wrote this hymn? Peter Parker - /// \remark Not yet implemented - Reference -}; - -/// \brief Stores either a schema or a datatype -struct IkarusValueSchema; - -/// \see ikarus_value_schema_from_layout_const -IkarusValueSchema * ikarus_value_schema_from_layout( - IkarusValueLayout * layout, - IkarusErrorData * error_out -); - -/// \brief Creates a value schema from a layout. -/// \param layout The layout to create the schema from. -/// \pre \li Must not be null. -/// \param error_out \see errors.h -/// \return The created schema or null if an error occurs. -IkarusValueSchema const * ikarus_value_schema_from_layout_const( - IkarusValueLayout const * layout, - IkarusErrorData * error_out -); - -/// \brief Creates a value schema from a datatype. -/// \param type The datatype to create the schema from. -/// \param error_out \see errors.h -/// \return The created schema or null if an error occurs. -IkarusValueSchema * ikarus_value_schema_from_data_type( - IkarusValueDataType type, - IkarusErrorData * error_out -); - -/// \brief Frees a value schema. -/// \param schema The schema to free. -/// \pre \li Must not be null. -/// \remark Must not be accessed after freeing. -void ikarus_value_schema_free(IkarusValueSchema * schema); - -/// \see ikarus_value_schema_visit_const -void ikarus_value_schema_visit( - IkarusValueSchema * schema, - void (*layout_visitor)(IkarusValueLayout * layout), - void (*data_type_visitor)(IkarusValueDataType type), - IkarusErrorData * error_out -); - -/// \brief Visits a value schema. -/// \param schema The schema to visit. -/// \pre \li Must not be null. -/// \param layout_visitor The function to call if the schema is a layout. Skipped if null. -/// \param data_type_visitor The function to call if the schema is a datatype. Skipped if null. -void ikarus_value_schema_visit_const( - IkarusValueSchema const * schema, - void (*layout_visitor)(IkarusValueLayout const * layout), - void (*data_type_visitor)(IkarusValueDataType type), - IkarusErrorData * error_out -); - -/// \brief Creates a constant layout. -/// \param schema The schema of the value. -/// \pre \li Must not be null. -/// \param value The value of the constant. -/// \pre \li Must not be null. -/// \param error_out \see errors.h -IkarusValueLayoutConstant * ikarus_value_layout_constant_create( - IkarusValueSchema * schema, - struct IkarusValue * value, - IkarusErrorData * error_out -); - -/// \brief Gets the underyling schema of a constant layout. -/// \param layout The layout to get the underyling schema of. -/// \pre \li Must not be null. -/// \param error_out \see errors.h -/// \return The underlying schema of the layout or null if an error occurs. -IkarusValueSchema const * ikarus_value_layout_constant_get_underyling_schema( - IkarusValueLayoutConstant const * layout, - IkarusErrorData * error_out -); - -/// \brief Gets the underyling value of a constant layout. -/// \param layout The layout to get the underyling value of. -/// \pre \li Must not be null. -/// \param error_out \see errors.h -/// \return The underlying value of the layout or null if an error occurs. -struct IkarusValue const * ikarus_value_layout_constant_get_underlying_value( - IkarusValueLayoutConstant const * layout, - IkarusErrorData * error_out -); - -/// \brief Creates a combination layout. -/// \param schemas The schemas of the values. -/// \pre \li Must not be null. -/// \param schemas_size The number of schemas. -/// \param error_out \see errors.h -/// \return The created layout or null if an error occurs. -/// \remark The schemas are copied. -IkarusValueLayoutCombination * ikarus_value_layout_combination_create( - IkarusValueSchema * schemas, - size_t schemas_size, - IkarusErrorData * error_out -); - -void ikarus_value_layout_combination_get_schemas( - IkarusValueLayoutCombination const * layout, - IkarusValueSchema ** schemas_out, - size_t * schemas_size_out, - IkarusErrorData * error_out -); - -size_t ikarus_value_layout_combination_get_schemas_count( - IkarusValueLayoutCombination const * layout, - IkarusErrorData * error_out -); - -IkarusValueLayoutList * ikarus_value_layout_list_create( - IkarusValueSchema * schema, - IkarusErrorData * error_out -); - -IkarusValueLayoutComplex * ikarus_value_layout_complex_create( - IkarusValueSchema * schemas, - size_t schemas_size, - IkarusErrorData * error_out -); - -IkarusValueLayoutComplex * ikarus_value_layout_complex_create_named( - IkarusValueSchema * schemas, - char const ** names, - size_t schemas_size, - IkarusErrorData * error_out -); - -IKARUS_END_HEADER - -/// @} diff --git a/include/module.modulemap b/include/module.modulemap deleted file mode 100644 index 6b2dbcb..0000000 --- a/include/module.modulemap +++ /dev/null @@ -1,6 +0,0 @@ -module ikarus { - header "ikarus/persistence/project.h" - header "ikarus/objects/entity.h" - header "ikarus/objects/blueprint.h" - export * -} \ No newline at end of file diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 0963d2e..b928e93 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -7,4 +7,4 @@ file( "*.c" ) -set(SOURCE_FILES ${FILES} PARENT_SCOPE) \ No newline at end of file +set(SOURCE_FILES ${FILES} PARENT_SCOPE) diff --git a/src/ikarus/errors.cpp b/src/ikarus/errors.cpp index 8f8ff3c..b3e4ae2 100644 --- a/src/ikarus/errors.cpp +++ b/src/ikarus/errors.cpp @@ -1,41 +1,72 @@ #include "ikarus/errors.h" +#include + +#include + +void safe_strcpy( + std::string_view const src, + char * dest, + std::size_t const dest_size +) { + int i = 0; + for (; i < dest_size - 1; ++i) { + if (src[i] == '\0') { + break; + } + + dest[i] = src[i]; + } + + dest[i] = '\0'; +} + char const * ikarus_get_error_info_name(IkarusErrorInfo info) { - switch (info) { - case IkarusErrorInfo_None: return "None"; + switch (info) { + case IkarusErrorInfo_None: return "None"; - case IkarusErrorInfo_Client_Misuse: return "Client::Misuse"; - case IkarusErrorInfo_Client_InvalidInput: return "Client::InvalidInput"; - case IkarusErrorInfo_Client_InvalidFormat: return "Client::InvalidFormat"; - case IkarusErrorInfo_Client_ConstraintViolated: return "Client::ConstraintViolated"; + case IkarusErrorInfo_Client_Misuse: return "Client::Misuse"; + case IkarusErrorInfo_Client_InvalidInput: return "Client::InvalidInput"; + case IkarusErrorInfo_Client_NonExistent: return "Client::NonExistent"; + case IkarusErrorInfo_Client_InvalidFormat: return "Client::InvalidFormat"; + case IkarusErrorInfo_Client_ConstraintViolated: + return "Client::ConstraintViolated"; - case IkarusErrorInfo_Filesystem_NotFound: return "Filesystem::NotFound"; - case IkarusErrorInfo_Filesystem_AlreadyExists: return "Filesystem::AlreadyExists"; - case IkarusErrorInfo_Filesystem_MissingPermissions: return "Filesystem::MissingPermissions"; - case IkarusErrorInfo_Filesystem_InsufficientSpace: return "Filesystem::InsufficientSpace"; - case IkarusErrorInfo_Filesystem_InvalidPath: return "Filesystem::InvalidPath"; + case IkarusErrorInfo_Filesystem_NotFound: return "Filesystem::NotFound"; + case IkarusErrorInfo_Filesystem_AlreadyExists: + return "Filesystem::AlreadyExists"; + case IkarusErrorInfo_Filesystem_MissingPermissions: + return "Filesystem::MissingPermissions"; + case IkarusErrorInfo_Filesystem_InsufficientSpace: + return "Filesystem::InsufficientSpace"; + case IkarusErrorInfo_Filesystem_InvalidPath: + return "Filesystem::InvalidPath"; - case IkarusErrorInfo_Database_ConnectionFailed: return "Database::ConnectionFailed"; - case IkarusErrorInfo_Database_QueryFailed: return "Database::QueryFailed"; - case IkarusErrorInfo_Database_MigrationFailed: return "Database::MigrationFailed"; - case IkarusErrorInfo_Database_InvalidState: return "Database::InvalidState"; + case IkarusErrorInfo_Database_ConnectionFailed: + return "Database::ConnectionFailed"; + case IkarusErrorInfo_Database_QueryFailed: return "Database::QueryFailed"; + case IkarusErrorInfo_Database_MigrationFailed: + return "Database::MigrationFailed"; + case IkarusErrorInfo_Database_InvalidState: return "Database::InvalidState"; - case IkarusErrorInfo_OS_SystemCallFailed: return "OS::SystemCallFailed"; - case IkarusErrorInfo_OS_InvalidReturnValue: return "OS::InvalidReturnValue"; - case IkarusErrorInfo_OS_InsufficientMemory: return "OS::InsufficientMemory"; + case IkarusErrorInfo_OS_SystemCallFailed: return "OS::SystemCallFailed"; + case IkarusErrorInfo_OS_InvalidReturnValue: return "OS::InvalidReturnValue"; + case IkarusErrorInfo_OS_InsufficientMemory: return "OS::InsufficientMemory"; - case IkarusErrorInfo_LibIkarus_InvalidState: return "LibIkarus::InvalidState"; - case IkarusErrorInfo_LibIkarus_CannotPerformOperation: return "LibIkarus::CannotPerformOperation"; - case IkarusErrorInfo_LibIkarus_Timeout: return "LibIkarus::Timeout"; + case IkarusErrorInfo_LibIkarus_InvalidState: + return "LibIkarus::InvalidState"; + case IkarusErrorInfo_LibIkarus_CannotPerformOperation: + return "LibIkarus::CannotPerformOperation"; + case IkarusErrorInfo_LibIkarus_Timeout: return "LibIkarus::Timeout"; - default: return "Invalid"; - } + default: return "Invalid"; + } } bool ikarus_error_data_is_success(IkarusErrorData const * data) { - return data->info == IkarusErrorInfo_None; + return data->info == IkarusErrorInfo_None; } bool ikarus_error_data_is_error(IkarusErrorData const * data) { - return data->info != IkarusErrorInfo_None; + return data->info != IkarusErrorInfo_None; } diff --git a/src/ikarus/errors.hpp b/src/ikarus/errors.hpp index e12a68f..55b3e8f 100644 --- a/src/ikarus/errors.hpp +++ b/src/ikarus/errors.hpp @@ -1,80 +1,169 @@ #pragma once #include +#include #include -inline void safe_strcpy(char * dest, std::string_view src, size_t dest_size) { - for (int i = 0; i < dest_size; ++i) { - if (src[i] == '\0') { - dest[i] = '\0'; - return; - } +void safe_strcpy( + std::string_view const src, + char * dest, + size_t const dest_size +); - dest[i] = src[i]; - } -} - -#define IKARUS_SET_ERROR(msg, err_info) \ - if (error_out != nullptr) { \ - safe_strcpy(static_cast(error_out->message), msg, IKARUS_ERROR_DATA_MAX_MESSAGE_LIMIT); \ - error_out->info = err_info; \ - } +#define IKARUS_SET_ERROR(msg, err_info) \ + if (error_out != nullptr) { \ + safe_strcpy( \ + msg, \ + static_cast(error_out->message), \ + IKARUS_ERROR_DATA_MAX_MESSAGE_LIMIT \ + ); \ + error_out->info = err_info; \ + } #define IKARUS_FAIL(ret, msg, err_info) \ - IKARUS_SET_ERROR(msg, err_info); \ - return ret + IKARUS_SET_ERROR(msg, err_info); \ + return ret #define IKARUS_FAIL_IF(condition, ret, msg, err_info) \ - if (condition) { \ - IKARUS_SET_ERROR(msg, err_info) \ - return ret; \ - } + if (condition) { \ + IKARUS_SET_ERROR(msg, err_info) \ + return ret; \ + } -#define IKARUS_FAIL_IF_ERROR(ret) \ - if (ikarus_error_data_is_error(error_out)) { \ - return ret; \ - } +#define IKARUS_TRY_OR_FAIL_IMPL(var_name, msg, err_info, ...) \ + auto var_name = __VA_ARGS__; \ + if (var_name.is_error()) { \ + IKARUS_SET_ERROR( \ + fmt::format( \ + fmt::runtime(msg), \ + std::move(var_name).unwrap_error() \ + ), \ + err_info \ + ); \ + return var_name; \ + } -#define IKARUS_FAIL_IF_NULL(ptr, ret) IKARUS_FAIL_IF(((ptr) == nullptr), ret, #ptr " must not be null", IkarusErrorInfo_Client_InvalidNull) +#define IKARUS_TRY_OR_FAIL(msg, err_info, ...) \ + IKARUS_TRY_OR_FAIL_IMPL( \ + CPPBASE_UNIQUE_NAME(result), \ + msg, \ + err_info, \ + __VA_ARGS__ \ + ); -#define IKARUS_TRY_OR_FAIL_IMPL(var_name, msg, err_info, ...) \ - auto var_name = __VA_ARGS__; \ - if (var_name.is_error()) { \ - IKARUS_SET_ERROR(fmt::format(msg, var_name.unwrap_error()), err_info); \ - return var_name; \ - } - -#define IKARUS_TRY_OR_FAIL(msg, err_info, ...) IKARUS_TRY_OR_FAIL_IMPL(CPPBASE_UNIQUE_NAME(result), msg, err_info, __VA_ARGS__); - -#define IKARUS_TRYRV_OR_FAIL_IMPL(var_name, ret, msg, err_info, ...) \ - auto var_name = __VA_ARGS__; \ - if (var_name.is_error()) { \ - IKARUS_SET_ERROR(fmt::format(msg, var_name.unwrap_error()), err_info); \ - return ret; \ - } +#define IKARUS_TRYRV_OR_FAIL_IMPL(var_name, ret, msg, err_info, ...) \ + auto var_name = __VA_ARGS__; \ + if (var_name.is_error()) { \ + IKARUS_SET_ERROR( \ + fmt::format( \ + fmt::runtime(msg), \ + std::move(var_name).unwrap_error() \ + ), \ + err_info \ + ); \ + return ret; \ + } #define IKARUS_TRYRV_OR_FAIL(ret, msg, err_info, ...) \ - IKARUS_TRYRV_OR_FAIL_IMPL(CPPBASE_UNIQUE_NAME(result), ret, msg, err_info, __VA_ARGS__); + IKARUS_TRYRV_OR_FAIL_IMPL( \ + CPPBASE_UNIQUE_NAME(result), \ + ret, \ + msg, \ + err_info, \ + __VA_ARGS__ \ + ); -#define IKARUS_VTRY_OR_FAIL_IMPL(var_name, value, msg, err_info, ...) \ - auto var_name = __VA_ARGS__; \ - if (var_name.is_error()) { \ - IKARUS_SET_ERROR(fmt::format(msg, var_name.unwrap_error()), err_info); \ - return var_name; \ - } \ - value = var_name.unwrap_value() +#define IKARUS_VTRY_OR_FAIL_IMPL(var_name, value, msg, err_info, ...) \ + auto var_name = __VA_ARGS__; \ + if (var_name.is_error()) { \ + IKARUS_SET_ERROR( \ + fmt::format( \ + fmt::runtime(msg), \ + std::move(var_name).unwrap_error() \ + ), \ + err_info \ + ); \ + return var_name; \ + } \ + value = std::move(var_name).unwrap_value() #define IKARUS_VTRY_OR_FAIL(value, msg, err_info, ...) \ - IKARUS_VTRY_OR_FAIL_IMPL(CPPBASE_UNIQUE_NAME(result), value, msg, err_info, __VA_ARGS__); + IKARUS_VTRY_OR_FAIL_IMPL( \ + CPPBASE_UNIQUE_NAME(result), \ + value, \ + msg, \ + err_info, \ + __VA_ARGS__ \ + ); -#define IKARUS_VTRYRV_OR_FAIL_IMPL(var_name, value, ret, msg, err_info, ...) \ - auto var_name = __VA_ARGS__; \ - if (var_name.is_error()) { \ - IKARUS_SET_ERROR(fmt::format(msg, var_name.unwrap_error()), err_info); \ - return ret; \ - } \ - value = var_name.unwrap_value() +#define IKARUS_VTRYRV_OR_FAIL_IMPL(var_name, value, ret, msg, err_info, ...) \ + auto var_name = __VA_ARGS__; \ + if (var_name.is_error()) { \ + IKARUS_SET_ERROR( \ + fmt::format(fmt::runtime(msg), var_name.unwrap_error()), \ + err_info \ + ); \ + return ret; \ + } \ + value = std::move(var_name).unwrap_value() #define IKARUS_VTRYRV_OR_FAIL(value, ret, msg, err_info, ...) \ - IKARUS_VTRYRV_OR_FAIL_IMPL(CPPBASE_UNIQUE_NAME(result), value, ret, msg, err_info, __VA_ARGS__); + IKARUS_VTRYRV_OR_FAIL_IMPL( \ + CPPBASE_UNIQUE_NAME(result), \ + value, \ + ret, \ + msg, \ + err_info, \ + __VA_ARGS__ \ + ); + +#define IKARUS_FAIL_IF_ERROR(ret) \ + if (ikarus_error_data_is_error(error_out)) { \ + return ret; \ + } + +#define IKARUS_FAIL_IF_NULL(ptr, ret) \ + IKARUS_FAIL_IF( \ + ((ptr) == nullptr), \ + ret, \ + #ptr " must not be null", \ + IkarusErrorInfo_Client_InvalidNull \ + ) + +#define IKARUS_FAIL_IF_NAME_INVALID(name, ret) \ + IKARUS_FAIL_IF_NULL(name, ret); \ + IKARUS_FAIL_IF( \ + cppbase::is_empty_or_blank(name), \ + ret, \ + #name " must not be empty", \ + IkarusErrorInfo_Client_InvalidInput \ + ); + +#define IKARUS_FAIL_IF_NOT_EXIST(object, ret) \ + IKARUS_VTRYRV_OR_FAIL( \ + auto exists, \ + ret, \ + fmt::format( \ + "failed to check if {} exists", \ + std::remove_cvref_t::object_name \ + ), \ + IkarusErrorInfo_Database_QueryFailed, \ + object->project->db->query_one( \ + fmt::format( \ + "SELECT EXISTS(SELECT 1 FROM `{}` WHERE `id` = ?)", \ + std::remove_cvref_t::table_name \ + ), \ + object->id \ + ) \ + ); \ + \ + IKARUS_FAIL_IF( \ + !exists, \ + ret, \ + fmt::format( \ + "{} doesn't exist", \ + std::remove_cvref_t::object_name \ + ), \ + IkarusErrorInfo_Client_NonExistent \ + ) diff --git a/src/ikarus/objects/blueprint.cpp b/src/ikarus/objects/blueprint.cpp index a2a5673..c25961f 100644 --- a/src/ikarus/objects/blueprint.cpp +++ b/src/ikarus/objects/blueprint.cpp @@ -1,168 +1,5 @@ #include "ikarus/objects/blueprint.h" -#include -#include -#include - #include #include -#include -#include -#include -#include #include -#include - -IkarusBlueprint::IkarusBlueprint(IkarusProject * project, int64_t id): - IkarusObject{project, id} {} - -std::string_view IkarusBlueprint::get_table_name() const noexcept { - return "blueprints"; -} - -IkarusBlueprint * ikarus_blueprint_create(struct IkarusProject * project, char const * name, IkarusErrorData * error_out) { - IKARUS_FAIL_IF_NULL(project, nullptr); - IKARUS_FAIL_IF_NAME_INVALID(name, nullptr); - - IKARUS_VTRYRV_OR_FAIL( - int64_t const id, - nullptr, - "failed to create blueprint: {}", - IkarusErrorInfo_Database_QueryFailed, - project->db->transact([name](auto * db) -> cppbase::Result { - TRY(db->execute("INSERT INTO `blueprints`(`name`) VALUES(?)", name)); - return cppbase::ok(db->last_insert_rowid()); - }) - ); - - return project->get_blueprint(id); -} - -void ikarus_blueprint_delete(IkarusBlueprint * blueprint, IkarusErrorData * error_out) { - IKARUS_FAIL_IF_NULL(blueprint, ); - IKARUS_FAIL_IF_OBJECT_MISSING(blueprint, ); - - IKARUS_TRYRV_OR_FAIL( - , - "unable to delete blueprint: {}", - IkarusErrorInfo_Database_QueryFailed, - blueprint->project->db->execute("DELETE FROM `blueprints` WHERE `id` = ?", blueprint->id) - ); - - blueprint->project->uncache(blueprint); -} - -int64_t ikarus_blueprint_get_id(IkarusBlueprint const * blueprint, IkarusErrorData * error_out) { - return ikarus::util::object_get_id(blueprint, error_out); -} - -IkarusProject * ikarus_blueprint_get_project(IkarusBlueprint const * blueprint, IkarusErrorData * error_out) { - return ikarus::util::object_get_project(blueprint, error_out); -} - -char const * ikarus_blueprint_get_name(IkarusBlueprint const * blueprint, IkarusErrorData * error_out) { - return ikarus::util::object_get_name(blueprint, error_out); -} - -void ikarus_blueprint_set_name(IkarusBlueprint * blueprint, char const * name, IkarusErrorData * error_out) { - ikarus::util::object_set_name(blueprint, name, error_out); -} - -void ikarus_blueprint_get_properties( - IkarusBlueprint const * blueprint, - struct IkarusProperty ** properties_out, - size_t properties_out_size, - IkarusErrorData * error_out -) { - IKARUS_FAIL_IF_NULL(blueprint, ); - IKARUS_FAIL_IF_OBJECT_MISSING(blueprint, ); - IKARUS_FAIL_IF_NULL(properties_out, ); - - if (properties_out_size == 0) { - return; - } - - std::tuple ids_and_types[properties_out_size]; - - IKARUS_TRYRV_OR_FAIL( - , - "unable to fetch blueprint properties from database: {}", - IkarusErrorInfo_Database_QueryFailed, - blueprint->project->db->query_many_buffered( - "SELECT `id` FROM `properties` WHERE `blueprint` = ?", - ids_and_types, - properties_out_size, - blueprint->id - ) - ) - - for (size_t i = 0; i < properties_out_size; ++i) { - auto [id, type] = ids_and_types[i]; - - properties_out[i] = blueprint->project->get_property(id, type); - } -} - -size_t ikarus_blueprint_get_property_count(IkarusBlueprint const * blueprint, IkarusErrorData * error_out) { - IKARUS_FAIL_IF_NULL(blueprint, 0); - IKARUS_FAIL_IF_OBJECT_MISSING(blueprint, 0); - - IKARUS_VTRYRV_OR_FAIL( - auto const ret, - 0, - "unable to fetch blueprint property count from database: {}", - IkarusErrorInfo_Database_QueryFailed, - blueprint->project->db->query_one("SELECT COUNT(*) FROM `properties` WHERE `blueprint` = ?", blueprint->id) - ); - - return ret; -} - -void ikarus_blueprint_get_linked_entities( - IkarusBlueprint const * blueprint, - struct IkarusEntity ** entities_out, - size_t entities_out_size, - IkarusErrorData * error_out -) { - IKARUS_FAIL_IF_NULL(blueprint, ); - IKARUS_FAIL_IF_OBJECT_MISSING(blueprint, ); - IKARUS_FAIL_IF_NULL(entities_out, ); - - if (entities_out_size == 0) { - return; - } - - int64_t ids[entities_out_size]; - - IKARUS_TRYRV_OR_FAIL( - , - "unable to fetch blueprint linked entities from database: {}", - IkarusErrorInfo_Database_QueryFailed, - blueprint->project->db->query_many_buffered( - "SELECT `entity` FROM `entity_blueprint_links` WHERE `blueprint` = ?", - ids, - entities_out_size, - blueprint->id - ) - ) - - for (size_t i = 0; i < entities_out_size; ++i) { - entities_out[i] = blueprint->project->get_entity(ids[i]); - } -} - -size_t ikarus_blueprint_get_linked_entity_count(IkarusBlueprint const * blueprint, IkarusErrorData * error_out) { - IKARUS_FAIL_IF_NULL(blueprint, 0); - IKARUS_FAIL_IF_OBJECT_MISSING(blueprint, 0); - - IKARUS_VTRYRV_OR_FAIL( - auto const ret, - 0, - "unable to fetch blueprint linked entity count from database: {}", - IkarusErrorInfo_Database_QueryFailed, - blueprint->project->db - ->query_one("SELECT COUNT(`entity`) FROM `entity_blueprint_links` WHERE `blueprint` = ?", blueprint->id) - ); - - return ret; -} diff --git a/src/ikarus/objects/blueprint.hpp b/src/ikarus/objects/blueprint.hpp index cd46d62..b56143f 100644 --- a/src/ikarus/objects/blueprint.hpp +++ b/src/ikarus/objects/blueprint.hpp @@ -1,19 +1,23 @@ #pragma once -#include +#include -struct IkarusBlueprint : public IkarusObject { -public: - IkarusBlueprint(struct IkarusProject * project, int64_t id); +struct IkarusBlueprint { + consteval static inline auto OBJECT_NAME() -> std::string_view { + return "blueprint"; + } - IkarusBlueprint(IkarusBlueprint const &) = default; - IkarusBlueprint(IkarusBlueprint &&) = default; + consteval static inline auto TABLE_NAME() -> std::string_view { + return "blueprints"; + } - IkarusBlueprint & operator=(IkarusBlueprint const &) = default; - IkarusBlueprint & operator=(IkarusBlueprint &&) = default; + IkarusBlueprint( + struct IkarusProject * project, + int64_t id, + std::string_view name + ); - ~IkarusBlueprint() override = default; - -public: - std::string_view get_table_name() const noexcept override; + struct IkarusProject * project; + int64_t id; + std::string name; }; diff --git a/src/ikarus/objects/entity.cpp b/src/ikarus/objects/entity.cpp index 2df1404..47f1f90 100644 --- a/src/ikarus/objects/entity.cpp +++ b/src/ikarus/objects/entity.cpp @@ -1,488 +1,171 @@ -#include "ikarus/objects/entity.h" - -#include +#include "entity.hpp" +#include #include -#include -#include -#include -#include +#include #include -#include -#include -#include -IkarusEntity::IkarusEntity(IkarusProject * project, int64_t id): - IkarusObject{project, id} {} - -std::string_view IkarusEntity::get_table_name() const noexcept { - return "entities"; -} +IkarusEntity::IkarusEntity( + struct IkarusProject * project, + int64_t id, + std::string_view name +): + project{project}, + id{id}, + name{name} {} IkarusEntity * ikarus_entity_create( - struct IkarusProject * project, - char const * name, - IkarusErrorData * error_out + struct IkarusProject * project, + char const * name, + IkarusEntityCreateFlags flags, + IkarusErrorData * error_out ) { - IKARUS_FAIL_IF_NULL(project, nullptr); - IKARUS_FAIL_IF_NAME_INVALID(name, nullptr); + IKARUS_FAIL_IF_NULL(project, nullptr); + IKARUS_FAIL_IF_NAME_INVALID(name, nullptr); - IKARUS_VTRYRV_OR_FAIL( - int64_t const id, - nullptr, - "failed to create entity: {}", - IkarusErrorInfo_Database_QueryFailed, - project->db->transact( - [name](auto * db - ) -> cppbase::Result { - TRY(db->execute( - "INSERT INTO `entities`(`name`) VALUES(?, ?)", - name - )); - return cppbase::ok(db->last_insert_rowid()); - } - ) - ); + IKARUS_TRYRV_OR_FAIL( + nullptr, + "failed to create entity: {}", + IkarusErrorInfo_Database_QueryFailed, + project->db->execute("INSERT INTO `entities`(`name`) VALUES(?)", name) + ); - return project->get_entity(id); + auto const id = project->db->last_insert_rowid(); + return new IkarusEntity{project, id, name}; } -void ikarus_entity_delete(IkarusEntity * entity, IkarusErrorData * error_out) { - IKARUS_FAIL_IF_NULL(entity, ); - IKARUS_FAIL_IF_OBJECT_MISSING(entity, ); - - IKARUS_TRYRV_OR_FAIL( - , - "unable to delete entity: {}", - IkarusErrorInfo_Database_QueryFailed, - entity->project->db - ->execute("DELETE FROM `entities` WHERE `id` = ?", entity->id) - ); - - entity->project->uncache(entity); -} - -int64_t -ikarus_entity_get_id(IkarusEntity const * entity, IkarusErrorData * error_out) { - return ikarus::util::object_get_id(entity, error_out); -} - -IkarusProject * ikarus_entity_get_project( - IkarusEntity const * entity, - IkarusErrorData * error_out +void ikarus_entity_delete( + IkarusEntity * entity, + IkarusEntityDeleteFlags flags, + IkarusErrorData * error_out ) { - return ikarus::util::object_get_project(entity, error_out); + IKARUS_FAIL_IF_NULL(entity, ); + IKARUS_FAIL_IF_NOT_EXIST(entity, ); + IKARUS_FAIL_IF_NULL(entity->project, ); + + IKARUS_TRYRV_OR_FAIL( + , + "failed to delete entity: {}", + IkarusErrorInfo_Database_QueryFailed, + entity->project->db + ->execute("DELETE FROM `entities` WHERE `id` = ?", entity->id) + ); + + delete entity; } -char const * ikarus_entity_get_name( - IkarusEntity const * entity, - IkarusErrorData * error_out +IkarusEntity * ikarus_entity_copy( + IkarusEntity * entity, + IkarusEntityCopyFlags flags, + IkarusErrorData * error_out ) { - return ikarus::util::object_get_name(entity, error_out); + IKARUS_FAIL_IF_NULL(entity, nullptr); + IKARUS_FAIL_IF_NOT_EXIST(entity, nullptr); + IKARUS_FAIL_IF_NULL(entity->project, nullptr); + + IKARUS_VTRYRV_OR_FAIL( + auto id, + nullptr, + "failed to copy entity: {}", + IkarusErrorInfo_Database_QueryFailed, + entity->project->db->transact( + [entity](auto * db) + -> cppbase::Result { + TRY(entity->project->db->execute( + "INSERT INTO `entities`(`name`) VALUES(?)", + entity->name.data() + )); + + TRY(entity->project->db->execute( + "INSERT INTO `entity_values`(`entity`, `name`, `value`)" + " SELECT ?1, `name`, `value` FROM `entity_values` WHERE " + "`entity` = ?1", + entity->id + )) + + TRY(entity->project->db->execute( + "INSERT INTO `entity_property_values`(" + " `entity`, " + " `property`," + " `value`" + ") " + "SELECT ?1, `property`, `value` FROM " + "`entity_property_values` " + "WHERE `entity` = ?1", + entity->id + )) + + TRY(entity->project->db->execute( + "INSERT INTO `entity_blueprint_links`(`entity`, " + "`blueprint`)" + "SELECT ?1, `property`, `value` FROM " + "`entity_property_values` " + "WHERE `entity` = ?1", + entity->id + )) + + return cppbase::ok(entity->project->db->last_insert_rowid()); + } + ) + ); + + return new IkarusEntity{entity->project, id, entity->name}; +} + +IkarusProject * +ikarus_entity_get_project(IkarusEntity * entity, IkarusErrorData * error_out) { + IKARUS_FAIL_IF_NULL(entity, nullptr); + IKARUS_FAIL_IF_NULL(entity->project, nullptr); + + return entity->project; +} + +char const * +ikarus_entity_get_name(IkarusEntity * entity, IkarusErrorData * error_out) { + IKARUS_FAIL_IF_NULL(entity, nullptr); + + return entity->name.data(); } void ikarus_entity_set_name( - IkarusEntity * entity, - char const * name, - IkarusErrorData * error_out + IkarusEntity * entity, + char const * name, + IkarusEntitySetNameFlags flags, + IkarusErrorData * error_out ) { - ikarus::util::object_set_name(entity, name, error_out); + IKARUS_FAIL_IF_NULL(entity, ); + IKARUS_FAIL_IF_NAME_INVALID(name, ); + + IKARUS_TRYRV_OR_FAIL( + , + "failed to set name for entity: {}", + IkarusErrorInfo_Database_QueryFailed, + entity->project->db->execute( + "UPDATE `entities` SET `name` = ? WHERE `id` = ?", + name, + entity->id + ) + ); + + entity->name = name; } -bool ikarus_entity_is_linked_to_blueprint( - IkarusEntity const * entity, - struct IkarusBlueprint const * blueprint, - IkarusErrorData * error_out +char const * ikarus_entity_get_value( + IkarusEntity * entity, + char const * name, + IkarusErrorData * error_out ) { - IKARUS_FAIL_IF_NULL(entity, false); - IKARUS_FAIL_IF_OBJECT_MISSING(entity, false); - IKARUS_FAIL_IF_NULL(blueprint, false); - IKARUS_FAIL_IF_OBJECT_MISSING(blueprint, false); - - IKARUS_VTRYRV_OR_FAIL( - auto const ret, - false, - "unable to check whether entity is linked to blueprint", - IkarusErrorInfo_Database_QueryFailed, - entity->project->db->query_one( - "SELECT EXISTS(SELECT 1 FROM `entity_blueprint_links` WHERE " - "`entity` = ? AND " - "`blueprint` = ?)", - entity->id, - blueprint->id - ) - ) - - return ret; -} - -void ikarus_entity_link_to_blueprint( - IkarusEntity * entity, - struct IkarusBlueprint * blueprint, - IkarusErrorData * error_out -) { - IKARUS_FAIL_IF_NULL(entity, ); - IKARUS_FAIL_IF_OBJECT_MISSING(entity, ); - IKARUS_FAIL_IF_NULL(blueprint, ); - IKARUS_FAIL_IF_OBJECT_MISSING(blueprint, ); - - IKARUS_TRYRV_OR_FAIL( - , - "unable to link entity to blueprint: {}", - IkarusErrorInfo_Database_QueryFailed, - entity->project->db->execute( - "INSERT INTO `entity_blueprint_links`(`entity`, `blueprint`) " - "VALUES(?, ?) ON " - "CONFLICT(`entity`, `blueprint`) DO NOTHING", - entity->id, - blueprint->id - ) - ); -} - -void ikarus_entity_unlink_from_blueprint( - IkarusEntity * entity, - struct IkarusBlueprint * blueprint, - IkarusErrorData * error_out -) { - IKARUS_FAIL_IF_NULL(entity, ); - IKARUS_FAIL_IF_OBJECT_MISSING(entity, ); - IKARUS_FAIL_IF_NULL(blueprint, ); - IKARUS_FAIL_IF_OBJECT_MISSING(blueprint, ); - - IKARUS_TRYRV_OR_FAIL( - , - "unable to unlink entity from blueprint: {}", - IkarusErrorInfo_Database_QueryFailed, - entity->project->db->execute( - "DELETE FROM `entity_blueprint_links` WHERE `entity` = ? AND " - "`blueprint` = ?", - entity->id, - blueprint->id - ) - ); - - IKARUS_TRYRV_OR_FAIL( - , - "unable to remove entity property values: {}", - IkarusErrorInfo_Database_QueryFailed, - entity->project->db->execute( - "DELETE FROM `entity_property_values` WHERE `entity` = ? AND " - "`property` IN (SELECT " - "`id` FROM `properties` WHERE `blueprint` = ?)", - entity->id, - blueprint->id - ) - ) -} - -void ikarus_entity_get_linked_blueprints( - IkarusEntity const * entity, - struct IkarusBlueprint ** blueprints_out, - size_t blueprints_out_size, - IkarusErrorData * error_out -) { - IKARUS_FAIL_IF_NULL(entity, ); - IKARUS_FAIL_IF_OBJECT_MISSING(entity, ); - IKARUS_FAIL_IF_NULL(blueprints_out, ); - - if (blueprints_out_size == 0) { - return; - } - - int64_t ids[blueprints_out_size]; - - IKARUS_TRYRV_OR_FAIL( - , - "unable to fetch entity linked blueprints from database: {}", - IkarusErrorInfo_Database_QueryFailed, - entity->project->db->query_many_buffered( - "SELECT `blueprint` FROM `entity_blueprint_links` WHERE `entity` = " - "?", - ids, - blueprints_out_size, - entity->id - ) - ) - - for (size_t i = 0; i < blueprints_out_size; ++i) { - blueprints_out[i] = entity->project->get_blueprint(ids[i]); - } -} - -size_t ikarus_entity_get_linked_blueprint_count( - IkarusEntity const * entity, - IkarusErrorData * error_out -) { - IKARUS_FAIL_IF_NULL(entity, 0); - IKARUS_FAIL_IF_OBJECT_MISSING(entity, 0); - - IKARUS_VTRYRV_OR_FAIL( - auto const ret, - 0, - "unable to fetch entity linked blueprint count from database: {}", - IkarusErrorInfo_Database_QueryFailed, - entity->project->db->query_one( - "SELECT COUNT(`blueprint`) FROM `entity_blueprint_links` WHERE " - "`entity` = ?", - entity->id - ) - ); - - return ret; -} - -bool ikarus_entity_has_value( - IkarusEntity const * entity, - char const * name, - IkarusErrorData * error_out -) { - IKARUS_FAIL_IF_NULL(entity, false); - IKARUS_FAIL_IF_OBJECT_MISSING(entity, false); - IKARUS_FAIL_IF_NAME_INVALID(name, false); - - IKARUS_VTRYRV_OR_FAIL( - auto const has_value, - false, - "unable to check whether entity has value: {}", - IkarusErrorInfo_Database_QueryFailed, - entity->project->db->query_one( - "SELECT EXISTS(SELECT 1 FROM `entity_values` WHERE `entity` = ? " - "AND `name` = ?)", - entity->id, - name - ) - ); - - return has_value; -} - -struct IkarusValue * ikarus_entity_get_value( - IkarusEntity const * entity, - char const * name, - IkarusErrorData * error_out -) { - IKARUS_FAIL_IF_NULL(entity, nullptr); - IKARUS_FAIL_IF_OBJECT_MISSING(entity, nullptr); - IKARUS_FAIL_IF_VALUE_MISSING(entity, name, nullptr); - IKARUS_FAIL_IF_NAME_INVALID(name, nullptr); - - auto * value = fetch_value_from_db( - entity->project, - error_out, - "SELECT `value` FROM `entity_values` WHERE `entity` = ? AND `name` = ?", - entity->id, - name - ); - - IKARUS_FAIL_IF_ERROR(nullptr); - - return value; + IKARUS_FAIL_IF_NULL(entity, nullptr); + IKARUS_FAIL_IF_NULL(name, nullptr); } void ikarus_entity_set_value( - IkarusEntity * entity, - char const * name, - struct IkarusValue const * value, - IkarusErrorData * error_out + IkarusEntity * entity, + char const * name, + char const * value, + IkarusErrorData * error_out ) { - IKARUS_FAIL_IF_NULL(entity, ); - IKARUS_FAIL_IF_OBJECT_MISSING(entity, ); - IKARUS_FAIL_IF_NAME_INVALID(name, ); - IKARUS_FAIL_IF_NULL(value, ); - - IKARUS_TRYRV_OR_FAIL( - , - "unable to set entity value: {}", - IkarusErrorInfo_Database_QueryFailed, - entity->project->db->execute( - "INSERT INTO `entity_values`(`entity`, `name`, `value`) VALUES(?1, " - "?2, ?3) ON " - "CONFLICT(`entity`, `name`) DO UPDATE SET `value` = ?3", - entity->id, - name, - boost::json::serialize(value->to_json()) - ) - ); -} - -void ikarus_entity_delete_value( - IkarusEntity * entity, - char const * name, - IkarusErrorData * error_out -) { - IKARUS_FAIL_IF_NULL(entity, ); - IKARUS_FAIL_IF_OBJECT_MISSING(entity, ); - IKARUS_FAIL_IF_VALUE_MISSING(entity, name, ); - IKARUS_FAIL_IF_NAME_INVALID(name, ); - - IKARUS_TRYRV_OR_FAIL( - , - "unable to delete entity value: {}", - IkarusErrorInfo_Database_QueryFailed, - entity->project->db->execute( - "DELETE FROM `entity_values` WHERE `entity` = ? AND `name` = ?", - entity->id, - name - ) - ); -} - -bool ikarus_entity_has_property( - IkarusEntity const * entity, - struct IkarusProperty const * property, - IkarusErrorData * error_out -) { - IKARUS_FAIL_IF_NULL(entity, false); - IKARUS_FAIL_IF_OBJECT_MISSING(entity, false); - IKARUS_FAIL_IF_NULL(property, false); - IKARUS_FAIL_IF_OBJECT_MISSING(property, false); - - // given that values are loaded lazily we can't just check - // `entity_property_values` here - IKARUS_VTRYRV_OR_FAIL( - auto const has_property, - false, - "unable to check whether entity has property: {}", - IkarusErrorInfo_Database_QueryFailed, - entity->project->db->query_one( - "SELECT EXISTS(\n" - " SELECT 1\n" - " FROM `entity_blueprint_links`\n" - " JOIN `properties` ON `properties`.`blueprint` = " - "`entity_blueprint_links`.`blueprint`\n" - " WHERE `entity_blueprint_links`.`entity` = ? AND " - "`properties`.`id` = ?\n" - ")", - entity->id, - property->id - ) - ) - - return has_property; -} - -void ikarus_entity_get_properties( - IkarusEntity const * entity, - struct IkarusProperty ** properties_out, - size_t properties_out_size, - IkarusErrorData * error_out -) { - IKARUS_FAIL_IF_NULL(entity, ); - IKARUS_FAIL_IF_OBJECT_MISSING(entity, ); - IKARUS_FAIL_IF_NULL(properties_out, ); - - if (properties_out_size == 0) { - return; - } - - std::tuple ids_and_types[properties_out_size]; - - // given that values are loaded lazily we can't just check - // `entity_property_values` here - IKARUS_TRYRV_OR_FAIL( - , - "unable to fetch properties from entity: {}", - IkarusErrorInfo_Database_QueryFailed, - entity->project->db->query_many_buffered( - "SELECT `properties`.`id`, `properties`.`type`\n" - "FROM `entity_blueprint_links`\n" - "JOIN `properties` ON `properties`.`blueprint` = " - "`entity_blueprint_links`.`blueprint`\n" - "WHERE `entity_blueprint_links`.`entity` = ?\n", - ids_and_types, - properties_out_size, - entity->id - ) - ); - - for (size_t i = 0; i < properties_out_size; ++i) { - auto [id, type] = ids_and_types[i]; - properties_out[i] = entity->project->get_property(id, type); - } -} - -size_t ikarus_entity_get_property_count( - IkarusEntity const * entity, - IkarusErrorData * error_out -) { - IKARUS_FAIL_IF_NULL(entity, 0); - IKARUS_FAIL_IF_OBJECT_MISSING(entity, 0); - - // given that values are loaded lazily we can't just check - // `entity_property_values` here - IKARUS_VTRYRV_OR_FAIL( - size_t const count, - 0, - "unable to fetch property count from entity: {}", - IkarusErrorInfo_Database_QueryFailed, - entity->project->db->query_one( - "SELECT COUNT(`properties`.`id`)\n" - "FROM `entity_blueprint_links`\n" - "JOIN `properties` ON `properties`.`blueprint` = " - "`entity_blueprint_links`.`blueprint`\n" - "WHERE `entity_blueprint_links`.`entity` = ?\n" - ")", - entity->id - ) - ); - - return count; -} - -struct IkarusValue * ikarus_entity_get_property_value( - IkarusEntity const * entity, - struct IkarusProperty const * property, - IkarusErrorData * error_out -) { - IKARUS_FAIL_IF_NULL(entity, nullptr); - IKARUS_FAIL_IF_OBJECT_MISSING(entity, nullptr); - IKARUS_FAIL_IF_NULL(property, nullptr); - IKARUS_FAIL_IF_OBJECT_MISSING(property, nullptr); - - auto * value = fetch_value_from_db( - entity->project, - error_out, - "SELECT IFNULL(\n" - " (\n" - " SELECT `value`\n" - " FROM `entity_property_values`\n" - " WHERE `entity` = ?1 AND `property` = ?2\n" - " ),\n" - " (SELECT `default_value` FROM `properties` WHERE `id` = ?2)\n" - ")", - entity->id, - property->id - ); - - IKARUS_FAIL_IF_ERROR(nullptr); - - return value; -} - -void ikarus_entity_set_property_value( - IkarusEntity * entity, - struct IkarusProperty const * property, - struct IkarusValue * value, - IkarusErrorData * error_out -) { - IKARUS_FAIL_IF_NULL(entity, ); - IKARUS_FAIL_IF_OBJECT_MISSING(entity, ); - IKARUS_FAIL_IF_NULL(property, ); - IKARUS_FAIL_IF_OBJECT_MISSING(property, ); - IKARUS_FAIL_IF_NULL(value, ); - - IKARUS_TRYRV_OR_FAIL( - , - "unable to set entity property value: {}", - IkarusErrorInfo_Database_QueryFailed, - entity->project->db->execute( - "INSERT INTO `entity_property_values`(`entity`, `property`, " - "`value`) VALUES(?1, ?2, " - "?3) ON CONFLICT(`entity`, `property`) DO UPDATE SET `value` = ?3", - entity->id, - property->id, - boost::json::serialize(value->to_json()) - ) - ); + IKARUS_FAIL_IF_NULL(entity, ); + IKARUS_FAIL_IF_NULL(name, ); + IKARUS_FAIL_IF_NULL(value, ); } diff --git a/src/ikarus/objects/entity.hpp b/src/ikarus/objects/entity.hpp index e3bc035..90a445e 100644 --- a/src/ikarus/objects/entity.hpp +++ b/src/ikarus/objects/entity.hpp @@ -1,19 +1,24 @@ #pragma once -#include +#include +#include -struct IkarusEntity : public IkarusObject { -public: - inline IkarusEntity(struct IkarusProject * project, int64_t id); +#include - IkarusEntity(IkarusEntity const &) = default; - IkarusEntity(IkarusEntity &&) = default; +struct IkarusEntity { + constinit static inline auto object_name = "entity"; + constinit static inline auto table_name = "entities"; - IkarusEntity & operator=(IkarusEntity const &) = default; - IkarusEntity & operator=(IkarusEntity &&) = default; + IkarusEntity( + struct IkarusProject * project, + int64_t id, + std::string_view name + ); - ~IkarusEntity() override = default; + struct IkarusProject * project; + int64_t id; + std::string name; -public: - std::string_view get_table_name() const noexcept override; + std::vector> values_ordered; + std::unordered_map values; }; diff --git a/src/ikarus/objects/object.cpp b/src/ikarus/objects/object.cpp deleted file mode 100644 index 01747cc..0000000 --- a/src/ikarus/objects/object.cpp +++ /dev/null @@ -1,7 +0,0 @@ -#include "object.hpp" - -#include - -IkarusObject::IkarusObject(IkarusProject * project, int64_t id): - project{project}, - id{id} {} diff --git a/src/ikarus/objects/object.hpp b/src/ikarus/objects/object.hpp deleted file mode 100644 index 96d5911..0000000 --- a/src/ikarus/objects/object.hpp +++ /dev/null @@ -1,36 +0,0 @@ -#pragma once - -#include - -class IkarusObject { -public: - IkarusObject(struct IkarusProject * project, int64_t id); - - IkarusObject(IkarusObject const &) = default; - IkarusObject(IkarusObject &&) = default; - - IkarusObject & operator=(IkarusObject const &) = default; - IkarusObject & operator=(IkarusObject &&) = default; - - virtual ~IkarusObject() = default; - -public: - virtual std::string_view get_table_name() const noexcept = 0; - -public: - struct IkarusProject * project; - int64_t id; -}; - -#define IKARUS_FAIL_IF_OBJECT_MISSING_IMPL(var_name, obj, ret) \ - IKARUS_VTRYRV_OR_FAIL( \ - bool const var_name, \ - ret, \ - "unable to check whether object exists: {}", \ - IkarusErrorInfo_Database_QueryFailed, \ - (obj)->project->db->template query_one("SELECT EXISTS(SELECT 1 FROM `objects` WHERE `id` = ?)", (obj)->id) \ - ) \ - \ - IKARUS_FAIL_IF(!(var_name), ret, "object does not exist", IkarusErrorInfo_Client_Misuse); - -#define IKARUS_FAIL_IF_OBJECT_MISSING(obj, ret) IKARUS_FAIL_IF_OBJECT_MISSING_IMPL(CPPBASE_UNIQUE_NAME(exists), obj, ret); diff --git a/src/ikarus/objects/properties/number_property.cpp b/src/ikarus/objects/properties/number_property.cpp deleted file mode 100644 index 60c9ccd..0000000 --- a/src/ikarus/objects/properties/number_property.cpp +++ /dev/null @@ -1,32 +0,0 @@ -#include "number_property.hpp" - -#include - -#include -#include -#include -#include - -IkarusNumberProperty::IkarusNumberProperty(IkarusProject * project, int64_t id): - IkarusProperty{project, id, this} {} - -IkarusNumberProperty * ikarus_number_property_create( - struct IkarusProject * project, - char const * name, - struct IkarusPropertyScope * property_source, - IkarusErrorData * error_out -) { - return ikarus::util::create_property(project, name, property_source, error_out); -} - -IkarusNumberValue * ikarus_number_property_get_default_value(IkarusNumberProperty * property, IkarusErrorData * error_out) { - return ikarus::util::get_default_value(property, error_out); -} - -void ikarus_number_property_set_default_value( - IkarusNumberProperty * property, - IkarusNumberValue * new_default_value, - IkarusErrorData * error_out -) { - ikarus::util::set_default_value(property, new_default_value, error_out); -} diff --git a/src/ikarus/objects/properties/number_property.hpp b/src/ikarus/objects/properties/number_property.hpp deleted file mode 100644 index 55ff25c..0000000 --- a/src/ikarus/objects/properties/number_property.hpp +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include -#include -#include - -struct IkarusNumberProperty : public IkarusProperty { -public: - using value_type = IkarusNumberValue; - constexpr auto static PropertyType = IkarusValueType_Number; - -public: - IkarusNumberProperty(struct IkarusProject * project, int64_t id); -}; diff --git a/src/ikarus/objects/properties/property.cpp b/src/ikarus/objects/properties/property.cpp deleted file mode 100644 index ecc2f3e..0000000 --- a/src/ikarus/objects/properties/property.cpp +++ /dev/null @@ -1,143 +0,0 @@ -#include "property.hpp" - -#include - -#include -#include -#include -#include -#include -#include -#include - -IkarusProperty::IkarusProperty(IkarusProject * project, int64_t id, Data data): - IkarusObject{project, id}, - data{data} {} - -IKA_API void ikarus_property_delete(IkarusProperty * property, IkarusErrorData * error_out) { - IKARUS_FAIL_IF_NULL(property, ); - IKARUS_FAIL_IF_OBJECT_MISSING(property, ); - - IKARUS_TRYRV_OR_FAIL( - , - "unable to delete property: {}", - IkarusErrorInfo_Database_QueryFailed, - property->project->db->execute("DELETE FROM `objects` WHERE `id` = ?", property->id) - ); - - property->project->uncache(property); -} - -int64_t ikarus_property_get_id(IkarusProperty const * property, IkarusErrorData * error_out) { - return ikarus::util::object_get_id(property, error_out); -} - -IkarusProject * ikarus_property_get_project(IkarusProperty const * property, IkarusErrorData * error_out) { - return ikarus::util::object_get_project(property, error_out); -} - -char const * ikarus_property_get_name(IkarusProperty const * property, IkarusErrorData * error_out) { - return ikarus::util::object_get_name(property, error_out); -} - -void ikarus_property_set_name(IkarusProperty * property, char const * name, IkarusErrorData * error_out) { - ikarus::util::object_set_name(property, name, error_out); -} - -IkarusValueType ikarus_property_get_type(IkarusProperty const * property, IkarusErrorData * error_out) { - IKARUS_FAIL_IF_NULL(property, IkarusValueType_Toggle); - IKARUS_FAIL_IF_OBJECT_MISSING(property, IkarusValueType_Toggle); - - IKARUS_VTRYRV_OR_FAIL( - auto const ret, - IkarusValueType_Toggle, - "unable to fetch property type from database: {}", - IkarusErrorInfo_Database_QueryFailed, - property->project->db->query_one("SELECT `type` FROM `properties` WHERE `id` = ?", property->id) - ); - - return static_cast(ret); -} - -IkarusPropertyScope const * ikarus_property_get_scope(IkarusProperty const * property, IkarusErrorData * error_out) { - IKARUS_FAIL_IF_NULL(property, nullptr); - IKARUS_FAIL_IF_OBJECT_MISSING(property, nullptr); - - IKARUS_VTRYRV_OR_FAIL( - auto const source, - nullptr, - "unable to fetch property source from database: {}", - IkarusErrorInfo_Database_QueryFailed, - property->project->db->query_one("SELECT `source` FROM `properties` WHERE `id` = ?", property->id) - ); - - switch (ikarus_id_get_object_type(source)) { - case IkarusObjectType_Blueprint: return new IkarusPropertyScope{property->project->get_blueprint(source)}; - case IkarusObjectType_Entity: return new IkarusPropertyScope{property->project->get_entity(source)}; - default: - IKARUS_FAIL( - nullptr, - fmt::format("invalid property source type: {}", ikarus_object_type_to_string(ikarus_id_get_object_type(source))), - IkarusErrorInfo_LibIkarus_InvalidState - ); - } -} - -IkarusValueData * ikarus_property_get_default_value(IkarusProperty const * property, IkarusErrorData * error_out) { - IKARUS_FAIL_IF_NULL(property, nullptr); - IKARUS_FAIL_IF_OBJECT_MISSING(property, nullptr); - - return fetch_value_from_db(property->project, error_out, "SELECT `default_value` FROM `properties` WHERE `id` = ?", property->id); -} - -void ikarus_property_visit( - IkarusProperty * property, - void (*toggle_property_visitor)(struct IkarusToggleProperty *, void *), - void (*number_property_visitor)(struct IkarusNumberProperty *, void *), - void (*text_property_visitor)(struct IkarusTextProperty *, void *), - void * data, - IkarusErrorData * error_out -) { - IKARUS_FAIL_IF_NULL(property, ); - IKARUS_FAIL_IF_OBJECT_MISSING(property, ); - - std::visit( - cppbase::overloaded{ - [toggle_property_visitor, data](IkarusToggleProperty * property) { toggle_property_visitor(property, data); }, - [number_property_visitor, data](IkarusNumberProperty * property) { number_property_visitor(property, data); }, - [text_property_visitor, data](IkarusTextProperty * property) { text_property_visitor(property, data); } - }, - property->data - ); -} - -void ikarus_property_visit_const( - IkarusProperty const * property, - void (*toggle_property_visitor)(struct IkarusToggleProperty const *, void *), - void (*number_property_visitor)(struct IkarusNumberProperty const *, void *), - void (*text_property_visitor)(struct IkarusTextProperty const *, void *), - void * data, - IkarusErrorData * error_out -) { - IKARUS_FAIL_IF_NULL(property, ); - IKARUS_FAIL_IF_OBJECT_MISSING(property, ); - - std::visit( - cppbase::overloaded{ - [toggle_property_visitor, data](IkarusToggleProperty const * property) { toggle_property_visitor(property, data); }, - [number_property_visitor, data](IkarusNumberProperty const * property) { number_property_visitor(property, data); }, - [text_property_visitor, data](IkarusTextProperty const * property) { text_property_visitor(property, data); } - }, - property->data - ); -} - -// No existence checks here for performance reasons. All methods on IkarusObject perform this check anyway. - -IkarusObject * ikarus_property_to_object(IkarusProperty * property) { - return static_cast(property); -} - -IkarusObject const * ikarus_property_to_object_const(IkarusProperty const * property) { - return static_cast(property); -} diff --git a/src/ikarus/objects/properties/property.hpp b/src/ikarus/objects/properties/property.hpp deleted file mode 100644 index 1fd0394..0000000 --- a/src/ikarus/objects/properties/property.hpp +++ /dev/null @@ -1,29 +0,0 @@ -#pragma once - -#include - -#include - -struct IkarusProperty : public IkarusObject { -public: - using Data = std::variant; - -public: - IkarusProperty(struct IkarusProject * project, int64_t id, Data data); - - IkarusProperty(IkarusProperty const &) = default; - IkarusProperty(IkarusProperty &&) = default; - - IkarusProperty & operator=(IkarusProperty const &) = default; - IkarusProperty & operator=(IkarusProperty &&) = default; - - ~IkarusProperty() override = default; - -public: - inline std::string_view get_table_name() const noexcept override { - return "properties"; - } - -public: - Data data; -}; diff --git a/src/ikarus/objects/properties/text_property.cpp b/src/ikarus/objects/properties/text_property.cpp deleted file mode 100644 index c51d653..0000000 --- a/src/ikarus/objects/properties/text_property.cpp +++ /dev/null @@ -1,32 +0,0 @@ -#include "text_property.hpp" - -#include - -#include -#include -#include -#include - -IkarusTextProperty::IkarusTextProperty(IkarusProject * project, int64_t id): - IkarusProperty{project, id, this} {} - -IkarusTextProperty * ikarus_text_property_create( - struct IkarusProject * project, - char const * name, - struct IkarusPropertyScope * property_source, - IkarusErrorData * error_out -) { - return ikarus::util::create_property(project, name, property_source, error_out); -} - -IkarusTextValue * ikarus_text_property_get_default_value(IkarusTextProperty * property, IkarusErrorData * error_out) { - return ikarus::util::get_default_value(property, error_out); -} - -void ikarus_text_property_set_default_value( - IkarusTextProperty * property, - IkarusTextValue * new_default_value, - IkarusErrorData * error_out -) { - ikarus::util::set_default_value(property, new_default_value, error_out); -} diff --git a/src/ikarus/objects/properties/text_property.hpp b/src/ikarus/objects/properties/text_property.hpp deleted file mode 100644 index b690cda..0000000 --- a/src/ikarus/objects/properties/text_property.hpp +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include -#include -#include - -struct IkarusTextProperty : public IkarusProperty { -public: - using value_type = IkarusTextValue; - constexpr auto static PropertyType = IkarusValueType_Text; - -public: - IkarusTextProperty(struct IkarusProject * project, int64_t id); -}; diff --git a/src/ikarus/objects/properties/toggle_property.cpp b/src/ikarus/objects/properties/toggle_property.cpp deleted file mode 100644 index d1705a2..0000000 --- a/src/ikarus/objects/properties/toggle_property.cpp +++ /dev/null @@ -1,32 +0,0 @@ -#include "toggle_property.hpp" - -#include - -#include -#include -#include -#include - -IkarusToggleProperty::IkarusToggleProperty(IkarusProject * project, int64_t id): - IkarusProperty{project, id, this} {} - -IkarusToggleProperty * ikarus_toggle_property_create( - struct IkarusProject * project, - char const * name, - struct IkarusPropertyScope * property_source, - IkarusErrorData * error_out -) { - return ikarus::util::create_property(project, name, property_source, error_out); -} - -IkarusToggleValue * ikarus_toggle_property_get_default_value(struct IkarusToggleProperty * property, IkarusErrorData * error_out) { - return ikarus::util::get_default_value(property, error_out); -} - -void ikarus_toggle_property_set_default_value( - struct IkarusToggleProperty * property, - struct IkarusToggleValue * new_default_value, - IkarusErrorData * error_out -) { - ikarus::util::set_default_value(property, new_default_value, error_out); -} diff --git a/src/ikarus/objects/properties/toggle_property.hpp b/src/ikarus/objects/properties/toggle_property.hpp deleted file mode 100644 index 35575ee..0000000 --- a/src/ikarus/objects/properties/toggle_property.hpp +++ /dev/null @@ -1,17 +0,0 @@ -#pragma once - -#include -#include -#include - -struct IkarusToggleProperty { -public: - using value_type = IkarusToggleValue; - constexpr auto static PropertyType = IkarusValueType_Toggle; - -public: - IkarusToggleProperty(struct IkarusProject * project, int64_t id); - -public: - IkarusProperty * property; -}; diff --git a/src/ikarus/objects/properties/util.hpp b/src/ikarus/objects/properties/util.hpp deleted file mode 100644 index 97146f1..0000000 --- a/src/ikarus/objects/properties/util.hpp +++ /dev/null @@ -1,95 +0,0 @@ -#pragma once - -#include - -#include - -#include -#include -#include -#include -#include -#include -#include - -namespace ikarus::util { -template -T * create_property( - struct IkarusProject * project, - char const * name, - struct IkarusPropertyScope * property_scope, - IkarusErrorData * error_out -) { - IKARUS_FAIL_IF_NULL(project, nullptr); - IKARUS_FAIL_IF_NULL(property_scope, nullptr); - IKARUS_FAIL_IF_NAME_INVALID(name, nullptr); - - IKARUS_VTRYRV_OR_FAIL( - int64_t const id, - nullptr, - "failed to create property: {}", - IkarusErrorInfo_Database_QueryFailed, - project->db->transact([name, property_scope](auto * db) -> cppbase::Result { - TRY(db->execute("INSERT INTO `objects`(`type`) VALUES(?)", IkarusObjectType_Property)); - auto id = ikarus_id_from_data_and_type(db->last_insert_rowid(), IkarusObjectType_Property); - TRY(db->execute( - "INSERT INTO `properties`(`id`, `name`, `type`, `source`) VALUES(?, ?, ?, ?)", - id, - name, - T::PropertyType, - property_scope->get_id() - )); - return cppbase::ok(id); - }) - ); - - auto * ret = dynamic_cast(project->get_property(id, T::PropertyType)); - - IKARUS_FAIL_IF( - ret == nullptr, - nullptr, - fmt::format("created {} cannot be casted down from IkarusProject", boost::typeindex::type_id().pretty_name()), - IkarusErrorInfo_LibIkarus_InvalidState - ); - - return ret; -} - -template -typename T::value_type * get_default_value(IkarusProperty const * property, IkarusErrorData * error_out) { - auto * value = ikarus_property_get_default_value(property, error_out); - IKARUS_FAIL_IF_ERROR(nullptr); - - auto * ret = boost::variant2::get_if(&value->data); - - IKARUS_FAIL_IF( - ret == nullptr, - nullptr, - fmt::format( - "{} default value is not a(n) {}", - boost::typeindex::type_id().pretty_name(), - boost::typeindex::type_id().pretty_name() - ), - IkarusErrorInfo_Database_InvalidState - ); - - return *ret; -} - -template -void set_default_value(T * property, typename T::value_type * new_default_value, IkarusErrorData * error_out) { - IKARUS_FAIL_IF_NULL(property, ); - IKARUS_FAIL_IF_OBJECT_MISSING(property, ); - IKARUS_FAIL_IF_NULL(new_default_value, ); - - auto value_json_str = boost::json::serialize(new_default_value->to_json()); - - IKARUS_TRYRV_OR_FAIL( - , - "unable to set property default value: {}", - IkarusErrorInfo_Database_QueryFailed, - property->project->db->execute("UPDATE `properties` SET `default_value` = ? WHERE `id` = ?", value_json_str, property->id) - ); -} - -} // namespace ikarus::util diff --git a/src/ikarus/objects/property.cpp b/src/ikarus/objects/property.cpp new file mode 100644 index 0000000..d096b18 --- /dev/null +++ b/src/ikarus/objects/property.cpp @@ -0,0 +1,15 @@ +#include "property.hpp" + +#include +#include +#include +#include + +IkarusProperty::IkarusProperty( + struct IkarusProject * project, + int64_t id, + std::string_view name +): + project{project}, + id{id}, + name{name} {} diff --git a/src/ikarus/objects/property.hpp b/src/ikarus/objects/property.hpp new file mode 100644 index 0000000..29143fb --- /dev/null +++ b/src/ikarus/objects/property.hpp @@ -0,0 +1,23 @@ +#pragma once + +#include + +struct IkarusProperty { + consteval static inline auto OBJECT_NAME() -> std::string_view { + return "property"; + } + + consteval static inline auto TABLE_NAME() -> std::string_view { + return "properties"; + } + + IkarusProperty( + struct IkarusProject * project, + int64_t id, + std::string_view name + ); + + struct IkarusProject * project; + int64_t id; + std::string name; +}; diff --git a/src/ikarus/objects/util.hpp b/src/ikarus/objects/util.hpp deleted file mode 100644 index e625f5d..0000000 --- a/src/ikarus/objects/util.hpp +++ /dev/null @@ -1,63 +0,0 @@ -#pragma once - -#include - -#include - -#include -#include -#include - -namespace ikarus::util { - -template -[[nodiscard]] int64_t object_get_id(O const * object, IkarusErrorData * error_out) { - IKARUS_FAIL_IF_NULL(object, 0); - IKARUS_FAIL_IF_OBJECT_MISSING(object, 0); - - return object->id; -} - -template -[[nodiscard]] IkarusProject * object_get_project(O const * object, IkarusErrorData * error_out) { - IKARUS_FAIL_IF_NULL(object, nullptr); - IKARUS_FAIL_IF_OBJECT_MISSING(object, nullptr); - - return object->project; -} - -template -[[nodiscard]] char const * object_get_name(O const * object, IkarusErrorData * error_out) { - IKARUS_FAIL_IF_NULL(object, nullptr); - IKARUS_FAIL_IF_OBJECT_MISSING(object, nullptr); - - IKARUS_VTRYRV_OR_FAIL( - auto const ret, - nullptr, - fmt::runtime(fmt::format("unable to fetch {} name: {{}}", ikarus_object_type_to_string(ikarus_id_get_object_type(object->id)))), - IkarusErrorInfo_Database_QueryFailed, - object->project->db - ->template query_one(fmt::format("SELECT `name` FROM `{}` WHERE `id` = ?", object->get_table_name()), object->id) - ); - - return strdup(ret.data()); -} - -#define IKARUS_FAIL_IF_NAME_INVALID(name, ret) IKARUS_FAIL_IF_NULL(name, ret); - -template -void object_set_name(O * object, char const * name, IkarusErrorData * error_out) { - IKARUS_FAIL_IF_NULL(object, ); - IKARUS_FAIL_IF_OBJECT_MISSING(object, ); - IKARUS_FAIL_IF_NULL(name, ); - IKARUS_FAIL_IF_NAME_INVALID(name, ); - - IKARUS_TRYRV_OR_FAIL( - , - fmt::runtime(fmt::format("unable to set {} name: {{}}", ikarus_object_type_to_string(ikarus_id_get_object_type(object->id)))), - IkarusErrorInfo_Database_QueryFailed, - object->project->db->execute(fmt::format("UPDATE `{}` SET `name` = ? WHERE `id` = ?", object->get_table_name()), name, object->id) - ); -} - -} // namespace ikarus::util diff --git a/src/ikarus/persistence/migrations.hpp b/src/ikarus/persistence/migrations.hpp index db649a5..a3a1d5e 100644 --- a/src/ikarus/persistence/migrations.hpp +++ b/src/ikarus/persistence/migrations.hpp @@ -1,7 +1,5 @@ #pragma once -#include - #include #include @@ -9,7 +7,10 @@ namespace ikarus { -CPPBASE_ASSET(m0_initial_layout, "ikarus/persistence/migrations/m0_initial_layout.sql"); +CPPBASE_ASSET( + m0_initial_layout, + "ikarus/persistence/migrations/m0_initial_layout.sql" +); class Migration : public sqlitecpp::Migration { public: @@ -27,7 +28,11 @@ public: std::string_view sql; }; -#define DECLARE_MIGRATION(name) std::make_unique(static_cast(name()), name##_size()) +#define DECLARE_MIGRATION(name) \ + std::make_unique( \ + static_cast(name()), \ + name##_size() \ + ) constexpr std::string_view DB_VERSION_KEY = "IKARUS_DB_VERSION"; std::vector> const MIGRATIONS = []() { diff --git a/src/ikarus/persistence/migrations/m0_initial_layout.sql b/src/ikarus/persistence/migrations/m0_initial_layout.sql index aa28c8a..8b263d7 100644 --- a/src/ikarus/persistence/migrations/m0_initial_layout.sql +++ b/src/ikarus/persistence/migrations/m0_initial_layout.sql @@ -6,13 +6,14 @@ CREATE TABLE `entities` CREATE TABLE `entity_values` ( + `id` INTEGER PRIMARY KEY, `entity` INTEGER NOT NULL REFERENCES `entities` (`id`) ON DELETE CASCADE, `name` TEXT NOT NULL, - `type` INT NOT NULL, `value` TEXT NOT NULL, - PRIMARY KEY (`entity`, `name`) -) WITHOUT ROWID, STRICT; + PRIMARY KEY (`id`), + UNIQUE (`entity`, `name`) +) STRICT; CREATE TABLE `blueprints` ( @@ -25,14 +26,11 @@ CREATE TABLE `properties` `id` INTEGER PRIMARY KEY, `blueprint` INTEGER NOT NULL REFERENCES `blueprints` (`id`) ON DELETE CASCADE, `name` TEXT NOT NULL, - `type` INT NOT NULL, - `cardinality` INT NOT NULL, + `schema` TEXT NOT NULL, `default_value` TEXT NOT NULL, `settings` TEXT NOT NULL ) STRICT; -CREATE INDEX `properties_type` ON `properties` (`type`); - CREATE TABLE `entity_blueprint_links` ( `entity` INTEGER NOT NULL REFERENCES `entities` (`id`) ON DELETE CASCADE, @@ -43,9 +41,11 @@ CREATE TABLE `entity_blueprint_links` CREATE TABLE `entity_property_values` ( + `id` INTEGER PRIMARY KEY, `entity` INTEGER NOT NULL REFERENCES `entities` (`id`) ON DELETE CASCADE, `property` INTEGER NOT NULL REFERENCES `properties` (`id`) ON DELETE CASCADE, `value` TEXT NOT NULL, - PRIMARY KEY (`entity`, `property`) -) WITHOUT ROWID, STRICT; + PRIMARY KEY (`id`), + UNIQUE (`entity`, `property`) +) STRICT; diff --git a/src/ikarus/persistence/project.cpp b/src/ikarus/persistence/project.cpp index 0d5b1e5..300bf86 100644 --- a/src/ikarus/persistence/project.cpp +++ b/src/ikarus/persistence/project.cpp @@ -1,339 +1,348 @@ #include "ikarus/persistence/project.h" +#include + #include +#include #include +#include +#include +#include #include #include -#include -#include -#include -#include -#include #include #include -IkarusProject::IkarusProject(std::string_view name, std::string_view path, std::unique_ptr && db): - name{name}, - path{std::move(path)}, - db{std::move(db)}, - _blueprints{}, - _properties{}, - _entities{} {} +constexpr char const * DB_PROJECT_ID_KEY = "project_id"; +constexpr char const * DB_PROJECT_NAME_KEY = "project_name"; -IkarusBlueprint * IkarusProject::get_blueprint(int64_t id) { - return get_cached_object(id, this->_blueprints); +auto create_impl( + std::string_view path, + std::string_view name, + IkarusErrorData * error_out +) -> std::unique_ptr { + IKARUS_VTRYRV_OR_FAIL( + auto db, + nullptr, + "failed to create project db: {}", + IkarusErrorInfo_Database_ConnectionFailed, + sqlitecpp::Connection::open(path) + ); + + auto close_db = [&]() { + if (db) { + LOG_INFO("closing project db"); + auto res = db->close(); + + if (res.is_error()) { + LOG_ERROR("failed to close project db: {}", res.unwrap_error()); + }; + } + }; + + IKARUS_TRYRV_OR_FAIL( + nullptr, + "failed to migrate project db: {}", + IkarusErrorInfo_Database_MigrationFailed, + db->migrate(ikarus::MIGRATIONS).on_error(close_db) + ); + + IKARUS_TRYRV_OR_FAIL( + nullptr, + "failed to set project id", + IkarusErrorInfo_Database_QueryFailed, + db->execute( + "INSERT INTO `metadata`(`key`, `value`) VALUES(?, ?)", + DB_PROJECT_ID_KEY, + boost::uuids::to_string(boost::uuids::random_generator()()) + ) + .on_error(close_db) + ); + + IKARUS_TRYRV_OR_FAIL( + nullptr, + "failed to set project id", + IkarusErrorInfo_Database_QueryFailed, + db->execute( + "INSERT INTO `metadata`(`key`, `value`) VALUES(?, ?)", + DB_PROJECT_NAME_KEY, + name + ) + .on_error(close_db) + ); + + return std::move(db); } -auto IkarusProject::uncache(IkarusBlueprint * blueprint) -> void { - remove_cached_object(blueprint, _blueprints); -} - -auto IkarusProject::get_entity(int64_t id) -> IkarusEntity * { - return get_cached_object(id, this->_entities); -} - -auto IkarusProject::uncache(IkarusEntity * entity) -> void { - remove_cached_object(entity, _entities); -} - -auto IkarusProject::get_property(int64_t id, IkarusValueType type) -> IkarusProperty * { - auto const iter = _properties.find(id); - - if (iter == _properties.cend()) { - switch (type) { - case IkarusValueType_Toggle: - return _properties.emplace(id, std::make_unique(this, id)).first->second.get(); - case IkarusValueType_Number: - return _properties.emplace(id, std::make_unique(this, id)).first->second.get(); - case IkarusValueType_Text: return _properties.emplace(id, std::make_unique(this, id)).first->second.get(); - } - } - - return iter->second.get(); -} - -auto IkarusProject::uncache(IkarusProperty * property) -> void { - remove_cached_object(property, _properties); -} - -IkarusProject * ikarus_project_create(char const * path, char const * name, IkarusErrorData * error_out) { - IKARUS_FAIL_IF_NULL(path, nullptr); - IKARUS_FAIL_IF_NULL(name, nullptr); - IKARUS_FAIL_IF(cppbase::is_empty_or_blank(path), nullptr, "path must not be empty", IkarusErrorInfo_Client_InvalidInput); - IKARUS_FAIL_IF(cppbase::is_empty_or_blank(name), nullptr, "name must not be empty", IkarusErrorInfo_Client_InvalidInput); - - boost::filesystem::path fs_path{path}; - - { - boost::system::error_code ec; - bool const exists = fs::exists(fs_path, ec); - IKARUS_FAIL_IF( - ec && ec != boost::system::errc::no_such_file_or_directory, - nullptr, - fmt::format("unable to check whether path is occupied: {}", ec.message()), - IkarusErrorInfo_Filesystem_AlreadyExists - ); - IKARUS_FAIL_IF(exists, nullptr, "path is already occupied", IkarusErrorInfo_Filesystem_AlreadyExists); - } - - IKARUS_VTRYRV_OR_FAIL( - auto db, - nullptr, - "failed to create project db: {}", - IkarusErrorInfo_Database_ConnectionFailed, - sqlitecpp::Connection::open(path) - ); - - IKARUS_TRYRV_OR_FAIL( - nullptr, - "failed to migrate project db: {}", - IkarusErrorInfo_Database_MigrationFailed, - db->migrate(ikarus::MIGRATIONS) - ); - - if (auto res = db->execute("INSERT INTO `metadata`(`key`, `value`) VALUES(?, ?)", DB_PROJECT_NAME_KEY, name); res.is_error()) { - boost::system::error_code ec; - fs::remove(fs_path, ec); - - IKARUS_FAIL_IF( - ec, - nullptr, - "failed to remove project db after being unable to insert name into metadata table: {}", - IkarusErrorInfo_Filesystem_AccessIssue - ); - - IKARUS_FAIL(nullptr, "failed to insert project name into metadata: {}", IkarusErrorInfo_Database_QueryFailed); - } - - return new IkarusProject{name, path, std::move(db)}; -} - -IkarusProject * ikarus_project_create_in_memory(char const * name, IkarusErrorData * error_out) { - IKARUS_FAIL_IF_NULL(name, nullptr); - IKARUS_FAIL_IF(cppbase::is_empty_or_blank(name), nullptr, "name must not be empty", IkarusErrorInfo_Client_InvalidInput); - - IKARUS_VTRYRV_OR_FAIL( - auto db, - nullptr, - "failed to create project db in memory: {}", - IkarusErrorInfo_Database_ConnectionFailed, - sqlitecpp::Connection::open_in_memory() - ); - - IKARUS_TRYRV_OR_FAIL( - nullptr, - "failed to migrate project db: {}", - IkarusErrorInfo_Database_MigrationFailed, - db->migrate(ikarus::MIGRATIONS) - ); - - IKARUS_TRYRV_OR_FAIL( - nullptr, - "failed to insert project name into metadata: {}", - IkarusErrorInfo_Database_QueryFailed, - db->execute("INSERT INTO `metadata`(`key`, `value`) VALUES(?, ?)", DB_PROJECT_NAME_KEY, name) - ); - - return new IkarusProject{name, ":memory:", std::move(db)}; -} - -IkarusProject * ikarus_project_open(char const * path, IkarusErrorData * error_out) { - IKARUS_FAIL_IF_NULL(path, nullptr); - IKARUS_FAIL_IF(cppbase::is_empty_or_blank(path), nullptr, "path must not be empty", IkarusErrorInfo_Client_InvalidInput); - - IKARUS_VTRYRV_OR_FAIL( - auto db, - nullptr, - "failed to open project db: {}", - IkarusErrorInfo_Database_ConnectionFailed, - sqlitecpp::Connection::open(path) - ); - - IKARUS_TRYRV_OR_FAIL( - nullptr, - "failed to migrate project db: {}", - IkarusErrorInfo_Database_MigrationFailed, - db->migrate(ikarus::MIGRATIONS) - ); - - IKARUS_VTRYRV_OR_FAIL( - auto const & name, - nullptr, - "failed to retrieve project name from metadata: {}", - IkarusErrorInfo_Database_QueryFailed, - db->query_one("SELECT `value` FROM `metadata` WHERE `key` = ?", DB_PROJECT_NAME_KEY) - ); - - return new IkarusProject{name, path, std::move(db)}; -} - -char const * ikarus_project_get_name(IkarusProject const * project, IkarusErrorData * error_out) { - IKARUS_FAIL_IF_NULL(project, nullptr); - - return project->name.data(); -} - -void ikarus_project_set_name(IkarusProject * project, char const * new_name, IkarusErrorData * error_out) { - IKARUS_FAIL_IF_NULL(project, ); - IKARUS_FAIL_IF_NULL(new_name, ); - - IKARUS_FAIL_IF(cppbase::is_empty_or_blank(new_name), , "name must not be empty", IkarusErrorInfo_Client_InvalidInput); - - IKARUS_TRYRV_OR_FAIL( - , - "failed to update project name: {}", - IkarusErrorInfo_Database_QueryFailed, - project->db->execute("UPDATE `metadata` SET `value` = ? WHERE `key` = ?", new_name, DB_PROJECT_NAME_KEY) - ); -} - -char const * ikarus_project_get_path(IkarusProject const * project, IkarusErrorData * error_out) { - IKARUS_FAIL_IF_NULL(project, nullptr); - - return project->path.data(); -} - -// these take a mutable project right now because the get_cached-* function must be mutable -// since we insert a backreference to the project into the objects, not ideal, -// but fine for now since "mutability" is a vague concept for projects anyway - -void ikarus_project_get_blueprints( - IkarusProject * project, - struct IkarusBlueprint ** blueprints_out, - size_t blueprints_out_size, - IkarusErrorData * error_out +IkarusProject * ikarus_project_create( + char const * path, + char const * name, + IkarusErrorData * error_out ) { - IKARUS_FAIL_IF_NULL(project, ); - IKARUS_FAIL_IF_NULL(blueprints_out, ); + IKARUS_FAIL_IF_NULL(path, nullptr); + IKARUS_FAIL_IF_NULL(name, nullptr); + IKARUS_FAIL_IF( + cppbase::is_empty_or_blank(path), + nullptr, + "path must not be empty", + IkarusErrorInfo_Client_InvalidInput + ); + IKARUS_FAIL_IF( + cppbase::is_empty_or_blank(name), + nullptr, + "name must not be empty", + IkarusErrorInfo_Client_InvalidInput + ); - if (blueprints_out_size == 0) { - return; - } + boost::filesystem::path fs_path{path}; - int64_t ids[blueprints_out_size]; + { + boost::system::error_code ec; + bool const exists = boost::filesystem::exists(fs_path, ec); + IKARUS_FAIL_IF( + ec && ec != boost::system::errc::no_such_file_or_directory, + nullptr, + fmt::format( + "unable to check whether path is occupied: {}", + ec.message() + ), + IkarusErrorInfo_Filesystem_AlreadyExists + ); + IKARUS_FAIL_IF( + exists, + nullptr, + "path is already occupied", + IkarusErrorInfo_Filesystem_AlreadyExists + ); + } - IKARUS_TRYRV_OR_FAIL( - , - "unable to fetch project blueprints from database: {}", - IkarusErrorInfo_Database_QueryFailed, - project->db->query_many_buffered("SELECT `id` FROM `blueprints`", ids, blueprints_out_size) - ); + if (auto db = create_impl(fs_path.c_str(), name, error_out); !db) { + LOG_WARN("creating project failed, removing file at {}", path); - for (size_t i = 0; i < blueprints_out_size; ++i) { - blueprints_out[i] = project->get_blueprint(ids[i]); - } + boost::system::error_code ec; + boost::filesystem::remove(fs_path, ec); + + IKARUS_FAIL_IF( + ec, + nullptr, + "failed to remove project db", + IkarusErrorInfo_Filesystem_MissingPermissions + ); + + IKARUS_FAIL( + nullptr, + "failed to insert project name into metadata: {}", + IkarusErrorInfo_Database_QueryFailed + ); + + return nullptr; + } else { + return new IkarusProject{name, path, std::move(db)}; + } } -size_t ikarus_project_get_blueprint_count(IkarusProject const * project, IkarusErrorData * error_out) { - IKARUS_FAIL_IF_NULL(project, 0); +IkarusProject * ikarus_project_create_in_memory( + char const * name, + IkarusErrorData * error_out +) { + IKARUS_FAIL_IF_NULL(name, nullptr); + IKARUS_FAIL_IF( + cppbase::is_empty_or_blank(name), + nullptr, + "name must not be empty", + IkarusErrorInfo_Client_InvalidInput + ); - IKARUS_VTRYRV_OR_FAIL( - auto const ret, - 0, - "unable to fetch project blueprint count from database: {}", - IkarusErrorInfo_Database_QueryFailed, - project->db->query_one("SELECT COUNT(*) FROM `blueprints`") - ); + if (auto db = create_impl(":memory:", name, error_out); !db) { + return nullptr; + } else { + IKARUS_TRYRV_OR_FAIL( + nullptr, + "failed to migrate project db: {}", + IkarusErrorInfo_Database_MigrationFailed, + db->migrate(ikarus::MIGRATIONS) + ); - return ret; + IKARUS_TRYRV_OR_FAIL( + nullptr, + "failed to insert project name into metadata: {}", + IkarusErrorInfo_Database_QueryFailed, + db->execute( + "INSERT INTO `metadata`(`key`, `value`) VALUES(?, ?)", + DB_PROJECT_NAME_KEY, + name + ) + ); + return new IkarusProject{name, ":memory:", std::move(db)}; + } +} + +IkarusProject * +ikarus_project_open(char const * path, IkarusErrorData * error_out) { + IKARUS_FAIL_IF_NULL(path, nullptr); + IKARUS_FAIL_IF( + cppbase::is_empty_or_blank(path), + nullptr, + "path must not be empty", + IkarusErrorInfo_Client_InvalidInput + ); + + IKARUS_VTRYRV_OR_FAIL( + auto db, + nullptr, + "failed to open project db: {}", + IkarusErrorInfo_Database_ConnectionFailed, + sqlitecpp::Connection::open(path) + ); + + IKARUS_TRYRV_OR_FAIL( + nullptr, + "failed to migrate project db: {}", + IkarusErrorInfo_Database_MigrationFailed, + db->migrate(ikarus::MIGRATIONS) + ); + + IKARUS_VTRYRV_OR_FAIL( + auto const & name, + nullptr, + "failed to retrieve project name from metadata: {}", + IkarusErrorInfo_Database_QueryFailed, + db->query_one( + "SELECT `value` FROM `metadata` WHERE `key` = ?", + DB_PROJECT_NAME_KEY + ) + ); + + return new IkarusProject{name, path, std::move(db)}; +} + +char const * ikarus_project_get_name( + IkarusProject const * project, + IkarusErrorData * error_out +) { + IKARUS_FAIL_IF_NULL(project, nullptr); + + return project->name.data(); +} + +void ikarus_project_set_name( + IkarusProject * project, + char const * new_name, + IkarusErrorData * error_out +) { + IKARUS_FAIL_IF_NULL(project, ); + IKARUS_FAIL_IF_NULL(new_name, ); + + IKARUS_FAIL_IF( + cppbase::is_empty_or_blank(new_name), + , + "name must not be empty", + IkarusErrorInfo_Client_InvalidInput + ); + + IKARUS_TRYRV_OR_FAIL( + , + "failed to update project name: {}", + IkarusErrorInfo_Database_QueryFailed, + project->db->execute( + "UPDATE `metadata` SET `value` = ? WHERE `key` = ?", + new_name, + DB_PROJECT_NAME_KEY + ) + ); +} + +char const * ikarus_project_get_path( + IkarusProject const * project, + IkarusErrorData * error_out +) { + IKARUS_FAIL_IF_NULL(project, nullptr); + + return project->path.c_str(); } void ikarus_project_get_entities( - IkarusProject * project, - struct IkarusEntity ** entities_out, - size_t entities_out_size, - IkarusErrorData * error_out + struct IkarusProject const * project, + int64_t * ids_out, + uint64_t ids_out_size, + IkarusErrorData * error_out ) { - IKARUS_FAIL_IF_NULL(project, ); - IKARUS_FAIL_IF_NULL(entities_out, ); + IKARUS_FAIL_IF_NULL(project, ); + IKARUS_FAIL_IF_NULL(ids_out, ); - if (entities_out_size == 0) { - return; - } + if (ids_out == 0) { + return; + } - int64_t ids[entities_out_size]; - - IKARUS_TRYRV_OR_FAIL( - , - "unable to fetch project entities from database: {}", - IkarusErrorInfo_Database_QueryFailed, - project->db->query_many_buffered("SELECT `id` FROM `entities`", ids, entities_out_size) - ); - - for (size_t i = 0; i < entities_out_size; ++i) { - entities_out[i] = project->get_entity(ids[i]); - } + IKARUS_TRYRV_OR_FAIL( + , + "unable to fetch project entities from database: {}", + IkarusErrorInfo_Database_QueryFailed, + project->db->query_many_buffered( + "SELECT `id` FROM `entities`", + ids_out, + ids_out_size + ) + ); } -size_t ikarus_project_get_entity_count(IkarusProject const * project, IkarusErrorData * error_out) { - IKARUS_FAIL_IF_NULL(project, 0); +size_t ikarus_project_get_entity_count( + IkarusProject const * project, + IkarusErrorData * error_out +) { + IKARUS_FAIL_IF_NULL(project, 0); - IKARUS_VTRYRV_OR_FAIL( - auto const ret, - 0, - "unable to fetch project entity count from database: {}", - IkarusErrorInfo_Database_QueryFailed, - project->db->query_one("SELECT COUNT(*) FROM `entities`") - ); + IKARUS_VTRYRV_OR_FAIL( + auto const ret, + 0, + "unable to fetch project entity count from database: {}", + IkarusErrorInfo_Database_QueryFailed, + project->db->query_one("SELECT COUNT(`id`) FROM `entities`") + ); - return ret; + return ret; } -struct IkarusEntity * get_entity_by_name(IkarusProject * project, char const * name, IkarusErrorData * error_out) { - IKARUS_FAIL_IF_NULL(project, nullptr); - IKARUS_FAIL_IF_NULL(name, nullptr); - IKARUS_FAIL_IF_NAME_INVALID(name, nullptr); +void ikarus_project_get_blueprints( + struct IkarusProject const * project, + int64_t * ids_out, + uint64_t ids_out_size, + IkarusErrorData * error_out +) { + IKARUS_FAIL_IF_NULL(project, ); + IKARUS_FAIL_IF_NULL(ids_out, ); - // TODO, 'InvalidInput' doesn't really make sense here, we'd need to adjust the macros to support distinguishing between different - // errors. In this case `sqlitecpp::MissingRow` and database related errors. Same for the other functions. - IKARUS_VTRYRV_OR_FAIL( - auto const id, - nullptr, - "unable to find entity in database: {}", - IkarusErrorInfo_Client_InvalidInput, - project->db->query_one("SELECT `id` FROM `entities` WHERE `name` = ?", name) - ); + if (ids_out == 0) { + return; + } - return project->get_entity(id); + IKARUS_TRYRV_OR_FAIL( + , + "unable to fetch project blueprints from database: {}", + IkarusErrorInfo_Database_QueryFailed, + project->db->query_many_buffered( + "SELECT `id` FROM `blueprints`", + ids_out, + ids_out_size + ) + ); } -struct IkarusProperty * -get_property_by_name(IkarusProject * project, IkarusPropertyScope * scope, char const * name, IkarusErrorData * error_out) { - IKARUS_FAIL_IF_NULL(project, nullptr); - IKARUS_FAIL_IF_NULL(name, nullptr); - IKARUS_FAIL_IF_NAME_INVALID(name, nullptr); +size_t ikarus_project_get_blueprint_count( + IkarusProject const * project, + IkarusErrorData * error_out +) { + IKARUS_FAIL_IF_NULL(project, 0); - IKARUS_VTRYRV_OR_FAIL( - auto const id_and_type, - nullptr, - "unable to find property in database: {}", - IkarusErrorInfo_Client_InvalidInput, - project->db->query_one( - "SELECT `id`, `type` FROM `properties` WHERE `name` = ? AND `scope` = ?", - name, - scope->get_id() - ) - ); + IKARUS_VTRYRV_OR_FAIL( + auto const ret, + 0, + "unable to fetch project blueprint count from database: {}", + IkarusErrorInfo_Database_QueryFailed, + project->db->query_one("SELECT COUNT(`id`) FROM `blueprints`") + ); - auto const [id, type] = id_and_type; - - return project->get_property(id, type); -} - -IkarusBlueprint * get_blueprints_by_name(IkarusProject * project, char const * name, IkarusErrorData * error_out) { - IKARUS_FAIL_IF_NULL(project, nullptr); - IKARUS_FAIL_IF_NULL(name, nullptr); - IKARUS_FAIL_IF_NAME_INVALID(name, nullptr); - - IKARUS_VTRYRV_OR_FAIL( - auto const id, - nullptr, - "unable to find blueprint in database: {}", - IkarusErrorInfo_Client_InvalidInput, - project->db->query_one("SELECT `id` FROM `blueprints` WHERE `name` = ?", name) - ); - - return project->get_blueprint(id); + return ret; } diff --git a/src/ikarus/persistence/project.hpp b/src/ikarus/persistence/project.hpp index 1dc69dc..f202ea2 100644 --- a/src/ikarus/persistence/project.hpp +++ b/src/ikarus/persistence/project.hpp @@ -1,58 +1,19 @@ #pragma once +#include +#include #include #include #include -#include -#include +#include +#include +#include -namespace fs = boost::filesystem; - -/// \private struct IkarusProject { -public: - IkarusProject(std::string_view name, std::string_view path, std::unique_ptr && db); - -public: - [[nodiscard]] auto get_blueprint(int64_t id) -> struct IkarusBlueprint *; - auto uncache(struct IkarusBlueprint * blueprint) -> void; - - [[nodiscard]] auto get_entity(int64_t id) -> struct IkarusEntity *; - auto uncache(struct IkarusEntity * entity) -> void; - - // TODO improve this to take a template param so that we don't have to cast in e.g. ikarus_toggle_property_create - [[nodiscard]] auto get_property(int64_t id, IkarusValueType type) -> struct IkarusProperty *; - auto uncache(struct IkarusProperty * property) -> void; - -private: - template - [[nodiscard]] T * get_cached_object(int64_t id, auto & cache) { - auto const iter = cache.find(id); - - if (iter == cache.cend()) { - return cache.emplace(id, std::make_unique(this, id)).first->second.get(); - } - - return iter->second.get(); - } - - template - void remove_cached_object(T * object, std::unordered_map> & cache) { - cache.erase(object->id); - } - -public: - std::string name; - std::string_view path; - std::unique_ptr db; - -private: - std::unordered_map> mutable _blueprints; - std::unordered_map> mutable _properties; - std::unordered_map> mutable _entities; + std::string name; + boost::filesystem::path path; + std::unique_ptr db; }; - -constexpr std::string_view DB_PROJECT_NAME_KEY = "PROJECT_NAME"; diff --git a/src/ikarus/values/data.cpp b/src/ikarus/values/data.cpp new file mode 100644 index 0000000..ac893b2 --- /dev/null +++ b/src/ikarus/values/data.cpp @@ -0,0 +1,217 @@ +#include "data.hpp" + +#include + +#include +#include + +#include +#include +#include +#include + +auto get_primitive_type(IkarusValueDataPrimitive const & primitive) + -> IkarusValuePrimitiveType { + return std::visit( + cppbase::overloaded{ + [](IkarusValueDataPrimitiveToggle const &) { + return IkarusValuePrimitiveType_Toggle; + }, + [](IkarusValueDataPrimitiveNumber const &) { + return IkarusValuePrimitiveType_Number; + }, + [](IkarusValueDataPrimitiveString const &) { + return IkarusValuePrimitiveType_Text; + } + }, + primitive + ); +} + +auto IkarusValueData::from_json(nlohmann::json const & json) + -> cppbase::Result { + if (!json.is_object()) { + return cppbase::err(IkarusJsonError{IkarusJsonInvalidTypeError{}}); + } + + IkarusValueData value{}; + + VTRY( + auto type, + deserialize_enum( + json, + "type", + IkarusValueDataType_Primitive, + IkarusValueDataType_Tuple + ) + ); + + switch (type) { + case IkarusValueDataType_Primitive: { + VTRY( + auto primitive, + deserialize_enum( + json, + "primitive", + IkarusValuePrimitiveType_Toggle, + IkarusValuePrimitiveType_Text + ) + ); + + switch (primitive) { + case IkarusValuePrimitiveType_Toggle: { + VTRY(auto data, deserialize_any(json, "data")); + + value.variant = IkarusValueDataPrimitiveToggle{data}; + break; + } + case IkarusValuePrimitiveType_Number: { + VTRY(auto data, deserialize_any(json, "data")); + + value.variant = IkarusValueDataPrimitiveNumber{data}; + break; + } + case IkarusValuePrimitiveType_Text: { + VTRY(auto data, deserialize_any(json, "data")); + + value.variant = IkarusValueDataPrimitiveString{data}; + break; + } + } + + break; + } + case IkarusValueDataType_List: { + std::vector> values_data{}; + VTRY( + auto data_json, + deserialize_any>(json, "data") + ); + + values_data.reserve(data_json.size()); + for (auto const & data_json : data_json) { + VTRY(auto value_data, IkarusValueData::from_json(data_json)); + values_data.emplace_back( + cppbase::make_owning(std::move(value_data)) + ); + } + + value.variant = IkarusValueDataList{values_data}; + break; + } + case IkarusValueDataType_Map: { + std::vector, + cppbase::owning_ptr>> + map_data{}; + + VTRY( + auto map_data_json, + deserialize_any>(json, "data") + ); + + map_data.reserve(map_data_json.size()); + + for (auto const & pair_json : map_data_json) { + VTRY(auto key_json, get_key(pair_json, "key")); + VTRY(auto value_json, get_key(pair_json, "value")); + VTRY(auto key, IkarusValueData::from_json(*key_json)); + VTRY(auto value, IkarusValueData::from_json(*value_json)); + + map_data.emplace_back( + cppbase::make_owning(key), + cppbase::make_owning(value) + ); + } + + value.variant = IkarusValueDataMap{map_data}; + break; + } + case IkarusValueDataType_Tuple: { + std::vector> values_data{}; + + VTRY( + auto values_json, + deserialize_any>(json, "data") + ); + + values_data.reserve(values_json.size()); + + for (auto const & value_json : values_json) { + VTRY(auto value_data, IkarusValueData::from_json(value_json)); + values_data.emplace_back( + cppbase::make_owning(value_data) + ); + } + + value.variant = IkarusValueDataTuple{values_data}; + break; + } + } + + return cppbase::ok(value); +} + +auto IkarusValueData::to_json( + nlohmann::json & json, + IkarusValueData const & value +) -> void { + std::visit( + cppbase::overloaded{ + [&](IkarusValueDataPrimitive const & primitive) { + std::visit( + cppbase::overloaded{ + [&](IkarusValueDataPrimitiveToggle const & toggle) { + json["type"] = IkarusValueDataType_Primitive; + json["primitive"] = IkarusValuePrimitiveType_Toggle; + json["data"] = toggle.value; + }, + [&](IkarusValueDataPrimitiveNumber const & number) { + json["type"] = IkarusValueDataType_Primitive; + json["primitive"] = IkarusValuePrimitiveType_Number; + json["data"] = number.value; + }, + [&](IkarusValueDataPrimitiveString const & string) { + json["type"] = IkarusValueDataType_Primitive; + json["primitive"] = IkarusValuePrimitiveType_Text; + json["data"] = string.value; + } + }, + primitive + ); + }, + [&](IkarusValueDataList const & list) { + json["type"] = IkarusValueDataType_List; + json["data"] = list.values | + std::views::transform([](auto const & data) { + nlohmann::json j; + IkarusValueData::to_json(j, *data); + return j; + }) | + std::ranges::to>(); + }, + [&](IkarusValueDataMap const & map) { + json["type"] = IkarusValueDataType_Map; + json["data"] = + map.values | std::views::transform([](auto const & pair) { + nlohmann::json j; + IkarusValueData::to_json(j["key"], *pair.first); + IkarusValueData::to_json(j["value"], *pair.second); + return j; + }) | + std::ranges::to>(); + }, + [&](IkarusValueDataTuple const & tuple) { + json["type"] = IkarusValueDataType_Tuple; + json["data"] = tuple.values | + std::views::transform([](auto const & data) { + nlohmann::json j; + IkarusValueData::to_json(j, *data); + return j; + }) | + std::ranges::to>(); + } + }, + value.variant + ); +} diff --git a/src/ikarus/values/data.hpp b/src/ikarus/values/data.hpp new file mode 100644 index 0000000..d4e92ad --- /dev/null +++ b/src/ikarus/values/data.hpp @@ -0,0 +1,65 @@ +#pragma once + +#include +#include + +#include + +#include +#include + +#include +#include +#include + +struct IkarusValueData; + +struct IkarusValueDataPrimitiveToggle { + bool value; +}; + +struct IkarusValueDataPrimitiveNumber { + double value; +}; + +struct IkarusValueDataPrimitiveString { + std::string value; +}; + +using IkarusValueDataPrimitive = std::variant< + IkarusValueDataPrimitiveToggle, + IkarusValueDataPrimitiveNumber, + IkarusValueDataPrimitiveString>; + +struct IkarusValueDataList { + std::vector> values; +}; + +struct IkarusValueDataMap { + std::vector, + cppbase::owning_ptr>> + values; +}; + +struct IkarusValueDataTuple { + std::vector> values; +}; + +struct IkarusValueData { + using IkarusValueDataVariant = std::variant< + IkarusValueDataPrimitive, + IkarusValueDataList, + IkarusValueDataMap, + IkarusValueDataTuple>; + + static auto from_json(nlohmann::json const & json) + -> cppbase::Result; + static auto to_json(nlohmann::json & json, IkarusValueData const & value) + -> void; + + IkarusValueDataVariant variant; +}; + +auto get_primitive_type(IkarusValueDataPrimitive const & primitive) + -> IkarusValuePrimitiveType; diff --git a/src/ikarus/values/entity_property_value.cpp b/src/ikarus/values/entity_property_value.cpp deleted file mode 100644 index 165383d..0000000 --- a/src/ikarus/values/entity_property_value.cpp +++ /dev/null @@ -1,21 +0,0 @@ -#include "entity_property_value.hpp" - -#include - -IkarusEntity const * ikarus_entity_property_value_get_entity(IkarusEntityPropertyValue const * value, IkarusErrorData * error_out) { - IKARUS_FAIL_IF_NULL(value, nullptr); - - return value->entity; -} - -IkarusProperty const * ikarus_entity_property_value_get_property(IkarusEntityPropertyValue const * value, IkarusErrorData * error_out) { - IKARUS_FAIL_IF_NULL(value, nullptr); - - return value->property; -} - -IkarusValue const * ikarus_entity_property_value_get_value(IkarusEntityPropertyValue const * value, IkarusErrorData * error_out) { - IKARUS_FAIL_IF_NULL(value, nullptr); - - return value->value; -} diff --git a/src/ikarus/values/entity_property_value.hpp b/src/ikarus/values/entity_property_value.hpp deleted file mode 100644 index 6f70f09..0000000 --- a/src/ikarus/values/entity_property_value.hpp +++ /dev/null @@ -1 +0,0 @@ -#pragma once diff --git a/src/ikarus/values/errors.hpp b/src/ikarus/values/errors.hpp new file mode 100644 index 0000000..ed752af --- /dev/null +++ b/src/ikarus/values/errors.hpp @@ -0,0 +1,36 @@ +#pragma once + +#include + +struct IkarusJsonMissingKeyError {}; + +struct IkarusJsonInvalidTypeError {}; + +struct IkarusJsonEnumOutOfBoundsError {}; + +struct IkarusJsonUnknownError {}; + +using IkarusJsonError = std::variant< + IkarusJsonMissingKeyError, + IkarusJsonInvalidTypeError, + IkarusJsonEnumOutOfBoundsError, + IkarusJsonUnknownError>; + +struct IkarusValueSchemaParseError { + IkarusJsonError error; +}; + +struct IkarusValueDataParseError { + IkarusJsonError error; +}; + +struct IkarusValueParseErrorDataSchemaMismatch {}; + +using IkarusValueParseError = std::variant< + IkarusJsonError, + IkarusValueSchemaParseError, + IkarusValueDataParseError, + IkarusValueParseErrorDataSchemaMismatch>; + +using IkarusValuesParseError = + std::variant; diff --git a/src/ikarus/values/number_value.cpp b/src/ikarus/values/number_value.cpp deleted file mode 100644 index 41fba42..0000000 --- a/src/ikarus/values/number_value.cpp +++ /dev/null @@ -1,65 +0,0 @@ -#include "ikarus/values/number_value.h" - -#include - -#include -#include - -IkarusNumberValue::IkarusNumberValue(): - IkarusValueData{this} {} - -IkarusNumberValue * ikarus_number_value_data_create() { - return new IkarusNumberValue{}; -} - -double const * ikarus_number_value_data_get(IkarusNumberValue * value, size_t idx) { - return ikarus_value_data_base_get(value, idx); -} - -size_t ikarus_number_value_data_get_size(IkarusNumberValue const * value) { - return ikarus_value_data_base_get_size(value); -} - -void ikarus_number_value_data_set(IkarusNumberValue * value, size_t idx, double new_data) { - return ikarus_value_data_base_set(value, idx, new_data); -} - -void ikarus_number_value_data_remove(IkarusNumberValue * value, size_t idx) { - return ikarus_value_data_base_remove(value, idx); -} - -void ikarus_number_value_data_insert(IkarusNumberValue * value, size_t idx, long double new_data) { - return ikarus_value_data_base_insert(value, idx, new_data); -} - -void ikarus_number_value_data_clear(IkarusNumberValue * value) { - return ikarus_value_data_base_clear(value); -} - -bool ikarus_number_value_data_is_undefined(IkarusNumberValue const * value) { - return ikarus_value_data_base_is_undefined(value); -} - -void ikarus_number_value_data_set_undefined(IkarusNumberValue * value, bool undefined) { - return ikarus_value_data_base_set_undefined(value, undefined); -} - -char const * ikarus_number_value_data_to_string(IkarusNumberValue const * value) { - return ikarus_value_data_base_to_string(value, [](auto const & value) { return value; }); -} - -bool ikarus_number_value_data_is_equal(IkarusNumberValue const * lhs, IkarusNumberValue const * rhs) { - return ikarus_value_data_base_is_equal(lhs, rhs); -} - -IkarusNumberValue * ikarus_number_value_data_copy(IkarusNumberValue const * value) { - return ikarus_value_data_base_copy(value); -} - -struct IkarusValueData * ikarus_number_value_data_to_value(IkarusNumberValue * value) { - return ikarus_value_data_base_to_value(value); -} - -struct IkarusValueData const * ikarus_number_value_data_to_value_data_const(IkarusNumberValue const * value) { - return ikarus_value_data_base_to_value_data_const(value); -} diff --git a/src/ikarus/values/number_value.hpp b/src/ikarus/values/number_value.hpp deleted file mode 100644 index bd4bec5..0000000 --- a/src/ikarus/values/number_value.hpp +++ /dev/null @@ -1,25 +0,0 @@ -#pragma once - -#include -#include - -#include - -struct IkarusNumberValue : IkarusValueData { -public: - using DataType = double; - -public: - explicit IkarusNumberValue(); - - IkarusNumberValue(IkarusNumberValue const &) = default; - IkarusNumberValue(IkarusNumberValue &&) = default; - - IkarusNumberValue & operator=(IkarusNumberValue const &) = default; - IkarusNumberValue & operator=(IkarusNumberValue &&) = default; - - ~IkarusNumberValue() override = default; - -public: - boost::variant2::variant> data{}; -}; diff --git a/src/ikarus/values/schema.cpp b/src/ikarus/values/schema.cpp new file mode 100644 index 0000000..e6cbd24 --- /dev/null +++ b/src/ikarus/values/schema.cpp @@ -0,0 +1,177 @@ +#include "schema.hpp" + +#include + +#include +#include +#include + +auto IkarusValueSchema::from_json(nlohmann::json const & json) + -> cppbase::Result { + if (!json.is_object()) { + return cppbase::err( + IkarusValueSchemaParseError{ + IkarusJsonError{IkarusJsonInvalidTypeError{}} + } + ); + } + + IkarusValueSchema schema{}; + + VTRY( + auto type, + deserialize_enum( + json, + "type", + IkarusValueSchemaType_Primitive, + IkarusValueSchemaType_Tuple + ) + ); + + switch (type) { + case IkarusValueSchemaType_Primitive: { + VTRY( + auto primitive, + deserialize_enum( + json, + "primitive", + IkarusValuePrimitiveType_Toggle, + IkarusValuePrimitiveType_Text + ) + ); + schema.variant = IkarusValueSchemaPrimitive{primitive}; + break; + } + case IkarusValueSchemaType_List: { + VTRY(auto sub_schema, IkarusValueSchema::from_json(json["schema"])); + schema.variant = IkarusValueSchemaList{ + cppbase::make_owning(std::move(sub_schema)) + }; + break; + } + case IkarusValueSchemaType_Map: { + VTRY(auto key_schema, IkarusValueSchema::from_json(json["key_schema"])); + VTRY( + auto value_schema, + IkarusValueSchema::from_json(json["value_schema"]) + ); + schema.variant = IkarusValueSchemaMap{ + cppbase::make_owning(std::move(key_schema)), + cppbase::make_owning(std::move(value_schema)) + }; + break; + } + case IkarusValueSchemaType_Tuple: { + VTRY( + auto sub_schemas_json, + deserialize_any>(json, "schemas") + ); + + std::vector> sub_schemas{}; + sub_schemas.reserve(sub_schemas_json.size()); + + for (auto const & sub_schema_json : sub_schemas_json) { + VTRY(auto schema, IkarusValueSchema::from_json(sub_schema_json)); + sub_schemas.emplace_back( + cppbase::make_owning(std::move(schema)) + ); + } + + schema.variant = IkarusValueSchemaTuple{sub_schemas}; + break; + } + } + + return cppbase::ok(std::move(schema)); +} + +auto IkarusValueSchema::to_json( + nlohmann::json & json, + IkarusValueSchema const & schema +) -> void { + std::visit( + cppbase::overloaded{ + [&json](IkarusValueSchemaPrimitive const & schema) { + json["type"] = IkarusValueSchemaType_Primitive; + json["primitive"] = schema.type; + }, + [&json](IkarusValueSchemaList const & schema) { + json["type"] = IkarusValueSchemaType_List; + IkarusValueSchema::to_json(json["schema"], *schema.sub_schema); + }, + [&json](IkarusValueSchemaMap const & schema) { + json["type"] = IkarusValueSchemaType_Map; + IkarusValueSchema::to_json( + json["key_schema"], + *schema.key_schema + ); + IkarusValueSchema::to_json( + json["value_schema"], + *schema.value_schema + ); + }, + [&json](IkarusValueSchemaTuple const & schema) { + json["type"] = IkarusValueSchemaType_Tuple; + + std::vector sub_schemas{}; + sub_schemas.reserve(schema.sub_schemas.size()); + + for (auto const & sub_schema : schema.sub_schemas) { + nlohmann::json sub_schema_json{}; + IkarusValueSchema::to_json(sub_schema_json, *sub_schema); + sub_schemas.push_back(sub_schema_json); + } + + json["schemas"] = sub_schemas; + } + }, + schema.variant + ); +} + +auto IkarusValueSchema::validate(IkarusValueData const & data) const -> bool { + return std::visit( + cppbase::overloaded{ + [](IkarusValueSchemaPrimitive const & schema, + IkarusValueDataPrimitive const & data) { + return get_primitive_type(data) == schema.type; + }, + [](IkarusValueSchemaList const & schema, + IkarusValueDataList const & data) { + for (auto const & value : data.values) { + if (!schema.sub_schema->validate(*value)) { + return false; + } + } + return true; + }, + [](IkarusValueSchemaMap const & schema, + IkarusValueDataMap const & data) { + for (auto const & pair : data.values) { + if (!schema.key_schema->validate(*pair.first) || + !schema.value_schema->validate(*pair.second)) { + return false; + } + } + return true; + }, + [](IkarusValueSchemaTuple const & schema, + IkarusValueDataTuple const & data) { + if (schema.sub_schemas.size() != data.values.size()) { + return false; + } + + for (size_t i = 0; i < schema.sub_schemas.size(); ++i) { + if (!schema.sub_schemas[i]->validate(*data.values[i])) { + return false; + } + } + + return true; + }, + [](auto const &, auto const &) { return false; } + }, + variant, + data.variant + ); +} diff --git a/src/ikarus/values/schema.hpp b/src/ikarus/values/schema.hpp new file mode 100644 index 0000000..4f4256c --- /dev/null +++ b/src/ikarus/values/schema.hpp @@ -0,0 +1,51 @@ +#pragma once + +#include +#include +#include + +#include + +#include +#include + +#include +#include + +struct IkarusValue; +struct IkarusValueData; +struct IkarusValueSchema; + +struct IkarusValueSchemaPrimitive { + IkarusValuePrimitiveType type; +}; + +struct IkarusValueSchemaList { + cppbase::owning_ptr sub_schema; +}; + +struct IkarusValueSchemaMap { + cppbase::owning_ptr key_schema; + cppbase::owning_ptr value_schema; +}; + +struct IkarusValueSchemaTuple { + std::vector> sub_schemas; +}; + +struct IkarusValueSchema { + using IkarusValueSchemaVariant = std::variant< + IkarusValueSchemaPrimitive, + IkarusValueSchemaList, + IkarusValueSchemaMap, + IkarusValueSchemaTuple>; + + static auto from_json(nlohmann::json const & json) + -> cppbase::Result; + static auto to_json(nlohmann::json & json, IkarusValueSchema const & value) + -> void; + + auto validate(IkarusValueData const & data) const -> bool; + + IkarusValueSchemaVariant variant; +}; diff --git a/src/ikarus/values/shared.hpp b/src/ikarus/values/shared.hpp new file mode 100644 index 0000000..a4d50ac --- /dev/null +++ b/src/ikarus/values/shared.hpp @@ -0,0 +1,65 @@ +#pragma once + +#include "errors.hpp" + +#include + +#include +#include + +inline auto get_key(nlohmann::json const & json, std::string_view key) + -> cppbase:: + Result { + auto iter = json.find(key); + if (iter == json.end()) { + return cppbase::err(IkarusJsonMissingKeyError{}); + } + + return cppbase::ok(iter); +} + +template +auto serialize_enum(nlohmann::json & json, std::string_view key, E value) + -> void { + json[key] = static_cast>(value); +} + +template + requires std::is_integral_v> +auto deserialize_enum( + nlohmann::json const & json, + std::string_view key, + E min, + E max +) -> cppbase::Result { + VTRY(auto iter, get_key(json, key)); + + if (!iter->is_number_integer()) { + return cppbase::err(IkarusJsonError{}); + } + + auto value = iter->get>(); + + if (value < static_cast>(min) || + value > static_cast>(max)) { + return cppbase::err(IkarusJsonError{}); + } + + return cppbase::ok(static_cast(value)); +} + +template +auto deserialize_any(nlohmann::json const & json, std::string_view key) + -> cppbase::Result { + VTRY(auto iter, get_key(json, key)); + + try { + return cppbase::ok(iter->get()); + } catch (nlohmann::json::type_error const &) { + return cppbase::err(IkarusJsonInvalidTypeError{}); + } catch (nlohmann::json::out_of_range const &) { + return cppbase::err(IkarusJsonEnumOutOfBoundsError{}); + } catch (nlohmann::json::exception const &) { + return cppbase::err(IkarusJsonUnknownError{}); + } +} diff --git a/src/ikarus/values/text_value.cpp b/src/ikarus/values/text_value.cpp deleted file mode 100644 index 9400f2e..0000000 --- a/src/ikarus/values/text_value.cpp +++ /dev/null @@ -1,66 +0,0 @@ -#include "ikarus/values/text_value.h" - -#include -#include - -#include -#include - -IkarusTextValue::IkarusTextValue(): - IkarusValueData{this} {} - -IkarusTextValue * ikarus_text_value_data_create() { - return new IkarusTextValue{}; -} - -char const * ikarus_text_value_data_get(IkarusTextValue * value, size_t idx) { - return ikarus_value_data_base_get(value, idx)->data(); -} - -size_t ikarus_text_value_data_get_size(IkarusTextValue const * value) { - return ikarus_value_data_base_get_size(value); -} - -void ikarus_text_value_data_set(IkarusTextValue * value, size_t idx, char const * new_data) { - return ikarus_value_data_base_set(value, idx, new_data); -} - -void ikarus_text_value_data_remove(IkarusTextValue * value, size_t idx) { - return ikarus_value_data_base_remove(value, idx); -} - -void ikarus_text_value_data_insert(IkarusTextValue * value, size_t idx, char const * new_data) { - return ikarus_value_data_base_insert(value, idx, new_data); -} - -void ikarus_text_value_data_clear(IkarusTextValue * value) { - return ikarus_value_data_base_clear(value); -} - -bool ikarus_text_value_data_is_undefined(IkarusTextValue const * value) { - return ikarus_value_data_base_is_undefined(value); -} - -void ikarus_text_value_data_set_undefined(IkarusTextValue * value, bool undefined) { - return ikarus_value_data_base_set_undefined(value, undefined); -} - -char const * ikarus_text_value_data_to_string(IkarusTextValue const * value) { - return ikarus_value_data_base_to_string(value, [](auto const & value) { return value; }); -} - -bool ikarus_text_value_data_is_equal(IkarusTextValue const * lhs, IkarusTextValue const * rhs) { - return ikarus_value_data_base_is_equal(lhs, rhs); -} - -IkarusTextValue * ikarus_text_value_data_copy(IkarusTextValue const * value) { - return ikarus_value_data_base_copy(value); -} - -struct IkarusValueData * ikarus_text_value_data_to_value(IkarusTextValue * value) { - return ikarus_value_data_base_to_value(value); -} - -struct IkarusValueData const * ikarus_text_value_data_to_value_data_const(IkarusTextValue const * value) { - return ikarus_value_data_base_to_value_data_const(value); -} diff --git a/src/ikarus/values/text_value.hpp b/src/ikarus/values/text_value.hpp deleted file mode 100644 index a1e36ea..0000000 --- a/src/ikarus/values/text_value.hpp +++ /dev/null @@ -1,24 +0,0 @@ -#pragma once - -#include - -#include - -struct IkarusTextValue : IkarusValueData { -public: - using DataType = std::string; - -public: - explicit IkarusTextValue(); - - IkarusTextValue(IkarusTextValue const &) = default; - IkarusTextValue(IkarusTextValue &&) = default; - - IkarusTextValue & operator=(IkarusTextValue const &) = default; - IkarusTextValue & operator=(IkarusTextValue &&) = default; - - ~IkarusTextValue() override = default; - -public: - boost::variant2::variant> data{}; -}; diff --git a/src/ikarus/values/toggle_value.cpp b/src/ikarus/values/toggle_value.cpp deleted file mode 100644 index fb76e68..0000000 --- a/src/ikarus/values/toggle_value.cpp +++ /dev/null @@ -1,66 +0,0 @@ -#include "ikarus/values/toggle_value.h" - -#include -#include - -#include -#include - -IkarusToggleValue::IkarusToggleValue(): - IkarusValueData{this} {} - -IkarusToggleValue * ikarus_toggle_value_data_create() { - return new IkarusToggleValue{}; -} - -bool const * ikarus_toggle_value_data_get(IkarusToggleValue * value, size_t idx) { - return ikarus_value_data_base_get(value, idx); -} - -size_t ikarus_toggle_value_data_get_size(IkarusToggleValue const * value) { - return ikarus_value_data_base_get_size(value); -} - -void ikarus_toggle_value_data_set(IkarusToggleValue * value, size_t idx, bool new_data) { - return ikarus_value_data_base_set(value, idx, new_data); -} - -void ikarus_toggle_value_data_remove(IkarusToggleValue * value, size_t idx) { - return ikarus_value_data_base_remove(value, idx); -} - -void ikarus_toggle_value_data_insert(IkarusToggleValue * value, size_t idx, bool new_data) { - return ikarus_value_data_base_insert(value, idx, new_data); -} - -void ikarus_toggle_value_data_clear(IkarusToggleValue * value) { - return ikarus_value_data_base_clear(value); -} - -bool ikarus_toggle_value_data_is_undefined(IkarusToggleValue const * value) { - return ikarus_value_data_base_is_undefined(value); -} - -void ikarus_toggle_value_data_set_undefined(IkarusToggleValue * value, bool undefined) { - return ikarus_value_data_base_set_undefined(value, undefined); -} - -char const * ikarus_toggle_value_data_to_string(IkarusToggleValue const * value) { - return ikarus_value_data_base_to_string(value, [](auto const & value) { return value ? "✓" : "✗"; }); -} - -bool ikarus_toggle_value_data_is_equal(IkarusToggleValue const * lhs, IkarusToggleValue const * rhs) { - return ikarus_value_data_base_is_equal(lhs, rhs); -} - -IkarusToggleValue * ikarus_toggle_value_data_copy(IkarusToggleValue const * value) { - return ikarus_value_data_base_copy(value); -} - -struct IkarusValueData * ikarus_toggle_value_data_to_value(IkarusToggleValue * value) { - return ikarus_value_data_base_to_value(value); -} - -struct IkarusValueData const * ikarus_toggle_value_data_to_value_data_const(IkarusToggleValue const * value) { - return ikarus_value_data_base_to_value_data_const(value); -} diff --git a/src/ikarus/values/toggle_value.hpp b/src/ikarus/values/toggle_value.hpp deleted file mode 100644 index fade2c1..0000000 --- a/src/ikarus/values/toggle_value.hpp +++ /dev/null @@ -1,24 +0,0 @@ -#pragma once - -#include - -#include - -struct IkarusToggleValue : IkarusValueData { -public: - using DataType = bool; - -public: - explicit IkarusToggleValue(); - - IkarusToggleValue(IkarusToggleValue const &) = default; - IkarusToggleValue(IkarusToggleValue &&) = default; - - IkarusToggleValue & operator=(IkarusToggleValue const &) = default; - IkarusToggleValue & operator=(IkarusToggleValue &&) = default; - - ~IkarusToggleValue() override = default; - -public: - boost::variant2::variant> data{}; -}; diff --git a/src/ikarus/values/value.cpp b/src/ikarus/values/value.cpp index de57e26..07c0c24 100644 --- a/src/ikarus/values/value.cpp +++ b/src/ikarus/values/value.cpp @@ -1,134 +1,58 @@ -#include "ikarus/values/value.h" +#include "value.hpp" -#include +#include +#include +#include +#include +#include +#include -#include -#include +auto IkarusValue::from_json(nlohmann::json const & json) + -> cppbase::Result { + if (!json.is_object()) { + return cppbase::err(IkarusJsonError{IkarusJsonInvalidTypeError{}}); + } -// required for header-only inclusion -#include + IkarusValue value{}; -#include -#include -#include -#include -#include -#include + VTRY(value.schema, IkarusValueSchema::from_json(json["schema"])); + VTRY(value.data, IkarusValueData::from_json(json["data"])); -IkarusValue::IkarusValue(Data data, IkarusValueCardinality cardinality): - data{data}, - cardinality{cardinality} {} + if (!value.schema.validate(value.data)) { + return cppbase::err(IkarusValueParseErrorDataSchemaMismatch{}); + } -cppbase::Result IkarusValue::from_json(boost::json::value json) { - if (auto const * obj = json.if_object(); obj == nullptr) { - return cppbase::err(FromJsonError{}); - } else { - int64_t const * type; - int64_t const * cardinality; - boost::json::value const * data; - - if (auto const * type_value = obj->if_contains(IKARUS_VALUE_JSON_TYPE_KEY); type_value == nullptr) { - return cppbase::err(FromJsonError{}); - } else if (type = type_value->if_int64(); type == nullptr) { - return cppbase::err(FromJsonError{}); - } - - if (auto const * cardinality_value = obj->if_contains(IKARUS_VALUE_JSON_CARDINALITY_KEY); cardinality_value == nullptr) { - return cppbase::err(FromJsonError{}); - } else if (cardinality = cardinality_value->if_int64(); cardinality == nullptr) { - return cppbase::err(FromJsonError{}); - } else if (*cardinality != IkarusValueCardinality_Single && *cardinality != IkarusValueCardinality_Multiple) { - return cppbase::err(FromJsonError{}); - } - - if (data = obj->if_contains(IKARUS_VALUE_JSON_DATA_KEY); data == nullptr) { - return cppbase::err(FromJsonError{}); - } - - auto create_value = [data, cardinality]() -> cppbase::Result { - T * ret = nullptr; - - ret->cardinality = *cardinality; - - if (data->is_null()) { - ret = new T{}; - ret->data = boost::variant2::monostate{}; - } else { - auto res = - boost::json::try_value_to>(*data - ); - - if (res.has_error()) { - return cppbase::err(FromJsonError{}); - } - - ret = new T{}; - ret->data = std::move(res.value()); - } - - return cppbase::ok(ret); - }; - - switch (*type) { - case IkarusValueType_Toggle: { - return create_value.operator()(); - } - case IkarusValueType_Number: { - return create_value.operator()(); - } - case IkarusValueType_Text: { - return create_value.operator()(); - } - default: { - return cppbase::err(FromJsonError{}); - } - } - } + return cppbase::ok(std::move(value)); } -boost::json::value IkarusValue::to_json() const { - auto type = std::visit( - cppbase::overloaded{ - []([[maybe_unused]] IkarusToggleValue const * value) { return IkarusValueType_Toggle; }, - []([[maybe_unused]] IkarusNumberValue const * value) { return IkarusValueType_Number; }, - []([[maybe_unused]] IkarusTextValue const * value) { return IkarusValueType_Text; } - }, - data - ); - - auto data_json = std::visit( - [](T const * value) -> boost::json::value { - return std::visit( - cppbase::overloaded{ - []([[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 { - { IKARUS_VALUE_JSON_TYPE_KEY, type}, - {IKARUS_VALUE_JSON_CARDINALITY_KEY, cardinality}, - { IKARUS_VALUE_JSON_DATA_KEY, data_json} - }; +auto IkarusValue::to_json(nlohmann::json & json, IkarusValue const & value) + -> void { + IkarusValueSchema::to_json(json["schema"], value.schema); + IkarusValueData::to_json(json["data"], value.data); } -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->data - ); +auto IkarusValues::from_json(nlohmann::json const & json) + -> cppbase::Result { + IkarusValues values{}; + + for (auto const & json_entry : json) { + VTRY(auto name_json, get_key(json_entry, "name")); + + if (!name_json->is_string()) { + return cppbase::err(IkarusJsonInvalidTypeError{}); + } + + VTRY(auto value_json, get_key(json_entry, "value")); + + VTRY(auto value, IkarusValue::from_json(*value_json)); + + values.values.emplace_back( + std::make_pair( + std::move(name_json->get()), + std::move(value) + ) + ); + } + + return cppbase::ok(std::move(values)); } diff --git a/src/ikarus/values/value.hpp b/src/ikarus/values/value.hpp index 07e92fc..47b3600 100644 --- a/src/ikarus/values/value.hpp +++ b/src/ikarus/values/value.hpp @@ -1,98 +1,28 @@ #pragma once -#include +#include #include -#include -#include -#include - -constexpr auto IKARUS_VALUE_JSON_TYPE_KEY = "type"; -constexpr auto IKARUS_VALUE_JSON_CARDINALITY_KEY = "card"; -constexpr auto IKARUS_VALUE_JSON_DATA_KEY = "data"; +#include +#include +#include struct IkarusValue { -public: - using Data = std::variant; - constexpr static auto SMALL_VEC_VALUE_SIZE = 8; + IkarusValueSchema schema; + IkarusValueData data; -public: - explicit IkarusValue(Data data, IkarusValueCardinality cardinality); - - IkarusValue(IkarusValue const &) = default; - IkarusValue(IkarusValue &&) noexcept = default; - - IkarusValue & operator=(IkarusValue const &) = default; - IkarusValue & operator=(IkarusValue &&) noexcept = default; - - virtual ~IkarusValue() = default; - -public: - struct FromJsonError {}; - - [[nodiscard]] static cppbase::Result from_json(boost::json::value json); - [[nodiscard]] boost::json::value to_json() const; - -public: - Data data; - IkarusValueCardinality cardinality; + static auto from_json(nlohmann::json const & json) + -> cppbase::Result; + static auto to_json(nlohmann::json & json, IkarusValue const & value) + -> void; }; -template<> -struct fmt::formatter { - template - constexpr static auto parse(FormatParseContext & ctx) { - return ctx.end(); - } +struct IkarusValues { + static auto from_json(nlohmann::json const & json) + -> cppbase::Result; + static auto to_json(nlohmann::json & json, IkarusValues const & values) + -> void; - constexpr static auto format([[maybe_unused]] IkarusValue::FromJsonError const & error, fmt::format_context & ctx) { - return fmt::format_to(ctx.out(), "unable to parse ikarus value JSON"); - } + std::vector> values; }; - -template -IkarusValue * fetch_value_from_db(IkarusProject * project, IkarusErrorData * error_out, std::string_view query, Args &&... args) { - IKARUS_VTRYRV_OR_FAIL( - auto const value_str, - nullptr, - "unable to fetch entity property value from database: {}", - IkarusErrorInfo_Database_QueryFailed, - project->db->query_one(query, std::forward(args)...) - ); - - boost::json::error_code ec{}; - boost::json::value json_value = boost::json::parse(value_str, ec); - - if (ec) { - IKARUS_SET_ERROR(fmt::format("invalid json is stored in database: {}", ec.message()), IkarusErrorInfo_Database_InvalidState); - return nullptr; - } - - IKARUS_VTRYRV_OR_FAIL( - auto const ret, - nullptr, - "unable to fetch entity property value: {}", - IkarusErrorInfo_LibIkarus_CannotPerformOperation, - IkarusValue::from_json(std::move(json_value)) - ); - - return ret; -} - -#define IKARUS_FAIL_IF_VALUE_MISSING_IMPL(var_name, entity, name, ret) \ - IKARUS_VTRYRV_OR_FAIL( \ - bool const var_name, \ - ret, \ - "unable to check whether value exists: {}", \ - IkarusErrorInfo_Database_QueryFailed, \ - (entity)->project->db->template query_one( \ - "SELECT EXISTS(SELECT 1 FROM `entity_values` WHERE `entity` = ? AND `name` = ?)", \ - (entity)->id, \ - name \ - ) \ - ) \ - \ - IKARUS_FAIL_IF(!(var_name), ret, "entity value does not exist", IkarusErrorInfo_Client_Misuse); - -#define IKARUS_FAIL_IF_VALUE_MISSING(entity, name, ret) IKARUS_FAIL_IF_VALUE_MISSING_IMPL(CPPBASE_UNIQUE_NAME(exists), entity, name, ret); diff --git a/src/ikarus/values/value_base.hpp b/src/ikarus/values/value_base.hpp deleted file mode 100644 index 5fa18ae..0000000 --- a/src/ikarus/values/value_base.hpp +++ /dev/null @@ -1,126 +0,0 @@ -#pragma once - -#include - -#include - -#include - -template -typename V::DataType const * ikarus_value_data_base_get(V * value, size_t idx) { - if (auto * data = boost::variant2::get_if>( - &value->data - ); - data != nullptr) { - return &(*data)[idx]; - } - - return nullptr; -} - -template -size_t ikarus_value_data_base_get_size(V const * value) { - if (auto * data = boost::variant2::get_if>( - &value->data - ); - data != nullptr) { - return data->size(); - } - - return 0; -} - -template -void ikarus_value_data_base_set(V * value, size_t idx, typename V::DataType new_data) { - if (auto * data = boost::variant2::get_if>( - &value->data - ); - data != nullptr) { - (*data)[idx] = new_data; - } -} - -template -void ikarus_value_data_base_remove(V * value, size_t idx) { - if (auto * data = boost::variant2::get_if>( - &value->data - ); - data != nullptr) { - data->erase(data->begin() + idx); - } -} - -template -void ikarus_value_data_base_insert(V * value, size_t idx, typename V::DataType new_data) { - if (auto * data = boost::variant2::get_if>( - &value->data - ); - data != nullptr) { - data->insert(data->begin() + idx, new_data); - } -} - -template -void ikarus_value_data_base_clear(V * value) { - if (auto * data = boost::variant2::get_if>( - &value->data - ); - data != nullptr) { - data->clear(); - } -} - -template -bool ikarus_value_data_base_is_undefined(V const * value) { - return boost::variant2::holds_alternative(value->data); -} - -template -void ikarus_value_data_base_set_undefined(V * value, bool undefined) { - if (undefined) { - value->data = boost::variant2::monostate{}; - } else { - value->data = boost::container::small_vector{}; - } -} - -template F> -char const * ikarus_value_data_base_to_string(V const * value, F transformer) { - return boost::variant2::visit( - cppbase::overloaded{ - [](boost::variant2::monostate const &) -> char const * { return nullptr; }, - [&transformer](auto const & data) -> char const * { - auto buffer = fmt::memory_buffer{}; - - fmt::format_to( - std::back_inserter(buffer), - "{}", - fmt::join(data | std::views::transform(std::forward(transformer)), ", ") - ); - - return buffer.data(); - } - }, - value->data - ); -} - -template -bool ikarus_value_data_base_is_equal(V const * lhs, V const * rhs) { - return lhs->data == rhs->data; -} - -template -V * ikarus_value_data_base_copy(V const * value) { - return new V{*value}; -} - -template -struct IkarusValueData * ikarus_value_data_base_to_value(V * value) { - return static_cast(value); -} - -template -struct IkarusValueData const * ikarus_value_data_base_to_value_data_const(V const * value) { - return static_cast(value); -} diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt new file mode 100644 index 0000000..e69de29 diff --git a/tools/cmake/toolchains/mac.cmake b/tools/cmake/toolchains/mac.cmake new file mode 100644 index 0000000..b7120cd --- /dev/null +++ b/tools/cmake/toolchains/mac.cmake @@ -0,0 +1,5 @@ +set(CMAKE_SYSTEM_NAME Darwin) +set(CMAKE_SYSTEM_PROCESSOR arm) + +set(CMAKE_PREFIX_PATH "$ENV{HOMEBREW_PREFIX}/opt/llvm") +set(ICU_ROOT "$ENV{HOMEBREW_PREFIX}/opt/icu4c") diff --git a/vendor/CMakeLists.txt b/vendor/CMakeLists.txt index 611db2e..5b8f409 100644 --- a/vendor/CMakeLists.txt +++ b/vendor/CMakeLists.txt @@ -1,3 +1,8 @@ # order is important here since sqlitecpp otherwise duplicates cppbase add_subdirectory(cppbase) add_subdirectory(sqlitecpp) +add_subdirectory(json) + +if (LIBIKARUS_ENABLE_TESTS) + add_subdirectory(catch2) +endif () diff --git a/vendor/catch2 b/vendor/catch2 new file mode 160000 index 0000000..f5cee49 --- /dev/null +++ b/vendor/catch2 @@ -0,0 +1 @@ +Subproject commit f5cee49c71e7c0e805695b03e8af533783789762 diff --git a/vendor/json b/vendor/json new file mode 160000 index 0000000..6057b31 --- /dev/null +++ b/vendor/json @@ -0,0 +1 @@ +Subproject commit 6057b31df7fe0b958d1795defc108d1f26e26441 diff --git a/vendor/sqlitecpp b/vendor/sqlitecpp index 32fa3c1..8edc04b 160000 --- a/vendor/sqlitecpp +++ b/vendor/sqlitecpp @@ -1 +1 @@ -Subproject commit 32fa3c1a9beae1a2c49fdd08cc659ea6153da666 +Subproject commit 8edc04b73bdee4b487ca59abd68615fa66c7948b