|
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215 |
- #include "ini-config.h"
-
- const char* INI_ConfigGetCommandlineOption(uint8_t 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;
- }
-
- #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;
- }
|