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