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