finalise interface & documentation

Signed-off-by: Folling <mail@folling.io>
This commit is contained in:
folling 2023-11-06 13:14:39 +01:00 committed by Folling
parent c5157bd849
commit 52580a4382
Signed by: folling
SSH key fingerprint: SHA256:S9qEx5WCFFLK49tE/LKnKuJYM5sw+++Dn6qJbbyxnCY
56 changed files with 2074 additions and 780 deletions

View file

@ -1,21 +1,150 @@
#pragma once
/// \file blueprint_folder.h
/// \author Folling <mail@folling.io>
/// \author Folling <folling@ikarus.world>
#include <ikarus/id.h>
#include <ikarus/macros.h>
/// \addtogroup folder Folders
/// \addtogroup blueprints Blueprints
/// @{
IKARUS_BEGIN_HEADER
/// \brief A blueprint folder, storing blueprints and other blueprint folders.
struct IkarusBlueprintFolder {
/// \private \brief The id of the blueprint folder.
IkarusId id;
};
struct IkarusBlueprintFolder;
/// \brief Creates a blueprint folder.
/// \param project The project the blueprint folder is part of.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \param parent The parent folder of the blueprint folder.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \param position The position of the blueprint folder in the parent folder. \see #FolderPosition
/// \pre \li Must be within bounds for the parent folder.
/// \param name The name of the blueprint folder.
/// \pre \li Must not be null.
/// \pre \li Must not be empty.
/// \return The created blueprint folder or null if an error occurs.
/// \remark Must be freed using #ikarus_free.
IKA_API IkarusBlueprintFolder * ikarus_blueprint_folder_create(
struct IkarusProject * project, IkarusBlueprintFolder * parent, size_t position, char const * name
);
/// \brief Copies a blueprint folder.
/// \details Creates a copy of the blueprint folder without its children.
/// \param blueprint_folder The blueprint folder to copy.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \param parent The parent folder of the blueprint folder.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \param position The position of the blueprint folder in the parent folder. \see #FolderPosition
/// \pre \li Must be within bounds for the parent folder.
/// \param name The name of the blueprint folder.
/// \pre \li Must not be null.
/// \pre \li Must not be empty.
/// \return The created blueprint folder or null if an error occurs.
/// \remark Must be freed using #ikarus_free.
IKA_API IkarusBlueprintFolder * ikarus_blueprint_folder_copy(
IkarusBlueprintFolder * blueprint_folder, IkarusBlueprintFolder * parent, size_t position, char const * name
);
/// \brief Deletes a blueprint folder and all its children
/// \param blueprint_folder The blueprint folder to delete.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \param keep_children If true, the children of the blueprint folder will be moved to the parent folder.
IKA_API void ikarus_blueprint_folder_delete(IkarusBlueprintFolder * blueprint_folder, bool keep_children);
/// \brief Gets the project of a blueprint folder.
/// \param blueprint_folder The blueprint folder to get the project of.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \return The project of the blueprint folder or null if an error occurs.
IKA_API struct IkarusProject * ikarus_blueprint_folder_get_project(IkarusBlueprintFolder const * blueprint_folder);
/// \brief Gets the parent folder of a blueprint folder.
/// \param blueprint_folder The blueprint folder to get the parent folder of.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \return The parent folder of the blueprint folder or null if an error occurs.
IKA_API struct IkarusBlueprintFolder * ikarus_blueprint_folder_get_parent(IkarusBlueprintFolder const * blueprint_folder);
/// \brief Gets the position of a blueprint folder within its parent folder.
/// \param blueprint_folder The blueprint folder to get the position of.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \return The position of the blueprint folder or undefined if an error occurs.
IKA_API size_t ikarus_blueprint_folder_get_position(IkarusBlueprintFolder const * blueprint_folder);
/// \brief Gets the name of a blueprint folder.
/// \param blueprint_folder The blueprint folder to get the name of.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \return The name of the blueprint folder or null if an error occurs.
/// \remark The returned pointer is valid until the blueprint folder is freed but may be invalidated by other operations.
IKA_API char const * ikarus_blueprint_folder_get_name(IkarusBlueprintFolder const * blueprint_folder);
/// \brief Gets the number of children of a blueprint folder.
/// \param blueprint_folder The blueprint folder to get the number of children of.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \return The number of children or undefined if an error occurs.
IKA_API size_t ikarus_blueprint_folder_get_child_count(IkarusBlueprintFolder const * blueprint_folder);
/// \brief Gets the children of a blueprint folder.
/// \param blueprint_folder The blueprint folder to get the children of.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \param children_out The buffer to write the children to.
/// \pre \li Must not be null.
/// \param children_out_size The size of the buffer.
IKA_API void ikarus_blueprint_folder_get_children(
IkarusBlueprintFolder const * blueprint_folder, struct IkarusBlueprintTreeItem ** children_out, size_t children_out_size
);
/// \brief Sets the parent folder of an blueprint folder.
/// \param blueprint_folder The blueprint folder to set the parent folder of.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \param new_parent The new parent folder of the blueprint folder.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \param new_position The new position of the blueprint folder in the parent folder. \see #FolderPosition
/// \pre \li Must be within bounds for the parent folder.
/// \remark This adjusts the positions of old and new siblings.
IKA_API void ikarus_blueprint_folder_set_parent(
IkarusBlueprintFolder * blueprint_folder, struct IkarusEntityFolder * new_parent, size_t new_position
);
/// \brief Sets the position of an blueprint folder within its parent folder.
/// \param blueprint_folder The blueprint folder to set the position of.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \param new_position The new position of the blueprint folder. \see #FolderPosition
/// \pre \li Must be within bounds for the parent folder.
/// \remark This adjusts the positions of siblings.
IKA_API void ikarus_blueprint_folder_set_position(IkarusBlueprintFolder * blueprint_folder, size_t new_position);
/// \brief Sets the name of an blueprint folder.
/// \param blueprint_folder The blueprint folder to set the name of.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \param new_name The new name of the blueprint folder.
/// \pre \li Must not be null.
/// \pre \li Must not be empty.
IKA_API void ikarus_blueprint_folder_set_name(IkarusBlueprintFolder * blueprint_folder, char const * new_name);
/// \brief Converts a blueprint folder to a generic folder.
/// \param blueprint_folder The blueprint folder to convert.
/// \return The constructed folder, representing the blueprint folder.
IKA_API struct IkarusFolder * ikarus_blueprint_folder_to_folder(IkarusBlueprintFolder const * blueprint_folder);
/// \brief Converts a blueprint folder to an object.
/// \param blueprint_folder The blueprint folder to convert.
/// \return The constructed object, representing the blueprint folder.
IKA_API struct IkarusObject * ikarus_blueprint_folder_to_object(IkarusBlueprintFolder const * blueprint_folder);
IKARUS_END_HEADER

View file

@ -0,0 +1,31 @@
#pragma once
/// \file blueprint_tree_item.h
/// \author Folling <folling@ikarus.world>
#include <ikarus/macros.h>
/// \addtogroup blueprints Blueprints
/// @{
IKARUS_BEGIN_HEADER
struct IkarusBlueprintTreeItem;
/// \brief Visits a blueprint tree item, calling the appropriate visitor function.
/// \param item The item to visit.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \param blueprint_visitor The visitor function called if the item is a blueprint. Skipped if null.
/// \param blueprint_folder_visitor The visitor function called if the item is a blueprint folder. Skipped if null.
/// \param data The data passed to the visitor functions.
IKA_API void ikarus_blueprint_tree_item_visit(
struct IkarusBlueprintTreeItem * item,
void (*blueprint_visitor)(struct IkarusBlueprint * blueprint, void * data),
void (*blueprint_folder_visitor)(struct IkarusBlueprintFolder * folder, void * data),
void * data
);
IKARUS_END_HEADER
/// @}

View file

@ -1,21 +1,150 @@
#pragma once
/// \file entity_folder.h
/// \author Folling <mail@folling.io>
/// \author Folling <folling@ikarus.world>
#include <ikarus/id.h>
#include <ikarus/macros.h>
/// \addtogroup folder Folders
/// \addtogroup entities Entities
/// @{
IKARUS_BEGIN_HEADER
/// \brief A entity folder, storing entities and other entity folders.
struct IkarusEntityFolder {
/// \private \brief The id of the entity folder.
IkarusId id;
};
struct IkarusEntityFolder;
/// \brief Creates a entity folder.
/// \param project The project the entity folder is part of.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \param parent The parent folder of the entity folder.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \param position The position of the entity folder in the parent folder. \see #FolderPosition
/// \pre \li Must be within bounds for the parent folder.
/// \param name The name of the entity folder.
/// \pre \li Must not be null.
/// \pre \li Must not be empty.
/// \return The created entity folder or null if an error occurs.
/// \remark Must be freed using #ikarus_free.
IKA_API IkarusEntityFolder * ikarus_entity_folder_create(
struct IkarusProject * project, IkarusEntityFolder * parent, size_t position, char const * name
);
/// \brief Copies a entity folder.
/// \details Creates a copy of the entity folder without its children.
/// \param entity_folder The entity folder to copy.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \param parent The parent folder of the entity folder.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \param position The position of the entity folder in the parent folder. \see #FolderPosition
/// \pre \li Must be within bounds for the parent folder.
/// \param name The name of the entity folder.
/// \pre \li Must not be null.
/// \pre \li Must not be empty.
/// \return The created entity folder or null if an error occurs.
/// \remark Must be freed using #ikarus_free.
IKA_API IkarusEntityFolder * ikarus_entity_folder_copy(
IkarusEntityFolder * entity_folder, IkarusEntityFolder * parent, size_t position, char const * name
);
/// \brief Deletes a entity folder and all its children
/// \param entity_folder The entity folder to delete.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \param keep_children If true, the children of the entity folder will be moved to the parent folder.
IKA_API void ikarus_entity_folder_delete(IkarusEntityFolder * entity_folder, bool keep_children);
/// \brief Gets the project of a entity folder.
/// \param entity_folder The entity folder to get the project of.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \return The project of the entity folder or null if an error occurs.
IKA_API struct IkarusProject * ikarus_entity_folder_get_project(IkarusEntityFolder const * entity_folder);
/// \brief Gets the parent folder of a entity folder.
/// \param entity_folder The entity folder to get the parent folder of.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \return The parent folder of the entity folder or null if an error occurs.
IKA_API struct IkarusEntityFolder * ikarus_entity_folder_get_parent(IkarusEntityFolder const * entity_folder);
/// \brief Gets the position of a entity folder within its parent folder.
/// \param entity_folder The entity folder to get the position of.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \return The position of the entity folder or undefined if an error occurs.
IKA_API size_t ikarus_entity_folder_get_position(IkarusEntityFolder const * entity_folder);
/// \brief Gets the name of a entity folder.
/// \param entity_folder The entity folder to get the name of.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \return The name of the entity folder or null if an error occurs.
/// \remark The returned pointer is valid until the entity folder is freed but may be invalidated by other operations.
IKA_API char const * ikarus_entity_folder_get_name(IkarusEntityFolder const * entity_folder);
/// \brief Gets the number of children of a entity folder.
/// \param entity_folder The entity folder to get the number of children of.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \return The number of children or undefined if an error occurs.
IKA_API size_t ikarus_entity_folder_get_child_count(IkarusEntityFolder const * entity_folder);
/// \brief Gets the children of a entity folder.
/// \param entity_folder The entity folder to get the children of.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \param children_out The buffer to write the children to.
/// \pre \li Must not be null.
/// \param children_out_size The size of the buffer.
IKA_API void ikarus_entity_folder_get_children(
IkarusEntityFolder const * entity_folder, struct IkarusEntityTreeItem ** children_out, size_t children_out_size
);
/// \brief Sets the parent folder of an entity folder.
/// \param entity_folder The entity folder to set the parent folder of.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \param new_parent The new parent folder of the entity folder.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \param new_position The new position of the entity folder in the parent folder. \see #FolderPosition
/// \pre \li Must be within bounds for the parent folder.
/// \remark This adjusts the positions of old and new siblings.
IKA_API void ikarus_entity_folder_set_parent(
IkarusEntityFolder * entity_folder, struct IkarusEntityFolder * new_parent, size_t new_position
);
/// \brief Sets the position of an entity folder within its parent folder.
/// \param entity_folder The entity folder to set the position of.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \param new_position The new position of the entity folder. \see #FolderPosition
/// \pre \li Must be within bounds for the parent folder.
/// \remark This adjusts the positions of siblings.
IKA_API void ikarus_entity_folder_set_position(IkarusEntityFolder * entity_folder, size_t new_position);
/// \brief Sets the name of an entity folder.
/// \param entity_folder The entity folder to set the name of.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \param new_name The new name of the entity folder.
/// \pre \li Must not be null.
/// \pre \li Must not be empty.
IKA_API void ikarus_entity_folder_set_name(IkarusEntityFolder * entity_folder, char const * new_name);
/// \brief Converts a entity folder to a generic folder.
/// \param entity_folder The entity folder to convert.
/// \return The constructed folder, representing the entity folder.
IKA_API struct IkarusFolder * ikarus_entity_folder_to_folder(IkarusEntityFolder const * entity_folder);
/// \brief Converts a entity folder to an object.
/// \param entity_folder The entity folder to convert.
/// \return The constructed object, representing the entity folder.
IKA_API struct IkarusObject * ikarus_entity_folder_to_object(IkarusEntityFolder const * entity_folder);
IKARUS_END_HEADER

