mirror of
https://github.com/Relintai/sdl2_frt.git
synced 2024-12-16 11:06:49 +01:00
396 lines
9.9 KiB
C
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;
|
||
|
}
|