|
- #include "IZ_config.h"
-
- const char* IZ_ConfigGetCommandlineOption(u8 argc, const char* argv[], const char* val) {
- size_t n = strlen(val);
- int c = argc;
-
- while (--c > 0) {
-
- if (!strncmp(argv[c], val, n)) {
- if (!*(argv[c] + n) && c < argc - 1) {
- /* coverity treats unchecked argv as "tainted" */
- if (!argv[c + 1] || strlen(argv[c + 1]) > 1024)
- return NULL;
- return argv[c + 1];
- }
-
- if (argv[c][n] == '=')
- return &argv[c][n + 1];
- return argv[c] + n;
- }
- }
-
- return NULL;
- }
-
- typedef enum {
- IZ_CONFIG_SAVE_ITEM_ERROR = -1,
- IZ_CONFIG_SAVE_ITEM_OK,
- } IZ_ConfigSaveItemResult;
-
- #define IZ_CONFIG_REGISTER_INT_TYPE(ID, T) \
- typedef bool IZ_ConfigValidate##ID(T); \
- \
- typedef T IZ_ConfigDeserialize##ID(const char*); \
- \
- typedef void IZ_ConfigSerialize##ID(T, const char[128]); \
- \
- void IZ_ConfigEnsureValid##ID(IZ_ConfigItem* item, T raw_value, T default_value) { \
- T* dest = item->dest; \
- if (item->validator) { \
- IZ_ConfigValidate##ID* validate = item->validator; \
- if (validate(raw_value)) { \
- *dest = raw_value; \
- return; \
- } \
- *dest = default_value; \
- return; \
- } \
- *dest = raw_value; \
- } \
- \
- void IZ_ConfigLoad##ID(IZ_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) { \
- IZ_ConfigDeserialize##ID* deserialize = item->transformer.deserialize; \
- IZ_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); \
- } \
- IZ_ConfigEnsureValid##ID(item, raw_value, default_value); \
- } \
- \
- IZ_ConfigSaveItemResult IZ_ConfigSave##ID(IZ_ConfigItem* item, const char* config_path) { \
- T dest = *((T*) item->dest); \
- if (item->validator) { \
- IZ_ConfigValidate##ID* validate = item->validator; \
- if (!validate(dest)) { \
- dest = *((const T*) item->default_value); \
- } \
- } \
- \
- if (item->transformer.deserialize && item->transformer.serialize) { \
- IZ_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 IZ_ConfigOverride##ID(IZ_ConfigItem* item, u8 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 = IZ_ConfigGetCommandlineOption(argc, argv, item->cmdline_option))) { \
- dest = strtol(cmdline_buffer, &rest_of_string, 10); \
- if (strcmp(cmdline_buffer, rest_of_string) != 0) { \
- IZ_ConfigEnsureValid##ID(item, dest, config_value); \
- return; \
- } \
- } \
- }
-
- IZ_CONFIG_REGISTER_INT_TYPE(U8, u8);
- IZ_CONFIG_REGISTER_INT_TYPE(U16, u16);
- IZ_CONFIG_REGISTER_INT_TYPE(I32, i32);
-
- typedef bool IZ_ConfigLoadParamsStringValidator(const char*);
-
- void IZ_ConfigEnsureValidString(IZ_ConfigItem* item, const char* buffer) {
- if (item->validator) {
- IZ_ConfigLoadParamsStringValidator* validator = item->validator;
- if (validator(buffer)) {
- memcpy_s(item->dest, item->dest_size, buffer, item->dest_size);
- return;
- }
- memcpy_s(item->dest, item->dest_size, item->default_value, item->dest_size);
- return;
- }
- memcpy_s(item->dest, item->dest_size, buffer, item->dest_size);
- }
-
- void IZ_ConfigLoadString(IZ_ConfigItem* item, const char* config_path) {
- char buffer[item->dest_size];
- ini_gets(item->section, item->key, item->default_value, buffer, (i32) item->dest_size, config_path);
- IZ_ConfigEnsureValidString(item, buffer);
- }
-
- IZ_ConfigSaveItemResult IZ_ConfigSaveString(IZ_ConfigItem* item, const char* config_path) {
- const char* dest = (const char*) item->dest;
- if (item->validator) {
- IZ_ConfigLoadParamsStringValidator* validator = item->validator;
- if (!validator(dest)) {
- dest = (const char*) item->default_value;
- }
- }
-
- if (!ini_puts(item->section, item->key, dest, config_path)) {
- return IZ_CONFIG_SAVE_ITEM_ERROR;
- }
-
- return IZ_CONFIG_SAVE_ITEM_OK;
- }
-
- void IZ_ConfigOverrideString(IZ_ConfigItem* item, u8 argc, const char* argv[]) {
- if (!item->cmdline_option) {
- return;
- }
- const char* cmdline_buffer;
- if ((cmdline_buffer = IZ_ConfigGetCommandlineOption(argc, argv, item->cmdline_option))) {
- IZ_ConfigEnsureValidString(item, cmdline_buffer);
- }
- }
-
- void IZ_ConfigLoad(IZ_ConfigItem item[], const char* config_path) {
- u8 i;
- for (i = 0; item[i].type != IZ_CONFIG_TYPE_VOID; i += 1) {
- switch (item[i].type) {
- case IZ_CONFIG_TYPE_STRING:
- IZ_ConfigLoadString(&item[i], config_path);
- break;
- case IZ_CONFIG_TYPE_U8:
- IZ_ConfigLoadU8(&item[i], config_path);
- break;
- case IZ_CONFIG_TYPE_U16:
- IZ_ConfigLoadU16(&item[i], config_path);
- break;
- case IZ_CONFIG_TYPE_I32:
- IZ_ConfigLoadI32(&item[i], config_path);
- default:
- break;
- }
- }
- }
-
- IZ_ConfigSaveResult IZ_ConfigSave(IZ_ConfigItem item[], const char* config_path) {
- u8 i;
- i64 problems = 0;
- for (i = 0; item[i].type != IZ_CONFIG_TYPE_VOID; i += 1) {
- i8 result = 0;
- switch (item[i].type) {
- case IZ_CONFIG_TYPE_STRING:
- result = IZ_ConfigSaveString(&item[i], config_path);
- break;
- case IZ_CONFIG_TYPE_U8:
- result = IZ_ConfigSaveU8(&item[i], config_path);
- break;
- case IZ_CONFIG_TYPE_U16:
- result = IZ_ConfigSaveU16(&item[i], config_path);
- break;
- case IZ_CONFIG_TYPE_I32:
- result = IZ_ConfigSaveI32(&item[i], config_path);
- default:
- break;
- }
-
- if (result < 0) {
- problems |= (1u << (i64) i);
- }
- }
-
- return -problems;
- }
-
- void IZ_ConfigOverride(IZ_ConfigItem item[], u8 argc, const char* argv[]) {
- u8 i;
- for (i = 0; item[i].type != IZ_CONFIG_TYPE_VOID; i += 1) {
- switch (item[i].type) {
- case IZ_CONFIG_TYPE_STRING:
- IZ_ConfigOverrideString(&item[i], argc, argv);
- break;
- case IZ_CONFIG_TYPE_U8:
- IZ_ConfigOverrideU8(&item[i], argc, argv);
- break;
- case IZ_CONFIG_TYPE_U16:
- IZ_ConfigOverrideU16(&item[i], argc, argv);
- break;
- case IZ_CONFIG_TYPE_I32:
- IZ_ConfigOverrideI32(&item[i], argc, argv);
- break;
- default:
- break;
- }
- }
- }
-
- IZ_ConfigInitializeResult IZ_ConfigInitialize(IZ_ConfigItem item[], const char* config_path, u8 argc, const char* argv[]) {
- IZ_ConfigLoad(item, config_path);
- IZ_ConfigSaveResult save_result = IZ_ConfigSave(item, config_path);
- if (save_result < 0) {
- return IZ_CONFIG_INITIALIZE_RESULT_ERROR;
- }
- IZ_ConfigOverride(item, argc, argv);
- if (save_result > 0) {
- return IZ_CONFIG_INITIALIZE_RESULT_WARNING;
- }
- return IZ_CONFIG_INITIALIZE_RESULT_OK;
- }
|