View file

@ -0,0 +1,31 @@
#pragma once
/// \file entity_tree_item.h
/// \author Folling <folling@ikarus.world>
#include <ikarus/macros.h>
/// \addtogroup entities Entities
/// @{
IKARUS_BEGIN_HEADER
struct IkarusEntityTreeItem;
/// \brief Visits a entity tree item, calling the appropriate visitor function.
/// \param item The item to visit.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \param entity_visitor The visitor function called if the item is a entity. Skipped if null.
/// \param entity_folder_visitor The visitor function called if the item is a entity folder. Skipped if null.
/// \param data The data passed to the visitor functions.
IKA_API void ikarus_entity_tree_item_visit(
struct IkarusEntityTreeItem * item,
void (*entity_visitor)(struct IkarusEntity * entity, void * data),
void (*entity_folder_visitor)(struct IkarusEntityFolder * folder, void * data),
void * data
);
IKARUS_END_HEADER
/// @}

View file

@ -1,7 +1,7 @@
#pragma once
/// \file folder.h
/// \author Folling <mail@folling.io>
/// \author Folling <folling@ikarus.world>
#include <ikarus/folders/blueprint_folder.h>
#include <ikarus/folders/entity_folder.h>
@ -15,61 +15,23 @@ IKARUS_BEGIN_HEADER
/// \brief Folders are used to group objects together.
/// @{
/// \private \brief The data of a folder.
union IkarusFolderData {
/// \private \brief The blueprint folder data of the folder.
IkarusBlueprintFolder blueprint_folder;
/// \private \brief The property folder data of the folder.
IkarusPropertyFolder property_folder;
/// \private \brief The entity folder data of the folder.
IkarusEntityFolder entity_folder;
};
/// \brief A generic folder. Similar to how Objects wrap all types of objects, Folders wrap all types of folders.
struct IkarusFolder {
/// \private \brief The data of the folder.
IkarusFolderData data;
struct IkarusFolder;
/// \private \brief The type of the folder.
IkarusFolderType type;
};
/// \brief Constructs a folder from a blueprint folder.
/// \param blueprint_folder The blueprint folder to construct the folder from.
/// \return The constructed folder.
IKA_API IkarusFolder ikarus_folder_from_blueprint_folder(IkarusBlueprintFolder blueprint_folder);
/// \brief Constructs a folder from a property folder.
/// \param property_folder The property folder to construct the folder from.
/// \return The constructed folder.
IKA_API IkarusFolder ikarus_folder_from_property_folder(IkarusPropertyFolder property_folder);
/// \brief Constructs a folder from an entity folder.
/// \param entity_folder The entity folder to construct the folder from.
/// \return The constructed folder.
IKA_API IkarusFolder ikarus_folder_from_entity_folder(IkarusEntityFolder entity_folder);
/// \brief Fetches the folder type of a folder.
/// \param folder The folder to fetch the type of.
/// \return The type of the folder.
IKA_API IkarusFolderType ikarus_folder_get_type(IkarusFolder folder);
/// \brief Checks if two folders are equal.
/// \details Since ids store the type of the object, this boils down to a simple comparison of the ids.
/// \param left The left side of the comparison.
/// \param right The right side of the comparison.
/// \return True if the folders are equal, false otherwise
IKA_API bool ikarus_folder_is_equal(IkarusFolder left, IkarusFolder right);
/// \brief Special value for inserting objects at the end of a folder.
enum FolderPosition { FolderPosition_EndOfFolder = -1 };
/// \brief Visits a folder. Calling the appropriate function for the folder's type.
/// \param folder The folder to visit.
/// \param blueprint The function to call if the folder is a blueprint folder.
/// \param property The function to call if the folder is a property folder.
/// \param entity The function to call if the folder is an entity folder.
/// \param data The data to pass to the functions.
/// \param blueprint_visitor The function to call if the folder is a blueprint folder.
/// \param property_visitor The function to call if the folder is a property folder.
/// \param entity_visitor The function to call if the folder is an entity folder.
/// \param data The data passed to the visitor functions.
IKA_API void ikarus_folder_visit(
IkarusFolder folder,
void (*blueprint)(IkarusBlueprintFolder, void *),
void (*property)(IkarusPropertyFolder, void *),
void (*entity)(IkarusEntityFolder, void *),
IkarusFolder * folder,
void (*blueprint_visitor)(IkarusBlueprintFolder *, void *),
void (*property_visitor)(IkarusPropertyFolder *, void *),
void (*entity_visitor)(IkarusEntityFolder *, void *),
void * data
);

View file

@ -3,7 +3,7 @@
// IMPLEMENTATION_DETAIL_FOLDER_TYPES
/// \file folder_type.h
/// \author Folling <mail@folling.io>
/// \author Folling <folling@ikarus.world>
#include <ikarus/macros.h>
@ -11,16 +11,16 @@
/// @{
/// \brief The type of an folder.
/// \remark Folders have the 8th bit set.
/// \remark The values are identical to their counterparts in #IkarusObjectType.
enum IkarusFolderType {
/// \brief Not a folder or no folder.
IkarusFolderType_None = 0,
/// \brief An IkarusBlueprintFolder
IkarusFolderType_BlueprintFolder = 0b1000'0001,
IkarusFolderType_BlueprintFolder = 0b0100'0001,
/// \brief An IkarusPropertyFolder
IkarusFolderType_PropertyFolder = 0b1000'0010,
IkarusFolderType_PropertyFolder = 0b0100'0010,
/// \brief An IkarusEntityFolder
IkarusFolderType_EntityFolder = 0b1000'0011,
IkarusFolderType_EntityFolder = 0b0100'0011,
};
/// @}

View file

@ -1,22 +1,158 @@
#pragma once
#include <ikarus/id.h>
/// \file property_folder.h
/// \author Folling <folling@ikarus.world>
#include <ikarus/macros.h>
/// \file property_folder.h
/// \author Folling <mail@folling.io>
/// \addtogroup folder Folders
/// \addtogroup properties Properties
/// @{
IKARUS_BEGIN_HEADER
/// \brief A property folder, storing properties and other property folders.
/// \remark Property folders are scoped to the blueprint or entity they are associated with.
struct IkarusPropertyFolder {
/// \private \brief The id of the property folder.
IkarusId id;
};
struct IkarusPropertyFolder;
/// \brief Creates a property folder.
/// \param project The project the property folder is part of.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \param parent The parent folder of the property folder.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \param position The position of the property folder in the parent folder. \see #FolderPosition
/// \pre \li Must be within bounds for the parent folder.
/// \param name The name of the property folder.
/// \pre \li Must not be null.
/// \pre \li Must not be empty.
/// \return The created property folder or null if an error occurs.
/// \remark Must be freed using #ikarus_free.
IKA_API IkarusPropertyFolder * ikarus_property_folder_create(
struct IkarusProject * project, IkarusPropertyFolder * parent, size_t position, char const * name
);
/// \brief Copies a property folder.
/// \details Creates a copy of the property folder without its children.
/// \param property_folder The property folder to copy.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \param parent The parent folder of the property folder.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \param position The position of the property folder in the parent folder. \see #FolderPosition
/// \pre \li Must be within bounds for the parent folder.
/// \param name The name of the property folder.
/// \pre \li Must not be null.
/// \pre \li Must not be empty.
/// \return The created property folder or null if an error occurs.
/// \remark Must be freed using #ikarus_free.
IKA_API IkarusPropertyFolder * ikarus_property_folder_copy(
IkarusPropertyFolder * property_folder, IkarusPropertyFolder * parent, size_t position, char const * name
);
/// \brief Deletes a property folder and all its children
/// \param property_folder The property folder to delete.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \param keep_children If true, the children of the property folder will be moved to the parent folder.
IKA_API void ikarus_property_folder_delete(IkarusPropertyFolder * property_folder, bool keep_children);
/// \brief Gets the project of a property folder.
/// \param property_folder The property folder to get the project of.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \return The project of the property folder or null if an error occurs.
IKA_API struct IkarusProject * ikarus_property_folder_get_project(IkarusPropertyFolder const * property_folder);
/// \brief Gets the property source of a property folder.
/// \param property_folder The property folder to get the property source of.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \return The property source of the property folder or null if an error occurs.
/// \remark Must be freed using #ikarus_free.
IKA_API struct IkarusPropertySource * ikarus_property_folder_get_source(IkarusPropertyFolder const * property_folder);
/// \brief Gets the parent folder of a property folder.
/// \param property_folder The property folder to get the parent folder of.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \return The parent folder of the property folder or null if an error occurs.
IKA_API struct IkarusPropertyFolder * ikarus_property_folder_get_parent(IkarusPropertyFolder const * property_folder);
/// \brief Gets the position of a property folder within its parent folder.
/// \param property_folder The property folder to get the position of.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \return The position of the property folder or undefined if an error occurs.
IKA_API size_t ikarus_property_folder_get_position(IkarusPropertyFolder const * property_folder);
/// \brief Gets the name of a property folder.
/// \param property_folder The property folder to get the name of.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \return The name of the property folder or null if an error occurs.
/// \remark The returned pointer is valid until the property folder is freed but may be invalidated by other operations.
IKA_API char const * ikarus_property_folder_get_name(IkarusPropertyFolder const * property_folder);
/// \brief Gets the number of children of a property folder.
/// \param property_folder The property folder to get the number of children of.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \return The number of children or undefined if an error occurs.
IKA_API size_t ikarus_property_folder_get_child_count(IkarusPropertyFolder const * property_folder);
/// \brief Gets the children of a property folder.
/// \param property_folder The property folder to get the children of.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \param children_out The buffer to write the children to.
/// \pre \li Must not be null.
/// \param children_out_size The size of the buffer.
IKA_API void ikarus_property_folder_get_children(
IkarusPropertyFolder const * property_folder, struct IkarusPropertyTreeItem ** children_out, size_t children_out_size
);
/// \brief Sets the parent folder of an property folder.
/// \param property_folder The property folder to set the parent folder of.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \param new_parent The new parent folder of the property folder.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \param new_position The new position of the property folder in the parent folder. \see #FolderPosition
/// \pre \li Must be within bounds for the parent folder.
/// \remark This adjusts the positions of old and new siblings.
IKA_API void ikarus_property_folder_set_parent(
IkarusPropertyFolder * property_folder, struct IkarusPropertyFolder * new_parent, size_t new_position
);
/// \brief Sets the position of an property folder within its parent folder.
/// \param property_folder The property folder to set the position of.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \param new_position The new position of the property folder. \see #FolderPosition
/// \pre \li Must be within bounds for the parent folder.
/// \remark This adjusts the positions of siblings.
IKA_API void ikarus_property_folder_set_position(IkarusPropertyFolder * property_folder, size_t new_position);
/// \brief Sets the name of an property folder.
/// \param property_folder The property folder to set the name of.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \param new_name The new name of the property folder.
/// \pre \li Must not be null.
/// \pre \li Must not be empty.
IKA_API void ikarus_property_folder_set_name(IkarusPropertyFolder * property_folder, char const * new_name);
/// \brief Converts a property folder to a generic folder.
/// \param property_folder The property folder to convert.
/// \return The constructed folder, representing the property folder.
IKA_API struct IkarusFolder * ikarus_property_folder_to_folder(IkarusPropertyFolder const * property_folder);
/// \brief Converts a property folder to an object.
/// \param property_folder The property folder to convert.
/// \return The constructed object, representing the property folder.
IKA_API struct IkarusObject * ikarus_property_folder_to_object(IkarusPropertyFolder const * property_folder);
IKARUS_END_HEADER

