| From 8acdbd718b7828b5d8903a6254b2fa198b866491 Mon Sep 17 00:00:00 2001 |
| From: Florian Bezdeka <florian.bezdeka@siemens.com> |
| Date: Thu, 12 Nov 2020 11:45:28 +0000 |
| Subject: [PATCH] lib/boilerplate/iniparser: Allow building with GCC 10.2 |
| 2020101 |
| MIME-Version: 1.0 |
| Content-Type: text/plain; charset=UTF-8 |
| Content-Transfer-Encoding: 8bit |
| |
| Updating to upstream revision f858275f7f307eecba84c2f5429483f9f28007f8. |
| Upstream repository is located at [1]. |
| |
| The reason for updating was the following compiler error when trying |
| to compile with GCC 10.2 10.2.1 20201016. As it turned out the problem |
| was already addressed upstream: |
| |
| iniparser/iniparser.c: In function ‘iniparser_load’: |
| iniparser/iniparser.c:616:13: error: ‘sprintf’ arguments 3, 4 may |
| overlap destination object ‘buf’ [-Werror=restrict] |
| 616 | sprintf(tmp, "%s:%s", section, key); |
| | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| |
| I reviewed especially the API changes. Most of them are cleanups only |
| but two things should be pointed out: |
| |
| - The type of the size field of struct _dictionary_ changed from int |
| to ssize_t. The only user of this struct is |
| lib/analogy/calibration.c which uses this structure for internal |
| things only. It is never exposed to any public API so updating is |
| OK and fully backward compatible. |
| |
| - dictionary_new changed its signature |
| from dictionary_new(int size) |
| to dictionary_new(size_t size). |
| This function is not part of any public API. So updating does not |
| break backward compatibility. |
| |
| [1] https://github.com/ndevilla/iniparser |
| |
| Signed-off-by: Florian Bezdeka <florian.bezdeka@siemens.com> |
| Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com> |
| |
| [Retrieved from: |
| https://gitlab.denx.de/Xenomai/xenomai/-/commit/8acdbd718b7828b5d8903a6254b2fa198b866491] |
| Signed-off-by: Fabrice Fontaine <fontaine.fabrice@gmail.com> |
| --- |
| lib/boilerplate/iniparser/dictionary.c | 409 ++++++++++---------- |
| lib/boilerplate/iniparser/dictionary.h | 43 ++- |
| lib/boilerplate/iniparser/iniparser.c | 491 +++++++++++++++++-------- |
| lib/boilerplate/iniparser/iniparser.h | 131 +++++-- |
| 4 files changed, 646 insertions(+), 428 deletions(-) |
| |
| diff --git a/lib/boilerplate/iniparser/dictionary.c b/lib/boilerplate/iniparser/dictionary.c |
| index 5299b77ed..cb7ccd49e 100644 |
| --- a/lib/boilerplate/iniparser/dictionary.c |
| +++ b/lib/boilerplate/iniparser/dictionary.c |
| @@ -1,10 +1,8 @@ |
| /*-------------------------------------------------------------------------*/ |
| /** |
| - @file dictionary.c |
| - @author N. Devillard |
| - @date Sep 2007 |
| - @version $Revision: 1.27 $ |
| - @brief Implements a dictionary for string variables. |
| + @file dictionary.c |
| + @author N. Devillard |
| + @brief Implements a dictionary for string variables. |
| |
| This module implements a simple dictionary object, i.e. a list |
| of string/string associations. This object is useful to store e.g. |
| @@ -12,12 +10,8 @@ |
| */ |
| /*--------------------------------------------------------------------------*/ |
| |
| -/* |
| - $Id: dictionary.c,v 1.27 2007-11-23 21:39:18 ndevilla Exp $ |
| - $Revision: 1.27 $ |
| -*/ |
| /*--------------------------------------------------------------------------- |
| - Includes |
| + Includes |
| ---------------------------------------------------------------------------*/ |
| #include "dictionary.h" |
| |
| @@ -27,33 +21,18 @@ |
| #include <unistd.h> |
| |
| /** Maximum value size for integers and doubles. */ |
| -#define MAXVALSZ 1024 |
| +#define MAXVALSZ 1024 |
| |
| /** Minimal allocated number of entries in a dictionary */ |
| -#define DICTMINSZ 128 |
| +#define DICTMINSZ 128 |
| |
| /** Invalid key token */ |
| #define DICT_INVALID_KEY ((char*)-1) |
| |
| /*--------------------------------------------------------------------------- |
| - Private functions |
| + Private functions |
| ---------------------------------------------------------------------------*/ |
| |
| -/* Doubles the allocated size associated to a pointer */ |
| -/* 'size' is the current allocated size. */ |
| -static void * mem_double(void * ptr, int size) |
| -{ |
| - void * newptr ; |
| - |
| - newptr = calloc(2*size, 1); |
| - if (newptr==NULL) { |
| - return NULL ; |
| - } |
| - memcpy(newptr, ptr, size); |
| - free(ptr); |
| - return newptr ; |
| -} |
| - |
| /*-------------------------------------------------------------------------*/ |
| /** |
| @brief Duplicate a string |
| @@ -67,23 +46,68 @@ static void * mem_double(void * ptr, int size) |
| static char * xstrdup(const char * s) |
| { |
| char * t ; |
| + size_t len ; |
| if (!s) |
| return NULL ; |
| - t = malloc(strlen(s)+1) ; |
| + |
| + len = strlen(s) + 1 ; |
| + t = (char*) malloc(len) ; |
| if (t) { |
| - strcpy(t,s); |
| + memcpy(t, s, len) ; |
| } |
| return t ; |
| } |
| |
| +/*-------------------------------------------------------------------------*/ |
| +/** |
| + @brief Double the size of the dictionary |
| + @param d Dictionary to grow |
| + @return This function returns non-zero in case of failure |
| + */ |
| +/*--------------------------------------------------------------------------*/ |
| +static int dictionary_grow(dictionary * d) |
| +{ |
| + char ** new_val ; |
| + char ** new_key ; |
| + unsigned * new_hash ; |
| + |
| + new_val = (char**) calloc(d->size * 2, sizeof *d->val); |
| + new_key = (char**) calloc(d->size * 2, sizeof *d->key); |
| + new_hash = (unsigned*) calloc(d->size * 2, sizeof *d->hash); |
| + if (!new_val || !new_key || !new_hash) { |
| + /* An allocation failed, leave the dictionary unchanged */ |
| + if (new_val) |
| + free(new_val); |
| + if (new_key) |
| + free(new_key); |
| + if (new_hash) |
| + free(new_hash); |
| + return -1 ; |
| + } |
| + /* Initialize the newly allocated space */ |
| + memcpy(new_val, d->val, d->size * sizeof(char *)); |
| + memcpy(new_key, d->key, d->size * sizeof(char *)); |
| + memcpy(new_hash, d->hash, d->size * sizeof(unsigned)); |
| + /* Delete previous data */ |
| + free(d->val); |
| + free(d->key); |
| + free(d->hash); |
| + /* Actually update the dictionary */ |
| + d->size *= 2 ; |
| + d->val = new_val; |
| + d->key = new_key; |
| + d->hash = new_hash; |
| + return 0 ; |
| +} |
| + |
| /*--------------------------------------------------------------------------- |
| - Function codes |
| + Function codes |
| ---------------------------------------------------------------------------*/ |
| /*-------------------------------------------------------------------------*/ |
| /** |
| - @brief Compute the hash key for a string. |
| - @param key Character string to use for key. |
| - @return 1 unsigned int on at least 32 bits. |
| + @brief Compute the hash key for a string. |
| + @param key Character string to use for key. |
| + @return 1 unsigned int on at least 32 bits. |
| |
| This hash function has been taken from an Article in Dr Dobbs Journal. |
| This is normally a collision-free function, distributing keys evenly. |
| @@ -93,84 +117,88 @@ static char * xstrdup(const char * s) |
| /*--------------------------------------------------------------------------*/ |
| unsigned dictionary_hash(const char * key) |
| { |
| - int len ; |
| - unsigned hash ; |
| - int i ; |
| - |
| - len = strlen(key); |
| - for (hash=0, i=0 ; i<len ; i++) { |
| - hash += (unsigned)key[i] ; |
| - hash += (hash<<10); |
| - hash ^= (hash>>6) ; |
| - } |
| - hash += (hash <<3); |
| - hash ^= (hash >>11); |
| - hash += (hash <<15); |
| - return hash ; |
| + size_t len ; |
| + unsigned hash ; |
| + size_t i ; |
| + |
| + if (!key) |
| + return 0 ; |
| + |
| + len = strlen(key); |
| + for (hash=0, i=0 ; i<len ; i++) { |
| + hash += (unsigned)key[i] ; |
| + hash += (hash<<10); |
| + hash ^= (hash>>6) ; |
| + } |
| + hash += (hash <<3); |
| + hash ^= (hash >>11); |
| + hash += (hash <<15); |
| + return hash ; |
| } |
| |
| /*-------------------------------------------------------------------------*/ |
| /** |
| - @brief Create a new dictionary object. |
| - @param size Optional initial size of the dictionary. |
| - @return 1 newly allocated dictionary objet. |
| + @brief Create a new dictionary object. |
| + @param size Optional initial size of the dictionary. |
| + @return 1 newly allocated dictionary objet. |
| |
| This function allocates a new dictionary object of given size and returns |
| it. If you do not know in advance (roughly) the number of entries in the |
| dictionary, give size=0. |
| */ |
| -/*--------------------------------------------------------------------------*/ |
| -dictionary * dictionary_new(int size) |
| +/*-------------------------------------------------------------------------*/ |
| +dictionary * dictionary_new(size_t size) |
| { |
| - dictionary * d ; |
| - |
| - /* If no size was specified, allocate space for DICTMINSZ */ |
| - if (size<DICTMINSZ) size=DICTMINSZ ; |
| - |
| - if (!(d = (dictionary *)calloc(1, sizeof(dictionary)))) { |
| - return NULL; |
| - } |
| - d->size = size ; |
| - d->val = (char **)calloc(size, sizeof(char*)); |
| - d->key = (char **)calloc(size, sizeof(char*)); |
| - d->hash = (unsigned int *)calloc(size, sizeof(unsigned)); |
| - return d ; |
| + dictionary * d ; |
| + |
| + /* If no size was specified, allocate space for DICTMINSZ */ |
| + if (size<DICTMINSZ) size=DICTMINSZ ; |
| + |
| + d = (dictionary*) calloc(1, sizeof *d) ; |
| + |
| + if (d) { |
| + d->size = size ; |
| + d->val = (char**) calloc(size, sizeof *d->val); |
| + d->key = (char**) calloc(size, sizeof *d->key); |
| + d->hash = (unsigned*) calloc(size, sizeof *d->hash); |
| + } |
| + return d ; |
| } |
| |
| /*-------------------------------------------------------------------------*/ |
| /** |
| - @brief Delete a dictionary object |
| - @param d dictionary object to deallocate. |
| - @return void |
| + @brief Delete a dictionary object |
| + @param d dictionary object to deallocate. |
| + @return void |
| |
| Deallocate a dictionary object and all memory associated to it. |
| */ |
| /*--------------------------------------------------------------------------*/ |
| void dictionary_del(dictionary * d) |
| { |
| - int i ; |
| - |
| - if (d==NULL) return ; |
| - for (i=0 ; i<d->size ; i++) { |
| - if (d->key[i]!=NULL) |
| - free(d->key[i]); |
| - if (d->val[i]!=NULL) |
| - free(d->val[i]); |
| - } |
| - free(d->val); |
| - free(d->key); |
| - free(d->hash); |
| - free(d); |
| - return ; |
| + ssize_t i ; |
| + |
| + if (d==NULL) return ; |
| + for (i=0 ; i<d->size ; i++) { |
| + if (d->key[i]!=NULL) |
| + free(d->key[i]); |
| + if (d->val[i]!=NULL) |
| + free(d->val[i]); |
| + } |
| + free(d->val); |
| + free(d->key); |
| + free(d->hash); |
| + free(d); |
| + return ; |
| } |
| |
| /*-------------------------------------------------------------------------*/ |
| /** |
| - @brief Get a value from a dictionary. |
| - @param d dictionary object to search. |
| - @param key Key to look for in the dictionary. |
| + @brief Get a value from a dictionary. |
| + @param d dictionary object to search. |
| + @param key Key to look for in the dictionary. |
| @param def Default value to return if key not found. |
| - @return 1 pointer to internally allocated character string. |
| + @return 1 pointer to internally allocated character string. |
| |
| This function locates a key in a dictionary and returns a pointer to its |
| value, or the passed 'def' pointer if no such key can be found in |
| @@ -178,24 +206,24 @@ void dictionary_del(dictionary * d) |
| dictionary object, you should not try to free it or modify it. |
| */ |
| /*--------------------------------------------------------------------------*/ |
| -const char * dictionary_get(dictionary * d, const char * key, const char * def) |
| +const char * dictionary_get(const dictionary * d, const char * key, const char * def) |
| { |
| - unsigned hash ; |
| - int i ; |
| + unsigned hash ; |
| + ssize_t i ; |
| |
| - hash = dictionary_hash(key); |
| - for (i=0 ; i<d->size ; i++) { |
| + hash = dictionary_hash(key); |
| + for (i=0 ; i<d->size ; i++) { |
| if (d->key[i]==NULL) |
| continue ; |
| /* Compare hash */ |
| - if (hash==d->hash[i]) { |
| + if (hash==d->hash[i]) { |
| /* Compare string, to avoid hash collisions */ |
| if (!strcmp(key, d->key[i])) { |
| - return d->val[i] ; |
| - } |
| - } |
| - } |
| - return def ; |
| + return d->val[i] ; |
| + } |
| + } |
| + } |
| + return def ; |
| } |
| |
| /*-------------------------------------------------------------------------*/ |
| @@ -226,66 +254,57 @@ const char * dictionary_get(dictionary * d, const char * key, const char * def) |
| /*--------------------------------------------------------------------------*/ |
| int dictionary_set(dictionary * d, const char * key, const char * val) |
| { |
| - int i ; |
| - unsigned hash ; |
| - |
| - if (d==NULL || key==NULL) return -1 ; |
| - |
| - /* Compute hash for this key */ |
| - hash = dictionary_hash(key) ; |
| - /* Find if value is already in dictionary */ |
| - if (d->n>0) { |
| - for (i=0 ; i<d->size ; i++) { |
| + ssize_t i ; |
| + unsigned hash ; |
| + |
| + if (d==NULL || key==NULL) return -1 ; |
| + |
| + /* Compute hash for this key */ |
| + hash = dictionary_hash(key) ; |
| + /* Find if value is already in dictionary */ |
| + if (d->n>0) { |
| + for (i=0 ; i<d->size ; i++) { |
| if (d->key[i]==NULL) |
| continue ; |
| - if (hash==d->hash[i]) { /* Same hash value */ |
| - if (!strcmp(key, d->key[i])) { /* Same key */ |
| - /* Found a value: modify and return */ |
| - if (d->val[i]!=NULL) |
| - free(d->val[i]); |
| - d->val[i] = val ? xstrdup(val) : NULL ; |
| + if (hash==d->hash[i]) { /* Same hash value */ |
| + if (!strcmp(key, d->key[i])) { /* Same key */ |
| + /* Found a value: modify and return */ |
| + if (d->val[i]!=NULL) |
| + free(d->val[i]); |
| + d->val[i] = (val ? xstrdup(val) : NULL); |
| /* Value has been modified: return */ |
| - return 0 ; |
| - } |
| - } |
| - } |
| - } |
| - /* Add a new value */ |
| - /* See if dictionary needs to grow */ |
| - if (d->n==d->size) { |
| - |
| - /* Reached maximum size: reallocate dictionary */ |
| - d->val = (char **)mem_double(d->val, d->size * sizeof(char*)) ; |
| - d->key = (char **)mem_double(d->key, d->size * sizeof(char*)) ; |
| - d->hash = (unsigned int *)mem_double(d->hash, d->size * sizeof(unsigned)) ; |
| - if ((d->val==NULL) || (d->key==NULL) || (d->hash==NULL)) { |
| - /* Cannot grow dictionary */ |
| - return -1 ; |
| + return 0 ; |
| + } |
| + } |
| } |
| - /* Double size */ |
| - d->size *= 2 ; |
| - } |
| + } |
| + /* Add a new value */ |
| + /* See if dictionary needs to grow */ |
| + if (d->n==d->size) { |
| + /* Reached maximum size: reallocate dictionary */ |
| + if (dictionary_grow(d) != 0) |
| + return -1; |
| + } |
| |
| - /* Insert key in the first empty slot */ |
| - for (i=0 ; i<d->size ; i++) { |
| - if (d->key[i]==NULL) { |
| - /* Add key here */ |
| - break ; |
| - } |
| + /* Insert key in the first empty slot. Start at d->n and wrap at |
| + d->size. Because d->n < d->size this will necessarily |
| + terminate. */ |
| + for (i=d->n ; d->key[i] ; ) { |
| + if(++i == d->size) i = 0; |
| } |
| - /* Copy key */ |
| - d->key[i] = xstrdup(key); |
| - d->val[i] = val ? xstrdup(val) : NULL ; |
| - d->hash[i] = hash; |
| - d->n ++ ; |
| - return 0 ; |
| + /* Copy key */ |
| + d->key[i] = xstrdup(key); |
| + d->val[i] = (val ? xstrdup(val) : NULL) ; |
| + d->hash[i] = hash; |
| + d->n ++ ; |
| + return 0 ; |
| } |
| |
| /*-------------------------------------------------------------------------*/ |
| /** |
| - @brief Delete a key in a dictionary |
| - @param d dictionary object to modify. |
| - @param key Key to remove. |
| + @brief Delete a key in a dictionary |
| + @param d dictionary object to modify. |
| + @param key Key to remove. |
| @return void |
| |
| This function deletes a key in a dictionary. Nothing is done if the |
| @@ -294,26 +313,26 @@ int dictionary_set(dictionary * d, const char * key, const char * val) |
| /*--------------------------------------------------------------------------*/ |
| void dictionary_unset(dictionary * d, const char * key) |
| { |
| - unsigned hash ; |
| - int i ; |
| + unsigned hash ; |
| + ssize_t i ; |
| |
| - if (key == NULL) { |
| - return; |
| - } |
| + if (key == NULL || d == NULL) { |
| + return; |
| + } |
| |
| - hash = dictionary_hash(key); |
| - for (i=0 ; i<d->size ; i++) { |
| + hash = dictionary_hash(key); |
| + for (i=0 ; i<d->size ; i++) { |
| if (d->key[i]==NULL) |
| continue ; |
| /* Compare hash */ |
| - if (hash==d->hash[i]) { |
| + if (hash==d->hash[i]) { |
| /* Compare string, to avoid hash collisions */ |
| if (!strcmp(key, d->key[i])) { |
| /* Found key */ |
| break ; |
| - } |
| - } |
| - } |
| + } |
| + } |
| + } |
| if (i>=d->size) |
| /* Key not found */ |
| return ; |
| @@ -331,75 +350,31 @@ void dictionary_unset(dictionary * d, const char * key) |
| |
| /*-------------------------------------------------------------------------*/ |
| /** |
| - @brief Dump a dictionary to an opened file pointer. |
| - @param d Dictionary to dump |
| - @param out Opened file pointer. |
| - @return void |
| + @brief Dump a dictionary to an opened file pointer. |
| + @param d Dictionary to dump |
| + @param f Opened file pointer. |
| + @return void |
| |
| Dumps a dictionary onto an opened file pointer. Key pairs are printed out |
| as @c [Key]=[Value], one per line. It is Ok to provide stdout or stderr as |
| output file pointers. |
| */ |
| /*--------------------------------------------------------------------------*/ |
| -void dictionary_dump(dictionary * d, FILE * out) |
| +void dictionary_dump(const dictionary * d, FILE * out) |
| { |
| - int i ; |
| - |
| - if (d==NULL || out==NULL) return ; |
| - if (d->n<1) { |
| - fprintf(out, "empty dictionary\n"); |
| - return ; |
| - } |
| - for (i=0 ; i<d->size ; i++) { |
| + ssize_t i ; |
| + |
| + if (d==NULL || out==NULL) return ; |
| + if (d->n<1) { |
| + fprintf(out, "empty dictionary\n"); |
| + return ; |
| + } |
| + for (i=0 ; i<d->size ; i++) { |
| if (d->key[i]) { |
| fprintf(out, "%20s\t[%s]\n", |
| d->key[i], |
| d->val[i] ? d->val[i] : "UNDEF"); |
| } |
| - } |
| - return ; |
| -} |
| - |
| - |
| -/* Test code */ |
| -#ifdef TESTDIC |
| -#define NVALS 20000 |
| -int main(int argc, char *argv[]) |
| -{ |
| - dictionary * d ; |
| - char * val ; |
| - int i ; |
| - char cval[90] ; |
| - |
| - /* Allocate dictionary */ |
| - printf("allocating...\n"); |
| - d = dictionary_new(0); |
| - |
| - /* Set values in dictionary */ |
| - printf("setting %d values...\n", NVALS); |
| - for (i=0 ; i<NVALS ; i++) { |
| - sprintf(cval, "%04d", i); |
| - dictionary_set(d, cval, "salut"); |
| - } |
| - printf("getting %d values...\n", NVALS); |
| - for (i=0 ; i<NVALS ; i++) { |
| - sprintf(cval, "%04d", i); |
| - val = dictionary_get(d, cval, DICT_INVALID_KEY); |
| - if (val==DICT_INVALID_KEY) { |
| - printf("cannot get value for key [%s]\n", cval); |
| - } |
| - } |
| - printf("unsetting %d values...\n", NVALS); |
| - for (i=0 ; i<NVALS ; i++) { |
| - sprintf(cval, "%04d", i); |
| - dictionary_unset(d, cval); |
| - } |
| - if (d->n != 0) { |
| - printf("error deleting values\n"); |
| } |
| - printf("deallocating...\n"); |
| - dictionary_del(d); |
| - return 0 ; |
| + return ; |
| } |
| -#endif |
| -/* vim: set ts=4 et sw=4 tw=75 */ |
| diff --git a/lib/boilerplate/iniparser/dictionary.h b/lib/boilerplate/iniparser/dictionary.h |
| index fa4dcb727..d04b6ce71 100644 |
| --- a/lib/boilerplate/iniparser/dictionary.h |
| +++ b/lib/boilerplate/iniparser/dictionary.h |
| @@ -3,8 +3,6 @@ |
| /** |
| @file dictionary.h |
| @author N. Devillard |
| - @date Sep 2007 |
| - @version $Revision: 1.12 $ |
| @brief Implements a dictionary for string variables. |
| |
| This module implements a simple dictionary object, i.e. a list |
| @@ -13,18 +11,11 @@ |
| */ |
| /*--------------------------------------------------------------------------*/ |
| |
| -/* |
| - $Id: dictionary.h,v 1.12 2007-11-23 21:37:00 ndevilla Exp $ |
| - $Author: ndevilla $ |
| - $Date: 2007-11-23 21:37:00 $ |
| - $Revision: 1.12 $ |
| -*/ |
| - |
| #ifndef _DICTIONARY_H_ |
| #define _DICTIONARY_H_ |
| |
| /*--------------------------------------------------------------------------- |
| - Includes |
| + Includes |
| ---------------------------------------------------------------------------*/ |
| |
| #include <stdio.h> |
| @@ -32,14 +23,18 @@ |
| #include <string.h> |
| #include <unistd.h> |
| |
| +#ifdef __cplusplus |
| +extern "C" { |
| +#endif |
| + |
| /*--------------------------------------------------------------------------- |
| - New types |
| + New types |
| ---------------------------------------------------------------------------*/ |
| |
| |
| /*-------------------------------------------------------------------------*/ |
| /** |
| - @brief Dictionary object |
| + @brief Dictionary object |
| |
| This object contains a list of string/string associations. Each |
| association is identified by a unique string key. Looking up values |
| @@ -48,16 +43,16 @@ |
| */ |
| /*-------------------------------------------------------------------------*/ |
| typedef struct _dictionary_ { |
| - int n ; /** Number of entries in dictionary */ |
| - int size ; /** Storage size */ |
| - char ** val ; /** List of string values */ |
| - char ** key ; /** List of string keys */ |
| - unsigned * hash ; /** List of hash values for keys */ |
| + int n ; /** Number of entries in dictionary */ |
| + ssize_t size ; /** Storage size */ |
| + char ** val ; /** List of string values */ |
| + char ** key ; /** List of string keys */ |
| + unsigned * hash ; /** List of hash values for keys */ |
| } dictionary ; |
| |
| |
| /*--------------------------------------------------------------------------- |
| - Function prototypes |
| + Function prototypes |
| ---------------------------------------------------------------------------*/ |
| |
| /*-------------------------------------------------------------------------*/ |
| @@ -85,7 +80,7 @@ unsigned dictionary_hash(const char * key); |
| dictionary, give size=0. |
| */ |
| /*--------------------------------------------------------------------------*/ |
| -dictionary * dictionary_new(int size); |
| +dictionary * dictionary_new(size_t size); |
| |
| /*-------------------------------------------------------------------------*/ |
| /** |
| @@ -112,7 +107,7 @@ void dictionary_del(dictionary * vd); |
| dictionary object, you should not try to free it or modify it. |
| */ |
| /*--------------------------------------------------------------------------*/ |
| -const char * dictionary_get(dictionary * d, const char * key, const char * def); |
| +const char * dictionary_get(const dictionary * d, const char * key, const char * def); |
| |
| |
| /*-------------------------------------------------------------------------*/ |
| @@ -161,7 +156,7 @@ void dictionary_unset(dictionary * d, const char * key); |
| /** |
| @brief Dump a dictionary to an opened file pointer. |
| @param d Dictionary to dump |
| - @param out Opened file pointer. |
| + @param f Opened file pointer. |
| @return void |
| |
| Dumps a dictionary onto an opened file pointer. Key pairs are printed out |
| @@ -169,6 +164,10 @@ void dictionary_unset(dictionary * d, const char * key); |
| output file pointers. |
| */ |
| /*--------------------------------------------------------------------------*/ |
| -void dictionary_dump(dictionary * d, FILE * out); |
| +void dictionary_dump(const dictionary * d, FILE * out); |
| + |
| +#ifdef __cplusplus |
| +} |
| +#endif |
| |
| #endif |
| diff --git a/lib/boilerplate/iniparser/iniparser.c b/lib/boilerplate/iniparser/iniparser.c |
| index 5b2094a00..f1d165896 100644 |
| --- a/lib/boilerplate/iniparser/iniparser.c |
| +++ b/lib/boilerplate/iniparser/iniparser.c |
| @@ -3,19 +3,12 @@ |
| /** |
| @file iniparser.c |
| @author N. Devillard |
| - @date Sep 2007 |
| - @version 3.0 |
| @brief Parser for ini files. |
| */ |
| /*--------------------------------------------------------------------------*/ |
| -/* |
| - $Id: iniparser.c,v 2.18 2008-01-03 18:35:39 ndevilla Exp $ |
| - $Revision: 2.18 $ |
| - $Date: 2008-01-03 18:35:39 $ |
| -*/ |
| /*---------------------------- Includes ------------------------------------*/ |
| #include <ctype.h> |
| -#include <errno.h> |
| +#include <stdarg.h> |
| #include "iniparser.h" |
| |
| /*---------------------------- Defines -------------------------------------*/ |
| @@ -39,65 +32,115 @@ typedef enum _line_status_ { |
| |
| /*-------------------------------------------------------------------------*/ |
| /** |
| - @brief Convert a string to lowercase. |
| - @param s String to convert. |
| - @return ptr to statically allocated string. |
| - |
| - This function returns a pointer to a statically allocated string |
| - containing a lowercased version of the input string. Do not free |
| - or modify the returned string! Since the returned string is statically |
| - allocated, it will be modified at each function call (not re-entrant). |
| + @brief Convert a string to lowercase. |
| + @param in String to convert. |
| + @param out Output buffer. |
| + @param len Size of the out buffer. |
| + @return ptr to the out buffer or NULL if an error occured. |
| + |
| + This function convert a string into lowercase. |
| + At most len - 1 elements of the input string will be converted. |
| */ |
| /*--------------------------------------------------------------------------*/ |
| - |
| -static char strbuf[ASCIILINESZ+1]; |
| - |
| -static char * strlwc(const char * s) |
| +static const char * strlwc(const char * in, char *out, unsigned len) |
| { |
| - int i ; |
| + unsigned i ; |
| |
| - if (s==NULL) return NULL ; |
| - memset(strbuf, 0, ASCIILINESZ+1); |
| + if (in==NULL || out == NULL || len==0) return NULL ; |
| i=0 ; |
| - while (s[i] && i<ASCIILINESZ) { |
| - strbuf[i] = (char)tolower((int)s[i]); |
| + while (in[i] != '\0' && i < len-1) { |
| + out[i] = (char)tolower((int)in[i]); |
| i++ ; |
| } |
| - strbuf[ASCIILINESZ]=(char)0; |
| - return strbuf ; |
| + out[i] = '\0'; |
| + return out ; |
| +} |
| + |
| +/*-------------------------------------------------------------------------*/ |
| +/** |
| + @brief Duplicate a string |
| + @param s String to duplicate |
| + @return Pointer to a newly allocated string, to be freed with free() |
| + |
| + This is a replacement for strdup(). This implementation is provided |
| + for systems that do not have it. |
| + */ |
| +/*--------------------------------------------------------------------------*/ |
| +static char * xstrdup(const char * s) |
| +{ |
| + char * t ; |
| + size_t len ; |
| + if (!s) |
| + return NULL ; |
| + |
| + len = strlen(s) + 1 ; |
| + t = (char*) malloc(len) ; |
| + if (t) { |
| + memcpy(t, s, len) ; |
| + } |
| + return t ; |
| +} |
| + |
| +/*-------------------------------------------------------------------------*/ |
| +/** |
| + @brief Remove blanks at the beginning and the end of a string. |
| + @param str String to parse and alter. |
| + @return unsigned New size of the string. |
| + */ |
| +/*--------------------------------------------------------------------------*/ |
| +static unsigned strstrip(char * s) |
| +{ |
| + char *last = NULL ; |
| + char *dest = s; |
| + |
| + if (s==NULL) return 0; |
| + |
| + last = s + strlen(s); |
| + while (isspace((int)*s) && *s) s++; |
| + while (last > s) { |
| + if (!isspace((int)*(last-1))) |
| + break ; |
| + last -- ; |
| + } |
| + *last = (char)0; |
| + |
| + memmove(dest,s,last - s + 1); |
| + return last - s; |
| +} |
| + |
| +/*-------------------------------------------------------------------------*/ |
| +/** |
| + @brief Default error callback for iniparser: wraps `fprintf(stderr, ...)`. |
| + */ |
| +/*--------------------------------------------------------------------------*/ |
| +static int default_error_callback(const char *format, ...) |
| +{ |
| + int ret; |
| + va_list argptr; |
| + va_start(argptr, format); |
| + ret = vfprintf(stderr, format, argptr); |
| + va_end(argptr); |
| + return ret; |
| } |
| |
| +static int (*iniparser_error_callback)(const char*, ...) = default_error_callback; |
| + |
| /*-------------------------------------------------------------------------*/ |
| /** |
| - @brief Remove blanks at the beginning and the end of a string. |
| - @param s String to parse. |
| - @return ptr to statically allocated string. |
| - |
| - This function returns a pointer to a statically allocated string, |
| - which is identical to the input string, except that all blank |
| - characters at the end and the beg. of the string have been removed. |
| - Do not free or modify the returned string! Since the returned string |
| - is statically allocated, it will be modified at each function call |
| - (not re-entrant). |
| + @brief Configure a function to receive the error messages. |
| + @param errback Function to call. |
| + |
| + By default, the error will be printed on stderr. If a null pointer is passed |
| + as errback the error callback will be switched back to default. |
| */ |
| /*--------------------------------------------------------------------------*/ |
| -static char * strstrip(const char * s) |
| +void iniparser_set_error_callback(int (*errback)(const char *, ...)) |
| { |
| - char * last ; |
| - |
| - if (s==NULL) return NULL ; |
| - |
| - while (isspace((int)*s) && *s) s++; |
| - memset(strbuf, 0, ASCIILINESZ+1); |
| - strcpy(strbuf, s); |
| - last = strbuf + strlen(strbuf); |
| - while (last > strbuf) { |
| - if (!isspace((int)*(last-1))) |
| - break ; |
| - last -- ; |
| - } |
| - *last = (char)0; |
| - return (char*)strbuf ; |
| + if (errback) { |
| + iniparser_error_callback = errback; |
| + } else { |
| + iniparser_error_callback = default_error_callback; |
| + } |
| } |
| |
| /*-------------------------------------------------------------------------*/ |
| @@ -118,7 +161,7 @@ static char * strstrip(const char * s) |
| This function returns -1 in case of error. |
| */ |
| /*--------------------------------------------------------------------------*/ |
| -int iniparser_getnsec(dictionary * d) |
| +int iniparser_getnsec(const dictionary * d) |
| { |
| int i ; |
| int nsec ; |
| @@ -149,7 +192,7 @@ int iniparser_getnsec(dictionary * d) |
| This function returns NULL in case of error. |
| */ |
| /*--------------------------------------------------------------------------*/ |
| -const char * iniparser_getsecname(dictionary * d, int n) |
| +const char * iniparser_getsecname(const dictionary * d, int n) |
| { |
| int i ; |
| int foundsec ; |
| @@ -184,7 +227,7 @@ const char * iniparser_getsecname(dictionary * d, int n) |
| purposes mostly. |
| */ |
| /*--------------------------------------------------------------------------*/ |
| -void iniparser_dump(dictionary * d, FILE * f) |
| +void iniparser_dump(const dictionary * d, FILE * f) |
| { |
| int i ; |
| |
| @@ -212,13 +255,11 @@ void iniparser_dump(dictionary * d, FILE * f) |
| It is Ok to specify @c stderr or @c stdout as output files. |
| */ |
| /*--------------------------------------------------------------------------*/ |
| -void iniparser_dump_ini(dictionary * d, FILE * f) |
| +void iniparser_dump_ini(const dictionary * d, FILE * f) |
| { |
| - int i, j ; |
| - char keym[ASCIILINESZ+1]; |
| - int nsec ; |
| - const char * secname ; |
| - int seclen ; |
| + int i ; |
| + int nsec ; |
| + const char * secname ; |
| |
| if (d==NULL || f==NULL) return ; |
| |
| @@ -234,24 +275,126 @@ void iniparser_dump_ini(dictionary * d, FILE * f) |
| } |
| for (i=0 ; i<nsec ; i++) { |
| secname = iniparser_getsecname(d, i) ; |
| - seclen = (int)strlen(secname); |
| - fprintf(f, "\n[%s]\n", secname); |
| - sprintf(keym, "%s:", secname); |
| - for (j=0 ; j<d->size ; j++) { |
| - if (d->key[j]==NULL) |
| - continue ; |
| - if (!strncmp(d->key[j], keym, seclen+1)) { |
| - fprintf(f, |
| - "%-30s = %s\n", |
| - d->key[j]+seclen+1, |
| - d->val[j] ? d->val[j] : ""); |
| - } |
| + iniparser_dumpsection_ini(d, secname, f); |
| + } |
| + fprintf(f, "\n"); |
| + return ; |
| +} |
| + |
| +/*-------------------------------------------------------------------------*/ |
| +/** |
| + @brief Save a dictionary section to a loadable ini file |
| + @param d Dictionary to dump |
| + @param s Section name of dictionary to dump |
| + @param f Opened file pointer to dump to |
| + @return void |
| + |
| + This function dumps a given section of a given dictionary into a loadable ini |
| + file. It is Ok to specify @c stderr or @c stdout as output files. |
| + */ |
| +/*--------------------------------------------------------------------------*/ |
| +void iniparser_dumpsection_ini(const dictionary * d, const char * s, FILE * f) |
| +{ |
| + int j ; |
| + char keym[ASCIILINESZ+1]; |
| + int seclen ; |
| + |
| + if (d==NULL || f==NULL) return ; |
| + if (! iniparser_find_entry(d, s)) return ; |
| + |
| + seclen = (int)strlen(s); |
| + fprintf(f, "\n[%s]\n", s); |
| + sprintf(keym, "%s:", s); |
| + for (j=0 ; j<d->size ; j++) { |
| + if (d->key[j]==NULL) |
| + continue ; |
| + if (!strncmp(d->key[j], keym, seclen+1)) { |
| + fprintf(f, |
| + "%-30s = %s\n", |
| + d->key[j]+seclen+1, |
| + d->val[j] ? d->val[j] : ""); |
| } |
| } |
| fprintf(f, "\n"); |
| return ; |
| } |
| |
| +/*-------------------------------------------------------------------------*/ |
| +/** |
| + @brief Get the number of keys in a section of a dictionary. |
| + @param d Dictionary to examine |
| + @param s Section name of dictionary to examine |
| + @return Number of keys in section |
| + */ |
| +/*--------------------------------------------------------------------------*/ |
| +int iniparser_getsecnkeys(const dictionary * d, const char * s) |
| +{ |
| + int seclen, nkeys ; |
| + char keym[ASCIILINESZ+1]; |
| + int j ; |
| + |
| + nkeys = 0; |
| + |
| + if (d==NULL) return nkeys; |
| + if (! iniparser_find_entry(d, s)) return nkeys; |
| + |
| + seclen = (int)strlen(s); |
| + strlwc(s, keym, sizeof(keym)); |
| + keym[seclen] = ':'; |
| + |
| + for (j=0 ; j<d->size ; j++) { |
| + if (d->key[j]==NULL) |
| + continue ; |
| + if (!strncmp(d->key[j], keym, seclen+1)) |
| + nkeys++; |
| + } |
| + |
| + return nkeys; |
| + |
| +} |
| + |
| +/*-------------------------------------------------------------------------*/ |
| +/** |
| + @brief Get the number of keys in a section of a dictionary. |
| + @param d Dictionary to examine |
| + @param s Section name of dictionary to examine |
| + @param keys Already allocated array to store the keys in |
| + @return The pointer passed as `keys` argument or NULL in case of error |
| + |
| + This function queries a dictionary and finds all keys in a given section. |
| + The keys argument should be an array of pointers which size has been |
| + determined by calling `iniparser_getsecnkeys` function prior to this one. |
| + |
| + Each pointer in the returned char pointer-to-pointer is pointing to |
| + a string allocated in the dictionary; do not free or modify them. |
| + */ |
| +/*--------------------------------------------------------------------------*/ |
| +const char ** iniparser_getseckeys(const dictionary * d, const char * s, const char ** keys) |
| +{ |
| + int i, j, seclen ; |
| + char keym[ASCIILINESZ+1]; |
| + |
| + if (d==NULL || keys==NULL) return NULL; |
| + if (! iniparser_find_entry(d, s)) return NULL; |
| + |
| + seclen = (int)strlen(s); |
| + strlwc(s, keym, sizeof(keym)); |
| + keym[seclen] = ':'; |
| + |
| + i = 0; |
| + |
| + for (j=0 ; j<d->size ; j++) { |
| + if (d->key[j]==NULL) |
| + continue ; |
| + if (!strncmp(d->key[j], keym, seclen+1)) { |
| + keys[i] = d->key[j]; |
| + i++; |
| + } |
| + } |
| + |
| + return keys; |
| +} |
| + |
| /*-------------------------------------------------------------------------*/ |
| /** |
| @brief Get the string associated to a key |
| @@ -267,24 +410,27 @@ void iniparser_dump_ini(dictionary * d, FILE * f) |
| the dictionary, do not free or modify it. |
| */ |
| /*--------------------------------------------------------------------------*/ |
| -const char * iniparser_getstring(dictionary * d, const char * key, const char * def) |
| +const char * iniparser_getstring(const dictionary * d, const char * key, const char * def) |
| { |
| - char * lc_key ; |
| + const char * lc_key ; |
| + const char * sval ; |
| + char tmp_str[ASCIILINESZ+1]; |
| |
| if (d==NULL || key==NULL) |
| return def ; |
| |
| - lc_key = strlwc(key); |
| - return dictionary_get(d, lc_key, def); |
| + lc_key = strlwc(key, tmp_str, sizeof(tmp_str)); |
| + sval = dictionary_get(d, lc_key, def); |
| + return sval ; |
| } |
| |
| /*-------------------------------------------------------------------------*/ |
| /** |
| - @brief Get the string associated to a key, convert to an int |
| + @brief Get the string associated to a key, convert to an long int |
| @param d Dictionary to search |
| @param key Key string to look for |
| @param notfound Value to return in case of error |
| - @return integer |
| + @return long integer |
| |
| This function queries a dictionary for a key. A key as read from an |
| ini file is given as "section:key". If the key cannot be found, |
| @@ -305,13 +451,46 @@ const char * iniparser_getstring(dictionary * d, const char * key, const char * |
| Credits: Thanks to A. Becker for suggesting strtol() |
| */ |
| /*--------------------------------------------------------------------------*/ |
| -int iniparser_getint(dictionary * d, const char * key, int notfound) |
| +long int iniparser_getlongint(const dictionary * d, const char * key, long int notfound) |
| { |
| - const char * str ; |
| + const char * str ; |
| |
| str = iniparser_getstring(d, key, INI_INVALID_KEY); |
| if (str==INI_INVALID_KEY) return notfound ; |
| - return (int)strtol(str, NULL, 0); |
| + return strtol(str, NULL, 0); |
| +} |
| + |
| + |
| +/*-------------------------------------------------------------------------*/ |
| +/** |
| + @brief Get the string associated to a key, convert to an int |
| + @param d Dictionary to search |
| + @param key Key string to look for |
| + @param notfound Value to return in case of error |
| + @return integer |
| + |
| + This function queries a dictionary for a key. A key as read from an |
| + ini file is given as "section:key". If the key cannot be found, |
| + the notfound value is returned. |
| + |
| + Supported values for integers include the usual C notation |
| + so decimal, octal (starting with 0) and hexadecimal (starting with 0x) |
| + are supported. Examples: |
| + |
| + "42" -> 42 |
| + "042" -> 34 (octal -> decimal) |
| + "0x42" -> 66 (hexa -> decimal) |
| + |
| + Warning: the conversion may overflow in various ways. Conversion is |
| + totally outsourced to strtol(), see the associated man page for overflow |
| + handling. |
| + |
| + Credits: Thanks to A. Becker for suggesting strtol() |
| + */ |
| +/*--------------------------------------------------------------------------*/ |
| +int iniparser_getint(const dictionary * d, const char * key, int notfound) |
| +{ |
| + return (int)iniparser_getlongint(d, key, notfound); |
| } |
| |
| /*-------------------------------------------------------------------------*/ |
| @@ -327,9 +506,9 @@ int iniparser_getint(dictionary * d, const char * key, int notfound) |
| the notfound value is returned. |
| */ |
| /*--------------------------------------------------------------------------*/ |
| -double iniparser_getdouble(dictionary * d, const char * key, double notfound) |
| +double iniparser_getdouble(const dictionary * d, const char * key, double notfound) |
| { |
| - const char * str ; |
| + const char * str ; |
| |
| str = iniparser_getstring(d, key, INI_INVALID_KEY); |
| if (str==INI_INVALID_KEY) return notfound ; |
| @@ -368,10 +547,10 @@ double iniparser_getdouble(dictionary * d, const char * key, double notfound) |
| necessarily have to be 0 or 1. |
| */ |
| /*--------------------------------------------------------------------------*/ |
| -int iniparser_getboolean(dictionary * d, const char * key, int notfound) |
| +int iniparser_getboolean(const dictionary * d, const char * key, int notfound) |
| { |
| - const char * c ; |
| - int ret ; |
| + int ret ; |
| + const char * c ; |
| |
| c = iniparser_getstring(d, key, INI_INVALID_KEY); |
| if (c==INI_INVALID_KEY) return notfound ; |
| @@ -397,10 +576,7 @@ int iniparser_getboolean(dictionary * d, const char * key, int notfound) |
| of querying for the presence of sections in a dictionary. |
| */ |
| /*--------------------------------------------------------------------------*/ |
| -int iniparser_find_entry( |
| - dictionary * ini, |
| - const char * entry |
| -) |
| +int iniparser_find_entry(const dictionary * ini, const char * entry) |
| { |
| int found=0 ; |
| if (iniparser_getstring(ini, entry, INI_INVALID_KEY)!=INI_INVALID_KEY) { |
| @@ -418,13 +594,14 @@ int iniparser_find_entry( |
| @return int 0 if Ok, -1 otherwise. |
| |
| If the given entry can be found in the dictionary, it is modified to |
| - contain the provided value. If it cannot be found, -1 is returned. |
| + contain the provided value. If it cannot be found, the entry is created. |
| It is Ok to set val to NULL. |
| */ |
| /*--------------------------------------------------------------------------*/ |
| int iniparser_set(dictionary * ini, const char * entry, const char * val) |
| { |
| - return dictionary_set(ini, strlwc(entry), val) ; |
| + char tmp_str[ASCIILINESZ+1]; |
| + return dictionary_set(ini, strlwc(entry, tmp_str, sizeof(tmp_str)), val) ; |
| } |
| |
| /*-------------------------------------------------------------------------*/ |
| @@ -439,12 +616,13 @@ int iniparser_set(dictionary * ini, const char * entry, const char * val) |
| /*--------------------------------------------------------------------------*/ |
| void iniparser_unset(dictionary * ini, const char * entry) |
| { |
| - dictionary_unset(ini, strlwc(entry)); |
| + char tmp_str[ASCIILINESZ+1]; |
| + dictionary_unset(ini, strlwc(entry, tmp_str, sizeof(tmp_str))); |
| } |
| |
| /*-------------------------------------------------------------------------*/ |
| /** |
| - @brief Load a single line from an INI file |
| + @brief Load a single line from an INI file |
| @param input_line Input line, may be concatenated multi-line input |
| @param section Output space to store section |
| @param key Output space to store key |
| @@ -457,34 +635,39 @@ static line_status iniparser_line( |
| char * section, |
| char * key, |
| char * value) |
| -{ |
| +{ |
| line_status sta ; |
| - char line[ASCIILINESZ+1]; |
| - int len ; |
| + char * line = NULL; |
| + size_t len ; |
| |
| - strcpy(line, strstrip(input_line)); |
| - len = (int)strlen(line); |
| + line = xstrdup(input_line); |
| + len = strstrip(line); |
| |
| sta = LINE_UNPROCESSED ; |
| if (len<1) { |
| /* Empty line */ |
| sta = LINE_EMPTY ; |
| - } else if (line[0]=='#') { |
| + } else if (line[0]=='#' || line[0]==';') { |
| /* Comment line */ |
| - sta = LINE_COMMENT ; |
| + sta = LINE_COMMENT ; |
| } else if (line[0]=='[' && line[len-1]==']') { |
| /* Section name */ |
| sscanf(line, "[%[^]]", section); |
| - strcpy(section, strstrip(section)); |
| - strcpy(section, strlwc(section)); |
| + strstrip(section); |
| + strlwc(section, section, len); |
| sta = LINE_SECTION ; |
| } else if (sscanf (line, "%[^=] = \"%[^\"]\"", key, value) == 2 |
| - || sscanf (line, "%[^=] = '%[^\']'", key, value) == 2 |
| - || sscanf (line, "%[^=] = %[^;#]", key, value) == 2) { |
| - /* Usual key=value, with or without comments */ |
| - strcpy(key, strstrip(key)); |
| - strcpy(key, strlwc(key)); |
| - strcpy(value, strstrip(value)); |
| + || sscanf (line, "%[^=] = '%[^\']'", key, value) == 2) { |
| + /* Usual key=value with quotes, with or without comments */ |
| + strstrip(key); |
| + strlwc(key, key, len); |
| + /* Don't strip spaces from values surrounded with quotes */ |
| + sta = LINE_VALUE ; |
| + } else if (sscanf (line, "%[^=] = %[^;#]", key, value) == 2) { |
| + /* Usual key=value without quotes, with or without comments */ |
| + strstrip(key); |
| + strlwc(key, key, len); |
| + strstrip(value); |
| /* |
| * sscanf cannot handle '' or "" as empty values |
| * this is done here |
| @@ -501,14 +684,16 @@ static line_status iniparser_line( |
| * key=; |
| * key=# |
| */ |
| - strcpy(key, strstrip(key)); |
| - strcpy(key, strlwc(key)); |
| + strstrip(key); |
| + strlwc(key, key, len); |
| value[0]=0 ; |
| sta = LINE_VALUE ; |
| } else { |
| /* Generate syntax error */ |
| sta = LINE_ERROR ; |
| } |
| + |
| + free(line); |
| return sta ; |
| } |
| |
| @@ -528,44 +713,33 @@ static line_status iniparser_line( |
| /*--------------------------------------------------------------------------*/ |
| dictionary * iniparser_load(const char * ininame) |
| { |
| - char *buf; |
| FILE * in ; |
| |
| - char *line; |
| - char *section; |
| - char *key; |
| - char *tmp; |
| - char *val; |
| + char line [ASCIILINESZ+1] ; |
| + char section [ASCIILINESZ+1] ; |
| + char key [ASCIILINESZ+1] ; |
| + char tmp [(ASCIILINESZ * 2) + 2] ; |
| + char val [ASCIILINESZ+1] ; |
| |
| int last=0 ; |
| int len ; |
| int lineno=0 ; |
| int errs=0; |
| - int ret; |
| + int mem_err=0; |
| |
| dictionary * dict ; |
| |
| - if ((in=fopen(ininame, "r"))==NULL) |
| + if ((in=fopen(ininame, "r"))==NULL) { |
| + iniparser_error_callback("iniparser: cannot open %s\n", ininame); |
| return NULL ; |
| + } |
| |
| dict = dictionary_new(0) ; |
| if (!dict) { |
| fclose(in); |
| - errno = ENOMEM; |
| return NULL ; |
| } |
| |
| - buf = malloc((ASCIILINESZ+1) * 5); |
| - if (buf == NULL) { |
| - errno = -ENOMEM; |
| - return NULL; |
| - } |
| - line = buf; |
| - section = line + ASCIILINESZ + 1; |
| - key = section + ASCIILINESZ + 1; |
| - tmp = key + ASCIILINESZ + 1; |
| - val = tmp + ASCIILINESZ + 1; |
| - |
| memset(line, 0, ASCIILINESZ); |
| memset(section, 0, ASCIILINESZ); |
| memset(key, 0, ASCIILINESZ); |
| @@ -575,18 +749,16 @@ dictionary * iniparser_load(const char * ininame) |
| while (fgets(line+last, ASCIILINESZ-last, in)!=NULL) { |
| lineno++ ; |
| len = (int)strlen(line)-1; |
| + if (len<=0) |
| + continue; |
| /* Safety check against buffer overflows */ |
| - if (last > 0 && line[len]!='\n') { |
| -#if 0 |
| - warning(anon_scope, |
| - "iniparser: input line too long in %s (%d)\n", |
| - ininame, |
| - lineno); |
| -#endif |
| + if (line[len]!='\n' && !feof(in)) { |
| + iniparser_error_callback( |
| + "iniparser: input line too long in %s (%d)\n", |
| + ininame, |
| + lineno); |
| dictionary_del(dict); |
| fclose(in); |
| - free(buf); |
| - errno = EINVAL; |
| return NULL ; |
| } |
| /* Get rid of \n and spaces at end of line */ |
| @@ -595,8 +767,11 @@ dictionary * iniparser_load(const char * ininame) |
| line[len]=0 ; |
| len-- ; |
| } |
| + if (len < 0) { /* Line was entirely \n and/or spaces */ |
| + len = 0; |
| + } |
| /* Detect multi-line */ |
| - if (len >= 0 && line[len]=='\\') { |
| + if (line[len]=='\\') { |
| /* Multi-line value */ |
| last=len ; |
| continue ; |
| @@ -609,24 +784,20 @@ dictionary * iniparser_load(const char * ininame) |
| break ; |
| |
| case LINE_SECTION: |
| - errs = dictionary_set(dict, section, NULL); |
| + mem_err = dictionary_set(dict, section, NULL); |
| break ; |
| |
| case LINE_VALUE: |
| sprintf(tmp, "%s:%s", section, key); |
| - errs = dictionary_set(dict, tmp, val) ; |
| + mem_err = dictionary_set(dict, tmp, val); |
| break ; |
| |
| - case LINE_ERROR: |
| -#if 0 |
| - printf("iniparser: syntax error in %s (%d):\n", |
| - ininame, |
| - lineno); |
| - printf( "-> %s\n", line); |
| - |
| -#endif |
| - |
| - ret = EINVAL; |
| + case LINE_ERROR: |
| + iniparser_error_callback( |
| + "iniparser: syntax error in %s (%d):\n-> %s\n", |
| + ininame, |
| + lineno, |
| + line); |
| errs++ ; |
| break; |
| |
| @@ -635,18 +806,16 @@ dictionary * iniparser_load(const char * ininame) |
| } |
| memset(line, 0, ASCIILINESZ); |
| last=0; |
| - if (errs<0) { |
| - ret = ENOMEM; |
| + if (mem_err<0) { |
| + iniparser_error_callback("iniparser: memory allocation failure\n"); |
| break ; |
| } |
| } |
| - fclose(in); |
| - free(buf); |
| if (errs) { |
| dictionary_del(dict); |
| dict = NULL ; |
| - errno = ret; |
| } |
| + fclose(in); |
| return dict ; |
| } |
| |
| @@ -665,5 +834,3 @@ void iniparser_freedict(dictionary * d) |
| { |
| dictionary_del(d); |
| } |
| - |
| -/* vim: set ts=4 et sw=4 tw=75 */ |
| diff --git a/lib/boilerplate/iniparser/iniparser.h b/lib/boilerplate/iniparser/iniparser.h |
| index d454cef34..37ff7b71b 100644 |
| --- a/lib/boilerplate/iniparser/iniparser.h |
| +++ b/lib/boilerplate/iniparser/iniparser.h |
| @@ -3,22 +3,15 @@ |
| /** |
| @file iniparser.h |
| @author N. Devillard |
| - @date Sep 2007 |
| - @version 3.0 |
| @brief Parser for ini files. |
| */ |
| /*--------------------------------------------------------------------------*/ |
| |
| -/* |
| - $Id: iniparser.h,v 1.24 2007-11-23 21:38:19 ndevilla Exp $ |
| - $Revision: 1.24 $ |
| -*/ |
| - |
| #ifndef _INIPARSER_H_ |
| #define _INIPARSER_H_ |
| |
| /*--------------------------------------------------------------------------- |
| - Includes |
| + Includes |
| ---------------------------------------------------------------------------*/ |
| |
| #include <stdio.h> |
| @@ -34,12 +27,21 @@ |
| |
| #include "dictionary.h" |
| |
| -/*--------------------------------------------------------------------------- |
| - Macros |
| - ---------------------------------------------------------------------------*/ |
| -/** For backwards compatibility only */ |
| -#define iniparser_getstr(d, k) iniparser_getstring(d, k, NULL) |
| -#define iniparser_setstr iniparser_setstring |
| +#ifdef __cplusplus |
| +extern "C" { |
| +#endif |
| + |
| +/*-------------------------------------------------------------------------*/ |
| +/** |
| + @brief Configure a function to receive the error messages. |
| + @param errback Function to call. |
| + |
| + By default, the error will be printed on stderr. If a null pointer is passed |
| + as errback the error callback will be switched back to default. |
| + */ |
| +/*--------------------------------------------------------------------------*/ |
| + |
| +void iniparser_set_error_callback(int (*errback)(const char *, ...)); |
| |
| /*-------------------------------------------------------------------------*/ |
| /** |
| @@ -60,7 +62,7 @@ |
| */ |
| /*--------------------------------------------------------------------------*/ |
| |
| -int iniparser_getnsec(dictionary * d); |
| +int iniparser_getnsec(const dictionary * d); |
| |
| |
| /*-------------------------------------------------------------------------*/ |
| @@ -78,7 +80,7 @@ int iniparser_getnsec(dictionary * d); |
| */ |
| /*--------------------------------------------------------------------------*/ |
| |
| -const char * iniparser_getsecname(dictionary * d, int n); |
| +const char * iniparser_getsecname(const dictionary * d, int n); |
| |
| |
| /*-------------------------------------------------------------------------*/ |
| @@ -93,7 +95,22 @@ const char * iniparser_getsecname(dictionary * d, int n); |
| */ |
| /*--------------------------------------------------------------------------*/ |
| |
| -void iniparser_dump_ini(dictionary * d, FILE * f); |
| +void iniparser_dump_ini(const dictionary * d, FILE * f); |
| + |
| +/*-------------------------------------------------------------------------*/ |
| +/** |
| + @brief Save a dictionary section to a loadable ini file |
| + @param d Dictionary to dump |
| + @param s Section name of dictionary to dump |
| + @param f Opened file pointer to dump to |
| + @return void |
| + |
| + This function dumps a given section of a given dictionary into a loadable ini |
| + file. It is Ok to specify @c stderr or @c stdout as output files. |
| + */ |
| +/*--------------------------------------------------------------------------*/ |
| + |
| +void iniparser_dumpsection_ini(const dictionary * d, const char * s, FILE * f); |
| |
| /*-------------------------------------------------------------------------*/ |
| /** |
| @@ -108,7 +125,36 @@ void iniparser_dump_ini(dictionary * d, FILE * f); |
| purposes mostly. |
| */ |
| /*--------------------------------------------------------------------------*/ |
| -void iniparser_dump(dictionary * d, FILE * f); |
| +void iniparser_dump(const dictionary * d, FILE * f); |
| + |
| +/*-------------------------------------------------------------------------*/ |
| +/** |
| + @brief Get the number of keys in a section of a dictionary. |
| + @param d Dictionary to examine |
| + @param s Section name of dictionary to examine |
| + @return Number of keys in section |
| + */ |
| +/*--------------------------------------------------------------------------*/ |
| +int iniparser_getsecnkeys(const dictionary * d, const char * s); |
| + |
| +/*-------------------------------------------------------------------------*/ |
| +/** |
| + @brief Get the number of keys in a section of a dictionary. |
| + @param d Dictionary to examine |
| + @param s Section name of dictionary to examine |
| + @param keys Already allocated array to store the keys in |
| + @return The pointer passed as `keys` argument or NULL in case of error |
| + |
| + This function queries a dictionary and finds all keys in a given section. |
| + The keys argument should be an array of pointers which size has been |
| + determined by calling `iniparser_getsecnkeys` function prior to this one. |
| + |
| + Each pointer in the returned char pointer-to-pointer is pointing to |
| + a string allocated in the dictionary; do not free or modify them. |
| + */ |
| +/*--------------------------------------------------------------------------*/ |
| +const char ** iniparser_getseckeys(const dictionary * d, const char * s, const char ** keys); |
| + |
| |
| /*-------------------------------------------------------------------------*/ |
| /** |
| @@ -125,7 +171,7 @@ void iniparser_dump(dictionary * d, FILE * f); |
| the dictionary, do not free or modify it. |
| */ |
| /*--------------------------------------------------------------------------*/ |
| -const char * iniparser_getstring(dictionary * d, const char * key, const char * def); |
| +const char * iniparser_getstring(const dictionary * d, const char * key, const char * def); |
| |
| /*-------------------------------------------------------------------------*/ |
| /** |
| @@ -154,7 +200,35 @@ const char * iniparser_getstring(dictionary * d, const char * key, const char * |
| Credits: Thanks to A. Becker for suggesting strtol() |
| */ |
| /*--------------------------------------------------------------------------*/ |
| -int iniparser_getint(dictionary * d, const char * key, int notfound); |
| +int iniparser_getint(const dictionary * d, const char * key, int notfound); |
| + |
| +/*-------------------------------------------------------------------------*/ |
| +/** |
| + @brief Get the string associated to a key, convert to an long int |
| + @param d Dictionary to search |
| + @param key Key string to look for |
| + @param notfound Value to return in case of error |
| + @return integer |
| + |
| + This function queries a dictionary for a key. A key as read from an |
| + ini file is given as "section:key". If the key cannot be found, |
| + the notfound value is returned. |
| + |
| + Supported values for integers include the usual C notation |
| + so decimal, octal (starting with 0) and hexadecimal (starting with 0x) |
| + are supported. Examples: |
| + |
| + - "42" -> 42 |
| + - "042" -> 34 (octal -> decimal) |
| + - "0x42" -> 66 (hexa -> decimal) |
| + |
| + Warning: the conversion may overflow in various ways. Conversion is |
| + totally outsourced to strtol(), see the associated man page for overflow |
| + handling. |
| + */ |
| +/*--------------------------------------------------------------------------*/ |
| +long int iniparser_getlongint(const dictionary * d, const char * key, long int notfound); |
| + |
| |
| /*-------------------------------------------------------------------------*/ |
| /** |
| @@ -169,7 +243,7 @@ int iniparser_getint(dictionary * d, const char * key, int notfound); |
| the notfound value is returned. |
| */ |
| /*--------------------------------------------------------------------------*/ |
| -double iniparser_getdouble(dictionary * d, const char * key, double notfound); |
| +double iniparser_getdouble(const dictionary * d, const char * key, double notfound); |
| |
| /*-------------------------------------------------------------------------*/ |
| /** |
| @@ -203,7 +277,7 @@ double iniparser_getdouble(dictionary * d, const char * key, double notfound); |
| necessarily have to be 0 or 1. |
| */ |
| /*--------------------------------------------------------------------------*/ |
| -int iniparser_getboolean(dictionary * d, const char * key, int notfound); |
| +int iniparser_getboolean(const dictionary * d, const char * key, int notfound); |
| |
| |
| /*-------------------------------------------------------------------------*/ |
| @@ -212,17 +286,16 @@ int iniparser_getboolean(dictionary * d, const char * key, int notfound); |
| @param ini Dictionary to modify. |
| @param entry Entry to modify (entry name) |
| @param val New value to associate to the entry. |
| - @return int 0 if Ok, -1 otherwise. |
| + @return int 0 if Ok, -1 otherwise. |
| |
| If the given entry can be found in the dictionary, it is modified to |
| - contain the provided value. If it cannot be found, -1 is returned. |
| + contain the provided value. If it cannot be found, the entry is created. |
| It is Ok to set val to NULL. |
| */ |
| /*--------------------------------------------------------------------------*/ |
| -int iniparser_setstring(dictionary * ini, const char * entry, const char * val); |
| - |
| int iniparser_set(dictionary * ini, const char * entry, const char * val); |
| |
| + |
| /*-------------------------------------------------------------------------*/ |
| /** |
| @brief Delete an entry in a dictionary |
| @@ -247,7 +320,7 @@ void iniparser_unset(dictionary * ini, const char * entry); |
| of querying for the presence of sections in a dictionary. |
| */ |
| /*--------------------------------------------------------------------------*/ |
| -int iniparser_find_entry(dictionary * ini, const char * entry) ; |
| +int iniparser_find_entry(const dictionary * ini, const char * entry) ; |
| |
| /*-------------------------------------------------------------------------*/ |
| /** |
| @@ -278,4 +351,8 @@ dictionary * iniparser_load(const char * ininame); |
| /*--------------------------------------------------------------------------*/ |
| void iniparser_freedict(dictionary * d); |
| |
| +#ifdef __cplusplus |
| +} |
| +#endif |
| + |
| #endif |
| -- |
| GitLab |
| |