4 * Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
11 * * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * * Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
17 * * Neither the name of Intel Corporation nor the names of its
18 * contributors may be used to endorse or promote products derived
19 * from this software without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38 #include <rte_common.h>
39 #include <rte_string_fns.h>
41 #include "rte_cfgfile.h"
43 struct rte_cfgfile_section
{
44 char name
[CFG_NAME_LEN
];
46 struct rte_cfgfile_entry
*entries
[0];
52 struct rte_cfgfile_section
*sections
[0];
55 /** when we resize a file structure, how many extra entries
56 * for new sections do we add in */
57 #define CFG_ALLOC_SECTION_BATCH 8
58 /** when we resize a section structure, how many extra entries
59 * for new entries do we add in */
60 #define CFG_ALLOC_ENTRY_BATCH 16
63 * Default cfgfile load parameters.
65 static const struct rte_cfgfile_parameters default_cfgfile_params
= {
66 .comment_character
= CFG_DEFAULT_COMMENT_CHARACTER
,
70 * Defines the list of acceptable comment characters supported by this
73 static const char valid_comment_chars
[] = {
82 _strip(char *str
, unsigned len
)
88 if (isspace(str
[len
-1])) {
89 /* strip trailing whitespace */
90 while (newlen
> 0 && isspace(str
[newlen
- 1]))
94 if (isspace(str
[0])) {
95 /* strip leading whitespace */
97 while (isspace(str
[start
]) && start
< newlen
)
101 for (i
= 0; i
< newlen
; i
++)
102 str
[i
] = str
[i
+start
];
109 rte_cfgfile_check_params(const struct rte_cfgfile_parameters
*params
)
111 unsigned int valid_comment
;
115 printf("Error - missing cfgfile parameters\n");
120 for (i
= 0; i
< RTE_DIM(valid_comment_chars
); i
++) {
121 if (params
->comment_character
== valid_comment_chars
[i
]) {
127 if (valid_comment
== 0) {
128 printf("Error - invalid comment characters %c\n",
129 params
->comment_character
);
137 rte_cfgfile_load(const char *filename
, int flags
)
139 return rte_cfgfile_load_with_params(filename
, flags
,
140 &default_cfgfile_params
);
144 rte_cfgfile_load_with_params(const char *filename
, int flags
,
145 const struct rte_cfgfile_parameters
*params
)
147 int allocated_sections
= CFG_ALLOC_SECTION_BATCH
;
148 int allocated_entries
= 0;
149 int curr_section
= -1;
151 char buffer
[CFG_NAME_LEN
+ CFG_VALUE_LEN
+ 4] = {0};
153 struct rte_cfgfile
*cfg
= NULL
;
155 if (rte_cfgfile_check_params(params
))
158 FILE *f
= fopen(filename
, "r");
162 cfg
= malloc(sizeof(*cfg
) + sizeof(cfg
->sections
[0]) *
167 memset(cfg
->sections
, 0, sizeof(cfg
->sections
[0]) * allocated_sections
);
169 if (flags
& CFG_FLAG_GLOBAL_SECTION
) {
171 allocated_entries
= CFG_ALLOC_ENTRY_BATCH
;
172 cfg
->sections
[curr_section
] = malloc(
173 sizeof(*cfg
->sections
[0]) +
174 sizeof(cfg
->sections
[0]->entries
[0]) *
176 if (cfg
->sections
[curr_section
] == NULL
) {
177 printf("Error - no memory for global section\n");
181 snprintf(cfg
->sections
[curr_section
]->name
,
182 sizeof(cfg
->sections
[0]->name
), "GLOBAL");
185 while (fgets(buffer
, sizeof(buffer
), f
) != NULL
) {
187 size_t len
= strnlen(buffer
, sizeof(buffer
));
189 if ((len
>= sizeof(buffer
) - 1) && (buffer
[len
-1] != '\n')) {
190 printf("Error line %d - no \\n found on string. "
191 "Check if line too long\n", lineno
);
194 pos
= memchr(buffer
, params
->comment_character
, len
);
200 len
= _strip(buffer
, len
);
201 if (buffer
[0] != '[' && memchr(buffer
, '=', len
) == NULL
)
204 if (buffer
[0] == '[') {
205 /* section heading line */
206 char *end
= memchr(buffer
, ']', len
);
208 printf("Error line %d - no terminating '['"
209 "character found\n", lineno
);
213 _strip(&buffer
[1], end
- &buffer
[1]);
215 /* close off old section and add start new one */
216 if (curr_section
>= 0)
217 cfg
->sections
[curr_section
]->num_entries
=
221 /* resize overall struct if we don't have room for more
223 if (curr_section
== allocated_sections
) {
224 allocated_sections
+= CFG_ALLOC_SECTION_BATCH
;
225 struct rte_cfgfile
*n_cfg
= realloc(cfg
,
226 sizeof(*cfg
) + sizeof(cfg
->sections
[0])
227 * allocated_sections
);
230 printf("Error - no more memory\n");
236 /* allocate space for new section */
237 allocated_entries
= CFG_ALLOC_ENTRY_BATCH
;
239 cfg
->sections
[curr_section
] = malloc(
240 sizeof(*cfg
->sections
[0]) +
241 sizeof(cfg
->sections
[0]->entries
[0]) *
243 if (cfg
->sections
[curr_section
] == NULL
) {
244 printf("Error - no more memory\n");
248 snprintf(cfg
->sections
[curr_section
]->name
,
249 sizeof(cfg
->sections
[0]->name
),
253 if (curr_section
< 0) {
254 printf("Error line %d - value outside of"
255 "section\n", lineno
);
259 struct rte_cfgfile_section
*sect
=
260 cfg
->sections
[curr_section
];
262 char *split
[2] = {NULL
};
263 n
= rte_strsplit(buffer
, sizeof(buffer
), split
, 2, '=');
264 if (flags
& CFG_FLAG_EMPTY_VALUES
) {
265 if ((n
< 1) || (n
> 2)) {
266 printf("Error at line %d - cannot split string, n=%d\n",
272 printf("Error at line %d - cannot split string, n=%d\n",
279 if (curr_entry
== allocated_entries
) {
280 allocated_entries
+= CFG_ALLOC_ENTRY_BATCH
;
281 struct rte_cfgfile_section
*n_sect
= realloc(
282 sect
, sizeof(*sect
) +
283 sizeof(sect
->entries
[0]) *
285 if (n_sect
== NULL
) {
287 printf("Error - no more memory\n");
290 sect
= cfg
->sections
[curr_section
] = n_sect
;
293 sect
->entries
[curr_entry
] = malloc(
294 sizeof(*sect
->entries
[0]));
295 if (sect
->entries
[curr_entry
] == NULL
) {
296 printf("Error - no more memory\n");
300 struct rte_cfgfile_entry
*entry
= sect
->entries
[
302 snprintf(entry
->name
, sizeof(entry
->name
), "%s",
304 snprintf(entry
->value
, sizeof(entry
->value
), "%s",
305 split
[1] ? split
[1] : "");
306 _strip(entry
->name
, strnlen(entry
->name
,
307 sizeof(entry
->name
)));
308 _strip(entry
->value
, strnlen(entry
->value
,
309 sizeof(entry
->value
)));
314 cfg
->num_sections
= curr_section
+ 1;
315 /* curr_section will still be -1 if we have an empty file */
316 if (curr_section
>= 0)
317 cfg
->sections
[curr_section
]->num_entries
= curr_entry
+ 1;
321 cfg
->num_sections
= curr_section
+ 1;
322 if (curr_section
>= 0)
323 cfg
->sections
[curr_section
]->num_entries
= curr_entry
+ 1;
324 rte_cfgfile_close(cfg
);
331 int rte_cfgfile_close(struct rte_cfgfile
*cfg
)
338 for (i
= 0; i
< cfg
->num_sections
; i
++) {
339 if (cfg
->sections
[i
] != NULL
) {
340 if (cfg
->sections
[i
]->num_entries
) {
341 for (j
= 0; j
< cfg
->sections
[i
]->num_entries
;
343 if (cfg
->sections
[i
]->entries
[j
] !=
345 free(cfg
->sections
[i
]->
349 free(cfg
->sections
[i
]);
358 rte_cfgfile_num_sections(struct rte_cfgfile
*cfg
, const char *sectionname
,
362 int num_sections
= 0;
363 for (i
= 0; i
< cfg
->num_sections
; i
++) {
364 if (strncmp(cfg
->sections
[i
]->name
, sectionname
, length
) == 0)
371 rte_cfgfile_sections(struct rte_cfgfile
*cfg
, char *sections
[],
376 for (i
= 0; i
< cfg
->num_sections
&& i
< max_sections
; i
++)
377 snprintf(sections
[i
], CFG_NAME_LEN
, "%s",
378 cfg
->sections
[i
]->name
);
383 static const struct rte_cfgfile_section
*
384 _get_section(struct rte_cfgfile
*cfg
, const char *sectionname
)
387 for (i
= 0; i
< cfg
->num_sections
; i
++) {
388 if (strncmp(cfg
->sections
[i
]->name
, sectionname
,
389 sizeof(cfg
->sections
[0]->name
)) == 0)
390 return cfg
->sections
[i
];
396 rte_cfgfile_has_section(struct rte_cfgfile
*cfg
, const char *sectionname
)
398 return _get_section(cfg
, sectionname
) != NULL
;
402 rte_cfgfile_section_num_entries(struct rte_cfgfile
*cfg
,
403 const char *sectionname
)
405 const struct rte_cfgfile_section
*s
= _get_section(cfg
, sectionname
);
408 return s
->num_entries
;
413 rte_cfgfile_section_entries(struct rte_cfgfile
*cfg
, const char *sectionname
,
414 struct rte_cfgfile_entry
*entries
, int max_entries
)
417 const struct rte_cfgfile_section
*sect
= _get_section(cfg
, sectionname
);
420 for (i
= 0; i
< max_entries
&& i
< sect
->num_entries
; i
++)
421 entries
[i
] = *sect
->entries
[i
];
426 rte_cfgfile_section_entries_by_index(struct rte_cfgfile
*cfg
, int index
,
428 struct rte_cfgfile_entry
*entries
, int max_entries
)
431 const struct rte_cfgfile_section
*sect
;
433 if (index
< 0 || index
>= cfg
->num_sections
)
436 sect
= cfg
->sections
[index
];
437 snprintf(sectionname
, CFG_NAME_LEN
, "%s", sect
->name
);
438 for (i
= 0; i
< max_entries
&& i
< sect
->num_entries
; i
++)
439 entries
[i
] = *sect
->entries
[i
];
444 rte_cfgfile_get_entry(struct rte_cfgfile
*cfg
, const char *sectionname
,
445 const char *entryname
)
448 const struct rte_cfgfile_section
*sect
= _get_section(cfg
, sectionname
);
451 for (i
= 0; i
< sect
->num_entries
; i
++)
452 if (strncmp(sect
->entries
[i
]->name
, entryname
, CFG_NAME_LEN
)
454 return sect
->entries
[i
]->value
;
459 rte_cfgfile_has_entry(struct rte_cfgfile
*cfg
, const char *sectionname
,
460 const char *entryname
)
462 return rte_cfgfile_get_entry(cfg
, sectionname
, entryname
) != NULL
;