View file

@ -0,0 +1,31 @@
#pragma once
/// \file property_tree_item.h
/// \author Folling <folling@ikarus.world>
#include <ikarus/macros.h>
/// \addtogroup properties Properties
/// @{
IKARUS_BEGIN_HEADER
struct IkarusPropertyTreeItem;
/// \brief Visits a property tree item, calling the appropriate visitor function.
/// \param item The item to visit.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \param property_visitor The visitor function called if the item is a property. Skipped if null.
/// \param property_folder_visitor The visitor function called if the item is a property folder. Skipped if null.
/// \param data The data passed to the visitor functions.
IKA_API void ikarus_property_tree_item_visit(
struct IkarusPropertyTreeItem * item,
void (*property_visitor)(struct IkarusProperty * property, void * data),
void (*property_folder_visitor)(struct IkarusPropertyFolder * folder, void * data),
void * data
);
IKARUS_END_HEADER
/// @}

16
include/ikarus/global.h Normal file
View file

@ -0,0 +1,16 @@
#pragma once
/// \file memory.h
/// \author Folling <folling@ikarus.world>
#include <ikarus/macros.h>
/// \addtogroup global Global
/// \brief Information relevant to the entire library.
/// @{
/// \brief Frees a pointer allocated by ikarus. Every pointer returned by a function must be freed using this function unless
/// explicitly stated otherwise.
IKA_API void ikarus_free(void * ptr);
/// @}

View file

@ -1,66 +0,0 @@
// IMPLEMENTATION_DETAIL_DATABASE
/// \file id.h
/// \author Folling <mail@folling.io>
#pragma once
#include <ikarus/macros.h>
#include <ikarus/objects/object_type.h>
#include <ikarus/stdtypes.h>
IKARUS_BEGIN_HEADER
/// \defgroup id Ids
/// \brief Ids are used to identify objects in the database.
/// \details They are stored as 64 bit integers with the following layout:
/// - first 8 bits: #IkarusObjectType - 255 possible values, 0 for special values
/// - last 56 bits: incremented counter generated by the database
/// @{
/// \brief A wrapper around a 64 bit integer that represents the id of an object.
/// \details They are stored as 64 bit integers with the following layout:
/// - first bit: ignored, technically we could use it, but SQLite doesn't support u64 integers.
/// To avoid ordering fiascos and potential index performance degradation we just skip the first bit.
/// - next 7 bits: #IkarusObjectType - 127 possible values, 0 for special values
/// - last 56 bits: incremented counter generated by the database
struct IkarusId {
/// \private \brief The value of the id.
int64_t data;
};
/// \brief A special id returned by failed functions.
IkarusId const IKARUS_ID_NONE{0};
/// \brief A special id used to indicate an optional id not being specified.
IkarusId const IKARUS_ID_UNSPECIFIED{1};
/// \private \brief Generates a new id for the given object type.
/// \param data The data from which the id will be constructed.
/// \return The generated id.
/// \pre data must be valid under the format described in Id. It should also point to an object in the database.
IkarusId ikarus_id_from_data(int64_t data);
/// \brief Checkes whether two ids are equal
/// \param left the left side of the comparison
/// \param right the right side of the comparison
/// \return True if the bits from the left id are equal to the bits of the right id
bool ikarus_id_is_equal(IkarusId left, IkarusId right);
/// \brief Fetches the object type of the given id.
/// \param id The id to fetch the object type for.
/// \return The object type of the given id.
IKA_API IkarusObjectType ikarus_id_get_object_type(IkarusId id);
/// \brief Checks if the given id is IKARUS_ID_NONE.
/// \param id The id to check.
/// \return True if the id is IKARUS_ID_NONE, false otherwise.
IKA_API bool ikarus_id_is_none(IkarusId id);
/// \brief Checks if the given id is IKARUS_ID_UNSPECIFIED.
/// \param id The id to check.
/// \return True if the id is IKARUS_ID_UNSPECIFIED, false otherwise.
IKA_API bool ikarus_id_is_unspecified(IkarusId id);
/// @}
IKARUS_END_HEADER

View file

@ -1,23 +1,210 @@
#pragma once
/// \file blueprint.h
/// \author Folling <mail@folling.io>
/// \author Folling <folling@ikarus.world>
#include <ikarus/id.h>
#include <ikarus/macros.h>
#include <ikarus/stdtypes.h>
/// \defgroup blueprints Blueprints
/// \brief Blueprints are templates for entities.
/// @{
IKARUS_BEGIN_HEADER
/// \brief A blueprint object.
/// \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.
struct IkarusBlueprint {
/// \private \brief The id of the blueprint.
IkarusId id;
};
/// Each entity the blueprint is linked to will have values for the blueprints properties.q
struct IkarusBlueprint;
/// \brief Creates a blueprint.
/// \param project The project the blueprint is part of.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \param parent The parent folder of the blueprint.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \param position The position of the blueprint in the parent folder. \see #FolderPosition
/// \pre \li Must be within bounds for the parent folder.
/// \param name The name of the blueprint.
/// \pre \li Must not be null.
/// \pre \li Must not be empty.
/// \return The created blueprint or null if an error occurs.
/// \remark Must be freed using #ikarus_free.
IKA_API IkarusBlueprint * ikarus_blueprint_create(
struct IkarusProject * project, struct IkarusBlueprintFolder * parent, size_t position, char const * name
);
/// \brief Creates a blueprint from an entity.
/// \details The created blueprint will have the same properties as the entity.
/// \param entity The entity to create the blueprint from.
/// \pre \li Must not be null.
/// \param link_entity If true, the entity will be linked to the blueprint. If not they will remain separate.
/// \param parent The parent folder of the blueprint.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \param position The position of the blueprint in the parent folder. \see #FolderPosition
/// \pre \li Must be within bounds for the parent folder.
/// \param name The name of the blueprint. Must not be empty.
/// \pre \li Must not be null.
/// \pre \li Must not be empty.
/// \return The created blueprint or null if an error occurs.
/// \remark Must be freed using #ikarus_free.
IKA_API IkarusBlueprint * ikarus_blueprint_create_from_entity(
struct IkarusEntity * entity, bool link_entity, struct IkarusBlueprintFolder * parent, size_t position, char const * name
);
/// \brief Copies a blueprint.
/// \details Creates a deep copy of the blueprint including all of its properties.
/// \param blueprint The blueprint to copy.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \param parent The parent folder of the blueprint.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \param position The position of the blueprint in the parent folder. \see #FolderPosition
/// \pre \li Must be within bounds for the parent folder.
/// \param name The name of the blueprint.
/// \pre \li Must not be null.
/// \pre \li Must not be empty.
/// \return The created blueprint or null if an error occurs.
/// \remark Linked entities won't be copied.
/// \remark Must be freed using #ikarus_free.
IKA_API IkarusBlueprint * ikarus_blueprint_copy(
IkarusBlueprint const * blueprint, struct IkarusBlueprintFolder * parent, size_t position, char const * name
);
/// \brief Deletes a blueprint.
/// \param blueprint The blueprint to delete.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \remark The blueprint must not be accessed after deletion.
IKA_API void ikarus_blueprint_delete(IkarusBlueprint * blueprint);
/// \brief Gets the project of a blueprint.
/// \param blueprint The blueprint to get the project of.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \return The project of the blueprint or null if an error occurs.
IKA_API struct IkarusProject * ikarus_blueprint_get_project(IkarusBlueprint const * blueprint);
/// \brief Gets the parent folder of a blueprint.
/// \param blueprint The blueprint to get the parent folder of.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \return The parent folder of the blueprint or null if an error occurs.
IKA_API struct IkarusBlueprintFolder * ikarus_blueprint_get_parent(IkarusBlueprint const * blueprint);
/// \brief Gets the position of a blueprint within its parent folder.
/// \param blueprint The blueprint to get the position of.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \return The position of the blueprint or undefined if an error occurs.
IKA_API size_t ikarus_blueprint_get_position(IkarusBlueprint const * blueprint);
/// \brief Gets the name of a blueprint.
/// \param blueprint The blueprint to get the name of.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \return The name of the blueprint or null if an error occurs.
/// \remark The returned pointer is valid until the blueprint is freed but may be invalidated by other operations.
IKA_API char const * ikarus_blueprint_get_name(IkarusBlueprint const * blueprint);
/// \brief Gets the property root folder of a blueprint.
/// \param blueprint The blueprint to get the root folder of.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \return The root folder of all properties of the blueprint or null if an error occurs.
/// \remark Must be freed using #ikarus_free.
IKA_API struct IkarusPropertyFolder * ikarus_blueprint_get_property_root_folder(IkarusBlueprint const * blueprint);
/// \brief Gets the number of properties of a blueprint.
/// \param blueprint The blueprint to get the number of properties of.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \return The number of properties or undefined if an error occurs.
IKA_API size_t ikarus_blueprint_get_property_count(IkarusBlueprint const * blueprint);
/// \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.
IKA_API void ikarus_blueprint_get_properties(
IkarusBlueprint const * blueprint, struct IkarusProperty ** properties_out, size_t properties_out_size
);
/// \brief Gets the number of entities linked to a blueprint.
/// \param blueprint The blueprint to get the number of linked entities of.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \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);
/// \brief Gets the entities linked to a blueprint.
/// \param blueprint The blueprint to get the linked 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.
IKA_API void ikarus_blueprint_get_linked_entities(
IkarusBlueprint const * blueprint, struct IkarusEntity ** entities_out, size_t entities_out_size
);
/// \brief Sets the parent folder of a blueprint.
/// \param blueprint The blueprint to set the parent folder of.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \param new_parent The new parent folder of the blueprint.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \param new_position The new position of the blueprint in the parent folder. \see #FolderPosition
/// \pre \li Must be within bounds for the parent folder.
/// \remark This adjusts the positions of old and new siblings.
IKA_API void ikarus_blueprint_set_parent(
IkarusBlueprint * blueprint, struct IkarusBlueprintFolder * new_parent, size_t new_position
);
/// \brief Sets the position of a blueprint within its parent folder.
/// \param blueprint The blueprint to set the position of.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \param new_position The new position of the blueprint. \see #FolderPosition
/// \pre \li Must be within bounds for the parent folder.
/// \remark This adjusts the positions of siblings.
IKA_API void ikarus_blueprint_set_position(IkarusBlueprint * blueprint, size_t new_position);
/// \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 new_name The new name of the blueprint.
/// \pre \li Must not be null.
/// \pre \li Must not be empty.
IKA_API void ikarus_blueprint_set_name(IkarusBlueprint * blueprint, char const * new_name);
/// \brief Converts a blueprint to an object.
/// \param blueprint The blueprint to convert.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \return The constructed object, representing the blueprint.
/// \remark Must be freed using #ikarus_free.
IKA_API struct IkarusObject * ikarus_blueprint_to_object(IkarusBlueprint const * blueprint);
/// \brief Compares two blueprints.
/// \param left The left blueprint to compare.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \param right The right blueprint to compare.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \return True if the two blueprints are equal, false otherwise.
/// \remark This neither performs a pointer comparison nor a deep comparison. When we say "equal" we mean that the two
/// blueprints reference the same blueprint in the same project.
IKA_API bool ikarus_blueprint_is_equal(IkarusBlueprint const * left, IkarusBlueprint const * right);
IKARUS_END_HEADER

