cscg22-gearboy

CSCG 2022 Challenge 'Gearboy'
git clone https://git.sinitax.com/sinitax/cscg22-gearboy
Log | Files | Refs | sfeed.txt

sut_configparser.c (7162B)


      1/* See COPYING.txt for the full license governing this code. */
      2/**
      3 * \file sut_configparser.c
      4 *
      5 * Source file for the parser for SUT config files.
      6 */
      7
      8#include <limits.h>
      9#include <string.h>
     10#include <SDL_test.h>
     11#include <SDL_rwops.h>
     12#include "SDL_visualtest_sut_configparser.h"
     13#include "SDL_visualtest_parsehelper.h"
     14#include "SDL_visualtest_rwhelper.h"
     15
     16int
     17SDLVisualTest_ParseSUTConfig(char* file, SDLVisualTest_SUTConfig* config)
     18{
     19    char line[MAX_SUTOPTION_LINE_LENGTH];
     20    SDLVisualTest_RWHelperBuffer buffer;
     21    char* token_ptr;
     22    char* token_end;
     23    int num_lines, i, token_len;
     24    SDL_RWops* rw;
     25
     26    if(!file)
     27    {
     28        SDLTest_LogError("file argument cannot be NULL");
     29        return 0;
     30    }
     31    if(!config)
     32    {
     33        SDLTest_LogError("config argument cannot be NULL");
     34        return 0;
     35    }
     36
     37    /* count the number of lines */
     38    rw = SDL_RWFromFile(file, "r");
     39    if(!rw)
     40    {
     41        SDLTest_LogError("SDL_RWFromFile() failed");
     42        return 0;
     43    }
     44    SDLVisualTest_RWHelperResetBuffer(&buffer);
     45    num_lines = SDLVisualTest_RWHelperCountNonEmptyLines(rw, &buffer, '#');
     46    if(num_lines == -1)
     47        return 0;
     48    else if(num_lines == 0)
     49    {
     50        config->options = NULL;
     51        config->num_options = 0;
     52        SDL_RWclose(rw);
     53        return 1;
     54    }
     55
     56    /* allocate memory */
     57    SDL_RWseek(rw, 0, RW_SEEK_SET);
     58    SDLVisualTest_RWHelperResetBuffer(&buffer);
     59    config->num_options = num_lines;
     60    config->options = (SDLVisualTest_SUTOption*)SDL_malloc(num_lines * 
     61                      sizeof(SDLVisualTest_SUTOption));
     62    if(!config->options)
     63    {
     64        SDLTest_LogError("malloc() failed");
     65        SDL_RWclose(rw);
     66        return 0;
     67    }
     68
     69    /* actually parse the options */
     70    for(i = 0; i < num_lines; i++)
     71    {
     72        if(!SDLVisualTest_RWHelperReadLine(rw, line, MAX_SUTOPTION_LINE_LENGTH,
     73                                           &buffer, '#'))
     74        {
     75            SDLTest_LogError("SDLVisualTest_RWHelperReadLine() failed");
     76            SDL_free(config->options);
     77            SDL_RWclose(rw);
     78            return 0;
     79        }
     80
     81        /* parse name */
     82        token_ptr = strtok(line, ", ");
     83        if(!token_ptr)
     84        {
     85            SDLTest_LogError("Could not parse line %d", i + 1);
     86            SDL_free(config->options);
     87            SDL_RWclose(rw);
     88            return 0;
     89        }
     90        token_len = SDL_strlen(token_ptr) + 1;
     91        SDL_strlcpy(config->options[i].name, token_ptr, token_len);
     92
     93        /* parse type */
     94        token_ptr = strtok(NULL, ", ");
     95        if(!token_ptr)
     96        {
     97            SDLTest_LogError("Could not parse line %d", i + 1);
     98            SDL_free(config->options);
     99            SDL_RWclose(rw);
    100            return 0;
    101        }
    102        if(SDL_strcmp(token_ptr, "string") == 0)
    103            config->options[i].type = SDL_SUT_OPTIONTYPE_STRING;
    104        else if(SDL_strcmp(token_ptr, "integer") == 0)
    105            config->options[i].type = SDL_SUT_OPTIONTYPE_INT;
    106        else if(SDL_strcmp(token_ptr, "enum") == 0)
    107            config->options[i].type = SDL_SUT_OPTIONTYPE_ENUM;
    108        else if(SDL_strcmp(token_ptr, "boolean") == 0)
    109            config->options[i].type = SDL_SUT_OPTIONTYPE_BOOL;
    110        else
    111        {
    112            SDLTest_LogError("Could not parse type token at line %d", i + 1);
    113            SDL_free(config->options);
    114            SDL_RWclose(rw);
    115            return 0;
    116        }
    117
    118        /* parse values */
    119        token_ptr = strtok(NULL, "]");
    120        if(!token_ptr)
    121        {
    122            SDLTest_LogError("Could not parse line %d", i + 1);
    123            SDL_free(config->options);
    124            SDL_RWclose(rw);
    125            return 0;
    126        }
    127        token_ptr = SDL_strchr(token_ptr, '[');
    128        if(!token_ptr)
    129        {
    130            SDLTest_LogError("Could not parse enum token at line %d", i + 1);
    131            SDL_free(config->options);
    132            SDL_RWclose(rw);
    133            return 0;
    134        }
    135        token_ptr++;
    136        if(config->options[i].type == SDL_SUT_OPTIONTYPE_INT)
    137        {
    138            if(SDL_sscanf(token_ptr, "%d %d", &config->options[i].data.range.min,
    139                          &config->options[i].data.range.max) != 2)
    140            {
    141                config->options[i].data.range.min = INT_MIN;
    142                config->options[i].data.range.max = INT_MAX;
    143            }
    144        }
    145        else if(config->options[i].type == SDL_SUT_OPTIONTYPE_ENUM)
    146        {
    147            config->options[i].data.enum_values = SDLVisualTest_Tokenize(token_ptr,
    148                                                  MAX_SUTOPTION_ENUMVAL_LEN);
    149            if(!config->options[i].data.enum_values)
    150            {
    151                SDLTest_LogError("Could not parse enum token at line %d", i + 1);
    152                SDL_free(config->options);
    153                SDL_RWclose(rw);
    154                return 0;
    155            }
    156        }
    157
    158        /* parse required */
    159        token_ptr = strtok(NULL, ", ");
    160        if(!token_ptr)
    161        {
    162            SDLTest_LogError("Could not parse line %d", i + 1);
    163            SDL_free(config->options);
    164            SDL_RWclose(rw);
    165            return 0;
    166        }
    167
    168        if(SDL_strcmp(token_ptr, "true") == 0)
    169            config->options[i].required = SDL_TRUE;
    170        else if(SDL_strcmp(token_ptr, "false") == 0)
    171            config->options[i].required = SDL_FALSE;
    172        else
    173        {
    174            SDLTest_LogError("Could not parse required token at line %d", i + 1);
    175            SDL_free(config->options);
    176            SDL_RWclose(rw);
    177            return 0;
    178        }
    179
    180        /* parse categories */
    181        token_ptr = strtok(NULL, ",");
    182        if(!token_ptr)
    183        {
    184            SDLTest_LogError("Could not parse line %d", i + 1);
    185            SDL_free(config->options);
    186            SDL_RWclose(rw);
    187            return 0;
    188        }
    189        token_ptr = SDL_strchr(token_ptr, '[');
    190        if(!token_ptr)
    191        {
    192            SDLTest_LogError("Could not parse enum token at line %d", i + 1);
    193            SDL_free(config->options);
    194            SDL_RWclose(rw);
    195            return 0;
    196        }
    197        token_ptr++;
    198        token_end = SDL_strchr(token_ptr, ']');
    199        *token_end = '\0';
    200        if(!token_end)
    201        {
    202            SDLTest_LogError("Could not parse enum token at line %d", i + 1);
    203            SDL_free(config->options);
    204            SDL_RWclose(rw);
    205            return 0;
    206        }
    207        config->options[i].categories = SDLVisualTest_Tokenize(token_ptr,
    208                                        MAX_SUTOPTION_CATEGORY_LEN);
    209    }
    210    SDL_RWclose(rw);
    211    return 1;
    212}
    213
    214void
    215SDLVisualTest_FreeSUTConfig(SDLVisualTest_SUTConfig* config)
    216{
    217    if(config && config->options)
    218    {
    219        SDLVisualTest_SUTOption* option;
    220        for(option = config->options;
    221            option != config->options + config->num_options; option++)
    222        {
    223            if(option->categories)
    224                SDL_free(option->categories);
    225            if(option->type == SDL_SUT_OPTIONTYPE_ENUM && option->data.enum_values)
    226                SDL_free(option->data.enum_values);
    227        }
    228        SDL_free(config->options);
    229        config->options = NULL;
    230        config->num_options = 0;
    231    }
    232}