2021-05-09 05:30:38 -04:00
|
|
|
/* See LICENSE.txt for the full license governing this code. */
|
2021-04-17 23:35:25 -04:00
|
|
|
/**
|
|
|
|
* \file sut_configparser.c
|
|
|
|
*
|
|
|
|
* Source file for the parser for SUT config files.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <limits.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <SDL_test.h>
|
|
|
|
#include <SDL_rwops.h>
|
|
|
|
#include "SDL_visualtest_sut_configparser.h"
|
|
|
|
#include "SDL_visualtest_parsehelper.h"
|
|
|
|
#include "SDL_visualtest_rwhelper.h"
|
|
|
|
|
|
|
|
int
|
|
|
|
SDLVisualTest_ParseSUTConfig(char* file, SDLVisualTest_SUTConfig* config)
|
|
|
|
{
|
|
|
|
char line[MAX_SUTOPTION_LINE_LENGTH];
|
|
|
|
SDLVisualTest_RWHelperBuffer buffer;
|
|
|
|
char* token_ptr;
|
|
|
|
char* token_end;
|
|
|
|
int num_lines, i, token_len;
|
|
|
|
SDL_RWops* rw;
|
|
|
|
|
|
|
|
if(!file)
|
|
|
|
{
|
|
|
|
SDLTest_LogError("file argument cannot be NULL");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
if(!config)
|
|
|
|
{
|
|
|
|
SDLTest_LogError("config argument cannot be NULL");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* count the number of lines */
|
|
|
|
rw = SDL_RWFromFile(file, "r");
|
|
|
|
if(!rw)
|
|
|
|
{
|
|
|
|
SDLTest_LogError("SDL_RWFromFile() failed");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
SDLVisualTest_RWHelperResetBuffer(&buffer);
|
|
|
|
num_lines = SDLVisualTest_RWHelperCountNonEmptyLines(rw, &buffer, '#');
|
|
|
|
if(num_lines == -1)
|
|
|
|
return 0;
|
|
|
|
else if(num_lines == 0)
|
|
|
|
{
|
|
|
|
config->options = NULL;
|
|
|
|
config->num_options = 0;
|
|
|
|
SDL_RWclose(rw);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* allocate memory */
|
|
|
|
SDL_RWseek(rw, 0, RW_SEEK_SET);
|
|
|
|
SDLVisualTest_RWHelperResetBuffer(&buffer);
|
|
|
|
config->num_options = num_lines;
|
|
|
|
config->options = (SDLVisualTest_SUTOption*)SDL_malloc(num_lines *
|
|
|
|
sizeof(SDLVisualTest_SUTOption));
|
|
|
|
if(!config->options)
|
|
|
|
{
|
|
|
|
SDLTest_LogError("malloc() failed");
|
|
|
|
SDL_RWclose(rw);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* actually parse the options */
|
|
|
|
for(i = 0; i < num_lines; i++)
|
|
|
|
{
|
|
|
|
if(!SDLVisualTest_RWHelperReadLine(rw, line, MAX_SUTOPTION_LINE_LENGTH,
|
|
|
|
&buffer, '#'))
|
|
|
|
{
|
|
|
|
SDLTest_LogError("SDLVisualTest_RWHelperReadLine() failed");
|
|
|
|
SDL_free(config->options);
|
|
|
|
SDL_RWclose(rw);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* parse name */
|
|
|
|
token_ptr = strtok(line, ", ");
|
|
|
|
if(!token_ptr)
|
|
|
|
{
|
|
|
|
SDLTest_LogError("Could not parse line %d", i + 1);
|
|
|
|
SDL_free(config->options);
|
|
|
|
SDL_RWclose(rw);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
token_len = SDL_strlen(token_ptr) + 1;
|
|
|
|
SDL_strlcpy(config->options[i].name, token_ptr, token_len);
|
|
|
|
|
|
|
|
/* parse type */
|
|
|
|
token_ptr = strtok(NULL, ", ");
|
|
|
|
if(!token_ptr)
|
|
|
|
{
|
|
|
|
SDLTest_LogError("Could not parse line %d", i + 1);
|
|
|
|
SDL_free(config->options);
|
|
|
|
SDL_RWclose(rw);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
if(SDL_strcmp(token_ptr, "string") == 0)
|
|
|
|
config->options[i].type = SDL_SUT_OPTIONTYPE_STRING;
|
|
|
|
else if(SDL_strcmp(token_ptr, "integer") == 0)
|
|
|
|
config->options[i].type = SDL_SUT_OPTIONTYPE_INT;
|
|
|
|
else if(SDL_strcmp(token_ptr, "enum") == 0)
|
|
|
|
config->options[i].type = SDL_SUT_OPTIONTYPE_ENUM;
|
|
|
|
else if(SDL_strcmp(token_ptr, "boolean") == 0)
|
|
|
|
config->options[i].type = SDL_SUT_OPTIONTYPE_BOOL;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
SDLTest_LogError("Could not parse type token at line %d", i + 1);
|
|
|
|
SDL_free(config->options);
|
|
|
|
SDL_RWclose(rw);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* parse values */
|
|
|
|
token_ptr = strtok(NULL, "]");
|
|
|
|
if(!token_ptr)
|
|
|
|
{
|
|
|
|
SDLTest_LogError("Could not parse line %d", i + 1);
|
|
|
|
SDL_free(config->options);
|
|
|
|
SDL_RWclose(rw);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
token_ptr = SDL_strchr(token_ptr, '[');
|
|
|
|
if(!token_ptr)
|
|
|
|
{
|
|
|
|
SDLTest_LogError("Could not parse enum token at line %d", i + 1);
|
|
|
|
SDL_free(config->options);
|
|
|
|
SDL_RWclose(rw);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
token_ptr++;
|
|
|
|
if(config->options[i].type == SDL_SUT_OPTIONTYPE_INT)
|
|
|
|
{
|
|
|
|
if(SDL_sscanf(token_ptr, "%d %d", &config->options[i].data.range.min,
|
|
|
|
&config->options[i].data.range.max) != 2)
|
|
|
|
{
|
|
|
|
config->options[i].data.range.min = INT_MIN;
|
|
|
|
config->options[i].data.range.max = INT_MAX;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if(config->options[i].type == SDL_SUT_OPTIONTYPE_ENUM)
|
|
|
|
{
|
|
|
|
config->options[i].data.enum_values = SDLVisualTest_Tokenize(token_ptr,
|
|
|
|
MAX_SUTOPTION_ENUMVAL_LEN);
|
|
|
|
if(!config->options[i].data.enum_values)
|
|
|
|
{
|
|
|
|
SDLTest_LogError("Could not parse enum token at line %d", i + 1);
|
|
|
|
SDL_free(config->options);
|
|
|
|
SDL_RWclose(rw);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* parse required */
|
|
|
|
token_ptr = strtok(NULL, ", ");
|
|
|
|
if(!token_ptr)
|
|
|
|
{
|
|
|
|
SDLTest_LogError("Could not parse line %d", i + 1);
|
|
|
|
SDL_free(config->options);
|
|
|
|
SDL_RWclose(rw);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(SDL_strcmp(token_ptr, "true") == 0)
|
|
|
|
config->options[i].required = SDL_TRUE;
|
|
|
|
else if(SDL_strcmp(token_ptr, "false") == 0)
|
|
|
|
config->options[i].required = SDL_FALSE;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
SDLTest_LogError("Could not parse required token at line %d", i + 1);
|
|
|
|
SDL_free(config->options);
|
|
|
|
SDL_RWclose(rw);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* parse categories */
|
|
|
|
token_ptr = strtok(NULL, ",");
|
|
|
|
if(!token_ptr)
|
|
|
|
{
|
|
|
|
SDLTest_LogError("Could not parse line %d", i + 1);
|
|
|
|
SDL_free(config->options);
|
|
|
|
SDL_RWclose(rw);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
token_ptr = SDL_strchr(token_ptr, '[');
|
|
|
|
if(!token_ptr)
|
|
|
|
{
|
|
|
|
SDLTest_LogError("Could not parse enum token at line %d", i + 1);
|
|
|
|
SDL_free(config->options);
|
|
|
|
SDL_RWclose(rw);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
token_ptr++;
|
|
|
|
token_end = SDL_strchr(token_ptr, ']');
|
|
|
|
*token_end = '\0';
|
|
|
|
if(!token_end)
|
|
|
|
{
|
|
|
|
SDLTest_LogError("Could not parse enum token at line %d", i + 1);
|
|
|
|
SDL_free(config->options);
|
|
|
|
SDL_RWclose(rw);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
config->options[i].categories = SDLVisualTest_Tokenize(token_ptr,
|
|
|
|
MAX_SUTOPTION_CATEGORY_LEN);
|
|
|
|
}
|
|
|
|
SDL_RWclose(rw);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
SDLVisualTest_FreeSUTConfig(SDLVisualTest_SUTConfig* config)
|
|
|
|
{
|
|
|
|
if(config && config->options)
|
|
|
|
{
|
|
|
|
SDLVisualTest_SUTOption* option;
|
|
|
|
for(option = config->options;
|
|
|
|
option != config->options + config->num_options; option++)
|
|
|
|
{
|
|
|
|
if(option->categories)
|
|
|
|
SDL_free(option->categories);
|
|
|
|
if(option->type == SDL_SUT_OPTIONTYPE_ENUM && option->data.enum_values)
|
|
|
|
SDL_free(option->data.enum_values);
|
|
|
|
}
|
|
|
|
SDL_free(config->options);
|
|
|
|
config->options = NULL;
|
|
|
|
config->num_options = 0;
|
|
|
|
}
|
|
|
|
}
|