action_configparser.c 9.9 KB

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