librnr  1.14.5
RoadNarrows Robotics Common Library 1
config.c
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////////////
2 //
3 // Package: RoadNarrows Robotics Common Library 1
4 //
5 // Library: librnr
6 //
7 // File: config.c
8 //
9 /*! \file
10  *
11  * $LastChangedDate: 2014-12-06 13:48:30 -0700 (Sat, 06 Dec 2014) $
12  * $Rev: 3823 $
13  *
14  * \brief Configuration parser definitions.
15  *
16  * This file has been modified from the original source (see below).
17  *
18  * \author Robin Knight (robin.knight@roadnarrows.com)
19  *
20  * \pkgcopyright{2005-2018,RoadNarrows LLC.,http://www.roadnarrows.com}
21  *
22  * <hr>
23  * \par Original Source and Copyright:
24  *
25  * \par Original Author:
26  * Jon Travis (jtravis@p00p.org)
27  *
28  * \par Original Copyright:
29  * (C) 1992-2002
30  *
31  * \par Original Header:
32  * See "Original Source Header EULA" in source file.
33  *
34  * <hr>
35  */
36 // Permission is hereby granted, without written agreement and without
37 // license or royalty fees, to use, copy, modify, and distribute this
38 // software and its documentation for any purpose, provided that
39 // (1) The above copyright notice and the following two paragraphs
40 // appear in all copies of the source code and (2) redistributions
41 // including binaries reproduces these notices in the supporting
42 // documentation. Substantial modifications to this software may be
43 // copyrighted by their authors and need not follow the licensing terms
44 // described here, provided that the new terms are clearly indicated in
45 // all files where they apply.
46 //
47 // IN NO EVENT SHALL THE AUTHOR, ROADNARROWS LLC, OR ANY MEMBERS/EMPLOYEES
48 // OF ROADNARROW LLC OR DISTRIBUTORS OF THIS SOFTWARE BE LIABLE TO ANY
49 // PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
50 // DAMAGES ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION,
51 // EVEN IF THE AUTHORS OR ANY OF THE ABOVE PARTIES HAVE BEEN ADVISED OF
52 // THE POSSIBILITY OF SUCH DAMAGE.
53 //
54 // THE AUTHOR AND ROADNARROWS LLC SPECIFICALLY DISCLAIM ANY WARRANTIES,
55 // INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
56 // FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN
57 // "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO
58 // PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
59 //
60 //
61 // Original Source Header EULA:
62 //
63 // camserv - An internet streaming picture application
64 //
65 // Copyright (C) 1999-2002 Jon Travis (jtravis@p00p.org)
66 //
67 // This program is free software; you can redistribute it and/or modify
68 // it under the terms of the GNU General Public License as published by
69 // the Free Software Foundation; either version 2 of the License, or
70 // (at your option) any later version.
71 //
72 // This program is distributed in the hope that it will be useful,
73 // but WITHOUT ANY WARRANTY; without even the implied warranty of
74 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
75 // GNU General Public License for more details.
76 //
77 // You should have received a copy of the GNU General Public License
78 // along with this program; if not, write to the Free Software
79 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
80 //
81 ////////////////////////////////////////////////////////////////////////////////
82 
83 #include <stdio.h>
84 #include <stdlib.h>
85 #include <string.h>
86 #include <ctype.h>
87 
88 #include "rnr/rnrconfig.h"
89 #include "rnr/log.h"
90 #include "rnr/new.h"
91 #include "rnr/hash.h"
92 #include "rnr/config.h"
93 
94 // ---------------------------------------------------------------------------
95 // Private Interface
96 // ---------------------------------------------------------------------------
97 
98 /*!
99  * Configuration limits.
100  */
101 #define HASH_MIN_SECTIONS (hashcount_t)8 ///< min. num. of database sections
102 #define HASH_MAX_SECTIONS HASHCOUNT_T_MAX ///< max. num. of database sections
103 #define HASH_MIN_ENTRIES (hashcount_t)8 ///< min. num. of section entries
104 #define HASH_MAX_ENTRIES HASHCOUNT_T_MAX ///< max. num. of section entries
105 
106 /*!
107  * \brief Maximum input line size.
108  */
109 #define HASH_INPUT_BUF_SIZE 1024
110 
111 /*!
112  * Configuration section structure type.
113  */
115 {
116  char *m_sSectionName; ///< section name
117  hash_t *m_hashSection; ///< section's key=value entries hash table
118 };
119 
120 /*!
121  * Configuration database structure type.
122  */
123 struct config_t
124 {
125  char *m_sMainName; ///< configuration name
126  hash_t *m_hashMain; ///< main hash table of sections
127 };
128 
129 /*!
130  * Configuration iterator type.
131  */
133 {
134  hscan_t m_scanHash; ///< hash table scanner (iterator)
135 };
136 
137 /*!
138  * Internal counter to make configuration names unique.
139  */
140 static int ConfigMainCounter = 0;
141 
142 /*!
143  * \brief Add or update a key-value pair in the given section.
144  *
145  * \param pSect Configuration section to update.
146  * \param sKey Section key to add or update.
147  * \param sVal Key value to add
148  *
149  * \return Returns OK(0) on success, RC_ERROR(-1) on failure.
150  */
152  const char *sKey,
153  const char *sVal)
154 {
155  hnode_t *pHashNode;
156  char *sKeyDup;
157  char *sValDup;
158 
159  // Lookup key in section. If it exists, then replace with new value
160  if( (pHashNode = hash_lookup(pSect->m_hashSection, sKey)) != NULL )
161  {
162  sValDup = new_strdup(sVal);
163 
164  // delete old value
165  delete(hnode_get(pHashNode));
166 
167  // replacing with new value
168  hnode_put(pHashNode, sValDup);
169  }
170 
171  // New section key
172  else
173  {
174  sKeyDup = new_strdup(sKey);
175  sValDup = new_strdup(sVal);
176 
177  if( !hash_insert(pSect->m_hashSection, sKeyDup, sValDup) )
178  {
179  delete(sKeyDup);
180  delete(sValDup);
181  return RC_ERROR;
182  }
183  }
184 
185  return OK;
186 }
187 
188 /*!
189  * \brief Delete section entry hash callback.
190  *
191  * When a key-value entry or section is deleted, the hash will make a callback
192  * to this function to delete the hash key and data.
193  *
194  * \param pKey Section key to delete.
195  * \param pData Key value to delete.
196  */
197 static void ConfigSectionHashDeleteCb(void *pKey, void *pData)
198 {
199  delete(pKey); // section hash key (char *)
200  delete(pData); // section hash data (char *)
201 }
202 
203 /*!
204  * \brief Delete section hash callback.
205  *
206  * When a section or configuration datatbase is deleted, the hash will make a
207  * callback to this function to delete the hash key and data (section).
208  *
209  * \param pKey Section key to main hash.
210  * \param pData Key data to delete (ConfigSection_T *).
211  */
212 static void ConfigMainHashDeleteCb(void *pKey, void *pData)
213 {
214  ConfigSection_T *pSect;
215 
216  // main hash key points to section name, so don't delete here
217 
218  pSect = (ConfigSection_T *)pData; // main hash data
219  hash_table_destroy(pSect->m_hashSection); // section hash table
220  delete(pSect->m_sSectionName); // section name
221  delete(pSect); // section
222 }
223 
224 
225 // ---------------------------------------------------------------------------
226 // Public Interface
227 // ---------------------------------------------------------------------------
228 
229 // ...........................................................................
230 // Configuration Database Functions
231 // ...........................................................................
232 
233 /*!
234  * \brief Create and initialize a new empty configuration database.
235  *
236  * \param sMainName Name of configuration database. If Null, then a name
237  * will be auto-generated.
238  *
239  * \return
240  * Returns new configuration database on success.\n
241  * Returns NULL on failure.
242  */
243 Config_T *ConfigDbNew(const char *sMainName)
244 {
245  Config_T *pConfig;
246  char buf[32];
247 
248  LOGDIAG4CALL(_TSTR(sMainName));
249 
250  // new main configuration structure
251  pConfig = NEW(Config_T);
252 
253  // new empty main hash table of sections
254  pConfig->m_hashMain = hash_table_create(true,
257  NULL,
258  NULL,
260 
261  if( pConfig->m_hashMain == NULL )
262  {
263  LOGERROR("failed to create new configuration main hash table");
264  delete(pConfig);
265  return NULL;
266  }
267 
268  // create internal name
269  if( sMainName == NULL )
270  {
271  snprintf(buf, sizeof(buf), "__config.%d", ConfigMainCounter++);
272  buf[sizeof(buf)-1] = 0;
273  pConfig->m_sMainName = new_strdup(buf);
274  }
275 
276  // use given name
277  else
278  {
279  pConfig->m_sMainName = new_strdup(sMainName);
280  }
281 
282  LOGDIAG3(_TPTR(pConfig));
283 
284  return pConfig;
285 }
286 
287 /*!
288  * \brief Delete the configuration database.
289  *
290  * All sections, section key=value entries, plus the database itself are
291  * deleted.
292  *
293  * \param pConfig Configuration database.
294  */
295 void ConfigDbDelete(Config_T *pConfig)
296 {
297  LOGDIAG4CALL(_TSTR(pConfig));
298 
299  if( pConfig == NULL )
300  {
301  return;
302  }
303 
304  // delete all sections and section entries
305  hash_table_destroy(pConfig->m_hashMain);
306 
307  // now delete the structure
308  delete(pConfig->m_sMainName);
309  delete(pConfig);
310 }
311 
312 /*!
313  * \brief Create a new configuration database from a configuration file.
314  *
315  * The file syntax must conform to the simplified 'INI' format supported
316  * by librnr config.
317  *
318  * The file is closed upon exiting this function.
319  *
320  * \param sFileName File path name of configuration file.
321  *
322  * \return
323  * Returns populated configuration database on success.\n
324  * Returns NULL on failure.
325  */
326 Config_T *ConfigDbRead(const char *sFileName)
327 {
328  FILE *fp;
329  Config_T *pConfig;
330 
331  LOGDIAG4CALL(_TSTR(sFileName));
332 
333  CHKPTR(sFileName, NULL);
334 
335  if( (fp = fopen(sFileName, "r")) == NULL )
336  {
337  LOGSYSERROR("%s", sFileName);
338  return NULL;
339  }
340  else
341  {
342  pConfig = ConfigDbReadFp(fp, sFileName);
343  fclose(fp);
344  LOGDIAG4(_TPTR(pConfig));
345  return pConfig;
346  }
347 }
348 
349 /*!
350  * \brief Create a new configuration database from a opened configuration file.
351  *
352  * The file syntax must conform to the simplified 'INI' format supported
353  * by librnr config.
354  *
355  * The file is remains open upon exiting this function.
356  *
357  * \param fp Input file pointer.
358  * \param sFileName Input file name. NULL is okay.
359  *
360  * \return
361  * Returns populated configuration database on success.\n
362  * Returns NULL on failure.
363  */
364 Config_T *ConfigDbReadFp(FILE *fp, const char *sFileName)
365 {
366  Config_T *pConfig;
367  ConfigSection_T *pCurSect;
368  char bufGet[HASH_INPUT_BUF_SIZE];
369  char bufKey[HASH_INPUT_BUF_SIZE];
370  char bufSep[HASH_INPUT_BUF_SIZE];
371  char bufVal[HASH_INPUT_BUF_SIZE];
372  char *s, *t;
373  int nLineNum;
374  int i;
375 
376  LOGDIAG4CALL(_TPTR(fp), _TSTR(sFileName));
377 
378  CHKPTR(fp, NULL);
379 
380  // New configuration
381  if( (pConfig = ConfigDbNew(sFileName)) == NULL )
382  {
383  return NULL;
384  }
385 
386  pCurSect = NULL;
387  nLineNum = 0;
388 
389  while( fgets(bufGet, (int)sizeof(bufGet), fp) != NULL )
390  {
391  nLineNum++;
392 
393  // eat white-space
394  for(i=0; isspace((int)bufGet[i]); ++i);
395 
396  // comment or white space
397  if( (bufGet[i] == 0) || (bufGet[i] == '#') || (bufGet[0] == '\n') )
398  {
399  continue; // empty or comment line
400  }
401 
402  //
403  // Begin a section
404  //
405  if( bufGet[i] == '[' )
406  {
407  if( (t = strrchr(bufGet+i, ']' )) == NULL )
408  {
409  LOGERROR("Config %s: Line %d: malformed section statement: %d",
410  pConfig->m_sMainName, nLineNum );
411  continue; // recoverable error
412  }
413  s = &bufGet[i+1];
414  *t = '\0';
415 
416  if( (pCurSect = ConfigSectionNew(pConfig, s)) == NULL )
417  {
418  LOGERROR("Config %s: [%s]: Line %d: failed adding section",
419  pConfig->m_sMainName, s, nLineNum);
420  ConfigDbDelete(pConfig);
421  return NULL; // non-recoverable error
422  }
423  continue;
424  }
425 
426  //
427  // Orphaned Key-Value Pair
428  //
429  if( pCurSect == NULL )
430  {
431  LOGERROR("Config %s: Line %d: not in a section",
432  pConfig->m_sMainName, nLineNum );
433  continue; // recoverable error
434  }
435 
436  //
437  // Key-Value Pair
438  //
439  bufKey[0] = bufSep[0] = bufVal[0] = 0;
440  if( sscanf(bufGet+i, "%[^:= \t]%[:= \t]%[^\n#]", bufKey, bufSep, bufVal)
441  != 3)
442  {
443  LOGERROR("Config %s: [%s]: Line %d: malformed input",
444  pConfig->m_sMainName, pCurSect->m_sSectionName, nLineNum );
445  continue; // recoverable error
446  }
447 
448  // strip any trailing white-space
449  i = (int)strlen(bufVal) - 1;
450  while( (i >= 0) && isspace((int)bufVal[i]) )
451  {
452  --i;
453  }
454  if( i < 0 )
455  {
456  LOGERROR("Config %s: [%s]: Line %d: malformed input",
457  pConfig->m_sMainName, pCurSect->m_sSectionName, nLineNum );
458  continue; // recoverable error
459  }
460  else
461  {
462  bufVal[i+1] = 0;
463  }
464 
465  if( ConfigSectionAddPair(pCurSect, bufKey, bufVal) == RC_ERROR )
466  {
467  LOGERROR("Config %s: [%s]: Line %d: failed to add key=value enttry",
468  pConfig->m_sMainName, pCurSect->m_sSectionName, nLineNum );
469  ConfigDbDelete(pConfig);
470  return NULL; // non-recoverable error
471  }
472  }
473 
474  LOGDIAG4(_TPTR(pConfig));
475 
476  return pConfig;
477 }
478 
479 /*!
480  * \brief Get the current name assigned to the configuration database.
481  *
482  * \param pConfig Configuration database.
483  *
484  * \return Returns current name.
485  */
486 const char *ConfigDbGetName(Config_T *pConfig)
487 {
488  CHKPTR(pConfig, NULL);
489  return pConfig->m_sMainName;
490 }
491 
492 /*!
493  * \brief Assign a new name for the configuration database.
494  *
495  * \param pConfig Configuration database.
496  * \param sMainName New database name.
497  */
498 void ConfigDbSetName(Config_T *pConfig, const char *sMainName)
499 {
500  CHKPTR(pConfig);
501  CHKPTR(sMainName);
502  delete(pConfig->m_sMainName);
503  pConfig->m_sMainName = new_strdup(sMainName);
504 }
505 
506 /*!
507  * \brief Print configuration database to the output file stream.
508  *
509  * The output format is valid for input.
510  *
511  * \param pConfig Configuration database.
512  * \param fp Output file pointer.
513  */
514 void ConfigDbPrint(Config_T *pConfig, FILE *fp)
515 {
516  hscan_t scanHash;
517  hnode_t *pHashNode;
518  ConfigSection_T *pSect;
519 
520  fprintf(fp, "# Configuration %s\n", pConfig->m_sMainName);
521  hash_scan_begin(&scanHash, pConfig->m_hashMain);
522  while((pHashNode = hash_scan_next(&scanHash)) != NULL )
523  {
524  pSect = (ConfigSection_T *)hnode_get(pHashNode);
525  ConfigSectionPrint(pSect, fp);
526  fprintf(fp, "\n");
527  }
528 }
529 
530 
531 // ...........................................................................
532 // Configuration Section Functions
533 // ...........................................................................
534 
535 /*!
536  * \brief Add a new empty section to the configuration database.
537  *
538  * The section cannot already exist.
539  *
540  * \param pConfig Configuration database.
541  * \param sSectionName Configuration section name.
542  *
543  * \return
544  * Returns configuration section on success.\n
545  * NULL on failure.
546  */
547 ConfigSection_T *ConfigSectionNew(Config_T *pConfig, const char *sSectionName)
548 {
549  ConfigSection_T *pSect;
550 
551  LOGDIAG4CALL(_TPTR(pConfig), _TSTR(sSectionName));
552 
553  CHKPTR(pConfig, NULL);
554  CHKPTR(sSectionName, NULL);
555 
556  // make sure section does not already exist
557  if( hash_lookup(pConfig->m_hashMain, sSectionName) != NULL )
558  {
559  LOGERROR("%s: [%s]: section multiply defined",
560  pConfig->m_sMainName, sSectionName);
561  return NULL;
562  }
563 
564  // new section structure
565  pSect = NEW(ConfigSection_T);
566 
567  // new section hash table of key=value entries
568  pSect->m_hashSection = hash_table_create(true,
571  NULL,
572  NULL,
574 
575  if( pSect->m_hashSection == NULL )
576  {
577  LOGERROR("%s: [%s]: failed to create new section hash table",
578  pConfig->m_sMainName, sSectionName);
579  delete(pSect);
580  return NULL;
581  }
582 
583  // section name
584  pSect->m_sSectionName = new_strdup(sSectionName);
585 
586  // insert section into main hash table
587  hash_insert(pConfig->m_hashMain, (char *)pSect->m_sSectionName, pSect);
588 
589  return pSect;
590 }
591 
592 /*!
593  * \brief Delete a section from the configuration database.
594  *
595  * \param pConfig Configuration database.
596  * \param pSect Configuration section to delete.
597  *
598  * \return Returns OK(0) on success, RC_ERROR(-1) on failure.
599  */
601 {
602  LOGDIAG4CALL(_TPTR(pConfig), _TPTR(pSect));
603 
604  if( pSect == NULL )
605  {
606  return OK;
607  }
608 
609  // make sure section exist
610  if( hash_lookup(pConfig->m_hashMain, pSect->m_sSectionName) == NULL )
611  {
612  LOGERROR("%s: [%s]: section not define",
613  pConfig->m_sMainName, pSect->m_sSectionName);
614  return RC_ERROR;
615  }
616 
617  // delete all section entries
618  else
619  {
620  hash_delete(pConfig->m_hashMain, pSect->m_sSectionName);
621  return OK;
622  }
623 }
624 
625 /*!
626  * \brief Get a section from the configuration database.
627  *
628  * \param pConfig Configuration database.
629  * \param sSectionName Configuration section name.
630  *
631  * \return
632  * Returns configuration section on success.\n
633  * NULL on failure.
634  */
635 ConfigSection_T *ConfigSectionGet(Config_T *pConfig, const char *sSectionName)
636 {
637  hnode_t *pHashNode;
638 
639  if( (pHashNode = hash_lookup(pConfig->m_hashMain, sSectionName)) != NULL )
640  {
641  return (ConfigSection_T *)hnode_get(pHashNode);
642  }
643  return NULL;
644 }
645 
646 /*!
647  * \brief Print one section to the output file stream.
648  *
649  * The output format is valid for input.
650  *
651  * \param pSect Configuration section.
652  * \param fp Output file pointer.
653  */
654 void ConfigSectionPrint(ConfigSection_T *pSect, FILE *fp)
655 {
656  hscan_t scanHash;
657  hnode_t *pHashNode;
658 
659  fprintf(fp, "[%s]\n", pSect->m_sSectionName);
660  hash_scan_begin(&scanHash, pSect->m_hashSection);
661  while( (pHashNode = hash_scan_next(&scanHash)) != NULL )
662  {
663  fprintf(fp, "%s=%s\n",
664  (char *)hnode_getkey(pHashNode), (char *)hnode_get(pHashNode));
665  }
666 }
667 
668 
669 // ...........................................................................
670 // Configuration Get key=value Entry Functions
671 // ...........................................................................
672 
673 /*!
674  * \brief Get a string value from the configuration database.
675  *
676  * \param pConfig Configuration database.
677  * \param sSectionName Configuration section name.
678  * \param sKey Section key.
679  *
680  * \return Returns string value one success, NULL on failure.
681  */
682 const char *ConfigGetStr(Config_T *pConfig, const char *sSectionName,
683  const char *sKey)
684 {
685  ConfigSection_T *pSect;
686  hnode_t *pHashNode;
687 
688  if( (pSect = ConfigSectionGet(pConfig, sSectionName)) == NULL )
689  {
690  return NULL;
691  }
692 
693  else if( (pHashNode = hash_lookup(pSect->m_hashSection, sKey)) == NULL )
694  {
695  return NULL;
696  }
697 
698  else
699  {
700  return hnode_get(pHashNode);
701  }
702 }
703 
704 /*!
705  * \brief Get and convert a long value from the configuration database.
706  *
707  * \param pConfig Configuration database.
708  * \param sSectionName Configuration section name.
709  * \param sKey Section key.
710  * \param pVal Converted value.
711  *
712  * \return Returns OK(0) on success, RC_ERROR(-1) on failure.
713  */
714 int ConfigGetLong(Config_T *pConfig, const char *sSectionName,
715  const char *sKey, long *pVal)
716 {
717  const char *sVal;
718  long lVal;
719  char *sEnd;
720 
721  if( (sVal = ConfigGetStr(pConfig, sSectionName, sKey)) == NULL )
722  {
723  return RC_ERROR;
724  }
725  else if( (sVal == NULL) || (*sVal == 0) )
726  {
727  LOGERROR("Config %s: [%s]: value is null",
728  pConfig->m_sMainName, sSectionName);
729  return RC_ERROR;
730  }
731  else
732  {
733  lVal = strtol(sVal, &sEnd, 0);
734 
735  if( *sEnd != 0 )
736  {
737  LOGERROR("Config %s: [%s]: %s=%s: not an integer",
738  pConfig->m_sMainName, sSectionName, sKey, sVal);
739  return RC_ERROR;
740  }
741  else
742  {
743  *pVal = lVal;
744  return OK;
745  }
746  }
747 }
748 
749 /*!
750  * \brief Get and convert a double value from the configuration database.
751  *
752  * \param pConfig Configuration database.
753  * \param sSectionName Configuration section name.
754  * \param sKey Section key.
755  * \param pVal Converted value.
756  *
757  * \return Returns OK(0) on success, RC_ERROR(-1) on failure.
758  */
759 int ConfigGetDouble(Config_T *pConfig, const char *sSectionName,
760  const char *sKey, double *pVal)
761 {
762  const char *sVal;
763  double fVal;
764  char *sEnd;
765 
766  if( (sVal = ConfigGetStr(pConfig, sSectionName, sKey)) == NULL )
767  {
768  return RC_ERROR;
769  }
770  else if( (sVal == NULL) || (*sVal == 0) )
771  {
772  LOGERROR("Config %s: [%s]: value is null",
773  pConfig->m_sMainName, sSectionName);
774  return RC_ERROR;
775  }
776  else
777  {
778  fVal = strtod(sVal, &sEnd);
779 
780  if( *sEnd != 0 )
781  {
782  LOGERROR("Config %s: [%s]: %s=%s: not a float",
783  pConfig->m_sMainName, sSectionName, sKey, sVal);
784  return RC_ERROR;
785  }
786  else
787  {
788  *pVal = fVal;
789  return OK;
790  }
791  }
792 }
793 
794 
795 // ...........................................................................
796 // Configuration Set key=value Entry Functions
797 // ...........................................................................
798 
799 /*!
800  * \brief Set or update a string value in the configuration database.
801  *
802  * \param pConfig Configuration database.
803  * \param sSectionName Configuration section name.
804  * \param sKey Section key.
805  * \param sVal Section key value.
806  *
807  * \return Returns OK(0) on success, RC_ERROR(-1) on failure.
808  */
809 int ConfigSetStr(Config_T *pConfig, const char *sSectionName,
810  const char *sKey, const char *sVal)
811 {
812  ConfigSection_T *pSect;
813 
814  LOGDIAG4CALL(_TPTR(pConfig), _TSTR(sSectionName), _TSTR(sKey), _TSTR(sVal));
815 
816  /* Can't add to an undefined section! */
817  if( (pSect = ConfigSectionGet(pConfig, sSectionName)) == NULL )
818  {
819  LOGDIAG4("%s: [%s]: section not defined",
820  pConfig->m_sMainName, sSectionName);
821  return RC_ERROR;
822  }
823  else
824  {
825  return ConfigSectionAddPair(pSect, sKey, sVal);
826  }
827 }
828 
829 /*!
830  * \brief Set or update a long value in the configuration database.
831  *
832  * The long value is converted to a string prior to adding to the database.
833  *
834  * \param pConfig Configuration database.
835  * \param sSectionName Configuration section name.
836  * \param sKey Section key.
837  * \param lVal Section key long value.
838  *
839  * \return Returns OK(0) on success, RC_ERROR(-1) on failure.
840  */
841 int ConfigSetLong(Config_T *pConfig, const char *sSectionName,
842  const char *sKey, long lVal)
843 {
844  char buf[64];
845 
846  sprintf(buf, "%ld", lVal);
847  return ConfigSetStr(pConfig, sSectionName, sKey, buf);
848 }
849 
850 /*!
851  * \brief Set or update an unsigned long value in the configuration database.
852  *
853  * The long value is converted to a string prior to adding to the database.
854  *
855  * \param pConfig Configuration database.
856  * \param sSectionName Configuration section name.
857  * \param sKey Section key.
858  * \param ulVal Section key unsigned long value.
859  *
860  * \return Returns OK(0) on success, RC_ERROR(-1) on failure.
861  */
862 int ConfigSetULong(Config_T *pConfig, const char *sSectionName,
863  const char *sKey, unsigned long ulVal)
864 {
865  char buf[64];
866 
867  sprintf(buf, "%lu", ulVal);
868  return ConfigSetStr(pConfig, sSectionName, sKey, buf);
869 }
870 
871 /*!
872  * \brief Set or update a double value in the configuration database.
873  *
874  * The double value is converted to a string prior to adding to the database.
875  *
876  * \param pConfig Configuration database.
877  * \param sSectionName Configuration section name.
878  * \param sKey Section key.
879  * \param fVal Section key double value.
880  *
881  * \return Returns OK(0) on success, RC_ERROR(-1) on failure.
882  */
883 int ConfigSetDouble(Config_T *pConfig, const char *sSectionName,
884  const char *sKey, double fVal)
885 {
886  char buf[64];
887 
888  sprintf(buf, "%.16f", fVal);
889  return ConfigSetStr(pConfig, sSectionName, sKey, buf);
890 }
891 
892 
893 // ...........................................................................
894 // Configuration Delete Entry Functions
895 // ...........................................................................
896 
897 /*!
898  * \brief Delete entry from the configuration database.
899  *
900  * \param pConfig Configuration database.
901  * \param sSectionName Configuration section name.
902  * \param sKey Section key.
903  *
904  * \return Returns OK(0) on success, RC_ERROR(-1) on failure.
905  */
906 int ConfigDelete(Config_T *pConfig, const char *sSectionName, const char *sKey)
907 {
908  ConfigSection_T *pSect;
909 
910  /* Can't add to an undefined section! */
911  if( (pSect = ConfigSectionGet(pConfig, sSectionName)) == NULL )
912  {
913  LOGDIAG4("%s: [%s]: section not defined",
914  pConfig->m_sMainName, sSectionName);
915  return RC_ERROR;
916  }
917  else if( !hash_delete(pSect->m_hashSection, (char *)sKey) )
918  {
919  LOGDIAG4("%s: [%s]: %s could not delete",
920  pConfig->m_sMainName, sSectionName, sKey);
921  return RC_ERROR;
922  }
923  else
924  {
925  return OK;
926  }
927 }
928 
929 
930 // ...........................................................................
931 // Configuration Iterator Functions
932 // ...........................................................................
933 
934 /*!
935  * \brief Create a new configuration database iterator.
936  *
937  * The iterator will iterator over section names.
938  *
939  * \param pConfig Configuration database.
940  *
941  * \return New iterator.
942  */
944 {
945  ConfigIter_T *pIter;
946 
947  pIter = NEW(ConfigIter_T);
948  hash_scan_begin(&pIter->m_scanHash, pConfig->m_hashMain);
949 
950  return pIter;
951 }
952 
953 /*!
954  * \brief Create a new configuration section iterator.
955  *
956  * The iterator will iterator over section keys.
957  *
958  * \param pConfig Configuration database.
959  * \param sSectionName Configuration section name.
960  *
961  * \return New iterator.
962  */
963 ConfigIter_T *ConfigSectionIterNew(Config_T *pConfig, const char *sSectionName)
964 {
965  ConfigSection_T *pSect;
966  ConfigIter_T *pIter;
967 
968  if( (pSect = ConfigSectionGet(pConfig, sSectionName)) == NULL )
969  {
970  return NULL;
971  }
972  else
973  {
974  pIter = NEW(ConfigIter_T);
975  hash_scan_begin(&pIter->m_scanHash, pSect->m_hashSection);
976  return pIter;
977  }
978 }
979 
980 /*!
981  * \brief Delete a configuration iterator.
982  *
983  * \param pIter Configuration iterator.
984  */
986 {
987  delete(pIter);
988 }
989 
990 /*!
991  * \brief Get the next value in iteration.
992  *
993  * After an iterator is created, the first call will return the first vale.
994  * Subsequent calls return the next values.
995  *
996  * If iterator was created to iterate over the section names, then the values
997  * returned are section names. If the iterator was created to iterate over
998  * section keys, then the values returned are keys.
999  *
1000  * \param pIter Configuration iterator.
1001  *
1002  * \return Returns next value on success, NULL at end of iteration.
1003  */
1004 const char *ConfigIterNext(ConfigIter_T *pIter)
1005 {
1006  hnode_t *pHashNode;
1007 
1008  if( pIter == NULL )
1009  {
1010  return NULL;
1011  }
1012  else if( (pHashNode = hash_scan_next(&pIter->m_scanHash)) == NULL )
1013  {
1014  return NULL;
1015  }
1016  else
1017  {
1018  return hnode_getkey(pHashNode);
1019  }
1020 }
char * m_sMainName
configuration name
Definition: config.c:125
void ConfigIterDelete(ConfigIter_T *pIter)
Delete a configuration iterator.
Definition: config.c:985
char * m_sSectionName
section name
Definition: config.c:116
static int ConfigMainCounter
Definition: config.c:140
#define hnode_getkey(N)
Get hash node hash key.
Definition: hash.h:409
static int ConfigSectionAddPair(ConfigSection_T *pSect, const char *sKey, const char *sVal)
Add or update a key-value pair in the given section.
Definition: config.c:151
int ConfigDelete(Config_T *pConfig, const char *sSectionName, const char *sKey)
Delete entry from the configuration database.
Definition: config.c:906
hnode_t * hash_scan_next(hscan_t *scan)
Retrieve the next node from the hash table.
Definition: hash.c:998
char * new_strdup(const char *s)
Duplicate a string.
Definition: new.c:176
int ConfigSetStr(Config_T *pConfig, const char *sSectionName, const char *sKey, const char *sVal)
Set or update a string value in the configuration database.
Definition: config.c:809
#define CHKPTR(p,...)
Checks validity of pointer.
Definition: log.h:651
#define LOGDIAG3(fmt,...)
Standard Diagnostic Level 3 logging.
Definition: log.h:393
#define OK
Okay.
Definition: rnrconfig.h:301
Configuration parser declarations.
#define NULL
null pointer
Definition: rnrconfig.h:199
General purpose hash data and function declarations.
#define HASH_MAX_ENTRIES
max. num. of section entries
Definition: config.c:104
Memory allocation and deallocation declarations.
hnode_t * hash_lookup(hash_t *hash, const void *key)
Find a node in the hash table and return a pointer to it.
Definition: hash.c:1246
const char * ConfigGetStr(Config_T *pConfig, const char *sSectionName, const char *sKey)
Get a string value from the configuration database.
Definition: config.c:682
void ConfigDbPrint(Config_T *pConfig, FILE *fp)
Print configuration database to the output file stream.
Definition: config.c:514
Config_T * ConfigDbReadFp(FILE *fp, const char *sFileName)
Create a new configuration database from a opened configuration file.
Definition: config.c:364
ConfigIter_T * ConfigDbIterNew(Config_T *pConfig)
Create a new configuration database iterator.
Definition: config.c:943
#define LOGSYSERROR(fmt,...)
Standard System Error logging.
Definition: log.h:509
#define RC_ERROR
common function error return code
Definition: rnrconfig.h:316
bool_t hash_delete(hash_t *hash, void *key)
Unlink and delete a hash node with the given key from the hash table.
Definition: hash.c:1310
#define HASH_MAX_SECTIONS
max. num. of database sections
Definition: config.c:102
Config_T * ConfigDbNew(const char *sMainName)
Create and initialize a new empty configuration database.
Definition: config.c:243
#define LOGERROR(fmt,...)
Standard Error logging.
Definition: log.h:488
#define HASH_MIN_SECTIONS
min. num. of database sections
Definition: config.c:101
#define LOGDIAG4(fmt,...)
Standard Diagnostic Level 4 logging.
Definition: log.h:386
int ConfigSectionDelete(Config_T *pConfig, ConfigSection_T *pSect)
Delete a section from the configuration database.
Definition: config.c:600
ConfigSection_T * ConfigSectionNew(Config_T *pConfig, const char *sSectionName)
Add a new empty section to the configuration database.
Definition: config.c:547
static void ConfigMainHashDeleteCb(void *pKey, void *pData)
Delete section hash callback.
Definition: config.c:212
const char * ConfigIterNext(ConfigIter_T *pIter)
Get the next value in iteration.
Definition: config.c:1004
#define NEW(T)
Allocate new type.
Definition: new.h:49
int ConfigSetULong(Config_T *pConfig, const char *sSectionName, const char *sKey, unsigned long ulVal)
Set or update an unsigned long value in the configuration database.
Definition: config.c:862
#define HASH_INPUT_BUF_SIZE
Maximum input line size.
Definition: config.c:109
void hash_scan_begin(hscan_t *scan, hash_t *hash)
Reset the hash scanner (iterator).
Definition: hash.c:937
ConfigSection_T * ConfigSectionGet(Config_T *pConfig, const char *sSectionName)
Get a section from the configuration database.
Definition: config.c:635
RoadNarrows Robotics common configuration file.
hash_t * m_hashMain
main hash table of sections
Definition: config.c:126
Hash scanner structure.
Definition: hash.h:302
#define _TSTR(var)
string variable
Definition: log.h:578
#define hnode_get(N)
Get hash node user data.
Definition: hash.h:403
hash_t * hash_table_create(bool_t isdynamic, hashcount_t minsize, hashcount_t maxsize, hash_comp_t compfun, hash_fun_t hashfun, hnode_data_free_t freedatafun)
Create a dynamic hash table.
Definition: hash.c:691
int ConfigGetLong(Config_T *pConfig, const char *sSectionName, const char *sKey, long *pVal)
Get and convert a long value from the configuration database.
Definition: config.c:714
void ConfigDbSetName(Config_T *pConfig, const char *sMainName)
Assign a new name for the configuration database.
Definition: config.c:498
#define _TPTR(var)
pointer
Definition: log.h:587
#define LOGDIAG4CALL(...)
Standard Diagnostic Level 4 function call tracing.
Definition: log.h:442
void ConfigDbDelete(Config_T *pConfig)
Delete the configuration database.
Definition: config.c:295
Hash table control structure.
Definition: hash.h:267
int ConfigSetDouble(Config_T *pConfig, const char *sSectionName, const char *sKey, double fVal)
Set or update a double value in the configuration database.
Definition: config.c:883
void ConfigSectionPrint(ConfigSection_T *pSect, FILE *fp)
Print one section to the output file stream.
Definition: config.c:654
int ConfigSetLong(Config_T *pConfig, const char *sSectionName, const char *sKey, long lVal)
Set or update a long value in the configuration database.
Definition: config.c:841
Hash chain node structure.
Definition: hash.h:149
hash_t * m_hashSection
section&#39;s key=value entries hash table
Definition: config.c:117
Logger declarations.
bool_t hash_insert(hash_t *hash, void *key, void *data)
Insert user data with the given key into the hash table.
Definition: hash.c:1283
ConfigIter_T * ConfigSectionIterNew(Config_T *pConfig, const char *sSectionName)
Create a new configuration section iterator.
Definition: config.c:963
int ConfigGetDouble(Config_T *pConfig, const char *sSectionName, const char *sKey, double *pVal)
Get and convert a double value from the configuration database.
Definition: config.c:759
hscan_t m_scanHash
hash table scanner (iterator)
Definition: config.c:134
#define HASH_MIN_ENTRIES
min. num. of section entries
Definition: config.c:103
#define hnode_put(N, V)
Pet hash node user data.
Definition: hash.h:416
const char * ConfigDbGetName(Config_T *pConfig)
Get the current name assigned to the configuration database.
Definition: config.c:486
void hash_table_destroy(hash_t *hash)
Delete the hash table, all of its entries, and all of the user data.
Definition: hash.c:750
static void ConfigSectionHashDeleteCb(void *pKey, void *pData)
Delete section entry hash callback.
Definition: config.c:197
Config_T * ConfigDbRead(const char *sFileName)
Create a new configuration database from a configuration file.
Definition: config.c:326