2D Run-and-gun shooter inspired by One Man's Doomsday, Counter-Strike, and Metal Slug.
Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.
 
 
 
 
 
 

251 рядки
6.9 KiB

  1. #include "IZ_config.h"
  2. const char* IZ_ConfigGetCommandlineOption(u8 argc, const char* argv[], const char* val) {
  3. size_t n = strlen(val);
  4. int c = argc;
  5. while (--c > 0) {
  6. if (!strncmp(argv[c], val, n)) {
  7. if (!*(argv[c] + n) && c < argc - 1) {
  8. /* coverity treats unchecked argv as "tainted" */
  9. if (!argv[c + 1] || strlen(argv[c + 1]) > 1024)
  10. return NULL;
  11. return argv[c + 1];
  12. }
  13. if (argv[c][n] == '=')
  14. return &argv[c][n + 1];
  15. return argv[c] + n;
  16. }
  17. }
  18. return NULL;
  19. }
  20. typedef enum {
  21. IZ_CONFIG_SAVE_ITEM_ERROR = -1,
  22. IZ_CONFIG_SAVE_ITEM_OK,
  23. } IZ_ConfigSaveItemResult;
  24. #define IZ_CONFIG_REGISTER_INT_TYPE(ID, T) \
  25. typedef bool IZ_ConfigValidate##ID(T); \
  26. \
  27. typedef T IZ_ConfigDeserialize##ID(const char*); \
  28. \
  29. typedef void IZ_ConfigSerialize##ID(T, const char[128]); \
  30. \
  31. void IZ_ConfigEnsureValid##ID(IZ_ConfigItem* item, T raw_value, T default_value) { \
  32. T* dest = item->dest; \
  33. if (item->validator) { \
  34. IZ_ConfigValidate##ID* validate = item->validator; \
  35. if (validate(raw_value)) { \
  36. *dest = raw_value; \
  37. return; \
  38. } \
  39. *dest = default_value; \
  40. return; \
  41. } \
  42. *dest = raw_value; \
  43. } \
  44. \
  45. void IZ_ConfigLoad##ID(IZ_ConfigItem* item, const char* config_path) { \
  46. static T raw_value; \
  47. static T default_value; \
  48. default_value = *((T*) item->default_value); \
  49. if (item->transformer.deserialize && item->transformer.serialize) { \
  50. IZ_ConfigDeserialize##ID* deserialize = item->transformer.deserialize; \
  51. IZ_ConfigSerialize##ID* serialize = item->transformer.serialize; \
  52. const char serialized_default_value[128]; \
  53. if (default_value) { \
  54. serialize(default_value, serialized_default_value); \
  55. } \
  56. char buffer[128]; \
  57. ini_gets(item->section, item->key, serialized_default_value, buffer, 128, config_path); \
  58. raw_value = deserialize(buffer); \
  59. } else { \
  60. raw_value = ini_getl(item->section, item->key, default_value, config_path); \
  61. } \
  62. IZ_ConfigEnsureValid##ID(item, raw_value, default_value); \
  63. } \
  64. \
  65. IZ_ConfigSaveItemResult IZ_ConfigSave##ID(IZ_ConfigItem* item, const char* config_path) { \
  66. T dest = *((T*) item->dest); \
  67. if (item->validator) { \
  68. IZ_ConfigValidate##ID* validate = item->validator; \
  69. if (!validate(dest)) { \
  70. dest = *((const T*) item->default_value); \
  71. } \
  72. } \
  73. \
  74. if (item->transformer.deserialize && item->transformer.serialize) { \
  75. IZ_ConfigSerialize##ID* serialize = item->transformer.serialize; \
  76. const char serialized_value[128]; \
  77. serialize(dest, serialized_value); \
  78. if (!ini_puts(item->section, item->key, serialized_value, config_path)) { \
  79. return -1; \
  80. } \
  81. return 0; \
  82. } \
  83. \
  84. if (!ini_putl(item->section, item->key, dest, config_path)) { \
  85. return -1; \
  86. } \
  87. \
  88. return 0; \
  89. } \
  90. \
  91. void IZ_ConfigOverride##ID(IZ_ConfigItem* item, u8 argc, const char* argv[]) { \
  92. if (!item->cmdline_option) { \
  93. return; \
  94. } \
  95. const char* cmdline_buffer; \
  96. char* rest_of_string; \
  97. static T dest; \
  98. static T config_value; \
  99. config_value = *((T*) item->dest); \
  100. if ((cmdline_buffer = IZ_ConfigGetCommandlineOption(argc, argv, item->cmdline_option))) { \
  101. dest = strtol(cmdline_buffer, &rest_of_string, 10); \
  102. if (strcmp(cmdline_buffer, rest_of_string) != 0) { \
  103. IZ_ConfigEnsureValid##ID(item, dest, config_value); \
  104. return; \
  105. } \
  106. } \
  107. }
  108. IZ_CONFIG_REGISTER_INT_TYPE(U8, u8);
  109. IZ_CONFIG_REGISTER_INT_TYPE(U16, u16);
  110. IZ_CONFIG_REGISTER_INT_TYPE(I32, i32);
  111. typedef bool IZ_ConfigLoadParamsStringValidator(const char*);
  112. void IZ_ConfigEnsureValidString(IZ_ConfigItem* item, const char* buffer) {
  113. if (item->validator) {
  114. IZ_ConfigLoadParamsStringValidator* validator = item->validator;
  115. if (validator(buffer)) {
  116. memcpy_s(item->dest, item->dest_size, buffer, item->dest_size);
  117. return;
  118. }
  119. memcpy_s(item->dest, item->dest_size, item->default_value, item->dest_size);
  120. return;
  121. }
  122. memcpy_s(item->dest, item->dest_size, buffer, item->dest_size);
  123. }
  124. void IZ_ConfigLoadString(IZ_ConfigItem* item, const char* config_path) {
  125. char buffer[item->dest_size];
  126. ini_gets(item->section, item->key, item->default_value, buffer, (i32) item->dest_size, config_path);
  127. IZ_ConfigEnsureValidString(item, buffer);
  128. }
  129. IZ_ConfigSaveItemResult IZ_ConfigSaveString(IZ_ConfigItem* item, const char* config_path) {
  130. const char* dest = (const char*) item->dest;
  131. if (item->validator) {
  132. IZ_ConfigLoadParamsStringValidator* validator = item->validator;
  133. if (!validator(dest)) {
  134. dest = (const char*) item->default_value;
  135. }
  136. }
  137. if (!ini_puts(item->section, item->key, dest, config_path)) {
  138. return IZ_CONFIG_SAVE_ITEM_ERROR;
  139. }
  140. return IZ_CONFIG_SAVE_ITEM_OK;
  141. }
  142. void IZ_ConfigOverrideString(IZ_ConfigItem* item, u8 argc, const char* argv[]) {
  143. if (!item->cmdline_option) {
  144. return;
  145. }
  146. const char* cmdline_buffer;
  147. if ((cmdline_buffer = IZ_ConfigGetCommandlineOption(argc, argv, item->cmdline_option))) {
  148. IZ_ConfigEnsureValidString(item, cmdline_buffer);
  149. }
  150. }
  151. void IZ_ConfigLoad(IZ_ConfigItem item[], const char* config_path) {
  152. u8 i;
  153. for (i = 0; item[i].type != IZ_CONFIG_TYPE_VOID; i += 1) {
  154. switch (item[i].type) {
  155. case IZ_CONFIG_TYPE_STRING:
  156. IZ_ConfigLoadString(&item[i], config_path);
  157. break;
  158. case IZ_CONFIG_TYPE_U8:
  159. IZ_ConfigLoadU8(&item[i], config_path);
  160. break;
  161. case IZ_CONFIG_TYPE_U16:
  162. IZ_ConfigLoadU16(&item[i], config_path);
  163. break;
  164. case IZ_CONFIG_TYPE_I32:
  165. IZ_ConfigLoadI32(&item[i], config_path);
  166. default:
  167. break;
  168. }
  169. }
  170. }
  171. IZ_ConfigSaveResult IZ_ConfigSave(IZ_ConfigItem item[], const char* config_path) {
  172. u8 i;
  173. i64 problems = 0;
  174. for (i = 0; item[i].type != IZ_CONFIG_TYPE_VOID; i += 1) {
  175. i8 result = 0;
  176. switch (item[i].type) {
  177. case IZ_CONFIG_TYPE_STRING:
  178. result = IZ_ConfigSaveString(&item[i], config_path);
  179. break;
  180. case IZ_CONFIG_TYPE_U8:
  181. result = IZ_ConfigSaveU8(&item[i], config_path);
  182. break;
  183. case IZ_CONFIG_TYPE_U16:
  184. result = IZ_ConfigSaveU16(&item[i], config_path);
  185. break;
  186. case IZ_CONFIG_TYPE_I32:
  187. result = IZ_ConfigSaveI32(&item[i], config_path);
  188. default:
  189. break;
  190. }
  191. if (result < 0) {
  192. problems |= (1u << (i64) i);
  193. }
  194. }
  195. return -problems;
  196. }
  197. void IZ_ConfigOverride(IZ_ConfigItem item[], u8 argc, const char* argv[]) {
  198. u8 i;
  199. for (i = 0; item[i].type != IZ_CONFIG_TYPE_VOID; i += 1) {
  200. switch (item[i].type) {
  201. case IZ_CONFIG_TYPE_STRING:
  202. IZ_ConfigOverrideString(&item[i], argc, argv);
  203. break;
  204. case IZ_CONFIG_TYPE_U8:
  205. IZ_ConfigOverrideU8(&item[i], argc, argv);
  206. break;
  207. case IZ_CONFIG_TYPE_U16:
  208. IZ_ConfigOverrideU16(&item[i], argc, argv);
  209. break;
  210. case IZ_CONFIG_TYPE_I32:
  211. IZ_ConfigOverrideI32(&item[i], argc, argv);
  212. break;
  213. default:
  214. break;
  215. }
  216. }
  217. }
  218. IZ_ConfigInitializeResult IZ_ConfigInitialize(IZ_ConfigItem item[], const char* config_path, u8 argc, const char* argv[]) {
  219. IZ_ConfigLoad(item, config_path);
  220. IZ_ConfigSaveResult save_result = IZ_ConfigSave(item, config_path);
  221. if (save_result < 0) {
  222. return IZ_CONFIG_INITIALIZE_RESULT_ERROR;
  223. }
  224. IZ_ConfigOverride(item, argc, argv);
  225. if (save_result > 0) {
  226. return IZ_CONFIG_INITIALIZE_RESULT_WARNING;
  227. }
  228. return IZ_CONFIG_INITIALIZE_RESULT_OK;
  229. }