🛠️🐜 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.

399 lines
10 KiB

  1. /* See LICENSE.txt for the full license governing this code. */
  2. /**
  3. * \file action_configparser.c
  4. *
  5. * Source file for the parser for action config files.
  6. */
  7. #include <SDL_stdinc.h>
  8. #include <SDL_test.h>
  9. #include <string.h>
  10. #include "SDL_visualtest_action_configparser.h"
  11. #include "SDL_visualtest_rwhelper.h"
  12. #include "SDL_visualtest_parsehelper.h"
  13. static void
  14. FreeAction(SDLVisualTest_Action* action)
  15. {
  16. if(!action)
  17. return;
  18. switch(action->type)
  19. {
  20. case SDL_ACTION_LAUNCH:
  21. {
  22. char* path;
  23. char* args;
  24. path = action->extra.process.path;
  25. args = action->extra.process.args;
  26. if(path)
  27. SDL_free(path);
  28. if(args)
  29. SDL_free(args);
  30. action->extra.process.path = NULL;
  31. action->extra.process.args = NULL;
  32. }
  33. break;
  34. default:
  35. break;
  36. }
  37. }
  38. int
  39. SDLVisualTest_EnqueueAction(SDLVisualTest_ActionQueue* queue,
  40. SDLVisualTest_Action action)
  41. {
  42. SDLVisualTest_ActionNode* node;
  43. if(!queue)
  44. {
  45. SDLTest_LogError("queue argument cannot be NULL");
  46. return 0;
  47. }
  48. node = (SDLVisualTest_ActionNode*)SDL_malloc(
  49. sizeof(SDLVisualTest_ActionNode));
  50. if(!node)
  51. {
  52. SDLTest_LogError("SDL_malloc() failed");
  53. return 0;
  54. }
  55. node->action = action;
  56. node->next = NULL;
  57. queue->size++;
  58. if(!queue->rear)
  59. queue->rear = queue->front = node;
  60. else
  61. {
  62. queue->rear->next = node;
  63. queue->rear = node;
  64. }
  65. return 1;
  66. }
  67. int
  68. SDLVisualTest_DequeueAction(SDLVisualTest_ActionQueue* queue)
  69. {
  70. SDLVisualTest_ActionNode* node;
  71. if(!queue)
  72. {
  73. SDLTest_LogError("queue argument cannot be NULL");
  74. return 0;
  75. }
  76. if(SDLVisualTest_IsActionQueueEmpty(queue))
  77. {
  78. SDLTest_LogError("cannot dequeue from empty queue");
  79. return 0;
  80. }
  81. if(queue->front == queue->rear)
  82. {
  83. FreeAction(&queue->front->action);
  84. SDL_free(queue->front);
  85. queue->front = queue->rear = NULL;
  86. }
  87. else
  88. {
  89. node = queue->front;
  90. queue->front = queue->front->next;
  91. FreeAction(&node->action);
  92. SDL_free(node);
  93. }
  94. queue->size--;
  95. return 1;
  96. }
  97. void
  98. SDLVisualTest_InitActionQueue(SDLVisualTest_ActionQueue* queue)
  99. {
  100. if(!queue)
  101. {
  102. SDLTest_LogError("queue argument cannot be NULL");
  103. return;
  104. }
  105. queue->front = NULL;
  106. queue->rear = NULL;
  107. queue->size = 0;
  108. }
  109. SDLVisualTest_Action*
  110. SDLVisualTest_GetQueueFront(SDLVisualTest_ActionQueue* queue)
  111. {
  112. if(!queue)
  113. {
  114. SDLTest_LogError("queue argument cannot be NULL");
  115. return NULL;
  116. }
  117. if(!queue->front)
  118. {
  119. SDLTest_LogError("cannot get front of empty queue");
  120. return NULL;
  121. }
  122. return &queue->front->action;
  123. }
  124. int
  125. SDLVisualTest_IsActionQueueEmpty(SDLVisualTest_ActionQueue* queue)
  126. {
  127. if(!queue)
  128. {
  129. SDLTest_LogError("queue argument cannot be NULL");
  130. return 1;
  131. }
  132. if(queue->size > 0)
  133. return 0;
  134. return 1;
  135. }
  136. void
  137. SDLVisualTest_EmptyActionQueue(SDLVisualTest_ActionQueue* queue)
  138. {
  139. if(queue)
  140. {
  141. while(!SDLVisualTest_IsActionQueueEmpty(queue))
  142. SDLVisualTest_DequeueAction(queue);
  143. }
  144. }
  145. /* Since the size of the queue is not likely to be larger than 100 elements
  146. we can get away with using insertion sort. */
  147. static void
  148. SortQueue(SDLVisualTest_ActionQueue* queue)
  149. {
  150. SDLVisualTest_ActionNode* head;
  151. SDLVisualTest_ActionNode* tail;
  152. if(!queue || SDLVisualTest_IsActionQueueEmpty(queue))
  153. return;
  154. head = queue->front;
  155. for(tail = head; tail && tail->next;)
  156. {
  157. SDLVisualTest_ActionNode* pos;
  158. SDLVisualTest_ActionNode* element = tail->next;
  159. if(element->action.time < head->action.time)
  160. {
  161. tail->next = tail->next->next;
  162. element->next = head;
  163. head = element;
  164. }
  165. else if(element->action.time >= tail->action.time)
  166. {
  167. tail = tail->next;
  168. }
  169. else
  170. {
  171. for(pos = head;
  172. (pos->next->action.time < element->action.time);
  173. pos = pos->next);
  174. tail->next = tail->next->next;
  175. element->next = pos->next;
  176. pos->next = element;
  177. }
  178. }
  179. queue->front = head;
  180. queue->rear = tail;
  181. }
  182. int
  183. SDLVisualTest_InsertIntoActionQueue(SDLVisualTest_ActionQueue* queue,
  184. SDLVisualTest_Action action)
  185. {
  186. SDLVisualTest_ActionNode* n;
  187. SDLVisualTest_ActionNode* prev;
  188. SDLVisualTest_ActionNode* newnode;
  189. if(!queue)
  190. {
  191. SDLTest_LogError("queue argument cannot be NULL");
  192. return 0;
  193. }
  194. if(SDLVisualTest_IsActionQueueEmpty(queue))
  195. {
  196. if(!SDLVisualTest_EnqueueAction(queue, action))
  197. {
  198. SDLTest_LogError("SDLVisualTest_EnqueueAction() failed");
  199. return 0;
  200. }
  201. return 1;
  202. }
  203. newnode = (SDLVisualTest_ActionNode*)SDL_malloc(sizeof(SDLVisualTest_ActionNode));
  204. if(!newnode)
  205. {
  206. SDLTest_LogError("SDL_malloc() failed");
  207. return 0;
  208. }
  209. newnode->action = action;
  210. queue->size++;
  211. for(n = queue->front, prev = NULL; n; n = n->next)
  212. {
  213. if(action.time < n->action.time)
  214. {
  215. if(prev)
  216. {
  217. prev->next = newnode;
  218. newnode->next = n;
  219. }
  220. else
  221. {
  222. newnode->next = queue->front;
  223. queue->front = newnode;
  224. }
  225. return 1;
  226. }
  227. prev = n;
  228. }
  229. queue->rear->next = newnode;
  230. newnode->next = NULL;
  231. queue->rear = newnode;
  232. return 1;
  233. }
  234. int
  235. SDLVisualTest_ParseActionConfig(const char* file, SDLVisualTest_ActionQueue* queue)
  236. {
  237. char line[MAX_ACTION_LINE_LENGTH];
  238. SDLVisualTest_RWHelperBuffer buffer;
  239. char* token_ptr;
  240. int linenum;
  241. SDL_RWops* rw;
  242. if(!file)
  243. {
  244. SDLTest_LogError("file argument cannot be NULL");
  245. return 0;
  246. }
  247. if(!queue)
  248. {
  249. SDLTest_LogError("queue argument cannot be NULL");
  250. return 0;
  251. }
  252. rw = SDL_RWFromFile(file, "r");
  253. if(!rw)
  254. {
  255. SDLTest_LogError("SDL_RWFromFile() failed");
  256. return 0;
  257. }
  258. SDLVisualTest_RWHelperResetBuffer(&buffer);
  259. SDLVisualTest_InitActionQueue(queue);
  260. linenum = 0;
  261. while(SDLVisualTest_RWHelperReadLine(rw, line, MAX_ACTION_LINE_LENGTH,
  262. &buffer, '#'))
  263. {
  264. SDLVisualTest_Action action;
  265. int hr, min, sec;
  266. /* parse time */
  267. token_ptr = strtok(line, " ");
  268. if(!token_ptr ||
  269. (SDL_sscanf(token_ptr, "%d:%d:%d", &hr, &min, &sec) != 3))
  270. {
  271. SDLTest_LogError("Could not parse time token at line: %d",
  272. linenum);
  273. SDLVisualTest_EmptyActionQueue(queue);
  274. SDL_RWclose(rw);
  275. return 0;
  276. }
  277. action.time = (((hr * 60 + min) * 60) + sec) * 1000;
  278. /* parse type */
  279. token_ptr = strtok(NULL, " ");
  280. if(SDL_strcasecmp(token_ptr, "launch") == 0)
  281. action.type = SDL_ACTION_LAUNCH;
  282. else if(SDL_strcasecmp(token_ptr, "kill") == 0)
  283. action.type = SDL_ACTION_KILL;
  284. else if(SDL_strcasecmp(token_ptr, "quit") == 0)
  285. action.type = SDL_ACTION_QUIT;
  286. else if(SDL_strcasecmp(token_ptr, "screenshot") == 0)
  287. action.type = SDL_ACTION_SCREENSHOT;
  288. else if(SDL_strcasecmp(token_ptr, "verify") == 0)
  289. action.type = SDL_ACTION_VERIFY;
  290. else
  291. {
  292. SDLTest_LogError("Could not parse type token at line: %d",
  293. linenum);
  294. SDLVisualTest_EmptyActionQueue(queue);
  295. SDL_RWclose(rw);
  296. return 0;
  297. }
  298. /* parse the extra field */
  299. if(action.type == SDL_ACTION_LAUNCH)
  300. {
  301. int len;
  302. char* args;
  303. char* path;
  304. token_ptr = strtok(NULL, " ");
  305. len = token_ptr ? SDL_strlen(token_ptr) : 0;
  306. if(len <= 0)
  307. {
  308. SDLTest_LogError("Please specify the process to launch at line: %d",
  309. linenum);
  310. SDLVisualTest_EmptyActionQueue(queue);
  311. SDL_RWclose(rw);
  312. return 0;
  313. }
  314. path = (char*)SDL_malloc(sizeof(char) * (len + 1));
  315. if(!path)
  316. {
  317. SDLTest_LogError("SDL_malloc() failed");
  318. SDLVisualTest_EmptyActionQueue(queue);
  319. SDL_RWclose(rw);
  320. return 0;
  321. }
  322. SDL_strlcpy(path, token_ptr, len + 1);
  323. token_ptr = strtok(NULL, "");
  324. len = token_ptr ? SDL_strlen(token_ptr) : 0;
  325. if(len > 0)
  326. {
  327. args = (char*)SDL_malloc(sizeof(char) * (len + 1));
  328. if(!args)
  329. {
  330. SDLTest_LogError("SDL_malloc() failed");
  331. SDL_free(path);
  332. SDLVisualTest_EmptyActionQueue(queue);
  333. SDL_RWclose(rw);
  334. return 0;
  335. }
  336. SDL_strlcpy(args, token_ptr, len + 1);
  337. }
  338. else
  339. args = NULL;
  340. action.extra.process.path = path;
  341. action.extra.process.args = args;
  342. }
  343. /* add the action to the queue */
  344. if(!SDLVisualTest_EnqueueAction(queue, action))
  345. {
  346. SDLTest_LogError("SDLVisualTest_EnqueueAction() failed");
  347. if(action.type == SDL_ACTION_LAUNCH)
  348. {
  349. SDL_free(action.extra.process.path);
  350. if(action.extra.process.args)
  351. SDL_free(action.extra.process.args);
  352. }
  353. SDLVisualTest_EmptyActionQueue(queue);
  354. SDL_RWclose(rw);
  355. return 0;
  356. }
  357. }
  358. /* sort the queue of actions */
  359. SortQueue(queue);
  360. SDL_RWclose(rw);
  361. return 1;
  362. }