sdl2_frt/visualtest/src/action_configparser.c
Sam Lantinga 2bb344d6dc Don't crash when no WM is present.
CR: Sam Lantinga.
2013-11-27 10:29:27 -08:00

396 lines
9.9 KiB
C

/* See COPYING.txt for the full license governing this code. */
/**
* \file action_configparser.c
*
* Source file for the parser for action config files.
*/
#include <SDL_stdinc.h>
#include <SDL_test.h>
#include <string.h>
#include "SDL_visualtest_action_configparser.h"
#include "SDL_visualtest_rwhelper.h"
#include "SDL_visualtest_parsehelper.h"
static void
FreeAction(SDLVisualTest_Action* action)
{
if(!action)
return;
switch(action->type)
{
case SDL_ACTION_LAUNCH:
{
char* path;
char* args;
path = action->extra.process.path;
args = action->extra.process.args;
if(path)
SDL_free(path);
if(args)
SDL_free(args);
action->extra.process.path = NULL;
action->extra.process.args = NULL;
}
break;
}
}
int
SDLVisualTest_EnqueueAction(SDLVisualTest_ActionQueue* queue,
SDLVisualTest_Action action)
{
SDLVisualTest_ActionNode* node;
if(!queue)
{
SDLTest_LogError("queue argument cannot be NULL");
return 0;
}
node = (SDLVisualTest_ActionNode*)SDL_malloc(
sizeof(SDLVisualTest_ActionNode));
if(!node)
{
SDLTest_LogError("malloc() failed");
return 0;
}
node->action = action;
node->next = NULL;
queue->size++;
if(!queue->rear)
queue->rear = queue->front = node;
else
{
queue->rear->next = node;
queue->rear = node;
}
return 1;
}
int
SDLVisualTest_DequeueAction(SDLVisualTest_ActionQueue* queue)
{
SDLVisualTest_ActionNode* node;
if(!queue)
{
SDLTest_LogError("queue argument cannot be NULL");
return 0;
}
if(SDLVisualTest_IsActionQueueEmpty(queue))
{
SDLTest_LogError("cannot dequeue from empty queue");
return 0;
}
if(queue->front == queue->rear)
{
FreeAction(&queue->front->action);
SDL_free(queue->front);
queue->front = queue->rear = NULL;
}
else
{
node = queue->front;
queue->front = queue->front->next;
FreeAction(&node->action);
SDL_free(node);
}
queue->size--;
return 1;
}
void
SDLVisualTest_InitActionQueue(SDLVisualTest_ActionQueue* queue)
{
if(!queue)
{
SDLTest_LogError("queue argument cannot be NULL");
return;
}
queue->front = NULL;
queue->rear = NULL;
queue->size = 0;
}
SDLVisualTest_Action*
SDLVisualTest_GetQueueFront(SDLVisualTest_ActionQueue* queue)
{
if(!queue)
{
SDLTest_LogError("queue argument cannot be NULL");
return NULL;
}
if(!queue->front)
{
SDLTest_LogError("cannot get front of empty queue");
return NULL;
}
return &queue->front->action;
}
int
SDLVisualTest_IsActionQueueEmpty(SDLVisualTest_ActionQueue* queue)
{
if(!queue)
{
SDLTest_LogError("queue argument cannot be NULL");
return 1;
}
if(queue->size > 0)
return 0;
return 1;
}
void
SDLVisualTest_EmptyActionQueue(SDLVisualTest_ActionQueue* queue)
{
if(queue)
{
while(!SDLVisualTest_IsActionQueueEmpty(queue))
SDLVisualTest_DequeueAction(queue);
}
}
/* Since the size of the queue is not likely to be larger than 100 elements
we can get away with using insertion sort. */
static void
SortQueue(SDLVisualTest_ActionQueue* queue)
{
SDLVisualTest_ActionNode* head;
SDLVisualTest_ActionNode* tail;
if(!queue || SDLVisualTest_IsActionQueueEmpty(queue))
return;
head = queue->front;
for(tail = head; tail && tail->next;)
{
SDLVisualTest_ActionNode* pos;
SDLVisualTest_ActionNode* element = tail->next;
if(element->action.time < head->action.time)
{
tail->next = tail->next->next;
element->next = head;
head = element;
}
else if(element->action.time >= tail->action.time)
{
tail = tail->next;
}
else
{
for(pos = head;
(pos->next->action.time < element->action.time);
pos = pos->next);
tail->next = tail->next->next;
element->next = pos->next;
pos->next = element;
}
}
queue->front = head;
queue->rear = tail;
}
int
SDLVisualTest_InsertIntoActionQueue(SDLVisualTest_ActionQueue* queue,
SDLVisualTest_Action action)
{
SDLVisualTest_ActionNode* n;
SDLVisualTest_ActionNode* prev;
SDLVisualTest_ActionNode* newnode;
if(!queue)
{
SDLTest_LogError("queue argument cannot be NULL");
return 0;
}
if(SDLVisualTest_IsActionQueueEmpty(queue))
{
if(!SDLVisualTest_EnqueueAction(queue, action))
{
SDLTest_LogError("SDLVisualTest_EnqueueAction() failed");
return 0;
}
return 1;
}
newnode = (SDLVisualTest_ActionNode*)malloc(sizeof(SDLVisualTest_ActionNode));
if(!newnode)
{
SDLTest_LogError("malloc() failed");
return 0;
}
newnode->action = action;
queue->size++;
for(n = queue->front, prev = NULL; n; n = n->next)
{
if(action.time < n->action.time)
{
if(prev)
{
prev->next = newnode;
newnode->next = n;
}
else
{
newnode->next = queue->front;
queue->front = newnode;
}
return 1;
}
prev = n;
}
queue->rear->next = newnode;
newnode->next = NULL;
queue->rear = newnode;
return 1;
}
int
SDLVisualTest_ParseActionConfig(char* file, SDLVisualTest_ActionQueue* queue)
{
char line[MAX_ACTION_LINE_LENGTH];
SDLVisualTest_RWHelperBuffer buffer;
char* token_ptr;
int linenum;
SDL_RWops* rw;
if(!file)
{
SDLTest_LogError("file argument cannot be NULL");
return 0;
}
if(!queue)
{
SDLTest_LogError("queue argument cannot be NULL");
return 0;
}
rw = SDL_RWFromFile(file, "r");
if(!rw)
{
SDLTest_LogError("SDL_RWFromFile() failed");
return 0;
}
SDLVisualTest_RWHelperResetBuffer(&buffer);
SDLVisualTest_InitActionQueue(queue);
linenum = 0;
while(SDLVisualTest_RWHelperReadLine(rw, line, MAX_ACTION_LINE_LENGTH,
&buffer, '#'))
{
SDLVisualTest_Action action;
int hr, min, sec;
/* parse time */
token_ptr = strtok(line, " ");
if(!token_ptr ||
(SDL_sscanf(token_ptr, "%d:%d:%d", &hr, &min, &sec) != 3))
{
SDLTest_LogError("Could not parse time token at line: %d",
linenum);
SDLVisualTest_EmptyActionQueue(queue);
SDL_RWclose(rw);
return 0;
}
action.time = (((hr * 60 + min) * 60) + sec) * 1000;
/* parse type */
token_ptr = strtok(NULL, " ");
if(SDL_strcasecmp(token_ptr, "launch") == 0)
action.type = SDL_ACTION_LAUNCH;
else if(SDL_strcasecmp(token_ptr, "kill") == 0)
action.type = SDL_ACTION_KILL;
else if(SDL_strcasecmp(token_ptr, "quit") == 0)
action.type = SDL_ACTION_QUIT;
else if(SDL_strcasecmp(token_ptr, "screenshot") == 0)
action.type = SDL_ACTION_SCREENSHOT;
else if(SDL_strcasecmp(token_ptr, "verify") == 0)
action.type = SDL_ACTION_VERIFY;
else
{
SDLTest_LogError("Could not parse type token at line: %d",
linenum);
SDLVisualTest_EmptyActionQueue(queue);
SDL_RWclose(rw);
return 0;
}
/* parse the extra field */
if(action.type == SDL_ACTION_LAUNCH)
{
int len;
char* args;
char* path;
token_ptr = strtok(NULL, " ");
len = token_ptr ? SDL_strlen(token_ptr) : 0;
if(len <= 0)
{
SDLTest_LogError("Please specify the process to launch at line: %d",
linenum);
SDLVisualTest_EmptyActionQueue(queue);
SDL_RWclose(rw);
return 0;
}
path = (char*)SDL_malloc(sizeof(char) * (len + 1));
if(!path)
{
SDLTest_LogError("malloc() failed");
SDLVisualTest_EmptyActionQueue(queue);
SDL_RWclose(rw);
return 0;
}
SDL_strlcpy(path, token_ptr, len + 1);
token_ptr = strtok(NULL, "");
len = token_ptr ? SDL_strlen(token_ptr) : 0;
if(len > 0)
{
args = (char*)SDL_malloc(sizeof(char) * (len + 1));
if(!args)
{
SDLTest_LogError("malloc() failed");
SDL_free(path);
SDLVisualTest_EmptyActionQueue(queue);
SDL_RWclose(rw);
return 0;
}
SDL_strlcpy(args, token_ptr, len + 1);
}
else
args = NULL;
action.extra.process.path = path;
action.extra.process.args = args;
}
/* add the action to the queue */
if(!SDLVisualTest_EnqueueAction(queue, action))
{
SDLTest_LogError("SDLVisualTest_EnqueueAction() failed");
if(action.type == SDL_ACTION_LAUNCH)
{
SDL_free(action.extra.process.path);
if(action.extra.process.args)
SDL_free(action.extra.process.args);
}
SDLVisualTest_EmptyActionQueue(queue);
SDL_RWclose(rw);
return 0;
}
}
/* sort the queue of actions */
SortQueue(queue);
SDL_RWclose(rw);
return 1;
}