change error system & function signatures

Signed-off-by: Folling <mail@folling.io>
This commit is contained in:
Folling 2024-01-02 15:14:39 +01:00 committed by Folling
parent 41f00bc871
commit 70f1fe7de0
Signed by: folling
SSH key fingerprint: SHA256:S9qEx5WCFFLK49tE/LKnKuJYM5sw+++Dn6qJbbyxnCY
28 changed files with 633 additions and 651 deletions

View file

@ -7,57 +7,111 @@
/// \addtogroup errors Errors
/// \brief Error handling within libikarus
/// \details Errors are stored for each project, akin to the errno handling in C.
/// We store multiple pieces of information about the error occurring. For more information see
/// #ikarus_project_get_error_message.
/// \details Functions in Ikarus may fail, in which case they have an out parameter for the error.
/// Upon erring the function will store relevant information about the error in the out parameter.
/// If the out parameter is null nothing will be stored. This is not recommended as it essentially ignores errors.
/// For the sake of simplicity we have avoided mechanisms that "force" clients to handle errors.
/// Note that Ikarus does not check for null pointers. Passing null pointers to functions that do not explicitly state that they accept null
/// pointers is undefined behaviour. This decision is done for the sake of brevity and readability. `project_get_name(project)` is also
/// synonymous to `project->get_name()` in OOP languages, which shares the same semantics.
/// @{
IKARUS_BEGIN_HEADER
/// \brief Delineates what caused an error.
/// \details First 2 bytes delineate the major type, next 2 bytes delineate the minor type, next 4 bytes delineate the
/// detail type.
/// \remark Note that this doesn't show responsibility. An error with source "SubSystem" could still be the
/// fault of libikarus.
/// fault of libikarus, it just indicates where the error occurred.
enum IkarusErrorInfo {
/// \brief No error occurred.
IkarusErrorInfo_Source_None = 0x0001000000000000,
IkarusErrorInfo_None = 0x0,
/// \brief The error was caused by the client.
IkarusErrorInfo_Source_Client = 0x0001000000000001,
/// \brief The error was caused by a sub-system of libikarus.
IkarusErrorInfo_Source_SubSystem = 0x0001000000000002,
IkarusErrorInfo_Client = 0x10100000,
/// \brief The error was caused by a dependency (e.g. boost) of libikarus.
IkarusErrorInfo_Dependency = 0x10200000,
/// \brief The error was caused by the filesystem.
IkarusErrorInfo_Filesystem = 0x10300000,
/// \brief The error was caused by the database.
IkarusErrorInfo_Database = 0x10400000,
/// \brief The error was caused by the underlying OS.
IkarusErrorInfo_OS = 0x10500000,
/// \brief The error was caused by libikarus itself.
IkarusErrorInfo_Source_LibIkarus = 0x0001000000000003,
/// \brief The error was caused by an unknown source.
IkarusErrorInfo_Source_Unknown = 0x00010000FFFFFFFF,
/// \brief No error occurred.
IkarusErrorInfo_Type_None = 0x0002000000000000,
/// \brief The user misused the API.
IkarusErrorInfo_LibIkarus = 0x10600000,
/// \brief The client misused the API.
/// Example: Accessing a resource that does not exist.
IkarusErrorInfo_Type_Client_Misuse = 0x0002000100000001,
/// \brief The user provided invalid input.
/// Example: Passing null for a pointer that must not be null.
IkarusErrorInfo_Type_Client_Input = 0x0002000100000002,
/// \brief An error occurred while interacting with a dependency from ikarus.
/// Example: An error occurred in the underlying OS library.
IkarusErrorInfo_Type_SubSystem_Dependency = 0x0002000200000001,
/// \brief An error occurred while interacting with the database.
/// Example: An error occurred while executing a query.
IkarusErrorInfo_Type_SubSystem_Database = 0x0002000200000002,
/// \brief An error occurred while interacting with the filesystem.
/// Example: An error occurred while reading a file.
IkarusErrorInfo_Type_SubSystem_Filesystem = 0x0002000200000003,
IkarusErrorInfo_Client_Misuse = 0x10100001,
/// \brief The client provided a null value for a parameter that must not be null.
/// Example: Passing null for `ikarus_project_get_name`
IkarusErrorInfo_Client_InvalidNull = 0x10100002,
/// \brief The client provided an index that was out of bounds for some array.
/// Example: Passing the index 3 for an `IkarusToggleValue` with size 3.
IkarusErrorInfo_Client_IndexOutOfBounds = 0x10100003,
/// \brief The client provided a numeric value that was out of bounds
/// Example: Passing the value 2^32 to an i32 (might be passed as a string).
IkarusErrorInfo_Client_ValueOutOfBounds = 0x10100004,
/// \brief The client provided invalid input that doesn't fit in any of the other categories.
/// Example: Passing an empty/blank string for a string that must be non-empty/-blank.
IkarusErrorInfo_Client_InvalidInput = 0x10100005,
/// \brief The client provided valid data in an invalid format.
/// Example: Passing a malformed JSON string.
IkarusErrorInfo_Client_InvalidFormat = 0x10100006,
/// \brief The client violated a constraint.
/// \details This error is most likely caused by endusers.
/// Example: A user tries to set the age of a character to an value outside of their specified range.
IkarusErrorInfo_Client_ConstraintViolated = 0x10100007,
/// \brief A file was not found.
IkarusErrorInfo_Filesystem_NotFound = 0x10300001,
/// \brief A file or directory already exists.
IkarusErrorInfo_Filesystem_AlreadyExists = 0x10300002,
/// \brief Missing permissions to access a file or directory.
IkarusErrorInfo_Filesystem_MissingPermissions = 0x10300003,
/// \brief Insufficient space to perform an operation.
IkarusErrorInfo_Filesystem_InsufficientSpace = 0x10300004,
/// \brief A path is invalid.
IkarusErrorInfo_Filesystem_InvalidPath = 0x10300005,
/// \brief A database connection failed.
IkarusErrorInfo_Database_ConnectionFailed = 0x10400001,
/// \brief A database query failed.
IkarusErrorInfo_Database_QueryFailed = 0x10400002,
/// \brief A database migration failed.
IkarusErrorInfo_Database_MigrationFailed = 0x10400003,
/// \brief A database is in an invalid state. This indicates a corrupt project.
/// Example: An entity is linked to a non-existant blueprint.
IkarusErrorInfo_Database_InvalidState = 0x10400004,
/// \brief A system call failed.
IkarusErrorInfo_OS_SystemCallFailed = 0x10500001,
/// \brief A system call returned an invalid value.
IkarusErrorInfo_OS_InvalidReturnValue = 0x10500002,
/// \brief An OOM error occurred.
IkarusErrorInfo_OS_InsufficientMemory = 0x10500003,
/// \brief A datapoint within ikarus is invalid for the current state of the system.
/// Example: The name of an object is found to be invalid UTF8.
IkarusErrorInfo_Type_LibIkarus_InvalidState = 0x0002000300000001,
/// \brief LibIkarus is unable to perform a certain operation that should succeed.
/// Example: Migrating a project fails
IkarusErrorInfo_Type_LibIkarus_CannotPerformOperation = 0x0002000300000002,
/// \brief LibIkarus is unable to perform a certain operation within a given timeframe.
IkarusErrorInfo_LibIkarus_InvalidState = 0x20030001,
/// \brief libikarus is unable to perform a certain operation within a given timeframe.
/// Example: A query takes longer than the timeout.
IkarusErrorInfo_Type_LibIkarus_Timeout = 0x0002000300000003,
/// \brief The type of error is unknown.
IkarusErrorInfo_Type_Unknown = 0xFFFFFFFFFFFFFFFF,
IkarusErrorInfo_LibIkarus_Timeout = 0x20030003,
};
/// \brief The data limits for an error.
enum IkarusErrorDataLimit {
/// \brief The maximum number of error infos that can be stored in an error.
IkarusErrorDataLimit_MaxErrorInfos = 8,
/// \brief The maximum length of an error message.
IkarusErrorDataLimit_MaxMessageLength = 128,
};
/// \brief The data stored for an error
struct IkarusErrorData {
/// \brief The scope of the error.
/// \details This array may at most hold #IkarusErrorDataLimit_MaxErrorInfos elements.
/// The first occurrence of #IkarusErrorInfo_None signifies the end of the array. If this happens at idx x== 0, no error occurred.
IkarusErrorInfo infos[IkarusErrorDataLimit_MaxErrorInfos];
char message[IkarusErrorDataLimit_MaxMessageLength];
};
/// \brief Gets the name of an error info.
@ -66,6 +120,20 @@ enum IkarusErrorInfo {
/// \remark The returned pointer is valid for the lifetime of the program and must not be freed.
IKA_API char const * get_error_info_name(IkarusErrorInfo info);
/// \brief Checks if an error data is a success.
/// \param data The error data to check.
/// \return True if the error data is a success, false otherwise.
IKA_API bool ikarus_error_data_is_success(IkarusErrorData const * data);
/// \brief Checks if an error data is an error.
/// \param data The error data to check.
/// \return True if the error data is an error, false otherwise.
IKA_API bool ikarus_error_data_is_error(IkarusErrorData const * data);
/// \brief Formats the error data in a reasonable but unspecified way.
/// \param data The error data to format.
/// \return The formatted error data.
/// \remark Ownership of the returned pointer is passed to the user and must be freed at their leisure using ikarus_free.
IKA_API char const * ikarus_error_data_pretty_format(IkarusErrorData const * data);
IKARUS_END_HEADER
/// @}