View file

@ -1,10 +1,9 @@
#pragma once
#include <ikarus/id.h>
#include <ikarus/macros.h>
/// \file entity.h
/// \author Folling <mail@folling.io>
/// \author Folling <folling@ikarus.world>
/// \defgroup entities Entities
/// \brief Entities are the core building blocks of Ikarus.
@ -17,7 +16,7 @@ IKARUS_BEGIN_HEADER
///
/// Properties can be associated with Entities in two ways:
/// - Directly: The property is linked to the entity.
/// - Indirectly: The property is linked to a blueprint of the entity.
/// - Indirectly: The property is linked to a blueprint the entity is linked to.
///
/// For each property an entity is linked to, it has a value. These values depend on the property's type.
/// For more information on the types see the property documentation.
@ -31,10 +30,223 @@ IKARUS_BEGIN_HEADER
/// \remark Values are guaranteed to be in valid format for a given type
/// but not guaranteed to be valid under the settings of the property.
/// This is because changing the settings can invalidate existing values without resetting them.
struct IkarusEntity {
/// \private \brief The ID of the entity.
IkarusId id;
};
struct IkarusEntity;
/// \brief Creates an entity.
/// \param project The project the entity is part of.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \param parent The parent folder of the entity.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \param position The position of the entity in the parent folder. \see #FolderPosition
/// \pre \li Must be within bounds for the parent folder.
/// \param name The name of the entity.
/// \pre \li Must not be null.
/// \pre \li Must not be empty.
/// \param blueprints Blueprints to link the entity to (0..n). Null is treated as an empty array.
/// \param blueprints_count The number of blueprints.
/// \return The created entity or null if an error occurs.
/// \remark Must be freed using #ikarus_free.
IKA_API IkarusEntity * ikarus_entity_create(
struct IkarusProject * project,
struct IkarusEntityFolder * parent,
size_t position,
char const * name,
struct IkarusBlueprint ** blueprints,
size_t blueprints_count
);
/// \brief Copies an entity.
/// \details Creates a deep copy of the entity including all of its properties & associated values.
/// \param entity The entity to copy.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \param parent The parent folder of the entity.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \param position The position of the entity in the parent folder. \see #FolderPosition
/// \pre \li Must be within bounds for the parent folder.
/// \param name The name of the entity.
/// \pre \li Must not be null.
/// \pre \li Must not be empty.
/// \return The created entity or null if an error occurs.
/// \remark Must be freed using #ikarus_free.
IKA_API IkarusEntity * ikarus_entity_copy(
struct IkarusEntity * entity, struct IkarusEntityFolder * parent, size_t position, char const * name
);
/// \brief Deletes an entity.
/// \param entity The entity to delete.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \remark The entity must not be accessed after deletion.
IKA_API void ikarus_entity_delete(IkarusEntity * entity);
IKA_API bool ikarus_entity_is_linked_to_blueprint(IkarusEntity const * entity, struct IkarusBlueprint const * blueprint);
/// \brief Checks if an entity has a specific property.
/// \param entity The entity to check.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \param property The property to check.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \return True if the entity has the property, false otherwise.
IKA_API bool ikarus_entity_has_property(IkarusEntity const * entity, struct IkarusProperty const * property);
/// \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.
/// \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);
/// \brief Unlinks an entity from a blueprint. All values of the properties of the blueprint the entity is linked with 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.
/// \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);
/// \brief Gets the project of an entity.
/// \param entity The entity to get the project of.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \return The project of the entity or null if an error occurs.
IKA_API struct IkarusProject * ikarus_entity_get_project(IkarusEntity const * entity);
/// \brief Gets the parent folder of an entity.
/// \param entity The entity to get the parent folder of.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \return The parent folder of the entity or null if an error occurs.
IKA_API struct IkarusEntityFolder * ikarus_entity_get_parent(IkarusEntity const * entity);
/// \brief Gets the position of an entity within its parent folder.
/// \param entity The entity to get the position of.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \return The position of the entity or undefined if an error occurs.
IKA_API size_t ikarus_entity_get_position(IkarusEntity const * entity);
/// \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.
/// \return The name of the entity or null if an error occurs.
/// \remark The returned pointer is valid until the entity is freed but may be invalidated by other operations.
IKA_API char const * ikarus_entity_get_name(IkarusEntity const * entity);
/// \brief Gets the property root folder of an entity.
/// \param entity The entity to get the root folder of.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \return The root folder of all properties of the entity or null if an error occurs.
/// \remark Must be freed using #ikarus_free.
IKA_API struct IkarusPropertyFolder * ikarus_entity_get_property_root_folder(IkarusEntity const * entity);
/// \brief Gets the number of properties of an entity.
/// \param entity The entity to get the number of properties of.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \return The number of properties or undefined if an error occurs.
IKA_API size_t ikarus_entity_get_property_count(IkarusEntity const * entity);
/// \brief Gets the properties of an entity.
/// \param entity The entity 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.
IKA_API void ikarus_entity_get_properties(
IkarusEntity const * entity, struct IkarusProperty ** properties_out, size_t properties_out_size
);
/// \brief Gets the value of a property of an entity.
/// \details If the entity has never set the value of the property, the default value is returned (which may be indeterminate).
/// \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.
/// \return The value of the property or null if the entity does not have the property or an error occurs.
/// \remark Must be freed using #ikarus_free.
IKA_API struct IkarusEntityValue * get_value(IkarusEntity const * entity, struct IkarusProperty const * property);
/// \brief Sets the parent folder of an entity.
/// \param entity The entity to set the parent folder of.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \param new_parent The new parent folder of the entity.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \param new_position The new position of the entity in the parent folder. \see #FolderPosition
/// \pre \li Must be within bounds for the parent folder.
/// \remark This adjusts the positions of old and new siblings.
IKA_API void ikarus_entity_set_parent(IkarusEntity * entity, struct IkarusEntityFolder * new_parent, size_t new_position);
/// \brief Sets the position of an entity within its parent folder.
/// \param entity The entity to set the position of.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \param new_position The new position of the entity. \see #FolderPosition
/// \pre \li Must be within bounds for the parent folder.
/// \remark This adjusts the positions of siblings.
IKA_API void ikarus_entity_set_position(IkarusEntity * entity, size_t new_position);
/// \brief Sets the name of an entity.
/// \param entity The entity to set the name of.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \param new_name The new name of the entity.
/// \pre \li Must not be null.
/// \pre \li Must not be empty.
IKA_API void ikarus_entity_set_name(IkarusEntity * entity, char const * new_name);
/// \brief Sets the value of a property of an entity.
/// \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 not be null.
/// \pre \li Must be of the same type as the property.
/// \param validate_settings If set, this function fails not only if the type of the value is invalid, but also if it's not
/// valid under the properties settings. \see property.h
/// \remark If the entity does not have the property, this function fails.
IKA_API void ikarus_entity_set_value(
IkarusEntity * entity, struct IkarusProperty const * property, struct IkarusValue * value, bool validate_settings
);
/// \brief Converts an entity to an object.
/// \param entity The entity to convert.
/// \return The constructed object, representing the entity.
/// \remark Must be freed using #ikarus_free.
IKA_API struct IkarusObject * ikarus_entity_to_object(IkarusEntity const * entity);
/// \brief Compares two entities.
/// \param left The left entity to compare.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \param right The right entity to compare.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \return True if the two entities are equal, false otherwise.
/// \remark This neither performs a pointer comparison nor a deep comparison. When we say "equal" we mean that the two
/// entities reference the same entity in the same project.
IKA_API bool ikarus_entity_is_equal(IkarusEntity const * left, IkarusEntity const * right);
IKARUS_END_HEADER

View file

