🛠️🐜 Antkeeper superbuild with dependencies included https://antkeeper.com
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.

232 lines
7.0 KiB

  1. /* See COPYING.txt for the full license governing this code. */
  2. /**
  3. * \file sut_configparser.c
  4. *
  5. * Source file for the parser for SUT config files.
  6. */
  7. #include <limits.h>
  8. #include <string.h>
  9. #include <SDL_test.h>
  10. #include <SDL_rwops.h>
  11. #include "SDL_visualtest_sut_configparser.h"
  12. #include "SDL_visualtest_parsehelper.h"
  13. #include "SDL_visualtest_rwhelper.h"
  14. int
  15. SDLVisualTest_ParseSUTConfig(char* file, SDLVisualTest_SUTConfig* config)
  16. {
  17. char line[MAX_SUTOPTION_LINE_LENGTH];
  18. SDLVisualTest_RWHelperBuffer buffer;
  19. char* token_ptr;
  20. char* token_end;
  21. int num_lines, i, token_len;
  22. SDL_RWops* rw;
  23. if(!file)
  24. {
  25. SDLTest_LogError("file argument cannot be NULL");
  26. return 0;
  27. }
  28. if(!config)
  29. {
  30. SDLTest_LogError("config argument cannot be NULL");
  31. return 0;
  32. }
  33. /* count the number of lines */
  34. rw = SDL_RWFromFile(file, "r");
  35. if(!rw)
  36. {
  37. SDLTest_LogError("SDL_RWFromFile() failed");
  38. return 0;
  39. }
  40. SDLVisualTest_RWHelperResetBuffer(&buffer);
  41. num_lines = SDLVisualTest_RWHelperCountNonEmptyLines(rw, &buffer, '#');
  42. if(num_lines == -1)
  43. return 0;
  44. else if(num_lines == 0)
  45. {
  46. config->options = NULL;
  47. config->num_options = 0;
  48. SDL_RWclose(rw);
  49. return 1;
  50. }
  51. /* allocate memory */
  52. SDL_RWseek(rw, 0, RW_SEEK_SET);
  53. SDLVisualTest_RWHelperResetBuffer(&buffer);
  54. config->num_options = num_lines;
  55. config->options = (SDLVisualTest_SUTOption*)SDL_malloc(num_lines *
  56. sizeof(SDLVisualTest_SUTOption));
  57. if(!config->options)
  58. {
  59. SDLTest_LogError("malloc() failed");
  60. SDL_RWclose(rw);
  61. return 0;
  62. }
  63. /* actually parse the options */
  64. for(i = 0; i < num_lines; i++)
  65. {
  66. if(!SDLVisualTest_RWHelperReadLine(rw, line, MAX_SUTOPTION_LINE_LENGTH,
  67. &buffer, '#'))
  68. {
  69. SDLTest_LogError("SDLVisualTest_RWHelperReadLine() failed");
  70. SDL_free(config->options);
  71. SDL_RWclose(rw);
  72. return 0;
  73. }
  74. /* parse name */
  75. token_ptr = strtok(line, ", ");
  76. if(!token_ptr)
  77. {
  78. SDLTest_LogError("Could not parse line %d", i + 1);
  79. SDL_free(config->options);
  80. SDL_RWclose(rw);
  81. return 0;
  82. }
  83. token_len = SDL_strlen(token_ptr) + 1;
  84. SDL_strlcpy(config->options[i].name, token_ptr, token_len);
  85. /* parse type */
  86. token_ptr = strtok(NULL, ", ");
  87. if(!token_ptr)
  88. {
  89. SDLTest_LogError("Could not parse line %d", i + 1);
  90. SDL_free(config->options);
  91. SDL_RWclose(rw);
  92. return 0;
  93. }
  94. if(SDL_strcmp(token_ptr, "string") == 0)
  95. config->options[i].type = SDL_SUT_OPTIONTYPE_STRING;
  96. else if(SDL_strcmp(token_ptr, "integer") == 0)
  97. config->options[i].type = SDL_SUT_OPTIONTYPE_INT;
  98. else if(SDL_strcmp(token_ptr, "enum") == 0)
  99. config->options[i].type = SDL_SUT_OPTIONTYPE_ENUM;
  100. else if(SDL_strcmp(token_ptr, "boolean") == 0)
  101. config->options[i].type = SDL_SUT_OPTIONTYPE_BOOL;
  102. else
  103. {
  104. SDLTest_LogError("Could not parse type token at line %d", i + 1);
  105. SDL_free(config->options);
  106. SDL_RWclose(rw);
  107. return 0;
  108. }
  109. /* parse values */
  110. token_ptr = strtok(NULL, "]");
  111. if(!token_ptr)
  112. {
  113. SDLTest_LogError("Could not parse line %d", i + 1);
  114. SDL_free(config->options);
  115. SDL_RWclose(rw);
  116. return 0;
  117. }
  118. token_ptr = SDL_strchr(token_ptr, '[');
  119. if(!token_ptr)
  120. {
  121. SDLTest_LogError("Could not parse enum token at line %d", i + 1);
  122. SDL_free(config->options);
  123. SDL_RWclose(rw);
  124. return 0;
  125. }
  126. token_ptr++;
  127. if(config->options[i].type == SDL_SUT_OPTIONTYPE_INT)
  128. {
  129. if(SDL_sscanf(token_ptr, "%d %d", &config->options[i].data.range.min,
  130. &config->options[i].data.range.max) != 2)
  131. {
  132. config->options[i].data.range.min = INT_MIN;
  133. config->options[i].data.range.max = INT_MAX;
  134. }
  135. }
  136. else if(config->options[i].type == SDL_SUT_OPTIONTYPE_ENUM)
  137. {
  138. config->options[i].data.enum_values = SDLVisualTest_Tokenize(token_ptr,
  139. MAX_SUTOPTION_ENUMVAL_LEN);
  140. if(!config->options[i].data.enum_values)
  141. {
  142. SDLTest_LogError("Could not parse enum token at line %d", i + 1);
  143. SDL_free(config->options);
  144. SDL_RWclose(rw);
  145. return 0;
  146. }
  147. }
  148. /* parse required */
  149. token_ptr = strtok(NULL, ", ");
  150. if(!token_ptr)
  151. {
  152. SDLTest_LogError("Could not parse line %d", i + 1);
  153. SDL_free(config->options);
  154. SDL_RWclose(rw);
  155. return 0;
  156. }
  157. if(SDL_strcmp(token_ptr, "true") == 0)
  158. config->options[i].required = SDL_TRUE;
  159. else if(SDL_strcmp(token_ptr, "false") == 0)
  160. config->options[i].required = SDL_FALSE;
  161. else
  162. {
  163. SDLTest_LogError("Could not parse required token at line %d", i + 1);
  164. SDL_free(config->options);
  165. SDL_RWclose(rw);
  166. return 0;
  167. }
  168. /* parse categories */
  169. token_ptr = strtok(NULL, ",");
  170. if(!token_ptr)
  171. {
  172. SDLTest_LogError("Could not parse line %d", i + 1);
  173. SDL_free(config->options);
  174. SDL_RWclose(rw);
  175. return 0;
  176. }
  177. token_ptr = SDL_strchr(token_ptr, '[');
  178. if(!token_ptr)
  179. {
  180. SDLTest_LogError("Could not parse enum token at line %d", i + 1);
  181. SDL_free(config->options);
  182. SDL_RWclose(rw);
  183. return 0;
  184. }
  185. token_ptr++;
  186. token_end = SDL_strchr(token_ptr, ']');
  187. *token_end = '\0';
  188. if(!token_end)
  189. {
  190. SDLTest_LogError("Could not parse enum token at line %d", i + 1);
  191. SDL_free(config->options);
  192. SDL_RWclose(rw);
  193. return 0;
  194. }
  195. config->options[i].categories = SDLVisualTest_Tokenize(token_ptr,
  196. MAX_SUTOPTION_CATEGORY_LEN);
  197. }
  198. SDL_RWclose(rw);
  199. return 1;
  200. }
  201. void
  202. SDLVisualTest_FreeSUTConfig(SDLVisualTest_SUTConfig* config)
  203. {
  204. if(config && config->options)
  205. {
  206. SDLVisualTest_SUTOption* option;
  207. for(option = config->options;
  208. option != config->options + config->num_options; option++)
  209. {
  210. if(option->categories)
  211. SDL_free(option->categories);
  212. if(option->type == SDL_SUT_OPTIONTYPE_ENUM && option->data.enum_values)
  213. SDL_free(option->data.enum_values);
  214. }
  215. SDL_free(config->options);
  216. config->options = NULL;
  217. config->num_options = 0;
  218. }
  219. }