/* See COPYING.txt for the full license governing this code. */ /** * \file sut_configparser.c * * Source file for the parser for SUT config files. */ #include #include #include #include #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; } }