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}