@ -1,16 +1,9 @@
#pragma once
/// \file object.h
/// \author Folling <mail@folling.io>
/// \author Folling <folling@ikarus.world>
#include <ikarus/folders/blueprint_folder.h>
#include <ikarus/folders/entity_folder.h>
#include <ikarus/folders/property_folder.h>
#include <ikarus/macros.h>
#include <ikarus/objects/blueprint.h>
#include <ikarus/objects/entity.h>
#include <ikarus/objects/object_type.h>
#include <ikarus/objects/property.h>
/// \defgroup object Objects
/// \brief Objects are a compound type of all types of objects in the database.
@ -25,96 +18,26 @@
IKARUS_BEGIN_HEADER
struct IkarusFolder;
/// \private \brief The data of an object.
union IkarusObjectData {
/// \private \brief The blueprint data of the object.
IkarusBlueprint blueprint;
/// \private \brief The property data of the object.
IkarusProperty property;
/// \private \brief The entity data of the object.
IkarusEntity entity;
/// \private \brief The blueprint folder data of the object.
IkarusBlueprintFolder blueprint_folder;
/// \private \brief The property folder data of the object.
IkarusPropertyFolder property_folder;
/// \private \brief The entity folder data of the object.
IkarusEntityFolder entity_folder;
};
/// \brief A generic object. Wraps all types of objects, including folders.
struct IkarusObject {
/// \private \brief The type of the object.
IkarusObjectType type;
/// \private \brief The data of the object.
IkarusObjectData data;
};
/// \brief Constructs an object from a blueprint.
/// \param blueprint The blueprint to construct the object from.
/// \return The constructed object, representing the blueprint.
IKA_API IkarusObject ikarus_object_from_blueprint(IkarusBlueprint blueprint);
/// \brief Constructs an object from a property.
/// \param property The property to construct the object from.
/// \return The constructed object, representing the property.
IKA_API IkarusObject ikarus_object_from_property(IkarusProperty property);
/// \brief Constructs an object from an entity.
/// \param entity The entity to construct the object from.
/// \return The constructed object, representing the entity.
IKA_API IkarusObject ikarus_object_from_entity(IkarusEntity entity);
/// \brief Constructs an object from a blueprint folder.
/// \param blueprint The folder to construct the object from.
/// \return The constructed object, representing the folder.
IKA_API IkarusObject ikarus_object_from_blueprint_folder(IkarusBlueprintFolder folder);
/// \brief Constructs an object from a property folder.
/// \param property The folder to construct the object from.
/// \return The constructed object, representing the folder.
IKA_API IkarusObject ikarus_object_from_property_folder(IkarusPropertyFolder folder);
/// \brief Constructs an object from a entity folder.
/// \param entity The folder to construct the object from.
/// \return The constructed object, representing the folder.
IKA_API IkarusObject ikarus_object_from_entity_folder(IkarusEntityFolder folder);
/// \brief Constructs an object from a folder.
/// \param folder The folder to construct the object from.
/// \return The constructed object, representing the folder.
IKA_API IkarusObject ikarus_object_from_folder(IkarusFolder folder);
/// \brief Compares two objects for equality.
/// \details Since ids store the type of the object, this boils down to a simple comparison of the ids.
/// \param left The left side of the comparison.
/// \param right The right side of the comparison.
/// \return Whether the objects are equal.
IKA_API bool ikarus_object_is_equal(IkarusObject left, IkarusObject right);
/// \brief Fetches the type of an object.
/// \param object The object to fetch the type of.
/// \return The type of the object.
IKA_API IkarusObjectType ikarus_object_get_type(IkarusObject object);
struct IkarusObject;
/// \brief Visits an object. Calling the appropriate function for the object's type.
/// \param object The object to visit.
/// \param blueprint The function to call if the object is a blueprint.
/// \param property The function to call if the object is a property.
/// \param entity The function to call if the object is an entity.
/// \param blueprint_folder The function to call if the object is a blueprint folder.
/// \param property_folder The function to call if the object is a property folder.
/// \param entity_folder The function to call if the object is an entity folder.
/// \param data The data to pass to the functions.
/// \param blueprint_visitor The function to call if the object is a blueprint. Skipped if null.
/// \param property_visitor The function to call if the object is a property. Skipped if null.
/// \param entity_visitor The function to call if the object is an entity. Skipped if null.
/// \param blueprint_folder_visitor The function to call if the object is a blueprint folder. Skipped if null.
/// \param property_folder_visitor The function to call if the object is a property folder. Skipped if null.
/// \param entity_folder_visitor The function to call if the object is an entity folder. Skipped if null.
/// \param data The data passed to the visitor functions.
IKA_API void ikarus_object_visit(
IkarusObject object,
void (*visit_blueprint)(IkarusBlueprint, void *),
void (*visit_property)(IkarusProperty, void *),
void (*visit_entity)(IkarusEntity, void *),
void (*visit_blueprint_folder)(IkarusBlueprintFolder, void *),
void (*visit_property_folder)(IkarusPropertyFolder, void *),
void (*visit_entity_folder)(IkarusEntityFolder, void *),
IkarusObject * object,
void (*blueprint_visitor)(struct IkarusBlueprint *, void *),
void (*property_visitor)(struct IkarusProperty *, void *),
void (*entity_visitor)(struct IkarusEntity *, void *),
void (*blueprint_folder_visitor)(struct IkarusBlueprintFolder *, void *),
void (*property_folder_visitor)(struct IkarusPropertyFolder *, void *),
void (*entity_folder_visitor)(struct IkarusEntityFolder *, void *),
void * data
);

View file

@ -1,38 +1,36 @@
#pragma once
/// \file object_type.h
/// \author Folling <folling@ikarus.world>
#include <ikarus/macros.h>
/// \addtogroup objects Objects
/// @{
IKARUS_BEGIN_HEADER
// IMPLEMENTATION_DETAIL_OBJECT_TYPES
/// \file object.h
/// \author Folling <mail@folling.io>
#include <ikarus/folders/folder_type.h>
#include <ikarus/macros.h>
/// \addtogroup object Objects
/// @{
/// \brief The type of an object.
/// \remark Folders have the 4th bit set.
/// \remark The folder types are identical to their counterparts in #IkarusFolderType.
enum IkarusObjectType {
/// \brief Not an object or no object.
IkarusObjectType_None = 0,
/// \brief An IkarusBlueprint.
IkarusObjectType_Blueprint = 1,
IkarusObjectType_Blueprint = 0b00000001,
/// \brief An IkarusProperty.
IkarusObjectType_Property = 2,
IkarusObjectType_Property = 0b00000010,
/// \brief An IkarusEntity.
IkarusObjectType_Entity = 3,
IkarusObjectType_Entity = 0b00000011,
/// \brief An IkarusBlueprintFolder
IkarusObjectType_BlueprintFolder = IkarusFolderType_BlueprintFolder,
IkarusObjectType_BlueprintFolder = 0b01000001,
/// \brief An IkarusPropertyFolder
IkarusObjectType_PropertyFolder = IkarusFolderType_PropertyFolder,
IkarusObjectType_PropertyFolder = 0b01000010,
/// \brief An IkarusEntityFolder
IkarusObjectType_EntityFolder = IkarusFolderType_EntityFolder,
IkarusObjectType_EntityFolder = 0b01000011,
};
/// \brief Constructs an IkarusObjectType from an IkarusFolderType.
/// \param type The IkarusFolderType of which to construct the IkarusObjectType from.
/// \return The constructed IkarusObjectType, representing the folder type.
IKA_API IkarusObjectType ikarus_object_type_from_folder_type(IkarusFolderType type);
IKARUS_END_HEADER
/// @}

View file

@ -1,17 +1,16 @@
#pragma once
// IMPLEMENTATION_DETAIL_LAZY_VALUE_CREATION, IMPLEMENTATION_DETAIL_PROPERTY_TYPES
// IMPLEMENTATION_DETAIL_LAZY_VALUE_CREATION
/// \file property.h
/// \author Folling <mail@folling.io>
/// \author Folling <folling@ikarus.world>
#include <ikarus/id.h>
#include <ikarus/macros.h>
#include <ikarus/objects/blueprint.h>
#include <ikarus/objects/entity.h>
#include <ikarus/objects/property_type.h>
/// \defgroup properties Properties
/// \brief Properties define the structure and types of data.
/// @{
IKARUS_BEGIN_HEADER
@ -50,23 +49,181 @@ IKARUS_BEGIN_HEADER
/// Fetching the value for some property of some entity will return the property's default value if none is specified.
/// This default value is specified when the property is created and can be updated later.
/// \remark Properties' tree structures are scoped to the entity or blueprint they are associated with.
struct IkarusProperty {
/// \private \brief The id of the property.
IkarusId id;
};
struct IkarusProperty;
/// \brief The type of a property.
/// \details Designates the type of data stored by the property as well as which settings are
/// available.
/// \see IkarusPropertySettings
enum IkarusPropertyType {
/// \brief A true/false boolean-like value.
IkarusPropertyType_Toggle,
/// \brief An arbitrary numeric value.
IkarusPropertyType_Number,
/// \brief An arbitrary textual value.
IkarusPropertyType_Text,
};
/// \brief Creates a property
/// \param project The project the property is part of.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \param property_source The property source the property is part of.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \param parent_folder The parent folder of the property.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \param position The position of the property in the parent folder. \see #FolderPosition
/// \pre \li Must be within bounds for the parent folder.
/// \param name The name of the property.
/// \pre \li Must not be null.
/// \pre \li Must not be empty.
/// \param property_info The info of the property.
/// \pre \li Must not be null.
/// \return The created property or null if an error occurs.
/// \remark Must be freed using #ikarus_free.
IKA_API struct IkarusProperty * ikarus_property_create(
struct IkarusProject * project,
struct IkarusPropertySource * property_source,
struct IkarusPropertyFolder * parent_folder,
size_t position,
char const * name,
struct IkarusPropertyTypeInfo * property_info
);
/// \brief Copies a property.
/// \details Creates a deep copy of the property including all of its settings and associated values.
/// \param property The property to copy.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \param source The source to copy the property to.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \param parent_folder The parent folder of the property.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \param position The position of the property in the parent folder. \see #FolderPosition
/// \pre \li Must be within bounds for the parent folder.
/// \param name The name of the property.
/// \pre \li Must not be null.
/// \pre \li Must not be empty.
/// \return The created property or null if an error occurs.
/// \remark Must be freed using #ikarus_free.
IKA_API struct IkarusProperty * ikarus_property_copy(
struct IkarusProperty * property,
struct IkarusPropertySource * source,
struct IkarusPropertyFolder * parent_folder,
size_t position,
char const * name
);
/// \brief Deletes a property.
/// \param property The property to delete.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \remark The property must not be accessed after deletion.
IKA_API void ikarus_property_delete(struct IkarusProperty * property);
/// \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.
/// \return The project of the property or null if an error occurs.
IKA_API struct IkarusProject * ikarus_property_get_project(IkarusProperty const * property);
/// \brief Gets the parent folder of a property.
/// \param property The property to get the parent folder of.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \return The parent folder of the property or null if an error occurs.
IKA_API struct IkarusPropertyFolder * ikarus_property_get_parent(IkarusProperty const * property);
/// \brief Gets the position of a property within its parent folder.
/// \param property The property to get the position of.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \return The position of the property or undefined if an error occurs.
IKA_API size_t ikarus_property_get_position(IkarusProperty const * property);
/// \brief Gets the name of a property.
/// \param property The property to get the name of.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \return The name of the property or null if an error occurs.
/// \remark The returned pointer is valid until the property is freed but may be invalidated by other operations.
IKA_API char const * ikarus_property_get_name(IkarusProperty const * property);
/// \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.
/// \return The type info of the property or null if an error occurs.
/// \remark Must be freed using #ikarus_free.
IKA_API struct IkarusPropertyTypeInfo * ikarus_property_get_type_info(IkarusProperty const * property);
/// \brief Gets the source of a property.
/// \param property The property to get the source of.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \return The source of the property or null if an error occurs.
/// \remark Must be freed using #ikarus_free.
IKA_API struct IkarusPropertySource * ikarus_property_get_source(IkarusProperty const * property);
/// \brief Gets the default value of a property.
/// \param property The property to get the default value of.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \return The default value of the property or null if an error occurs.
/// \remark Must be freed using #ikarus_free.
IKA_API struct IkarusValue * ikarus_property_get_default_value(IkarusProperty const * property);
/// \brief Sets the parent folder of a property.
/// \param property The property to set the parent folder of.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \param new_parent The new parent folder of the property.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \param new_position The new position of the property in the parent folder. \see #FolderPosition
/// \pre \li Must be within bounds for the parent folder.
/// \remark This adjusts the positions of old and new siblings.
IKA_API void ikarus_property_set_parent(
IkarusProperty * property, struct IkarusPropertyFolder * new_parent, size_t new_position
);
/// \brief Sets the position of a property within its parent folder.
/// \param property The property to set the position of.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \param new_position The new position of the property. \see #FolderPosition
/// \pre \li Must be within bounds for the parent folder.
/// \remark This adjusts the positions of siblings.
IKA_API void ikarus_property_set_position(IkarusProperty * property, size_t new_position);
/// \brief Sets 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 new_name The new name of the property.
/// \pre \li Must not be null.
/// \pre \li Must not be empty.
IKA_API void ikarus_property_set_name(IkarusProperty * property, char const * new_name);
/// \brief Sets the type info of a property and resets all values to the new default value.
/// \param property The property to set the type info of.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \param new_type The new type info of the property.
/// \param attempt_conversion Whether to attempt to convert the property's values to the new type info. Conversion rules are
/// unspecified for now, but follow common sense.
IKA_API void ikarus_property_set_type_info(
IkarusProperty * property, struct IkarusPropertyTypeInfo new_type_info, bool attempt_conversion
);
/// \brief Converts a property to an object.
/// \param property The property to convert.
/// \return The constructed object, representing the property.
IKA_API struct IkarusObject * ikarus_property_to_object(IkarusProperty const * property);
/// \brief Compares two properties.
/// \param left The left property to compare.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \param right The right property to compare.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \return True if the two properties are equal, false otherwise.
/// \remark This neither performs a pointer comparison nor a deep comparison. When we say "equal" we mean that the two
/// properties reference the same property in the same project.
IKA_API bool ikarus_property_is_equal(IkarusProperty const * left, IkarusProperty const * right);
IKARUS_END_HEADER

