|  | /* See COPYING.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("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; | 
|  | } | 
|  | } |