action_configparser.c (10173B)
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 15static void 16FreeAction(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 42int 43SDLVisualTest_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 73int 74SDLVisualTest_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 104void 105SDLVisualTest_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 117SDLVisualTest_Action* 118SDLVisualTest_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 134int 135SDLVisualTest_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 148void 149SDLVisualTest_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. */ 160static void 161SortQueue(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 200int 201SDLVisualTest_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 258int 259SDLVisualTest_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}