• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
16 int
SDLVisualTest_ParseSUTConfig(char * file,SDLVisualTest_SUTConfig * config)17 SDLVisualTest_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 
214 void
SDLVisualTest_FreeSUTConfig(SDLVisualTest_SUTConfig * config)215 SDLVisualTest_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 }
233