View file

@ -0,0 +1,47 @@
#pragma once
/// \file property_source.h
/// \author Folling <folling@ikarus.world>
#include <ikarus/macros.h>
/// \addtogroup properties Properties
/// @{
IKARUS_BEGIN_HEADER
struct PropertySource;
/// \brief Creates an blueprint property source.
/// \param blueprint The blueprint to create the property source for.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \return The created property source or null if an error occurs.
/// \remark Must be freed using #ikarus_free.
IKA_API struct PropertySource * ikarus_property_source_create_blueprint(struct IkarusBlueprint * blueprint);
/// \brief Creates an entity property source.
/// \param entity The entity to create the property source for.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \return The created property source or null if an error occurs.
/// \remark Must be freed using #ikarus_free.
IKA_API struct PropertySource * ikarus_property_source_create_entity(struct IkarusEntity * entity);
/// \brief Visits a property source, calling the appropriate callback.
/// \param property_source The property source to visit.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \param blueprint_visitor The callback to call if the source is a blueprint, skipped if null.
/// \param entity_visitor The callback to call if the source is an entity, skipped if null.
/// \param user_data User data to pass to the callbacks.
IKA_API void ikarus_property_source_visit(
struct PropertySource * property_source,
void (*blueprint_visitor)(struct IkarusBlueprint *, void *),
void (*entity_visitor)(struct IkarusEntity *, void *),
void * user_data
);
IKARUS_END_HEADER
/// @}

View file

@ -3,29 +3,33 @@
// IMPLEMENTATION_DETAIL_PROPERTY_TYPES
/// \file property_type.h
/// \author Folling <mail@folling.io>
/// \author Folling <folling@ikarus.world>
#include <ikarus/macros.h>
IKARUS_BEGIN_HEADER
/// \defgroup property_types Property Types
/// \brief Property Types delineate the type of data stored by a property.
/// \addtogroup properties Properties
/// @{
IKARUS_BEGIN_HEADER
/// \brief The type of a property.
/// \details Designates the type of data stored by the property as well as which settings are
/// available.
/// \see IkarusPropertySettings
enum IkarusPropertyType {
/// \brief A true/false boolean-like value.
/// \brief A true/false boolean-esque value.
IkarusPropertyType_Toggle,
/// \brief An arbitrary numeric value.
/// \brief A numeric value, limited to IEEE 80 bit floating point numbers.
IkarusPropertyType_Number,
/// \brief An arbitrary textual value.
/// \brief An arbitrary UTF-8 textual value.
IkarusPropertyType_Text,
};
/// @}
/// \brief Fetches the default value for a property type.
/// \remark Not to be confused with the default value of a property. See ikarus_property_get_default_value
/// \param type The property type.
/// \return The default value for the property type or null if an error occurs.
IKA_API struct IkarusValue * ikarus_property_type_get_default_default_value(IkarusPropertyType type);
IKARUS_END_HEADER
/// @}

View file

@ -0,0 +1,79 @@
#pragma once
/// \file property_info.h
/// \author Folling <folling@ikarus.world>
#include <ikarus/macros.h>
/// \addtogroup properties Properties
/// @{
IKARUS_BEGIN_HEADER
/// \brief Information about a property.
/// \details Property information includes their type and settings consolidated to ascertain type safety.
struct IkarusPropertyTypeInfo;
/// \brief Information about a toggle property.
struct IkarusTogglePropertyInfo;
/// \brief Information about a number property.
struct IkarusNumberPropertyInfo;
/// \brief Information about a text property.
struct IkarusTextPropertyInfo;
/// \brief Creates a new toggle property info.
/// \return The created toggle property info.
/// \remark Must be freed with #ikarus_free.
IKA_API IkarusTogglePropertyInfo * ikarus_toggle_property_info_create();
/// \brief Sets the default value of a toggle property info.
/// \param toggle_property_info The toggle property info to set the default value of.
/// \pre \li Must not be null.
/// \param default_value The default value to set.
/// \pre \li Must not be null.
IKA_API void ikarus_toggle_property_info_set_default_value(
IkarusTogglePropertyInfo * toggle_property_info, struct IkarusToggleValue * default_value
);
/// \brief Converts a toggle property info to a generic property info.
/// \param toggle_property_info The toggle property info to convert.
/// \return The converted property info.
IKA_API IkarusPropertyTypeInfo * ikarus_toggle_property_info_to_property_info(IkarusTogglePropertyInfo * toggle_property_info);
/// \brief Creates a new number property info.
/// \return The created number property info.
/// \remark Must be freed with #ikarus_free.
IKA_API IkarusNumberPropertyInfo * ikarus_number_property_info_create();
/// \brief Sets the default value of a number property info.
/// \param number_property_info The number property info to set the default value of.
/// \pre \li Must not be null.
/// \param default_value The default value to set.
/// \pre \li Must not be null.
IKA_API void ikarus_number_property_info_set_default_value(
IkarusNumberPropertyInfo * number_property_info, struct IkarusNumberValue * default_value
);
/// \brief Converts a number property info to a generic property info.
/// \param number_property_info The number property info to convert.
/// \return The converted property info.
IKA_API IkarusPropertyTypeInfo * ikarus_number_property_info_to_property_info(IkarusNumberPropertyInfo * number_property_info);
/// \brief Creates a new text property info.
/// \return The created text property info.
/// \remark Must be freed with #ikarus_free.
IKA_API IkarusTextPropertyInfo * ikarus_text_property_info_create();
/// \brief Sets the default value of a text property info.
/// \param text_property_info The text property info to set the default value of.
/// \pre \li Must not be null.
/// \param default_value The default value to set.
/// \pre \li Must not be null.
IKA_API void ikarus_text_property_info_set_default_value(
IkarusTextPropertyInfo * text_property_info, struct IkarusTextValue * default_value
);
/// \brief Converts a text property info to a generic property info.
/// \param text_property_info The text property info to convert.
/// \return The converted property info.
IKA_API IkarusPropertyTypeInfo * ikarus_text_property_info_to_property_info(IkarusTextPropertyInfo * text_property_info);
IKARUS_END_HEADER
/// @}

View file

