Edit

kc3-lang/SDL/visualtest/src/sut_configparser.c

Branch :

  • Show log

    Commit

  • Author : Sylvain
    Date : 2021-11-22 16:22:39
    Hash : 5699e0fa
    Message : visualtest: use SDL_malloc

  • visualtest/src/sut_configparser.c
  • /* See LICENSE.txt for the full license governing this code. */
    /**
     * \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("SDL_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;
        }
    }