> -----Original Message----- > From: Allain Legacy [mailto:allain.leg...@windriver.com] > Sent: Wednesday, March 29, 2017 1:48 AM > To: Dumitrescu, Cristian <cristian.dumitre...@intel.com>; Richardson, Bruce > <bruce.richard...@intel.com> > Cc: dev@dpdk.org; yuanhan....@linux.intel.com; > thomas.monja...@6wind.com > Subject: [PATCH v3 3/6] cfgfile: add support for configurable comment > character > > The current cfgfile comment character is hardcoded to ';'. This commit a > new API to allow the user to specify which comment character to use while > parsing the file. > > This is to ease adoption by applications that have an existing > configuration file which may use a different comment character. For > instance, an application may already have a configuration file that uses > the '#' as the comment character. > > The approach of using a new API with an extensible parameters structure > was > used rather than simply adding a new argument to the existing API to allow > for additional arguments to be introduced in the future. > > Signed-off-by: Allain Legacy <allain.leg...@windriver.com> > --- > lib/librte_cfgfile/rte_cfgfile.c | 61 > ++++++++++++++++++++++++++++++++- > lib/librte_cfgfile/rte_cfgfile.h | 29 ++++++++++++++++ > test/test/test_cfgfile.c | 47 +++++++++++++++++++++++++ > test/test/test_cfgfiles/etc/sample2.ini | 12 +++++++ > 4 files changed, 148 insertions(+), 1 deletion(-) > create mode 100644 test/test/test_cfgfiles/etc/sample2.ini > > diff --git a/lib/librte_cfgfile/rte_cfgfile.c > b/lib/librte_cfgfile/rte_cfgfile.c > index 832fea829..63e34bbb0 100644 > --- a/lib/librte_cfgfile/rte_cfgfile.c > +++ b/lib/librte_cfgfile/rte_cfgfile.c > @@ -35,6 +35,7 @@ > #include <stdlib.h> > #include <string.h> > #include <ctype.h> > +#include <rte_common.h> > #include <rte_string_fns.h> > > #include "rte_cfgfile.h" > @@ -58,6 +59,25 @@ struct rte_cfgfile { > * for new entries do we add in */ > #define CFG_ALLOC_ENTRY_BATCH 16 > > +/** > + * Default cfgfile load parameters. > + */ > +static const struct rte_cfgfile_parameters default_cfgfile_params = { > + .comment_character = CFG_DEFAULT_COMMENT_CHARACTER, > +}; > + > +/** > + * Defines the list of acceptable comment characters supported by this > + * library. > + */ > +static const char valid_comment_chars[] = { > + '!', > + '#', > + '%', > + ';', > + '@' > +}; > + > static unsigned > _strip(char *str, unsigned len) > { > @@ -85,9 +105,45 @@ _strip(char *str, unsigned len) > return newlen; > } > > +static int > +rte_cfgfile_check_params(const struct rte_cfgfile_parameters *params) > +{ > + unsigned int valid_comment; > + unsigned int i; > + > + if (!params) { > + printf("Error - missing cfgfile parameters\n"); > + return -EINVAL; > + } > + > + valid_comment = 0; > + for (i = 0; i < RTE_DIM(valid_comment_chars); i++) { > + if (params->comment_character == valid_comment_chars[i]) > { > + valid_comment = 1; > + break; > + } > + } > + > + if (valid_comment == 0) { > + printf("Error - invalid comment characters %c\n", > + params->comment_character); > + return -ENOTSUP; > + } > + > + return 0; > +} > + > struct rte_cfgfile * > rte_cfgfile_load(const char *filename, int flags) > { > + return rte_cfgfile_load_with_params(filename, flags, > + &default_cfgfile_params); > +} > + > +struct rte_cfgfile * > +rte_cfgfile_load_with_params(const char *filename, int flags, > + const struct rte_cfgfile_parameters *params) > +{ > int allocated_sections = CFG_ALLOC_SECTION_BATCH; > int allocated_entries = 0; > int curr_section = -1; > @@ -96,6 +152,9 @@ rte_cfgfile_load(const char *filename, int flags) > int lineno = 0; > struct rte_cfgfile *cfg = NULL; > > + if (rte_cfgfile_check_params(params)) > + return NULL; > + > FILE *f = fopen(filename, "r"); > if (f == NULL) > return NULL; > @@ -132,7 +191,7 @@ rte_cfgfile_load(const char *filename, int flags) > "Check if line too long\n", lineno); > goto error1; > } > - pos = memchr(buffer, ';', sizeof(buffer)); > + pos = memchr(buffer, params->comment_character, > sizeof(buffer)); > if (pos != NULL) { > *pos = '\0'; > len = pos - buffer; > diff --git a/lib/librte_cfgfile/rte_cfgfile.h > b/lib/librte_cfgfile/rte_cfgfile.h > index 0e805c268..a7cd3944e 100644 > --- a/lib/librte_cfgfile/rte_cfgfile.h > +++ b/lib/librte_cfgfile/rte_cfgfile.h > @@ -66,6 +66,12 @@ struct rte_cfgfile_entry { > char value[CFG_VALUE_LEN]; /**< Value */ > }; > > +/** Configuration file operation optional arguments */ > +struct rte_cfgfile_parameters { > + char comment_character; > + /**< Config file comment character; one of '!', '#', '%', ';', '@' */
I think this comment should be placed above the structure field definition (preferable) or on the same line, but not below. > +}; > + > /**@{ cfgfile load operation flags */ > /** > * Indicates that the file supports key value entries before the first > defined > @@ -74,6 +80,9 @@ struct rte_cfgfile_entry { > #define CFG_FLAG_GLOBAL_SECTION (1 << 0) > /**@} */ > > +/** Defines the default comment character used for parsing config files. */ > +#define CFG_DEFAULT_COMMENT_CHARACTER ';' > + > /** > * Open config file > * > @@ -87,6 +96,26 @@ struct rte_cfgfile_entry { > struct rte_cfgfile *rte_cfgfile_load(const char *filename, int flags); > > /** > + * Open config file with specified optional parameters. Use @see > + * rte_cfgfile_init_parameters to setup the default parameters. > + * Please update this comment, as there is no rte_cfgfile_init() function anymore. > + * @param filename > + * Config file name > + * @param flags > + * Config file flags > + * @param params > + * Additional configuration attributes. Must be configured with default > + * values prior to invoking this API. Same here. > + * @return > + * Handle to configuration file on success, NULL otherwise > + * @param > + * > + */ > +struct rte_cfgfile *rte_cfgfile_load_with_params(const char *filename, > + int flags, const struct rte_cfgfile_parameters *params); > + > + > +/** > * Get number of sections in config file > * > * @param cfg > diff --git a/test/test/test_cfgfile.c b/test/test/test_cfgfile.c > index ad293cc89..0478de59e 100644 > --- a/test/test/test_cfgfile.c > +++ b/test/test/test_cfgfile.c > @@ -130,6 +130,30 @@ test_cfgfile_sample1(void) > } > > static int > +test_cfgfile_sample2(void) > +{ > + struct rte_cfgfile_parameters params; > + struct rte_cfgfile *cfgfile; > + int ret; > + > + /* override comment character */ > + memset(¶ms, 0, sizeof(params)); > + params.comment_character = '#'; > + > + cfgfile = rte_cfgfile_load_with_params(CFG_FILES_ETC > "/sample2.ini", 0, > + ¶ms); > + TEST_ASSERT_NOT_NULL(cfgfile, "Failed to parse sample2.ini"); > + > + ret = _test_cfgfile_sample(cfgfile); > + TEST_ASSERT_SUCCESS(ret, "Failed to validate sample file: %d", ret); > + > + ret = rte_cfgfile_close(cfgfile); > + TEST_ASSERT_SUCCESS(ret, "Failed to close cfgfile"); > + > + return 0; > +} > + > +static int > test_cfgfile_invalid_section_header(void) > { > struct rte_cfgfile *cfgfile; > @@ -141,6 +165,23 @@ test_cfgfile_invalid_section_header(void) > } > > static int > +test_cfgfile_invalid_comment(void) > +{ > + struct rte_cfgfile_parameters params; > + struct rte_cfgfile *cfgfile; > + > + /* override comment character with an invalid one */ > + memset(¶ms, 0, sizeof(params)); > + params.comment_character = '$'; > + > + cfgfile = rte_cfgfile_load_with_params(CFG_FILES_ETC > "/sample2.ini", 0, > + ¶ms); > + TEST_ASSERT_NULL(cfgfile, "Expected failured did not occur"); > + > + return 0; > +} > + > +static int > test_cfgfile_invalid_key_value_pair(void) > { > struct rte_cfgfile *cfgfile; > @@ -219,9 +260,15 @@ test_cfgfile(void) > if (test_cfgfile_sample1()) > return -1; > > + if (test_cfgfile_sample2()) > + return -1; > + > if (test_cfgfile_invalid_section_header()) > return -1; > > + if (test_cfgfile_invalid_comment()) > + return -1; > + > if (test_cfgfile_invalid_key_value_pair()) > return -1; > > diff --git a/test/test/test_cfgfiles/etc/sample2.ini > b/test/test/test_cfgfiles/etc/sample2.ini > new file mode 100644 > index 000000000..21075e976 > --- /dev/null > +++ b/test/test/test_cfgfiles/etc/sample2.ini > @@ -0,0 +1,12 @@ > +# this is a global comment > + > +[section1] > +# this is section 1 > +key1=value1 > + > +[section2] > +# this is section 2 > +#key1=value1 > +key2=value2 > +key3=value3 # this is key3 > +ignore-missing-separator > -- > 2.12.1