From 83381f4a5ff4f55359e714493e2a5cb495c6295c Mon Sep 17 00:00:00 2001 From: TheoryOfNekomata Date: Fri, 3 Mar 2023 13:24:19 +0800 Subject: [PATCH] Organize library Separate types from main definition. --- CMakeLists.txt | 10 ++- ini-config.c | 192 ------------------------------------------------- ini-config.h | 174 ++++++++++++++++++++++++-------------------- types/int.c | 93 ++++++++++++++++++++++++ types/int.h | 54 ++++++++++++++ types/string.c | 99 +++++++++++++++++++++++++ types/string.h | 14 ++++ 7 files changed, 365 insertions(+), 271 deletions(-) create mode 100644 types/int.c create mode 100644 types/int.h create mode 100644 types/string.c create mode 100644 types/string.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 27e4815..5610583 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,6 +7,10 @@ include_directories( "${CMAKE_HOME_DIRECTORY}/subprojects/minIni/dev" ) -add_executable(ini_config - ini-config.c - ini-config.h) +add_executable( + ini_config + ini-config.c + ini-config.h + int.c + int.h +) diff --git a/ini-config.c b/ini-config.c index fecdec2..cc85f81 100644 --- a/ini-config.c +++ b/ini-config.c @@ -21,195 +21,3 @@ const char* INI_ConfigGetCommandlineOption(uint8_t argc, const char* argv[], con return NULL; } - -#define INI_CONFIG_REGISTER_INT_TYPE(ID, T) \ -typedef bool INI_ConfigValidate##ID(T); \ - \ -typedef T INI_ConfigDeserialize##ID(const char*); \ - \ -typedef void INI_ConfigSerialize##ID(T, const char[128]); \ - \ -void INI_ConfigEnsureValid##ID(INI_ConfigItem* item, T raw_value, T default_value) { \ - T* dest = item->dest; \ - if (item->validator) { \ - INI_ConfigValidate##ID* validate = item->validator; \ - if (validate(raw_value)) { \ - *dest = raw_value; \ - return; \ - } \ - *dest = default_value; \ - return; \ - } \ - *dest = raw_value; \ -} \ - \ -void INI_ConfigLoad##ID(INI_ConfigItem* item, const char* config_path) { \ - static T raw_value; \ - static T default_value; \ - default_value = *((T*) item->default_value); \ - if (item->transformer.deserialize && item->transformer.serialize) { \ - INI_ConfigDeserialize##ID* deserialize = item->transformer.deserialize; \ - INI_ConfigSerialize##ID* serialize = item->transformer.serialize; \ - const char serialized_default_value[128]; \ - if (default_value) { \ - serialize(default_value, serialized_default_value); \ - } \ - char buffer[128]; \ - ini_gets(item->section, item->key, serialized_default_value, buffer, 128, config_path); \ - raw_value = deserialize(buffer); \ - } else { \ - raw_value = ini_getl(item->section, item->key, default_value, config_path); \ - } \ - INI_ConfigEnsureValid##ID(item, raw_value, default_value); \ -} \ - \ -INI_ConfigSaveItemResult INI_ConfigSave##ID(INI_ConfigItem* item, const char* config_path) { \ - T dest = *((T*) item->dest); \ - if (item->validator) { \ - INI_ConfigValidate##ID* validate = item->validator; \ - if (!validate(dest)) { \ - dest = *((const T*) item->default_value); \ - } \ - } \ - \ - if (item->transformer.deserialize && item->transformer.serialize) { \ - INI_ConfigSerialize##ID* serialize = item->transformer.serialize; \ - const char serialized_value[128]; \ - serialize(dest, serialized_value); \ - if (!ini_puts(item->section, item->key, serialized_value, config_path)) { \ - return -1; \ - } \ - return 0; \ - } \ - \ - if (!ini_putl(item->section, item->key, dest, config_path)) { \ - return -1; \ - } \ - \ - return 0; \ -} \ - \ -void INI_ConfigOverride##ID(INI_ConfigItem* item, uint8_t argc, const char* argv[]) { \ - if (!item->cmdline_option) { \ - return; \ - } \ - const char* cmdline_buffer; \ - char* rest_of_string; \ - static T dest; \ - static T config_value; \ - config_value = *((T*) item->dest); \ - if ((cmdline_buffer = INI_ConfigGetCommandlineOption(argc, argv, item->cmdline_option))) { \ - dest = strtol(cmdline_buffer, &rest_of_string, 10); \ - if (strcmp(cmdline_buffer, rest_of_string) != 0) { \ - INI_ConfigEnsureValid##ID(item, dest, config_value); \ - return; \ - } \ - } \ -} - -INI_CONFIG_REGISTER_INT_TYPE(U8, uint8_t); -INI_CONFIG_REGISTER_INT_TYPE(U16, uint16_t); -INI_CONFIG_REGISTER_INT_TYPE(U32, uint32_t); -INI_CONFIG_REGISTER_INT_TYPE(I8, int8_t); -INI_CONFIG_REGISTER_INT_TYPE(I16, int16_t); -INI_CONFIG_REGISTER_INT_TYPE(I32, int32_t); - -typedef bool INI_ConfigLoadParamsStringValidator(const char*); - -void INI_ConfigEnsureValidString(INI_ConfigItem* item, const char* buffer) { - if (item->validator) { - INI_ConfigLoadParamsStringValidator* validator = item->validator; - if (validator(buffer)) { - memcpy(item->dest, buffer, item->type.size); - return; - } - memcpy(item->dest, item->default_value, item->type.size); - return; - } - memcpy(item->dest, buffer, item->type.size); -} - -void INI_ConfigLoadString(INI_ConfigItem* item, const char* config_path) { - char buffer[item->type.size]; - ini_gets(item->section, item->key, item->default_value, buffer, (int32_t) item->type.size, config_path); - INI_ConfigEnsureValidString(item, buffer); -} - -INI_ConfigSaveItemResult INI_ConfigSaveString(INI_ConfigItem* item, const char* config_path) { - const char* dest = (const char*) item->dest; - if (item->validator) { - INI_ConfigLoadParamsStringValidator* validator = item->validator; - if (!validator(dest)) { - dest = (const char*) item->default_value; - } - } - - if (!ini_puts(item->section, item->key, dest, config_path)) { - return INI_CONFIG_SAVE_ITEM_ERROR; - } - - return INI_CONFIG_SAVE_ITEM_OK; -} - -void INI_ConfigOverrideString(INI_ConfigItem* item, uint8_t argc, const char* argv[]) { - if (!item->cmdline_option) { - return; - } - const char* cmdline_buffer; - if ((cmdline_buffer = INI_ConfigGetCommandlineOption(argc, argv, item->cmdline_option))) { - INI_ConfigEnsureValidString(item, cmdline_buffer); - } -} - -void INI_ConfigLoad(INI_ConfigItem item[], const char* config_path) { - uint8_t i; - for (i = 0; item[i].type.size > 0; i += 1) { - if (!item[i].type.load) { - continue; - } - item[i].type.load(&item[i], config_path); - } -} - -INI_ConfigSaveResult INI_ConfigSave(INI_ConfigItem item[], const char* config_path) { - uint8_t i; - int32_t problems = 0; - for (i = 0; item[i].type.size > 0; i += 1) { - int32_t result = item[i].type.save ? item[i].type.save(&item[i], config_path) : 0; - - if (result < 0) { - problems |= (1 << (int32_t) i); - } - } - - return -problems; -} - -void INI_ConfigOverride(INI_ConfigItem item[], uint8_t argc, const char* argv[]) { - uint8_t i; - for (i = 0; item[i].type.size > 0; i += 1) { - if (!item[i].type.override) { - continue; - } - - item[i].type.override(&item[i], argc, argv); - // TODO specify command-line arg external from config item? - - } -} - -INI_ConfigInitializeResult INI_ConfigInitialize(INI_ConfigItem item[], const char* config_path, uint8_t argc, const char* argv[]) { - INI_ConfigLoad(item, config_path); - INI_ConfigSaveResult save_result = INI_ConfigSave(item, config_path); - if (save_result < 0) { - //INI_LogError("config", "Sync failed! Result: %u", save_result); - return INI_CONFIG_INITIALIZE_RESULT_ERROR; - } - INI_ConfigOverride(item, argc, argv); - if (save_result > 0) { - //INI_LogWarn(false, "config", "Sync encountered issues. Result: %u", save_result); - return INI_CONFIG_INITIALIZE_RESULT_WARNING; - } - //INI_LogInfo(INI_LOG_CATEGORY_GLOBAL, "config", "Sync successful."); - return INI_CONFIG_INITIALIZE_RESULT_OK; -} diff --git a/ini-config.h b/ini-config.h index a07dbaa..4868f43 100644 --- a/ini-config.h +++ b/ini-config.h @@ -7,48 +7,138 @@ #include #include +/** + * Struct for transformer functions used for properly loading and saving the config item's value. + */ typedef struct { + /** + * Function that formats the value from memory to a value that is write-friendly to the config file. + */ void* serialize; + /** + * Function that formats the value from file to a value that is read-friendly to memory. + */ void* deserialize; -} INI_ConfigTransformer; +} INI_ConfigTransformer; // TODO: should we unify this with INI_ConfigType? struct INI_ConfigItem; +/** + * Function for loading a config item value from file to memory. + */ typedef void INI_ConfigTypeLoad(struct INI_ConfigItem*, const char*); +/** + * Result enum for saving config items. + */ typedef enum { + /** + * Result returned when saving a config item was not successful. + */ INI_CONFIG_SAVE_ITEM_ERROR = -1, + + /** + * Result returned when saving a config item was successful. + */ INI_CONFIG_SAVE_ITEM_OK, } INI_ConfigSaveItemResult; +/** + * Function for saving a config item value from memory to file. + */ typedef INI_ConfigSaveItemResult INI_ConfigTypeSave(struct INI_ConfigItem*, const char*); +/** + * Function for retrieving a config item value from the command-line to memory. + */ typedef void INI_ConfigTypeOverride(struct INI_ConfigItem*, uint8_t, const char*[]); + +/** + * Struct for the config item type. + */ typedef struct { + /** + * Size of the corresponding in-memory value of the config item. + */ size_t size; + /** + * Load function. + * @see INI_ConfigTypeLoad + */ INI_ConfigTypeLoad* load; + /** + * Save function. + * @see INI_ConfigTypeSave + */ INI_ConfigTypeSave* save; + /** + * Override function. + * @see INI_ConfigTypeOverride + */ INI_ConfigTypeOverride* override; } INI_ConfigType; +/** + * Struct for the config item, which occuptes a single key in a specific section of the config INI file. + */ typedef struct INI_ConfigItem { + /** + * Type of the config item. + */ INI_ConfigType type; + /** + * Section where this config item can be found. + */ const char* section; + /** + * Key where this config item value is serialized and stored. + */ const char* key; - const char* cmdline_option; + /** + * Command-line option for overriding this config item's value. + */ + const char* cmdline_option; // TODO: should we extract commandline parsing logic? + /** + * Default value of the config item, when the value could not be read from the config file. + */ const void* default_value; + /** + * Validator function for the config item's value. + */ void* validator; + /** + * Transformer functions. + * @see INI_ConfigTransformer + */ INI_ConfigTransformer transformer; + /** + * The memory address where the config item value will reside. This property should allow storing the amount of butes + * specified under `type.size`. + */ void* dest; } INI_ConfigItem; -void INI_ConfigGetDefaultPath(char*, size_t); - +/** + * Retrieves the value from a command-line option. + * @return The string value from the command-line option. + */ const char* INI_ConfigGetCommandlineOption(uint8_t, const char*[], const char*); +/** + * Result enum for initializing config items. + */ typedef enum { + /** + * Result returned when initializing all config items was not successful. + */ INI_CONFIG_INITIALIZE_RESULT_ERROR = -1, + /** + * Result returned when initializing all config items was successful. + */ INI_CONFIG_INITIALIZE_RESULT_OK, + /** + * Result returned when initializing some config items was successful. + */ INI_CONFIG_INITIALIZE_RESULT_WARNING } INI_ConfigInitializeResult; @@ -58,78 +148,10 @@ typedef int32_t INI_ConfigSaveResult; INI_ConfigSaveResult INI_ConfigSave(INI_ConfigItem[], const char*); -void INI_ConfigLoadU8(INI_ConfigItem*, const char*); -void INI_ConfigLoadU16(INI_ConfigItem*, const char*); -void INI_ConfigLoadU32(INI_ConfigItem*, const char*); -void INI_ConfigLoadI8(INI_ConfigItem*, const char*); -void INI_ConfigLoadI16(INI_ConfigItem*, const char*); -void INI_ConfigLoadI32(INI_ConfigItem*, const char*); -void INI_ConfigLoadString(INI_ConfigItem*, const char*); - -INI_ConfigSaveItemResult INI_ConfigSaveU8(INI_ConfigItem*, const char*); -INI_ConfigSaveItemResult INI_ConfigSaveU16(INI_ConfigItem*, const char*); -INI_ConfigSaveItemResult INI_ConfigSaveU32(INI_ConfigItem*, const char*); -INI_ConfigSaveItemResult INI_ConfigSaveI8(INI_ConfigItem*, const char*); -INI_ConfigSaveItemResult INI_ConfigSaveI16(INI_ConfigItem*, const char*); -INI_ConfigSaveItemResult INI_ConfigSaveI32(INI_ConfigItem*, const char*); -INI_ConfigSaveItemResult INI_ConfigSaveString(INI_ConfigItem*, const char*); - -void INI_ConfigOverrideU8(INI_ConfigItem*, uint8_t, const char*[]); -void INI_ConfigOverrideU16(INI_ConfigItem*, uint8_t, const char*[]); -void INI_ConfigOverrideU32(INI_ConfigItem*, uint8_t, const char*[]); -void INI_ConfigOverrideI8(INI_ConfigItem*, uint8_t, const char*[]); -void INI_ConfigOverrideI16(INI_ConfigItem*, uint8_t, const char*[]); -void INI_ConfigOverrideI32(INI_ConfigItem*, uint8_t, const char*[]); -void INI_ConfigOverrideString(INI_ConfigItem*, uint8_t, const char*[]); - -#define INI_CONFIG_TYPE_U8 (INI_ConfigType) { \ - .size = sizeof(uint8_t), \ - .load = INI_ConfigLoadU8, \ - .save = INI_ConfigSaveU8, \ - .override = INI_ConfigOverrideU8, \ -} - -#define INI_CONFIG_TYPE_U16 (INI_ConfigType) { \ - .size = sizeof(uint16_t), \ - .load = INI_ConfigLoadU16, \ - .save = INI_ConfigSaveU16, \ - .override = INI_ConfigOverrideU16, \ -} - -#define INI_CONFIG_TYPE_U32 (INI_ConfigType) { \ - .size = sizeof(uint32_t), \ - .load = INI_ConfigLoadU32, \ - .save = INI_ConfigSaveU32, \ - .override = INI_ConfigOverrideU32, \ -} - -#define INI_CONFIG_TYPE_I8 (INI_ConfigType) { \ - .size = sizeof(int8_t), \ - .load = INI_ConfigLoadI8, \ - .save = INI_ConfigSaveI8, \ - .override = INI_ConfigOverrideI8, \ -} - -#define INI_CONFIG_TYPE_I16 (INI_ConfigType) { \ - .size = sizeof(int16_t), \ - .load = INI_ConfigLoadI16, \ - .save = INI_ConfigSaveI16, \ - .override = INI_ConfigOverrideI16, \ -} - -#define INI_CONFIG_TYPE_I32 (INI_ConfigType) { \ - .size = sizeof(int32_t), \ - .load = INI_ConfigLoadI32, \ - .save = INI_ConfigSaveI32, \ - .override = INI_ConfigOverrideI32, \ -} - -#define INI_CONFIG_TYPE_FNS_STRING(X) (INI_ConfigType) { \ - .size = (sizeof(char) * X), \ - .load = INI_ConfigLoadString, \ - .save = INI_ConfigSaveString, \ - .override = INI_ConfigOverrideString, \ -} +#define INI_CONFIG_DECLARE_TYPE(ID) \ +INI_ConfigTypeLoad INI_ConfigLoad##ID; \ +INI_ConfigTypeSave INI_ConfigSave##ID; \ +INI_ConfigTypeOverride INI_ConfigOverride##ID #define INI_CONFIG_TRANSFORMER_NONE (INI_ConfigTransformer) { \ .serialize = NULL, \ diff --git a/types/int.c b/types/int.c new file mode 100644 index 0000000..e517759 --- /dev/null +++ b/types/int.c @@ -0,0 +1,93 @@ +#include "int.h" + +#define INI_CONFIG_IMPLEMENT_INT_TYPE(ID, T) \ +typedef bool INI_ConfigValidate##ID(T); \ + \ +typedef T INI_ConfigDeserialize##ID(const char*); \ + \ +typedef void INI_ConfigSerialize##ID(T, const char[128]); \ + \ +void INI_ConfigEnsureValid##ID(INI_ConfigItem* item, T raw_value, T default_value) { \ + T* dest = item->dest; \ + if (item->validator) { \ + INI_ConfigValidate##ID* validate = item->validator; \ + if (validate(raw_value)) { \ + *dest = raw_value; \ + return; \ + } \ + *dest = default_value; \ + return; \ + } \ + *dest = raw_value; \ +} \ + \ +void INI_ConfigLoad##ID(INI_ConfigItem* item, const char* config_path) { \ + static T raw_value; \ + static T default_value; \ + default_value = *((T*) item->default_value); \ + if (item->transformer.deserialize && item->transformer.serialize) { \ + INI_ConfigDeserialize##ID* deserialize = item->transformer.deserialize; \ + INI_ConfigSerialize##ID* serialize = item->transformer.serialize; \ + const char serialized_default_value[128]; \ + if (default_value) { \ + serialize(default_value, serialized_default_value); \ + } \ + char buffer[128]; \ + ini_gets(item->section, item->key, serialized_default_value, buffer, 128, config_path); \ + raw_value = deserialize(buffer); \ + } else { \ + raw_value = ini_getl(item->section, item->key, default_value, config_path); \ + } \ + INI_ConfigEnsureValid##ID(item, raw_value, default_value); \ +} \ + \ +INI_ConfigSaveItemResult INI_ConfigSave##ID(INI_ConfigItem* item, const char* config_path) { \ + T dest = *((T*) item->dest); \ + if (item->validator) { \ + INI_ConfigValidate##ID* validate = item->validator; \ + if (!validate(dest)) { \ + dest = *((const T*) item->default_value); \ + } \ + } \ + \ + if (item->transformer.deserialize && item->transformer.serialize) { \ + INI_ConfigSerialize##ID* serialize = item->transformer.serialize; \ + const char serialized_value[128]; \ + serialize(dest, serialized_value); \ + if (!ini_puts(item->section, item->key, serialized_value, config_path)) { \ + return -1; \ + } \ + return 0; \ + } \ + \ + if (!ini_putl(item->section, item->key, dest, config_path)) { \ + return -1; \ + } \ + \ + return 0; \ +} \ + \ +void INI_ConfigOverride##ID(INI_ConfigItem* item, uint8_t argc, const char* argv[]) { \ + if (!item->cmdline_option) { \ + return; \ + } \ + const char* cmdline_buffer; \ + char* rest_of_string; \ + static T dest; \ + static T config_value; \ + config_value = *((T*) item->dest); \ + if ((cmdline_buffer = INI_ConfigGetCommandlineOption(argc, argv, item->cmdline_option))) { \ + dest = strtol(cmdline_buffer, &rest_of_string, 10); \ + if (strcmp(cmdline_buffer, rest_of_string) != 0) { \ + INI_ConfigEnsureValid##ID(item, dest, config_value); \ + return; \ + } \ + } \ +} + +INI_CONFIG_IMPLEMENT_INT_TYPE(U8, uint8_t); +INI_CONFIG_IMPLEMENT_INT_TYPE(U16, uint16_t); +INI_CONFIG_IMPLEMENT_INT_TYPE(U32, uint32_t); +INI_CONFIG_IMPLEMENT_INT_TYPE(I8, int8_t); +INI_CONFIG_IMPLEMENT_INT_TYPE(I16, int16_t); +INI_CONFIG_IMPLEMENT_INT_TYPE(I32, int32_t); diff --git a/types/int.h b/types/int.h new file mode 100644 index 0000000..5180713 --- /dev/null +++ b/types/int.h @@ -0,0 +1,54 @@ +#ifndef INI_CONFIG_TYPES_INT_H +#define INI_CONFIG_TYPES_INT_H + +#include "ini-config.h" + +INI_CONFIG_DECLARE_TYPE(U8); +#define INI_CONFIG_TYPE_U8 (INI_ConfigType) { \ + .size = sizeof(uint8_t), \ + .load = INI_ConfigLoadU8, \ + .save = INI_ConfigSaveU8, \ + .override = INI_ConfigOverrideU8, \ +} + +INI_CONFIG_DECLARE_TYPE(U16); +#define INI_CONFIG_TYPE_U16 (INI_ConfigType) { \ + .size = sizeof(uint16_t), \ + .load = INI_ConfigLoadU16, \ + .save = INI_ConfigSaveU16, \ + .override = INI_ConfigOverrideU16, \ +} + +INI_CONFIG_DECLARE_TYPE(U32); +#define INI_CONFIG_TYPE_U32 (INI_ConfigType) { \ + .size = sizeof(uint32_t), \ + .load = INI_ConfigLoadU32, \ + .save = INI_ConfigSaveU32, \ + .override = INI_ConfigOverrideU32, \ +} + +INI_CONFIG_DECLARE_TYPE(I8); +#define INI_CONFIG_TYPE_I8 (INI_ConfigType) { \ + .size = sizeof(int8_t), \ + .load = INI_ConfigLoadI8, \ + .save = INI_ConfigSaveI8, \ + .override = INI_ConfigOverrideI8, \ +} + +INI_CONFIG_DECLARE_TYPE(I16); +#define INI_CONFIG_TYPE_I16 (INI_ConfigType) { \ + .size = sizeof(int16_t), \ + .load = INI_ConfigLoadI16, \ + .save = INI_ConfigSaveI16, \ + .override = INI_ConfigOverrideI16, \ +} + +INI_CONFIG_DECLARE_TYPE(I32); +#define INI_CONFIG_TYPE_I32 (INI_ConfigType) { \ + .size = sizeof(int32_t), \ + .load = INI_ConfigLoadI32, \ + .save = INI_ConfigSaveI32, \ + .override = INI_ConfigOverrideI32, \ +} + +#endif diff --git a/types/string.c b/types/string.c new file mode 100644 index 0000000..31166b4 --- /dev/null +++ b/types/string.c @@ -0,0 +1,99 @@ +#include "string.h" + + +typedef bool INI_ConfigLoadParamsStringValidator(const char*); + +void INI_ConfigEnsureValidString(INI_ConfigItem* item, const char* buffer) { + if (item->validator) { + INI_ConfigLoadParamsStringValidator* validator = item->validator; + if (validator(buffer)) { + memcpy(item->dest, buffer, item->type.size); + return; + } + memcpy(item->dest, item->default_value, item->type.size); + return; + } + memcpy(item->dest, buffer, item->type.size); +} + +void INI_ConfigLoadString(INI_ConfigItem* item, const char* config_path) { + char buffer[item->type.size]; + ini_gets(item->section, item->key, item->default_value, buffer, (int32_t) item->type.size, config_path); + INI_ConfigEnsureValidString(item, buffer); +} + +INI_ConfigSaveItemResult INI_ConfigSaveString(INI_ConfigItem* item, const char* config_path) { + const char* dest = (const char*) item->dest; + if (item->validator) { + INI_ConfigLoadParamsStringValidator* validator = item->validator; + if (!validator(dest)) { + dest = (const char*) item->default_value; + } + } + + if (!ini_puts(item->section, item->key, dest, config_path)) { + return INI_CONFIG_SAVE_ITEM_ERROR; + } + + return INI_CONFIG_SAVE_ITEM_OK; +} + +void INI_ConfigOverrideString(INI_ConfigItem* item, uint8_t argc, const char* argv[]) { + if (!item->cmdline_option) { + return; + } + const char* cmdline_buffer; + if ((cmdline_buffer = INI_ConfigGetCommandlineOption(argc, argv, item->cmdline_option))) { + INI_ConfigEnsureValidString(item, cmdline_buffer); + } +} + +void INI_ConfigLoad(INI_ConfigItem item[], const char* config_path) { + uint8_t i; + for (i = 0; item[i].type.size > 0; i += 1) { + if (!item[i].type.load) { + continue; + } + item[i].type.load(&item[i], config_path); + } +} + +INI_ConfigSaveResult INI_ConfigSave(INI_ConfigItem item[], const char* config_path) { + uint8_t i; + int32_t problems = 0; + for (i = 0; item[i].type.size > 0; i += 1) { + int32_t result = item[i].type.save ? item[i].type.save(&item[i], config_path) : 0; + + if (result < 0) { + problems |= (1 << (int32_t) i); + } + } + + return -problems; +} + +void INI_ConfigOverride(INI_ConfigItem item[], uint8_t argc, const char* argv[]) { + uint8_t i; + for (i = 0; item[i].type.size > 0; i += 1) { + if (!item[i].type.override) { + continue; + } + + item[i].type.override(&item[i], argc, argv); + // TODO specify command-line arg external from config item? + + } +} + +INI_ConfigInitializeResult INI_ConfigInitialize(INI_ConfigItem item[], const char* config_path, uint8_t argc, const char* argv[]) { + INI_ConfigLoad(item, config_path); + INI_ConfigSaveResult save_result = INI_ConfigSave(item, config_path); + if (save_result < 0) { + return INI_CONFIG_INITIALIZE_RESULT_ERROR; + } + INI_ConfigOverride(item, argc, argv); + if (save_result > 0) { + return INI_CONFIG_INITIALIZE_RESULT_WARNING; + } + return INI_CONFIG_INITIALIZE_RESULT_OK; +} diff --git a/types/string.h b/types/string.h new file mode 100644 index 0000000..82cbaf7 --- /dev/null +++ b/types/string.h @@ -0,0 +1,14 @@ +#ifndef INI_CONFIG_TYPES_STRING_H +#define INI_CONFIG_TYPES_STRING_H + +#include "ini-config.h" + +INI_CONFIG_DECLARE_TYPE(String); +#define INI_CONFIG_TYPE_STRING(X) (INI_ConfigType) { \ + .size = (sizeof(char) * X), \ + .load = INI_ConfigLoadString, \ + .save = INI_ConfigSaveString, \ + .override = INI_ConfigOverrideString, \ +} + +#endif