@ -0,0 +1,179 @@
#pragma once
/// \file project.h
/// \author Folling <folling@ikarus.world>
#include <ikarus/macros.h>
#include <ikarus/stdtypes.h>
/// \defgroup projects Projects
/// \brief Projects are the persistence mechanism of Ikarus. Each project contains a set of objects.
/// \details Projects are stored on the filesystem. Each project has a name.
/// @{
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
/// behavior.
struct IkarusProject;
/// \brief Creates a persisted project on the filesystem.
/// \param path The path to the project.
/// \pre \li Must not be null.
/// \pre \li Must point to a valid unused path on the system.
/// \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.
/// \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);
/// \brief Creates a project in memory.
/// \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.
/// \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);
/// \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.
/// \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);
/// \brief Copies a project to a new location.
/// \details The new project is not opened.
/// \param project The project to copy.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \param target_path The new location of the project.
/// \pre \li Must not be null.
/// \pre \li Must point to a valid unused path on the system.
/// \param target_name The name of the new project.
/// \pre \li Must not be null.
/// \pre \li Must not be empty.
/// \remark If successful the project connection remains intact. The previous location will still exist.
IKA_API void ikarus_project_copy(IkarusProject const * project, char const * target_path, char const * target_name);
/// \brief Deletes a project and all its associated data from the filesystem.
/// \param project The project to delete.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \remark also frees the project.
/// \remark In-Memory projects will just be freed.
/// \remark If deletion fails, the project pointer remains intact.
IKA_API void ikarus_project_delete(IkarusProject * project);
/// \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.
/// \return The name of the project.
/// \remark Must be freed using #ikarus_free.
IKA_API char const * ikarus_project_get_name(IkarusProject const * project);
/// \brief Sets the name of a project.
/// \param project The project to set the name of.
/// \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.
IKA_API void ikarus_project_set_name(IkarusProject * project, char const * new_name);
/// \brief Gets the path of a project.
/// \param project The project to get the path of.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \return The path of the project.
/// \remark Must be freed using #ikarus_free.
IKA_API char const * ikarus_project_get_path(IkarusProject const * project);
/// \brief Moves a project to a new location.
/// \param project The project to move.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \param target_path The new location of the project.
/// \pre \li Must not be null.
/// \pre \li Must point to a valid unused path on the system.
/// \remark If successful the project connection remains intact. The previous location will not exist anymore.
/// \remark Due to the nature of filesystems this function may not be atomic.
IKA_API void ikarus_project_move(IkarusProject * project, char const * target_path);
/// \brief Gets the error code of a project.
/// \param project The project to get the error code of.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \return The error code of the project.
IKA_API int ikarus_project_get_error_code(IkarusProject const * project);
/// \brief Gets the error message of a project.
/// \param project The project to get the error message of.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \return The error message of the project.
/// \remark The returned pointer is valid until the project is freed but may be altered by other operations.
/// \warning Must not be freed.
IKA_API char const * ikarus_project_get_error_message(IkarusProject const * project);
/// \brief Gets the blueprint root folder of a project.
/// \param project The project to get the blueprint root folder of.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \return The blueprint root folder of the project or null if an error occurs.
/// \remark Must be freed using #ikarus_free.
IKA_API struct IkarusBlueprintFolder * ikarus_project_get_blueprint_root_folder(IkarusProject const * project);
/// \brief Gets the number of blueprints of a project.
/// \param project The project to get the number of blueprints of.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \return The number of blueprints or undefined if an error occurs.
IKA_API size_t ikarus_project_get_blueprint_count(IkarusProject const * project);
/// \brief Gets the blueprints of a project.
/// \param project The project 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.
IKA_API void ikarus_project_get_blueprints(
IkarusProject const * project, struct IkarusBlueprint ** blueprints_out, size_t blueprints_out_size
);
/// \brief Gets the entity root folder of a project.
/// \param project The project to get the entity root folder of.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \return The entity root folder of the project or null if an error occurs.
/// \remark Must be freed using #ikarus_free.
IKA_API struct IkarusEntityFolder * ikarus_project_get_entity_root_folder(IkarusProject const * project);
/// \brief Gets the number of entities of a project.
/// \param project The project to get the number of entities of.
/// \pre \li Must not be null.
/// \pre \li Must exist.
/// \return The number of entities or undefined if an error occurs.
IKA_API size_t ikarus_project_get_entity_count(IkarusProject const * project);
/// \brief Gets the entities of a project.
/// \param project The project 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.
IKA_API void ikarus_project_get_entities(
IkarusProject const * project, struct IkarusEntity ** entities_out, size_t entities_out_size
);
IKARUS_END_HEADER
/// @}

View file

@ -1,7 +1,7 @@
#pragma once
/// \file blueprint_scope.h
/// \author Folling <mail@folling.io>
/// \author Folling <folling@ikarus.world>
#include <ikarus/id.h>
#include <ikarus/macros.h>
@ -12,14 +12,18 @@
IKARUS_BEGIN_HEADER
/// \brief The global scope of all blueprints.
struct IkarusBlueprintScope {
/// \private \brief Empty structs aren't allowed in C, so we need a dummy field.
short _dummy;
};
struct IkarusBlueprintScope;
/// \brief Creates a blueprint scope.
/// \return The created blueprint scope.
IKA_API IkarusBlueprintScope ikarus_blueprint_scope_create();
/// \remark Must be freed with #ikarus_free.
IKA_API IkarusBlueprintScope * ikarus_blueprint_scope_create();
/// \brief Converts a blueprint scope to an object scope.
/// \param scope The scope to convert.
/// \return The converted scope.
/// \remark Must be freed with #ikarus_free.
IKA_API struct IkarusObjectScope * ikarus_blueprint_scope_to_object_scope(IkarusBlueprintScope const * scope);
IKARUS_END_HEADER

View file

@ -1,9 +1,8 @@
#pragma once
/// \file entity_scope.h
/// \author Folling <mail@folling.io>
/// \author Folling <folling@ikarus.world>
#include <ikarus/id.h>
#include <ikarus/macros.h>
/// \addtogroup object_scopes ObjectScopes
@ -12,14 +11,18 @@
IKARUS_BEGIN_HEADER
/// \brief The global scope of all entities.
struct IkarusEntityScope {
/// \private \brief Empty structs aren't allowed in C, so we need a dummy field.
short _dummy;
};
struct IkarusEntityScope;
/// \brief Creates a entity scope.
/// \brief Creates an entity scope.
/// \return The created entity scope.
IKA_API IkarusEntityScope ikarus_entity_scope_create();
/// \remark Must be freed with #ikarus_free.
IKA_API IkarusEntityScope * ikarus_entity_scope_create();
/// Converts an entity scope to an object scope.
/// \param scope The scope to convert.
/// \return The converted scope.
/// \remark Must be freed with #ikarus_free.
IKA_API struct IkarusObjectScope * ikarus_entity_scope_to_object_scope(IkarusEntityScope const * scope);
IKARUS_END_HEADER

View file

@ -3,12 +3,9 @@
// IMPLEMENTATION_DETAIL_OBJECT_SCOPES
/// \file object_scope.h
/// \author Folling <mail@folling.io>
/// \author Folling <folling@ikarus.world>
#include <ikarus/macros.h>
#include <ikarus/scopes/blueprint_scope.h>
#include <ikarus/scopes/entity_scope.h>
#include <ikarus/scopes/property_scope.h>
/// \defgroup object_scopes Object Scopes
/// \brief Scopes define where objects belong to.
@ -17,65 +14,30 @@
IKARUS_BEGIN_HEADER
/// \private \brief The data for an object scope.
union IkarusObjectScopeData {
/// \private \brief The blueprint data of the scope.
IkarusBlueprintScope _blueprint;
/// \private \brief The property data of the scope.
IkarusPropertyScope _property;
/// \private \brief The entity data of the scope.
IkarusEntityScope _entity;
};
/// \brief The scope of an object.
struct IkarusObjectScope;
/// The type of an object scope.
/// \brief The type of an object scope.
enum IkarusObjectScopeType {
/// \brief The scope is a blueprint scope.
IkarusObjectScopeType_Blueprint,
IkarusObjectScopeType_Blueprint = 1,
/// \brief The scope is a property scope.
IkarusObjectScopeType_Property,
IkarusObjectScopeType_Property = 2,
/// \brief The scope is an entity scope.
IkarusObjectScopeType_Entity
IkarusObjectScopeType_Entity = 3
};
/// \brief The scope of an object.
struct IkarusObjectScope {
/// \private \brief Represents the type of the scope.
IkarusObjectScopeType _type;
/// \private \brief Represents the data of the scope.
IkarusObjectScopeData _data;
};
/// \brief Converts a blueprint scope to an object scope.
/// \param scope The scope to convert.
/// \return The converted scope.
IKA_API IkarusObjectScope ikarus_blueprint_scope_to_object_scope(IkarusBlueprintScope scope);
/// \brief Converts a property scope to an object scope.
/// \param scope The scope to convert.
/// \return The converted scope.
IKA_API IkarusObjectScope ikarus_property_scope_to_object_scope(IkarusPropertyScope scope);
/// Converts an entity scope to an object scope.
/// \param scope The scope to convert.
/// \return The converted scope.
IKA_API IkarusObjectScope ikarus_entity_scope_to_object_scope(IkarusEntityScope scope);
/// \brief Fetches the type of an object scope.
/// \param scope The scope to fetch the type of.
/// \return The type of the scope.
IKA_API IkarusObjectScopeType ikarus_object_scope_get_type(IkarusObjectScope scope);
/// \brief Visits an object scope, calling the appropriate function.
/// \param scope The scope to visit.
/// \param blueprint The function to call if the scope is an #IkarusBlueprintScope.
/// \param property The function to call if the scope is an #IkarusPropertyScope.
/// \param entity The function to call if the scope is an #IkarusEntityScope.
/// \param blueprint_visitor The function to call if the scope is an #IkarusBlueprintScope.
/// \param property_visitor The function to call if the scope is an #IkarusPropertyScope.
/// \param entity_visitor The function to call if the scope is an #IkarusEntityScope.
/// \remark function pointers may be null in which case they are not called.
IKA_API void ikarus_object_scope_visit(
IkarusObjectScope scope,
void (*blueprint)(IkarusBlueprintScope, void *),
void (*property)(IkarusPropertyScope, void *),
void (*entity)(IkarusEntityScope, void *),
IkarusObjectScope * scope,
void (*blueprint_visitor)(struct IkarusBlueprintScope *, void *),
void (*property_visitor)(struct IkarusPropertyScope *, void *),
void (*entity_visitor)(struct IkarusEntityScope *, void *),
void * data
);

View file

