* [dpdk-dev] [PATCH 1/3] librte_cfgfile: fix code formating in header file
2015-05-29 15:26 [dpdk-dev] [PATCH 0/3] librte_cfgfile rework and extension Maciej Gajdzica
@ 2015-05-29 15:26 ` Maciej Gajdzica
2015-05-29 15:26 ` [dpdk-dev] [PATCH 2/3] librte_compat: fix macro deffinition Maciej Gajdzica
` (2 subsequent siblings)
3 siblings, 0 replies; 7+ messages in thread
From: Maciej Gajdzica @ 2015-05-29 15:26 UTC (permalink / raw)
To: dev
From: Pawel Wodkowski <pawelx.wodkowski@intel.com>
Signed-off-by: Pawel Wodkowski <pawelx.wodkowski@intel.com>
---
lib/librte_cfgfile/rte_cfgfile.h | 27 ++++++++++++++++++---------
1 file changed, 18 insertions(+), 9 deletions(-)
diff --git a/lib/librte_cfgfile/rte_cfgfile.h b/lib/librte_cfgfile/rte_cfgfile.h
index 7c9fc91..860ce44 100644
--- a/lib/librte_cfgfile/rte_cfgfile.h
+++ b/lib/librte_cfgfile/rte_cfgfile.h
@@ -69,7 +69,8 @@ struct rte_cfgfile_entry {
* @return
* Handle to configuration file
*/
-struct rte_cfgfile *rte_cfgfile_load(const char *filename, int flags);
+struct rte_cfgfile *
+rte_cfgfile_load(const char *filename, int flags);
/**
* Get number of sections in config file
@@ -83,7 +84,8 @@ struct rte_cfgfile *rte_cfgfile_load(const char *filename, int flags);
* @return
* 0 on success, error code otherwise
*/
-int rte_cfgfile_num_sections(struct rte_cfgfile *cfg, const char *sec_name,
+int
+rte_cfgfile_num_sections(struct rte_cfgfile *cfg, const char *sec_name,
size_t length);
/**
@@ -103,7 +105,8 @@ int rte_cfgfile_num_sections(struct rte_cfgfile *cfg, const char *sec_name,
* @return
* 0 on success, error code otherwise
*/
-int rte_cfgfile_sections(struct rte_cfgfile *cfg, char *sections[],
+int
+rte_cfgfile_sections(struct rte_cfgfile *cfg, char *sections[],
int max_sections);
/**
@@ -116,7 +119,8 @@ int rte_cfgfile_sections(struct rte_cfgfile *cfg, char *sections[],
* @return
* TRUE (value different than 0) if section exists, FALSE (value 0) otherwise
*/
-int rte_cfgfile_has_section(struct rte_cfgfile *cfg, const char *sectionname);
+int
+rte_cfgfile_has_section(struct rte_cfgfile *cfg, const char *sectionname);
/**
* Get number of entries in given config file section
@@ -128,7 +132,8 @@ int rte_cfgfile_has_section(struct rte_cfgfile *cfg, const char *sectionname);
* @return
* Number of entries in section
*/
-int rte_cfgfile_section_num_entries(struct rte_cfgfile *cfg,
+int
+rte_cfgfile_section_num_entries(struct rte_cfgfile *cfg,
const char *sectionname);
/** Get section entries as key-value pairs
@@ -145,7 +150,8 @@ int rte_cfgfile_section_num_entries(struct rte_cfgfile *cfg,
* @return
* 0 on success, error code otherwise
*/
-int rte_cfgfile_section_entries(struct rte_cfgfile *cfg,
+int
+rte_cfgfile_section_entries(struct rte_cfgfile *cfg,
const char *sectionname,
struct rte_cfgfile_entry *entries,
int max_entries);
@@ -161,7 +167,8 @@ int rte_cfgfile_section_entries(struct rte_cfgfile *cfg,
* @return
* Entry value
*/
-const char *rte_cfgfile_get_entry(struct rte_cfgfile *cfg,
+const char *
+rte_cfgfile_get_entry(struct rte_cfgfile *cfg,
const char *sectionname,
const char *entryname);
@@ -176,7 +183,8 @@ const char *rte_cfgfile_get_entry(struct rte_cfgfile *cfg,
* @return
* TRUE (value different than 0) if entry exists, FALSE (value 0) otherwise
*/
-int rte_cfgfile_has_entry(struct rte_cfgfile *cfg, const char *sectionname,
+int
+rte_cfgfile_has_entry(struct rte_cfgfile *cfg, const char *sectionname,
const char *entryname);
/** Close config file
@@ -186,7 +194,8 @@ int rte_cfgfile_has_entry(struct rte_cfgfile *cfg, const char *sectionname,
* @return
* 0 on success, error code otherwise
*/
-int rte_cfgfile_close(struct rte_cfgfile *cfg);
+int
+rte_cfgfile_close(struct rte_cfgfile *cfg);
#ifdef __cplusplus
}
--
1.9.1
^ permalink raw reply [flat|nested] 7+ messages in thread
* [dpdk-dev] [PATCH 3/3] librte_cfgfile: rework
2015-05-29 15:26 [dpdk-dev] [PATCH 0/3] librte_cfgfile rework and extension Maciej Gajdzica
2015-05-29 15:26 ` [dpdk-dev] [PATCH 1/3] librte_cfgfile: fix code formating in header file Maciej Gajdzica
2015-05-29 15:26 ` [dpdk-dev] [PATCH 2/3] librte_compat: fix macro deffinition Maciej Gajdzica
@ 2015-05-29 15:26 ` Maciej Gajdzica
2015-06-15 9:29 ` Thomas Monjalon
2015-06-01 8:34 ` [dpdk-dev] [PATCH 0/3] librte_cfgfile rework and extension Dumitrescu, Cristian
3 siblings, 1 reply; 7+ messages in thread
From: Maciej Gajdzica @ 2015-05-29 15:26 UTC (permalink / raw)
To: dev
From: Pawel Wodkowski <pawelx.wodkowski@intel.com>
This patch add following features:
1. Make entry variable length - remove 64 byte limit.
2. Add line continue character '\' to make multiline values possible.
This patch also fixes following issues:
1. BUG: section were allocated as a block of memory. In rte_cfgfile_close()
free() was wrongly called on each section. This bug is fixed implicitly
by implementing new section allocation scheme.
2. Protect against multiple sections/entries in sections with the same
name.
Implications:
1. Change in struct rte_cfgfile_entry deffinition.
2. Change in rte_cfgfile_section_entries() declaration.
Signed-off-by: Pawel Wodkowski <pawelx.wodkowski@intel.com>
---
lib/librte_cfgfile/Makefile | 2 +-
lib/librte_cfgfile/rte_cfgfile.c | 792 ++++++++++++++++++++++-------
lib/librte_cfgfile/rte_cfgfile.h | 31 +-
lib/librte_cfgfile/rte_cfgfile_version.map | 8 +
4 files changed, 633 insertions(+), 200 deletions(-)
diff --git a/lib/librte_cfgfile/Makefile b/lib/librte_cfgfile/Makefile
index 032c240..616aef0 100644
--- a/lib/librte_cfgfile/Makefile
+++ b/lib/librte_cfgfile/Makefile
@@ -41,7 +41,7 @@ CFLAGS += $(WERROR_FLAGS)
EXPORT_MAP := rte_cfgfile_version.map
-LIBABIVER := 1
+LIBABIVER := 2
#
# all source are stored in SRCS-y
diff --git a/lib/librte_cfgfile/rte_cfgfile.c b/lib/librte_cfgfile/rte_cfgfile.c
index b81c273..defd80e 100644
--- a/lib/librte_cfgfile/rte_cfgfile.c
+++ b/lib/librte_cfgfile/rte_cfgfile.c
@@ -1,7 +1,7 @@
/*-
* BSD LICENSE
*
- * Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
+ * Copyright(c) 2010-2015 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -35,20 +35,26 @@
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
+#include <errno.h>
+
+#include <rte_compat.h>
+#include <rte_common.h>
#include <rte_string_fns.h>
#include "rte_cfgfile.h"
struct rte_cfgfile_section {
char name[CFG_NAME_LEN];
- int num_entries;
- struct rte_cfgfile_entry *entries[0];
+ size_t num_entries;
+ size_t allocated_entries;
+ struct rte_cfgfile_entry2 **entries;
};
struct rte_cfgfile {
int flags;
- int num_sections;
- struct rte_cfgfile_section *sections[0];
+ size_t num_sections;
+ size_t allocated_sections;
+ struct rte_cfgfile_section **sections;
};
/** when we resize a file structure, how many extra entries
@@ -58,208 +64,565 @@ struct rte_cfgfile {
* for new entries do we add in */
#define CFG_ALLOC_ENTRY_BATCH 16
-static unsigned
-_strip(char *str, unsigned len)
+/* Helpers */
+
+#define _skip_spaceses(str) ({ \
+ __typeof__(str) p = (str); \
+ while (isspace(*p)) \
+ p++; \
+ p; \
+})
+
+static size_t
+strip_leading_spaces(char *str, size_t len)
+{
+ char *start = _skip_spaceses(str);
+
+ if (*start == '\0') {
+ str[0] = '\0';
+ return 0;
+ } else if (start == str)
+ return len;
+
+ len -= start - str;
+ memmove(str, start, len);
+ str[len] = '\0';
+
+ return len;
+}
+
+static size_t
+strip_trailing_spaces(char *str, size_t len)
{
- int newlen = len;
+ size_t newlen = len;
+
+ /* strip trailing whitespace */
+ while (newlen > 0 && isspace(str[newlen - 1]))
+ str[--newlen] = '\0';
+
+ return newlen;
+}
+
+static size_t
+strip_white_spaces(char *str, size_t len)
+{
+ size_t newlen;
+
if (len == 0)
return 0;
- if (isspace(str[len-1])) {
- /* strip trailing whitespace */
- while (newlen > 0 && isspace(str[newlen - 1]))
- str[--newlen] = '\0';
+ /* strip trailing whitespace */
+ newlen = strip_trailing_spaces(str, len);
+ newlen = strip_leading_spaces(str, len);
+ return newlen;
+}
+
+static size_t
+strip_comment(char *buffer, size_t len)
+{
+ char *pos = memchr(buffer, ';', len);
+
+ if (pos == NULL)
+ return len;
+
+ if (len == 1) {
+ *pos = '\0';
+ return 0;
}
- if (isspace(str[0])) {
- /* strip leading whitespace */
- int i, start = 1;
- while (isspace(str[start]) && start < newlen)
- start++
- ; /* do nothing */
- newlen -= start;
- for (i = 0; i < newlen; i++)
- str[i] = str[i+start];
- str[i] = '\0';
+ if (buffer[len - 1] == '\n') {
+ if (buffer[len - 2] == '\\') {
+ pos[0] = '\\';
+ pos[1] = '\n';
+ pos[2] = '\0';
+ len = pos - buffer + 2;
+ } else {
+ pos[0] = '\n';
+ pos[1] = '\0';
+ len = pos - buffer + 1;
+ }
}
- return newlen;
+
+ return len;
}
-struct rte_cfgfile *
-rte_cfgfile_load(const char *filename, int flags)
+/* Get line from file. It concatanate lines with line continue.
+ * If *line is not NULL it must point to malloced data buffer and *len must
+ * be the length of *line.
+ */
+static int
+rte_cfgfile_getline(char **line, size_t *len, FILE *f, size_t *lineno)
{
- int allocated_sections = CFG_ALLOC_SECTION_BATCH;
- int allocated_entries = 0;
- int curr_section = -1;
- int curr_entry = -1;
- char buffer[256];
- int lineno = 0;
- struct rte_cfgfile *cfg = NULL;
+ char *str = NULL;
+ size_t str_len = 0;
- FILE *f = fopen(filename, "r");
- if (f == NULL)
- return NULL;
+ void *buf;
+ char *line_str = NULL;
+ size_t line_size = 0; /* Whole buffer size */
+ ssize_t line_len = 0; /* Length of line_str */
- cfg = malloc(sizeof(*cfg) + sizeof(cfg->sections[0]) *
- allocated_sections);
- if (cfg == NULL)
- goto error2;
+ size_t line_cnt = 0;
+ int status = 0;
- memset(cfg->sections, 0, sizeof(cfg->sections[0]) * allocated_sections);
+ if (!line) {
+ status = EINVAL;
+ goto error_exit;
+ }
- while (fgets(buffer, sizeof(buffer), f) != NULL) {
- char *pos = NULL;
- size_t len = strnlen(buffer, sizeof(buffer));
- lineno++;
- if ((len >= sizeof(buffer) - 1) && (buffer[len-1] != '\n')) {
- printf("Error line %d - no \\n found on string. "
- "Check if line too long\n", lineno);
- goto error1;
+ while (1) {
+ line_len = getline(&line_str, &line_size, f);
+ if (line_len <= 0) {
+ if (!feof(f)) {
+ status = -EIO;
+ goto error_exit;
+ }
+
+ break;
}
- pos = memchr(buffer, ';', sizeof(buffer));
- if (pos != NULL) {
- *pos = '\0';
- len = pos - buffer;
+
+ line_cnt++;
+ /* Replace last CR with LF */
+ if (line_len > 0 && line_str[line_len - 1] == '\r')
+ line_str[line_len - 1] = '\n';
+
+ /* Replace last CRLF with LF */
+ if (line_len > 1 && line_str[line_len - 2] == '\r' &&
+ line_str[line_len - 1] == '\n') {
+ line_str[line_len - 1] = '\0';
+ line_str[line_len - 2] = '\n';
+ line_len -= 1;
}
- len = _strip(buffer, len);
- if (buffer[0] != '[' && memchr(buffer, '=', len) == NULL)
- continue;
+ line_len = strip_comment(line_str, line_len);
- if (buffer[0] == '[') {
- /* section heading line */
- char *end = memchr(buffer, ']', len);
- if (end == NULL) {
- printf("Error line %d - no terminating '['"
- "character found\n", lineno);
- goto error1;
- }
- *end = '\0';
- _strip(&buffer[1], end - &buffer[1]);
-
- /* close off old section and add start new one */
- if (curr_section >= 0)
- cfg->sections[curr_section]->num_entries =
- curr_entry + 1;
- curr_section++;
-
- /* resize overall struct if we don't have room for more
- sections */
- if (curr_section == allocated_sections) {
- allocated_sections += CFG_ALLOC_SECTION_BATCH;
- struct rte_cfgfile *n_cfg = realloc(cfg,
- sizeof(*cfg) + sizeof(cfg->sections[0])
- * allocated_sections);
- if (n_cfg == NULL) {
- printf("Error - no more memory\n");
- goto error1;
- }
- cfg = n_cfg;
- }
+ /* Special case for first line. */
+ if (str == NULL) {
+ if (line_len == 0)
+ continue;
- /* allocate space for new section */
- allocated_entries = CFG_ALLOC_ENTRY_BATCH;
- curr_entry = -1;
- cfg->sections[curr_section] = malloc(
- sizeof(*cfg->sections[0]) +
- sizeof(cfg->sections[0]->entries[0]) *
- allocated_entries);
- if (cfg->sections[curr_section] == NULL) {
- printf("Error - no more memory\n");
- goto error1;
- }
+ str = line_str;
+ str_len = line_len;
- snprintf(cfg->sections[curr_section]->name,
- sizeof(cfg->sections[0]->name),
- "%s", &buffer[1]);
+ line_str = NULL;
+ line_len = 0;
} else {
- /* value line */
- if (curr_section < 0) {
- printf("Error line %d - value outside of"
- "section\n", lineno);
- goto error1;
- }
+ if (line_len == 0)
+ break;
- struct rte_cfgfile_section *sect =
- cfg->sections[curr_section];
- char *split[2];
- if (rte_strsplit(buffer, sizeof(buffer), split, 2, '=')
- != 2) {
- printf("Error at line %d - cannot split "
- "string\n", lineno);
- goto error1;
+ buf = realloc(str, str_len + line_len + 1);
+ if (buf == NULL) {
+ status = -ENOMEM;
+ goto error_exit;
}
- curr_entry++;
- if (curr_entry == allocated_entries) {
- allocated_entries += CFG_ALLOC_ENTRY_BATCH;
- struct rte_cfgfile_section *n_sect = realloc(
- sect, sizeof(*sect) +
- sizeof(sect->entries[0]) *
- allocated_entries);
- if (n_sect == NULL) {
- printf("Error - no more memory\n");
- goto error1;
- }
- sect = cfg->sections[curr_section] = n_sect;
+ str = buf;
+ memcpy(&str[str_len], line_str, line_len + 1);
+
+ str_len += line_len;
+ }
+
+ /* Check for line continue */
+ if (str_len < 2 || str[str_len - 1] != '\n' || str[str_len - 2] != '\\')
+ break;
+
+ /* Remove line continue character. */
+ str[str_len - 1] = '\0';
+ /* Change new line into space */
+ str[str_len - 2] = ' ';
+ str_len -= 1;
+ }
+
+ if (str_len) {
+ /* Squeeze str */
+ buf = realloc(str, str_len + 1);
+ if (buf == NULL) {
+ status = -ENOMEM;
+ goto error_exit;
+ }
+
+ free(*line);
+ *line = buf;
+ }
+
+ if (len)
+ *len = str_len;
+
+ if (lineno)
+ *lineno += line_cnt;
+
+ free(line_str);
+ return 0;
+
+error_exit:
+ printf("Error: %s\n", strerror(status));
+ if (lineno)
+ *lineno += line_cnt;
+ free(str);
+ free(line_str);
+ return status;
+}
+
+/* Section functions */
+
+static struct rte_cfgfile_section *
+rte_cfgfile_find_section(struct rte_cfgfile *cfg, const char *sectionname)
+{
+ size_t i;
+ struct rte_cfgfile_section *sect;
+
+ for (i = 0; i < cfg->num_sections; i++) {
+ sect = cfg->sections[i];
+ if (strncmp(sect->name, sectionname, sizeof(sect->name)) == 0)
+ return sect;
+ }
+
+ return NULL;
+}
+
+static int
+rte_cfgfile_create_section(struct rte_cfgfile_section **section,
+ const char *name)
+{
+ struct rte_cfgfile_section *s = NULL;
+ size_t name_len;
+
+ if (name == NULL || section == NULL)
+ return -EINVAL;
+
+ name_len = strlen(name);
+
+ if (name_len == 0 || name_len >= sizeof(s->name) - 1) {
+ printf("Empty or too long section name\n");
+ return -EINVAL;
+ }
+
+ /* Create new section */
+ s = malloc(sizeof(struct rte_cfgfile_section));
+ if (s == NULL)
+ return -ENOMEM;
+
+ memcpy(s->name, name, name_len);
+ s->name[name_len] = '\0';
+ s->allocated_entries = 0;
+ s->num_entries = 0;
+ s->entries = NULL;
+
+ *section = s;
+ return 0;
+}
+
+static int
+rte_cfgfile_add_section(struct rte_cfgfile *cfg,
+ struct rte_cfgfile_section *new_section)
+{
+ struct rte_cfgfile_section *s;
+
+ if (cfg == NULL || new_section == NULL)
+ return -EINVAL;
+
+ s = rte_cfgfile_find_section(cfg, new_section->name);
+ if (s != NULL) {
+ printf("Duplicate section '%s'\n", new_section->name);
+ return -EEXIST;
+ }
+
+ if (cfg->num_sections == cfg->allocated_sections) {
+ size_t new_count = cfg->allocated_sections + CFG_ALLOC_SECTION_BATCH;
+ struct rte_cfgfile_section **entries = realloc(cfg->sections,
+ sizeof(struct rte_cfgfile_section *) * new_count);
+
+ if (entries == NULL)
+ return -ENOMEM;
+
+ cfg->allocated_sections = new_count;
+ cfg->sections = entries;
+ }
+
+ cfg->sections[cfg->num_sections] = new_section;
+ cfg->num_sections++;
+ return 0;
+}
+
+static int
+rte_cfgfile_parse_section(struct rte_cfgfile_section **s, const char *buffer)
+{
+ const char *start, *end, *garbage;
+ struct rte_cfgfile_section *new_section = NULL;
+ char name[CFG_NAME_LEN];
+ int status;
+ size_t name_len;
+
+ /* Check input arguments and buffer if it contain section */
+ if (s == NULL || buffer == NULL)
+ return -EINVAL;
+
+ /* Find start and end of name */
+ start = _skip_spaceses(buffer);
+ if (*start != '[')
+ return -EINVAL;
+
+ start = _skip_spaceses(start + 1);
+ end = strchr(start, ']');
+ if (end == NULL) {
+ printf("No section name delimiter ']' encoutered\n");
+ return -EINVAL;
+ }
+
+ garbage = _skip_spaceses(end + 1);
+ if (*garbage != '\0') {
+ printf("Garbage after section '%s' definition: %s\n",
+ buffer, garbage);
+ return -EINVAL;
+ }
+
+ /* Check if name is proper size */
+ if (start != end) {
+ for (end--; start != end; end--)
+ if (!isspace(*end))
+ break;
+ end++;
+ }
+
+ name_len = end - start;
+ if (name_len == 1 || name_len >= sizeof(new_section->name) - 1) {
+ printf("Empty or too long section name\n");
+ return -EINVAL;
+ }
+
+ memcpy(name, start, name_len);
+ name[name_len] = '\0';
+
+ status = rte_cfgfile_create_section(&new_section, name);
+ if (status != 0)
+ return status;
+
+ *s = new_section;
+ return 0;
+}
+
+/* Section entry functions */
+
+static inline struct rte_cfgfile_entry2 *
+rte_cfgfile_find_entry(struct rte_cfgfile_section *sect, const char *entryname)
+{
+ struct rte_cfgfile_entry2 *ret = NULL;
+ size_t i;
+
+ for (i = 0; i < sect->num_entries; i++) {
+ if (strcmp(sect->entries[i]->name, entryname) == 0) {
+ ret = sect->entries[i];
+ break;
+ }
+ }
+
+ return ret;
+}
+
+static int
+rte_cfgfile_section_add_entry(struct rte_cfgfile_section *section,
+ const char *name, const char *value)
+{
+ struct rte_cfgfile_entry2 *entry = NULL;
+ int status = 0;
+ size_t name_length, value_length;
+
+ if (section == NULL) {
+ status = -EINVAL;
+ goto error_exit;
+ }
+
+ entry = rte_cfgfile_find_entry(section, name);
+ if (entry != NULL) {
+ status = -EEXIST;
+ goto error_exit;
+ }
+
+ entry = malloc(sizeof(struct rte_cfgfile_entry2));
+ if (entry == NULL) {
+ status = ENOMEM;
+ goto error_exit;
+ }
+
+ name_length = snprintf(entry->name, sizeof(entry->name), "%s", name);
+ if (name_length >= RTE_DIM(entry->name)) {
+ status = EINVAL;
+ goto error_exit;
+ }
+
+ entry->value = strdup(value);
+ if (entry->value == NULL) {
+ status = ENOMEM;
+ goto error_exit;
+ }
+ value_length = strlen(entry->value);
+
+ strip_white_spaces(entry->name, name_length);
+ strip_white_spaces(entry->value, value_length);
+
+ /* Add entry */
+ if (section->num_entries == section->allocated_entries) {
+ size_t new_count = section->allocated_entries + CFG_ALLOC_ENTRY_BATCH;
+ struct rte_cfgfile_entry2 **new_entries = realloc(section->entries,
+ sizeof(section->entries[0]) * new_count);
+
+ if (new_entries == NULL) {
+ status = ENOMEM;
+ goto error_exit;
+ }
+ section->entries = new_entries;
+ section->allocated_entries = new_count;
+ }
+
+ section->entries[section->num_entries] = entry;
+ section->num_entries++;
+
+ return 0;
+error_exit:
+ printf("Error: %s\n", strerror(status));
+ free(entry);
+ return -status;
+}
+
+/**
+ * Create new apty config file object.
+ *
+ * @param flags
+ * Config file flags, Reserved for future use. Must be set to 0.
+ * @return
+ * Handle to configuration file
+ */
+static struct rte_cfgfile *
+rte_cfgfile_create(__rte_unused int flags)
+{
+ struct rte_cfgfile *cfg = malloc(sizeof(struct rte_cfgfile));
+
+ if (cfg != NULL)
+ memset(cfg, 0, sizeof(struct rte_cfgfile));
+
+ return cfg;
+}
+
+/**
+* Open config *file*.
+*
+* @param file
+* Config stream to read.
+* @param flags
+* Config file flags, Reserved for future use. Must be set to 0.
+* @return
+* Handle to configuration file
+*/
+static struct rte_cfgfile *
+rte_cfgfile_read(FILE *f, int flags)
+{
+
+ char *line = NULL;
+ size_t line_size = 0;
+ char *pos;
+
+ struct rte_cfgfile *cfg = NULL;
+ struct rte_cfgfile_section *section = NULL;
+ size_t lineno = 0;
+ size_t current_lineno = 0;
+ int status = 0;
+
+ if (f == NULL)
+ return NULL;
+
+ cfg = rte_cfgfile_create(flags);
+ if (cfg == NULL)
+ goto error2;
+
+ while (!feof(f)) {
+ current_lineno = lineno;
+ status = rte_cfgfile_getline(&line, &line_size, f, &lineno);
+ if (status)
+ break;
+ else if (!line_size)
+ continue;
+
+ pos = _skip_spaceses(line);
+ if (*pos == '[') {
+ status = rte_cfgfile_parse_section(§ion, pos);
+ if (status == 0)
+ status = rte_cfgfile_add_section(cfg, section);
+ } else if (isalpha(*pos)) {
+ if (section == NULL) {
+ printf("Error line %zu - value outside of section\n",
+ current_lineno);
+ status = -EINVAL;
+ break;
}
- sect->entries[curr_entry] = malloc(
- sizeof(*sect->entries[0]));
- if (sect->entries[curr_entry] == NULL) {
- printf("Error - no more memory\n");
- goto error1;
+ char *split[2];
+
+ if (rte_strsplit(pos, line_size - (pos - line), split, 2, '=') == 2)
+ status = rte_cfgfile_section_add_entry(section,
+ split[0], split[1]);
+ else {
+ printf("Error at line %zu - cannot split string\n",
+ current_lineno);
+ status = -EINVAL;
}
+ } else if (*pos != '\0') {
+ printf("Invalid starting character '%c' on line %zu",
+ *pos, current_lineno);
- struct rte_cfgfile_entry *entry = sect->entries[
- curr_entry];
- snprintf(entry->name, sizeof(entry->name), "%s",
- split[0]);
- snprintf(entry->value, sizeof(entry->value), "%s",
- split[1]);
- _strip(entry->name, strnlen(entry->name,
- sizeof(entry->name)));
- _strip(entry->value, strnlen(entry->value,
- sizeof(entry->value)));
+ status = -EINVAL;
}
+
+ if (status)
+ break;
}
- fclose(f);
+
+ if (status)
+ goto error1;
+
+ free(line);
cfg->flags = flags;
- cfg->num_sections = curr_section + 1;
- /* curr_section will still be -1 if we have an empty file */
- if (curr_section >= 0)
- cfg->sections[curr_section]->num_entries = curr_entry + 1;
return cfg;
error1:
rte_cfgfile_close(cfg);
error2:
- fclose(f);
+ free(line);
return NULL;
}
+struct rte_cfgfile *
+rte_cfgfile_load(const char *filename, int flags)
+{
+ struct rte_cfgfile *cfg;
+ FILE *file = fopen(filename, "r");
+
+ if (file == NULL)
+ return NULL;
+ cfg = rte_cfgfile_read(file, flags);
+ fclose(file);
-int rte_cfgfile_close(struct rte_cfgfile *cfg)
+ return cfg;
+}
+
+int
+rte_cfgfile_close(struct rte_cfgfile *cfg)
{
- int i, j;
+ struct rte_cfgfile_section *s;
+ size_t i, j;
if (cfg == NULL)
return -1;
for (i = 0; i < cfg->num_sections; i++) {
- if (cfg->sections[i] != NULL) {
- if (cfg->sections[i]->num_entries) {
- for (j = 0; j < cfg->sections[i]->num_entries;
- j++) {
- if (cfg->sections[i]->entries[j] !=
- NULL)
- free(cfg->sections[i]->
- entries[j]);
- }
- }
- free(cfg->sections[i]);
+ s = cfg->sections[i];
+ for (j = 0; j < s->num_entries; j++) {
+ free(cfg->sections[i]->entries[j]->value);
+ free(cfg->sections[i]->entries[j]);
}
+ free(cfg->sections[i]->entries);
+ free(s);
}
+
+ free(cfg->sections);
free(cfg);
return 0;
@@ -267,10 +630,17 @@ int rte_cfgfile_close(struct rte_cfgfile *cfg)
int
rte_cfgfile_num_sections(struct rte_cfgfile *cfg, const char *sectionname,
-size_t length)
+ size_t length)
{
- int i;
+ size_t i;
int num_sections = 0;
+
+ if (cfg == NULL || (length > 0 && sectionname == NULL))
+ return -EINVAL;
+
+ if (length == 0)
+ return cfg->num_sections;
+
for (i = 0; i < cfg->num_sections; i++) {
if (strncmp(cfg->sections[i]->name, sectionname, length) == 0)
num_sections++;
@@ -280,77 +650,111 @@ size_t length)
int
rte_cfgfile_sections(struct rte_cfgfile *cfg, char *sections[],
- int max_sections)
+ int max_sections)
{
- int i;
+ size_t i;
- for (i = 0; i < cfg->num_sections && i < max_sections; i++)
+ for (i = 0; i < cfg->num_sections && (int)i < max_sections; i++)
snprintf(sections[i], CFG_NAME_LEN, "%s",
cfg->sections[i]->name);
return i;
}
-static const struct rte_cfgfile_section *
-_get_section(struct rte_cfgfile *cfg, const char *sectionname)
-{
- int i;
- for (i = 0; i < cfg->num_sections; i++) {
- if (strncmp(cfg->sections[i]->name, sectionname,
- sizeof(cfg->sections[0]->name)) == 0)
- return cfg->sections[i];
- }
- return NULL;
-}
-
int
rte_cfgfile_has_section(struct rte_cfgfile *cfg, const char *sectionname)
{
- return (_get_section(cfg, sectionname) != NULL);
+ return rte_cfgfile_find_section(cfg, sectionname) != NULL;
}
int
rte_cfgfile_section_num_entries(struct rte_cfgfile *cfg,
const char *sectionname)
{
- const struct rte_cfgfile_section *s = _get_section(cfg, sectionname);
+ struct rte_cfgfile_section *s = rte_cfgfile_find_section(cfg, sectionname);
+
if (s == NULL)
return -1;
+
return s->num_entries;
}
+int __vsym
+rte_cfgfile_section_entries_v20(struct rte_cfgfile *cfg,
+ const char *sectionname,
+ struct rte_cfgfile_entry *entries,
+ int max_entries)
+{
+ size_t i;
+ struct rte_cfgfile_section *sect;
-int
-rte_cfgfile_section_entries(struct rte_cfgfile *cfg, const char *sectionname,
- struct rte_cfgfile_entry *entries, int max_entries)
+ if (max_entries < 0 || (max_entries > 0 && entries == NULL))
+ return -EINVAL;
+
+ sect = rte_cfgfile_find_section(cfg, sectionname);
+ if (sect == NULL)
+ return -ENOENT;
+
+ for (i = 0; (int)i < max_entries && i < sect->num_entries; i++) {
+ snprintf(entries[i].name, sizeof(entries[i].name), "%s",
+ sect->entries[i]->name);
+
+ snprintf(entries[i].value, sizeof(entries[i].value), "%s",
+ sect->entries[i]->name);
+ }
+
+ return i;
+}
+
+VERSION_SYMBOL(rte_cfgfile_section_entries, _v20, 2.0);
+
+int __vsym
+rte_cfgfile_section_entries_v21(struct rte_cfgfile *cfg,
+ const char *sectionname, const struct rte_cfgfile_entry2 **entries,
+ int max_entries)
{
- int i;
- const struct rte_cfgfile_section *sect = _get_section(cfg, sectionname);
+ size_t i;
+ struct rte_cfgfile_section *sect;
+
+ if (max_entries < 0 || (max_entries > 0 && entries == NULL))
+ return -EINVAL;
+
+ sect = rte_cfgfile_find_section(cfg, sectionname);
if (sect == NULL)
- return -1;
- for (i = 0; i < max_entries && i < sect->num_entries; i++)
- entries[i] = *sect->entries[i];
+ return -ENOENT;
+
+ for (i = 0; (int)i < max_entries && i < sect->num_entries; i++)
+ entries[i] = sect->entries[i];
+
return i;
}
+BIND_DEFAULT_SYMBOL(rte_cfgfile_section_entries, _v21, 2.1);
+
const char *
rte_cfgfile_get_entry(struct rte_cfgfile *cfg, const char *sectionname,
const char *entryname)
{
- int i;
- const struct rte_cfgfile_section *sect = _get_section(cfg, sectionname);
+ struct rte_cfgfile_section *sect;
+ struct rte_cfgfile_entry2 *entry;
+
+ if (cfg == NULL)
+ return NULL;
+
+ sect = rte_cfgfile_find_section(cfg, sectionname);
if (sect == NULL)
return NULL;
- for (i = 0; i < sect->num_entries; i++)
- if (strncmp(sect->entries[i]->name, entryname, CFG_NAME_LEN)
- == 0)
- return sect->entries[i]->value;
- return NULL;
+
+ entry = rte_cfgfile_find_entry(sect, entryname);
+ if (entry == NULL)
+ return NULL;
+
+ return entry->value;
}
int
rte_cfgfile_has_entry(struct rte_cfgfile *cfg, const char *sectionname,
const char *entryname)
{
- return (rte_cfgfile_get_entry(cfg, sectionname, entryname) != NULL);
+ return rte_cfgfile_get_entry(cfg, sectionname, entryname) != NULL;
}
diff --git a/lib/librte_cfgfile/rte_cfgfile.h b/lib/librte_cfgfile/rte_cfgfile.h
index 860ce44..546b3b8 100644
--- a/lib/librte_cfgfile/rte_cfgfile.h
+++ b/lib/librte_cfgfile/rte_cfgfile.h
@@ -34,6 +34,8 @@
#ifndef __INCLUDE_RTE_CFGFILE_H__
#define __INCLUDE_RTE_CFGFILE_H__
+#include <rte_compat.h>
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -59,6 +61,12 @@ struct rte_cfgfile_entry {
char value[CFG_VALUE_LEN]; /**< Value */
};
+/** Configuration file entry */
+struct rte_cfgfile_entry2 {
+ char name[CFG_NAME_LEN]; /**< Name */
+ char *value; /**< Value */
+};
+
/**
* Open config file
*
@@ -73,7 +81,9 @@ struct rte_cfgfile *
rte_cfgfile_load(const char *filename, int flags);
/**
-* Get number of sections in config file
+* Get number of sections in config file which name start with *length*
+* characters of *sec_name*. If *length* is 0 *sec_name* is ignored and total
+* sections count is returned.
*
* @param cfg
* Config file
@@ -82,7 +92,7 @@ rte_cfgfile_load(const char *filename, int flags);
* @param length
* Maximum section name length
* @return
-* 0 on success, error code otherwise
+* Number of sections, or negative error code otherwise.
*/
int
rte_cfgfile_num_sections(struct rte_cfgfile *cfg, const char *sec_name,
@@ -103,7 +113,7 @@ rte_cfgfile_num_sections(struct rte_cfgfile *cfg, const char *sec_name,
* @param max_sections
* Maximum number of section names to be stored in sections array
* @return
-* 0 on success, error code otherwise
+* Number of section names in cfg on success, error code otherwise
*/
int
rte_cfgfile_sections(struct rte_cfgfile *cfg, char *sections[],
@@ -150,12 +160,23 @@ rte_cfgfile_section_num_entries(struct rte_cfgfile *cfg,
* @return
* 0 on success, error code otherwise
*/
-int
-rte_cfgfile_section_entries(struct rte_cfgfile *cfg,
+int rte_cfgfile_section_entries(struct rte_cfgfile *cfg,
+ const char *sectionname,
+ struct rte_cfgfile_entry **entries,
+ int max_entries);
+
+int __vsym
+rte_cfgfile_section_entries_v20(struct rte_cfgfile *cfg,
const char *sectionname,
struct rte_cfgfile_entry *entries,
int max_entries);
+int __vsym
+rte_cfgfile_section_entries_v21(struct rte_cfgfile *cfg,
+ const char *sectionname,
+ const struct rte_cfgfile_entry2 **entries,
+ int max_entries);
+
/** Get value of the named entry in named config file section
*
* @param cfg
diff --git a/lib/librte_cfgfile/rte_cfgfile_version.map b/lib/librte_cfgfile/rte_cfgfile_version.map
index bf6c6fd..cd83bf6 100644
--- a/lib/librte_cfgfile/rte_cfgfile_version.map
+++ b/lib/librte_cfgfile/rte_cfgfile_version.map
@@ -13,3 +13,11 @@ DPDK_2.0 {
local: *;
};
+
+DPDK_2.1 {
+ global:
+
+ rte_cfgfile_section_entries;
+
+ local: *;
+}
--
1.9.1
^ permalink raw reply [flat|nested] 7+ messages in thread