Define simple configuration on INI files.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

94 lines
2.9 KiB

  1. #include "int.h"
  2. #define INI_CONFIG_IMPLEMENT_INT_TYPE(ID, T) \
  3. typedef bool INI_ConfigValidate##ID(T); \
  4. \
  5. typedef T INI_ConfigDeserialize##ID(const char*); \
  6. \
  7. typedef void INI_ConfigSerialize##ID(T, const char[128]); \
  8. \
  9. void INI_ConfigEnsureValid##ID(INI_ConfigItem* item, T raw_value, T default_value) { \
  10. T* dest = item->dest; \
  11. if (item->validator) { \
  12. INI_ConfigValidate##ID* validate = item->validator; \
  13. if (validate(raw_value)) { \
  14. *dest = raw_value; \
  15. return; \
  16. } \
  17. *dest = default_value; \
  18. return; \
  19. } \
  20. *dest = raw_value; \
  21. } \
  22. \
  23. void INI_ConfigLoad##ID(INI_ConfigItem* item, const char* config_path) { \
  24. static T raw_value; \
  25. static T default_value; \
  26. default_value = *((T*) item->default_value); \
  27. if (item->transformer.deserialize && item->transformer.serialize) { \
  28. INI_ConfigDeserialize##ID* deserialize = item->transformer.deserialize; \
  29. INI_ConfigSerialize##ID* serialize = item->transformer.serialize; \
  30. const char serialized_default_value[128]; \
  31. if (default_value) { \
  32. serialize(default_value, serialized_default_value); \
  33. } \
  34. char buffer[128]; \
  35. ini_gets(item->section, item->key, serialized_default_value, buffer, 128, config_path); \
  36. raw_value = deserialize(buffer); \
  37. } else { \
  38. raw_value = ini_getl(item->section, item->key, default_value, config_path); \
  39. } \
  40. INI_ConfigEnsureValid##ID(item, raw_value, default_value); \
  41. } \
  42. \
  43. INI_ConfigSaveItemResult INI_ConfigSave##ID(INI_ConfigItem* item, const char* config_path) { \
  44. T dest = *((T*) item->dest); \
  45. if (item->validator) { \
  46. INI_ConfigValidate##ID* validate = item->validator; \
  47. if (!validate(dest)) { \
  48. dest = *((const T*) item->default_value); \
  49. } \
  50. } \
  51. \
  52. if (item->transformer.deserialize && item->transformer.serialize) { \
  53. INI_ConfigSerialize##ID* serialize = item->transformer.serialize; \
  54. const char serialized_value[128]; \
  55. serialize(dest, serialized_value); \
  56. if (!ini_puts(item->section, item->key, serialized_value, config_path)) { \
  57. return -1; \
  58. } \
  59. return 0; \
  60. } \
  61. \
  62. if (!ini_putl(item->section, item->key, dest, config_path)) { \
  63. return -1; \
  64. } \
  65. \
  66. return 0; \
  67. } \
  68. \
  69. void INI_ConfigOverride##ID(INI_ConfigItem* item, uint8_t argc, const char* argv[]) { \
  70. if (!item->cmdline_option) { \
  71. return; \
  72. } \
  73. const char* cmdline_buffer; \
  74. char* rest_of_string; \
  75. static T dest; \
  76. static T config_value; \
  77. config_value = *((T*) item->dest); \
  78. if ((cmdline_buffer = INI_ConfigGetCommandlineOption(argc, argv, item->cmdline_option))) { \
  79. dest = strtol(cmdline_buffer, &rest_of_string, 10); \
  80. if (strcmp(cmdline_buffer, rest_of_string) != 0) { \
  81. INI_ConfigEnsureValid##ID(item, dest, config_value); \
  82. return; \
  83. } \
  84. } \
  85. }
  86. INI_CONFIG_IMPLEMENT_INT_TYPE(U8, uint8_t);
  87. INI_CONFIG_IMPLEMENT_INT_TYPE(U16, uint16_t);
  88. INI_CONFIG_IMPLEMENT_INT_TYPE(U32, uint32_t);
  89. INI_CONFIG_IMPLEMENT_INT_TYPE(I8, int8_t);
  90. INI_CONFIG_IMPLEMENT_INT_TYPE(I16, int16_t);
  91. INI_CONFIG_IMPLEMENT_INT_TYPE(I32, int32_t);