@ -1,63 +1,46 @@
#pragma once
/// \file property_scope.h
/// \author Folling <mail@folling.io>
/// \author Folling <folling@ikarus.world>
#include <ikarus/id.h>
#include <ikarus/macros.h>
#include <ikarus/objects/blueprint.h>
#include <ikarus/objects/entity.h>
/// \addtogroup object_scopes ObjectScopes
/// @{
IKARUS_BEGIN_HEADER
/// \brief Data for a property scope. This can either be a blueprint or an entity.
union IkarusPropertyScopeData {
/// \private \brief The blueprint the property is scoped to.
IkarusBlueprint _blueprint;
/// \private \brief The entity the property is scoped to.
IkarusEntity _entity;
};
/// \brief The type of a property scope. This can either be a blueprint or an entity.
enum IkarusPropertyScopeType {
/// \brief The property is scoped to a blueprint.
IkarusPropertyScopeType_Blueprint,
/// \brief The property is scoped to an entity.
IkarusPropertyScopeType_Entity
};
/// \brief The scope of a property
struct IkarusPropertyScope {
/// \private \brief Represents the type of the scope.
IkarusPropertyScopeType _type;
/// \private \brief Represents the data of the scope.
IkarusPropertyScopeData _data;
};
struct IkarusPropertyScope;
/// \brief Creates a property scope from a blueprint.
/// \param blueprint The blueprint the property is scoped to.
/// \return The created property scope.
IKA_API IkarusPropertyScope ikarus_property_scope_create_blueprint(IkarusBlueprint blueprint);
/// \brief Creates a property scope from a entity.
/// \remark Must be freed with #ikarus_free.
IKA_API IkarusPropertyScope * ikarus_property_scope_create_blueprint(struct IkarusBlueprint * blueprint);
/// \brief Creates a property scope from an entity.
/// \param entity The entity the property is scoped to.
/// \return The created property scope.
IKA_API IkarusPropertyScope ikarus_property_scope_create_entity(IkarusEntity entity);
/// \remark Must be freed with #ikarus_free.
IKA_API IkarusPropertyScope * ikarus_property_scope_create_entity(struct IkarusEntity * entity);
/// \brief Fetches the type of an property scope.
/// \param scope The scope to fetch the type of.
/// \return The type of the scope.
IKA_API IkarusPropertyScopeType ikarus_property_scope_get_type(IkarusPropertyScope scope);
/// \brief Converts a property scope to an object scope.
/// \param scope The scope to convert.
/// \return The converted scope.
/// \remark Must be freed with #ikarus_free.
IKA_API struct IkarusObjectScope * ikarus_property_scope_to_object_scope(IkarusPropertyScope const * scope);
/// \brief Visits a property scope, calling the appropriate function.
/// \param scope The scope to to visit
/// \param blueprint The function to call if the property is scoped to a blueprint.
/// \param entity The function to call if the property is scoped to an entity.
/// \param data Optional data to pass to the functions.
void ikarus_property_scope_visit(
IkarusPropertyScope scope, void (*blueprint)(IkarusBlueprint, void *), void (*entity)(IkarusEntity, void *), void * data
/// \param blueprint_visitor The function to call if the property is scoped to a blueprint.
/// \param entity_visitor The function to call if the property is scoped to an entity.
/// \param data The data passed to the visitor functions.
IKA_API void ikarus_property_scope_visit(
IkarusPropertyScope * scope,
void (*blueprint_visitor)(struct IkarusBlueprint *, void *),
void (*entity_visitor)(struct IkarusEntity *, void *),
void * data
);
IKARUS_END_HEADER

View file

@ -3,6 +3,7 @@
#ifdef __cplusplus
#include <cstddef>
#include <cstdint>
// NOLINTNEXTLINE(google-global-names-in-headers)
using std::size_t;
#else
#include <stdint.h>

View file

@ -3,10 +3,10 @@
// IMPLEMENTATION_DETAIL_PROPERTY_TYPES
/// \file value.h
/// \author Folling <mail@folling.io>
/// \author Folling <folling@ikarus.world>
#include <ikarus/macros.h>
#include <ikarus/objects/property.h>
#include <ikarus/objects/property_type.h>
#include <ikarus/stdtypes.h>
IKARUS_BEGIN_HEADER
@ -15,149 +15,115 @@ IKARUS_BEGIN_HEADER
/// \brief The values stored in entities.
/// \details Each entity has a value for each property it is associated with.
/// The value is of the type specified by the property and constrained by the property's settings.
/// A value may be indeterminate which means it is unknown or not specified.
/// \see PropertyType PropertySettings
/// @{
/// \brief A true/false boolean-like value. For example "IsDead".
struct IkarusToggleValue {
/// \private \brief The value of the property.
bool _value;
};
struct IkarusToggleValue;
/// \brief An arbitrary numeric value. For example "Age".
struct IkarusNumberValue {
/// \private \brief The value of the property.
long double _value;
};
struct IkarusNumberValue;
/// \brief An arbitrary textual value. For example "First Name".
struct IkarusTextValue {
/// \private \brief The value of the property.
char const * _value;
};
/// \private \brief The data for a value.
union IkarusEntityValueData {
/// \private \brief The value as a toggle.
IkarusToggleValue toggle;
/// \private \brief The value as a number.
IkarusNumberValue number;
/// \private \brief The value as text.
IkarusTextValue text;
};
/// \brief The state of an entity value.
/// \details States provide insight into the nature of a value.
enum IkarusEntityValueState {
/// \brief The value is invalid.
IkarusEntityValueState_Invalid,
/// \brief The value is normal and can be used as-is.
IkarusEntityValueState_Normal,
/// \brief The value is unknown.
IkarusEntityValueState_Indeterminate,
};
struct IkarusTextValue;
/// \brief The value of an entity associated with a property.
struct IkarusEntityValue {
/// \private \brief The type of the value.
IkarusPropertyType _type;
/// \private \brief The data for the value.p
IkarusEntityValueData _data;
/// \private \brief The state of the value.
IkarusEntityValueState _state;
};
struct IkarusEntityValue;
/// \brief Creates an entity value from a toggle value.
/// \brief Creates a toggle value from a boolean.
/// \param value The toggle value.
/// \return The entity value.
IKA_API IkarusEntityValue ikarus_value_create_toggle(bool value);
/// \brief Creates an entity value from a number value.
/// \remark Must be freed with #ikarus_free.
IKA_API IkarusToggleValue * ikarus_toggle_value_create(bool value);
/// \brief Creates an indeterminate toggle value.
/// \return The entity value.
/// \remark Must be freed with #ikarus_free.
IKA_API IkarusToggleValue * ikarus_toggle_value_create_indeterminate();
/// \brief Sets the value of a toggle value.
/// \param value The toggle value.
/// \pre Must not be null.
/// \param new_value The new value.
IKA_API void ikarus_toggle_value_set(IkarusToggleValue * value, bool new_value);
/// \brief Creates a number value from a number.
/// \param value The number value.
/// \pre Must be finite & not NaN.
/// \return The entity value.
/// \remark If the value is NaN or infinity an InvalidEntityValue is returned.
IKA_API IkarusEntityValue ikarus_value_create_number(long double value);
/// \brief Creates an entity value from a text value.
/// \remark Must be freed with #ikarus_free.
IKA_API IkarusNumberValue * ikarus_number_value_create(long double value);
/// \brief Creates an indeterminate number value.
/// \return The entity value.
/// \remark Must be freed with #ikarus_free.
IKA_API IkarusNumberValue * ikarus_number_value_create_indeterminate();
/// \brief Sets the value of a number value.
/// \param value The number value.
/// \pre Must not be null.
/// \param new_value The new value.
IKA_API void ikarus_number_value_set(IkarusNumberValue * value, bool new_value);
/// \brief Creates a text value from string.
/// \param value The text value.
/// \pre Must not be null.
/// \return The entity value.
/// \remark If the value is null an InvalidEntityValue is returned.
IKA_API IkarusEntityValue ikarus_value_create_text(char const * value);
/// \brief Creates an indeterminate entity value of a given type.
/// \param type The type of the value.
/// \remark Must be freed with #ikarus_free.
IKA_API IkarusTextValue * ikarus_text_value_create(char const * value);
/// \brief Creates an indeterminate text value.
/// \return The entity value.
IKA_API IkarusEntityValue ikarus_value_create_indeterminate(IkarusPropertyType type);
/// \remark Must be freed with #ikarus_free.
IKA_API IkarusTextValue * ikarus_text_value_create_indeterminate();
/// \brief Sets the value of a text value.
/// \param value The text value.
/// \pre Must not be null.
/// \param new_value The new value.
IKA_API void ikarus_text_value_set(IkarusTextValue * value, bool new_value);
/// \brief Fetches the default value for a property type.
/// \remark Not to be confused with the default value of a property. See ikarus_property_get_default_value
/// \param type The property type.
/// \return The default value for the property type.
IKA_API IkarusEntityValue ikarus_value_get_default(IkarusPropertyType type);
/// \brief Checks if a toggle value is indeterminate.
/// \param value The toggle value.
/// \pre Must not be null.
/// \return True if the value is indeterminate, false otherwise.
IKA_API bool ikarus_toggle_value_is_indeterminate(IkarusToggleValue const * value);
/// \brief Checks if a number value is indeterminate.
/// \param value The number value.
/// \pre Must not be null.
/// \return True if the value is indeterminate, false otherwise.
IKA_API bool ikarus_number_value_is_indeterminate(IkarusNumberValue const * value);
/// \brief Checks if a text value is indeterminate.
/// \param value The text value.
/// \pre Must not be null.
/// \return True if the value is indeterminate, false otherwise.
IKA_API bool ikarus_text_value_is_indeterminate(IkarusTextValue const * value);
/// \brief Fetches the underlying value of a toggle value.
/// \param value The toggle value.
/// \return The underlying value.
/// \warning If the value is indeterminate, false is returned.
IKA_API bool ikarus_toggle_value_get_underlying(IkarusToggleValue const * value);
/// \brief Fetches the underlying value of a number value.
/// \param value The number value.
/// \return The underlying value.
/// \warning If the value is indeterminate, 0.0 is returned.
IKA_API long double ikarus_number_value_get_underlying(IkarusNumberValue const * value);
/// \brief Fetches the underlying value of a text value.
/// \param value The text value.
/// \return The underlying value.
/// \return A copy of the underlying value.
/// \remark The returned value is a copy and owned by the caller.
/// \warning If the value is indeterminate, an empty string is returned.
IKA_API char const * ikarus_text_value_get_underlying(IkarusTextValue const * value);
/// \brief Checks if a toggle value is equal to a boolean.
/// \param value The toggle value.
/// \param check The boolean value.
/// \return False if value is null. True if it is equal to check, false otherwise.
IKA_API bool ikarus_toggle_value_is_equal(IkarusToggleValue const * value, bool check);
/// \brief Checks if a number value is equal to a number.
/// \param value The number value.
/// \param check The number value.
/// \return False if value is null. True if it is equal to check, false otherwise.
IKA_API bool ikarus_number_value_is_equal(IkarusNumberValue const * value, long double check);
/// \brief Checks if a text value is equal to a string.
/// \param value The text value.
/// \param check The string value.
/// \return False if value or check are null. True if it is equal to check, false otherwise.
IKA_API bool ikarus_text_value_is_equal(IkarusTextValue const * value, char const * check);
/// \brief Checks if two entity values are equal.
/// \details Two entity values are equal if they are of the same type and their value is considered equal.
/// Note that floating point values can only be checked for approximate equality.
/// \param left The left-hand entity value.
/// \param right The right-hand entity value.
/// \return True if the values are considered equal, false otherwise.
/// \remark Null values compare false to all other values. As do invalid values. Indeterminate values however, compare true to
/// other indeterminate values of the same type.
IKA_API bool ikarus_value_is_equal(IkarusEntityValue const * left, IkarusEntityValue const * right);
/// \brief Checks if an entity value is invalid.
/// \param value The entity value.
/// \return True if the value is invalid or null, false otherwise.
IKA_API bool ikarus_value_is_invalid(IkarusEntityValue const * value);
/// \brief Fetches the type of an entity value.
/// \param value The entity value.
/// \return The type of the entity value.
IKA_API IkarusPropertyType ikarus_value_get_type(IkarusEntityValue const * value);
/// \brief Visits an entity value, calling the appropriate function for the value's type.
/// \param value The entity value to visit.
/// \param toggle The function to call if the value is a toggle value.
/// \param number The function to call if the value is a number value.
/// \param text The function to call if the value is a text value.
/// \param data The data to pass to the functions.
/// \remark function pointers may be null in which case they are not called.
/// \param toggle The function to call if the value is a toggle value. Skipped if null.
/// \param number The function to call if the value is a number value. Skipped if null.
/// \param text The function to call if the value is a text value. Skipped if null.
/// \param data The data passed to the visitor functions.
IKA_API void ikarus_value_visit(
IkarusEntityValue const * value,
void (*toggle)(IkarusToggleValue const *, void *),
void (*number)(IkarusNumberValue const *, void *),
void (*text)(IkarusTextValue const *, void *),
IkarusEntityValue * value,
void (*toggle)(IkarusToggleValue *, void *),
void (*number)(IkarusNumberValue *, void *),
void (*text)(IkarusTextValue *, void *),
void * data
);