/* * Copyright 2025 Slendi * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the “Software”), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ #ifndef DCFG_H #define DCFG_H #include #include #include #include #ifdef __cplusplus extern "C" { #endif typedef struct dcfg_Value dcfg_Value; typedef struct dcfg_Instance dcfg_Instance; // Type definitions typedef struct dcfg_StringView { char const *data; size_t size; } dcfg_StringView; #define dcfg_SV(cstr) ((dcfg_StringView) { .data = cstr, .size = strlen(cstr) }) typedef void *(*dcfg_AllocFn)(size_t); // This should automatically zero memory. typedef void (*dcfg_FreeFn)(void *); typedef char *(*dcfg_RealpathFn)(char const *); typedef void *(*dcfg_FopenFn)(char const *, char const *); typedef int (*dcfg_FseekFn)(void *, size_t, int); typedef long (*dcfg_FtellFn)(void *); typedef struct dcfg_InstanceCreateInfo { // Default using libc dcfg_AllocFn alloc; dcfg_FreeFn free; // If POSIX support is enabled, all of those are defined if NULL. dcfg_RealpathFn realpath; dcfg_FopenFn fopen; dcfg_FseekFn fseek; dcfg_FtellFn ftell; } dcfg_InstanceCreateInfo; typedef enum dcfg_ValueKind { dcfg_ValueType_Nil, dcfg_ValueType_Boolean, dcfg_ValueType_Integer, dcfg_ValueType_Real, dcfg_ValueType_String, dcfg_ValueType_Path, dcfg_ValueType_Object, dcfg_ValueType_Array, dcfg_ValueType_Function, dcfg_ValueType_MemberAccess, dcfg_ValueType_FunctionCall, } dcfg_ValueType; typedef dcfg_Value *(*dcfg_BuiltIn)(dcfg_Value **argv, size_t argc); typedef uint64_t dcfg_Version; #define DCFG_GET_MAJOR(v) (((v) >> 48) & 0xFFFF) #define DCFG_GET_MINOR(v) (((v) >> 32) & 0xFFFF) #define DCFG_GET_PATCH(v) ((v) & 0xFFFFFFFF) dcfg_Version dcfg_get_version(void); dcfg_Instance *dcfg_make_instance(dcfg_InstanceCreateInfo const *create_info); void dcfg_destroy_instance(dcfg_Instance *instance); char const *dcfg_last_error(dcfg_Instance *instance); // File path gets copied internally to instance to a Value * -> path hashmap for // evaluation. dcfg_Value *dcfg_parse( dcfg_Instance *instance, dcfg_StringView const file_path); void dcfg_destroy(dcfg_Value *value); bool dcfg_serialize_value(dcfg_Value *value, dcfg_StringView *out_sv); // Value type checking dcfg_ValueType dcfg_Value_type_ex(dcfg_Value *value, bool evaluate); static inline dcfg_ValueType dcfg_Value_type(dcfg_Value *value) { return dcfg_Value_type_ex(value, true); } // Value getters bool dcfg_Value_get_object_field_ex(dcfg_Value *value, dcfg_StringView const key, dcfg_Value **out_value, bool const evaluate); bool dcfg_Value_get_array_item_ex(dcfg_Value *value, size_t const index, dcfg_Value **out_value, bool const evaluate); bool dcfg_Value_get_function_body_ex( dcfg_Value *value, dcfg_Value **out_value, bool evaluate); bool dcfg_Value_get_boolean(dcfg_Value *value, bool *out_value); bool dcfg_Value_get_integer(dcfg_Value *value, int64_t *out_value); bool dcfg_Value_get_real(dcfg_Value *value, double *out_value); bool dcfg_Value_get_string(dcfg_Value *value, dcfg_StringView *out_sv); bool dcfg_Value_get_path(dcfg_Value *value, dcfg_StringView *out_sv); bool dcfg_Value_get_object_keys(dcfg_Value *value, size_t const capacity, size_t *out_count, dcfg_StringView *out_keys); bool dcfg_Value_get_array_size(dcfg_Value *value, size_t *out_size); static inline bool dcfg_Value_get_object_field( dcfg_Value *value, dcfg_StringView const key, dcfg_Value **out_value) { return dcfg_Value_get_object_field_ex(value, key, out_value, true); } static inline bool dcfg_Value_get_array_item( dcfg_Value *value, size_t const index, dcfg_Value **out_value) { return dcfg_Value_get_array_item_ex(value, index, out_value, true); } static inline bool dcfg_Value_get_function_body( dcfg_Value *value, dcfg_Value **out_value) { return dcfg_Value_get_function_body_ex(value, out_value, true); } // Allocates new values bool dcfg_call_function(dcfg_Value *function, dcfg_Value **args, size_t arg_count, dcfg_Value **out_value); // Allocates new values bool dcfg_Value_evaluate(dcfg_Value *value, dcfg_Value **out_value); // Allocates new values bool dcfg_Value_evaluate_toplevel(dcfg_Value *top, dcfg_Value **out_value, dcfg_StringView *function_names, dcfg_BuiltIn *functions, size_t function_count); #ifdef __cplusplus } #endif #endif // DCFG_H