Commit efb12a1d authored by Florian Bezdeka's avatar Florian Bezdeka Committed by Jan Kiszka
Browse files

lib/boilerplate/iniparser: Allow building with GCC 10.2 2020101

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: default avatarFlorian Bezdeka <florian.bezdeka@siemens.com>
Signed-off-by: Jan Kiszka's avatarJan Kiszka <jan.kiszka@siemens.com>
parent e1c30cf3
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
/** /**
@file dictionary.c @file dictionary.c
@author N. Devillard @author N. Devillard
@date Sep 2007 @brief Implements a dictionary for string variables.
@version $Revision: 1.27 $
@brief Implements a dictionary for string variables.
This module implements a simple dictionary object, i.e. a list This module implements a simple dictionary object, i.e. a list
of string/string associations. This object is useful to store e.g. of string/string associations. This object is useful to store e.g.
...@@ -12,12 +10,8 @@ ...@@ -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" #include "dictionary.h"
...@@ -27,33 +21,18 @@ ...@@ -27,33 +21,18 @@
#include <unistd.h> #include <unistd.h>
/** Maximum value size for integers and doubles. */ /** Maximum value size for integers and doubles. */
#define MAXVALSZ 1024 #define MAXVALSZ 1024
/** Minimal allocated number of entries in a dictionary */ /** Minimal allocated number of entries in a dictionary */
#define DICTMINSZ 128 #define DICTMINSZ 128
/** Invalid key token */ /** Invalid key token */
#define DICT_INVALID_KEY ((char*)-1) #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 @brief Duplicate a string
...@@ -67,23 +46,68 @@ static void * mem_double(void * ptr, int size) ...@@ -67,23 +46,68 @@ static void * mem_double(void * ptr, int size)
static char * xstrdup(const char * s) static char * xstrdup(const char * s)
{ {
char * t ; char * t ;
size_t len ;
if (!s) if (!s)
return NULL ; return NULL ;
t = malloc(strlen(s)+1) ;
len = strlen(s) + 1 ;
t = (char*) malloc(len) ;
if (t) { if (t) {
strcpy(t,s); memcpy(t, s, len) ;
} }
return t ; 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. @brief Compute the hash key for a string.
@param key Character string to use for key. @param key Character string to use for key.
@return 1 unsigned int on at least 32 bits. @return 1 unsigned int on at least 32 bits.
This hash function has been taken from an Article in Dr Dobbs Journal. This hash function has been taken from an Article in Dr Dobbs Journal.
This is normally a collision-free function, distributing keys evenly. This is normally a collision-free function, distributing keys evenly.
...@@ -93,84 +117,88 @@ static char * xstrdup(const char * s) ...@@ -93,84 +117,88 @@ static char * xstrdup(const char * s)
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
unsigned dictionary_hash(const char * key) unsigned dictionary_hash(const char * key)
{ {
int len ; size_t len ;
unsigned hash ; unsigned hash ;
int i ; size_t i ;
len = strlen(key); if (!key)
for (hash=0, i=0 ; i<len ; i++) { return 0 ;
hash += (unsigned)key[i] ;
hash += (hash<<10); len = strlen(key);
hash ^= (hash>>6) ; for (hash=0, i=0 ; i<len ; i++) {
} hash += (unsigned)key[i] ;
hash += (hash <<3); hash += (hash<<10);
hash ^= (hash >>11); hash ^= (hash>>6) ;
hash += (hash <<15); }
return hash ; hash += (hash <<3);
hash ^= (hash >>11);
hash += (hash <<15);
return hash ;
} }
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
/** /**
@brief Create a new dictionary object. @brief Create a new dictionary object.
@param size Optional initial size of the dictionary. @param size Optional initial size of the dictionary.
@return 1 newly allocated dictionary objet. @return 1 newly allocated dictionary objet.
This function allocates a new dictionary object of given size and returns 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 it. If you do not know in advance (roughly) the number of entries in the
dictionary, give size=0. dictionary, give size=0.
*/ */
/*--------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
dictionary * dictionary_new(int size) dictionary * dictionary_new(size_t size)
{ {
dictionary * d ; dictionary * d ;
/* If no size was specified, allocate space for DICTMINSZ */ /* If no size was specified, allocate space for DICTMINSZ */
if (size<DICTMINSZ) size=DICTMINSZ ; if (size<DICTMINSZ) size=DICTMINSZ ;
if (!(d = (dictionary *)calloc(1, sizeof(dictionary)))) { d = (dictionary*) calloc(1, sizeof *d) ;
return NULL;
} if (d) {
d->size = size ; d->size = size ;
d->val = (char **)calloc(size, sizeof(char*)); d->val = (char**) calloc(size, sizeof *d->val);
d->key = (char **)calloc(size, sizeof(char*)); d->key = (char**) calloc(size, sizeof *d->key);
d->hash = (unsigned int *)calloc(size, sizeof(unsigned)); d->hash = (unsigned*) calloc(size, sizeof *d->hash);
return d ; }
return d ;
} }
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
/** /**
@brief Delete a dictionary object @brief Delete a dictionary object
@param d dictionary object to deallocate. @param d dictionary object to deallocate.
@return void @return void
Deallocate a dictionary object and all memory associated to it. Deallocate a dictionary object and all memory associated to it.
*/ */
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
void dictionary_del(dictionary * d) void dictionary_del(dictionary * d)
{ {
int i ; ssize_t i ;
if (d==NULL) return ; if (d==NULL) return ;
for (i=0 ; i<d->size ; i++) { for (i=0 ; i<d->size ; i++) {
if (d->key[i]!=NULL) if (d->key[i]!=NULL)
free(d->key[i]); free(d->key[i]);
if (d->val[i]!=NULL) if (d->val[i]!=NULL)
free(d->val[i]); free(d->val[i]);
} }
free(d->val); free(d->val);
free(d->key); free(d->key);
free(d->hash); free(d->hash);
free(d); free(d);
return ; return ;
} }
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
/** /**
@brief Get a value from a dictionary. @brief Get a value from a dictionary.
@param d dictionary object to search. @param d dictionary object to search.
@param key Key to look for in the dictionary. @param key Key to look for in the dictionary.
@param def Default value to return if key not found. @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 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 value, or the passed 'def' pointer if no such key can be found in
...@@ -178,24 +206,24 @@ void dictionary_del(dictionary * d) ...@@ -178,24 +206,24 @@ void dictionary_del(dictionary * d)
dictionary object, you should not try to free it or modify it. 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 ; unsigned hash ;
int i ; ssize_t i ;
hash = dictionary_hash(key); hash = dictionary_hash(key);
for (i=0 ; i<d->size ; i++) { for (i=0 ; i<d->size ; i++) {
if (d->key[i]==NULL) if (d->key[i]==NULL)
continue ; continue ;
/* Compare hash */ /* Compare hash */
if (hash==d->hash[i]) { if (hash==d->hash[i]) {
/* Compare string, to avoid hash collisions */ /* Compare string, to avoid hash collisions */
if (!strcmp(key, d->key[i])) { if (!strcmp(key, d->key[i])) {
return d->val[i] ; return d->val[i] ;
} }
} }
} }
return def ; return def ;
} }
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
...@@ -226,66 +254,57 @@ const char * dictionary_get(dictionary * d, const char * key, const char * 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 dictionary_set(dictionary * d, const char * key, const char * val)
{ {
int i ; ssize_t i ;
unsigned hash ; unsigned hash ;
if (d==NULL || key==NULL) return -1 ; if (d==NULL || key==NULL) return -1 ;
/* Compute hash for this key */ /* Compute hash for this key */
hash = dictionary_hash(key) ; hash = dictionary_hash(key) ;
/* Find if value is already in dictionary */ /* Find if value is already in dictionary */
if (d->n>0) { if (d->n>0) {
for (i=0 ; i<d->size ; i++) { for (i=0 ; i<d->size ; i++) {
if (d->key[i]==NULL) if (d->key[i]==NULL)
continue ; continue ;
if (hash==d->hash[i]) { /* Same hash value */ if (hash==d->hash[i]) { /* Same hash value */
if (!strcmp(key, d->key[i])) { /* Same key */ if (!strcmp(key, d->key[i])) { /* Same key */
/* Found a value: modify and return */ /* Found a value: modify and return */
if (d->val[i]!=NULL) if (d->val[i]!=NULL)
free(d->val[i]); free(d->val[i]);
d->val[i] = val ? xstrdup(val) : NULL ; d->val[i] = (val ? xstrdup(val) : NULL);
/* Value has been modified: return */ /* Value has been modified: return */
return 0 ; 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 ;
} }
/* 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 */ /* Insert key in the first empty slot. Start at d->n and wrap at
for (i=0 ; i<d->size ; i++) { d->size. Because d->n < d->size this will necessarily
if (d->key[i]==NULL) { terminate. */
/* Add key here */ for (i=d->n ; d->key[i] ; ) {
break ; if(++i == d->size) i = 0;
}
} }
/* Copy key */ /* Copy key */
d->key[i] = xstrdup(key); d->key[i] = xstrdup(key);
d->val[i] = val ? xstrdup(val) : NULL ; d->val[i] = (val ? xstrdup(val) : NULL) ;
d->hash[i] = hash; d->hash[i] = hash;
d->n ++ ; d->n ++ ;
return 0 ; return 0 ;
} }
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
/** /**
@brief Delete a key in a dictionary @brief Delete a key in a dictionary
@param d dictionary object to modify. @param d dictionary object to modify.
@param key Key to remove. @param key Key to remove.
@return void @return void
This function deletes a key in a dictionary. Nothing is done if the 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) ...@@ -294,26 +313,26 @@ int dictionary_set(dictionary * d, const char * key, const char * val)
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
void dictionary_unset(dictionary * d, const char * key) void dictionary_unset(dictionary * d, const char * key)
{ {
unsigned hash ; unsigned hash ;
int i ; ssize_t i ;
if (key == NULL) { if (key == NULL || d == NULL) {
return; return;
} }
hash = dictionary_hash(key); hash = dictionary_hash(key);
for (i=0 ; i<d->size ; i++) { for (i=0 ; i<d->size ; i++) {
if (d->key[i]==NULL) if (d->key[i]==NULL)
continue ; continue ;
/* Compare hash */ /* Compare hash */
if (hash==d->hash[i]) { if (hash==d->hash[i]) {
/* Compare string, to avoid hash collisions */ /* Compare string, to avoid hash collisions */
if (!strcmp(key, d->key[i])) { if (!strcmp(key, d->key[i])) {
/* Found key */ /* Found key */
break ; break ;
} }
} }
} }
if (i>=d->size) if (i>=d->size)
/* Key not found */ /* Key not found */
return ; return ;
...@@ -331,75 +350,31 @@ void dictionary_unset(dictionary * d, const char * key) ...@@ -331,75 +350,31 @@ void dictionary_unset(dictionary * d, const char * key)
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
/** /**
@brief Dump a dictionary to an opened file pointer. @brief Dump a dictionary to an opened file pointer.
@param d Dictionary to dump @param d Dictionary to dump
@param out Opened file pointer. @param f Opened file pointer.
@return void @return void
Dumps a dictionary onto an opened file pointer. Key pairs are printed out 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 as @c [Key]=[Value], one per line. It is Ok to provide stdout or stderr as
output file pointers. output file pointers.
*/ */
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
void dictionary_dump(dictionary * d, FILE * out) void dictionary_dump(const dictionary * d, FILE * out)
{ {
int i ; ssize_t i ;
if (d==NULL || out==NULL) return ; if (d==NULL || out==NULL) return ;
if (d->n<1) { if (d->n<1) {
fprintf(out, "empty dictionary\n"); fprintf(out, "empty dictionary\n");
return ; return ;
} }
for (i=0 ; i<d->size ; i++) { for (i=0 ; i<d->size ; i++) {
if (d->key[i]) { if (d->key[i]) {
fprintf(out, "%20s\t[%s]\n", fprintf(out, "%20s\t[%s]\n",
d->key[i], d->key[i],
d->val[i] ? d->val[i] : "UNDEF"); 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");
}