Flow123d  release_1.8.2-1603-g0109a2b
read_ini.cc
Go to the documentation of this file.
1 /*!
2  *
3  * Copyright (C) 2015 Technical University of Liberec. All rights reserved.
4  *
5  * This program is free software; you can redistribute it and/or modify it under
6  * the terms of the GNU General Public License version 3 as published by the
7  * Free Software Foundation. (http://www.gnu.org/licenses/gpl-3.0.en.html)
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11  * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
12  *
13  *
14  * @file read_ini.cc
15  * @ingroup io
16  * @brief OPTIONS RUTINES - get program parameters, reading from options/ini file
17  * @section DESCRIPTION
18  *
19  * Functions OptGet* are implemented through OptGetStr - only one interface routine for
20  * various implementation the parameter default is always char *, which can be NULL in the case that
21  * explicit value is necessary and program should produce an error if corresponding
22  * parameter is not given.
23  *
24  * Current implementation is based on SimpleINI C++ library.
25  *
26  */
27 
28 #include <strings.h>
29 #include <string.h>
30 #include <unistd.h>
31 #include <limits.h>
32 
33 #include "system/system.hh"
34 #include "system/xio.h"
35 #include "io/read_ini.h"
36 
37 #include <boost/tokenizer.hpp>
38 #include "boost/lexical_cast.hpp"
39 #include <boost/algorithm/string.hpp>
40 
41 static struct Read_ini *read_ini = NULL;
42 
43 #define FOR_INI_ITEMS(i) for((i)=read_ini->ini_item;(i)!=NULL;(i)=(i)->next)
44 
45 static void make_ini_item_list(const char *fname);
46 static char *section_test(char *section);
47 static char *strip_spaces(char *string);
48 static struct Ini_item *new_item(struct Ini_item *prev,char *section, char *key, char *value);
49 
50 //#define xOptGetStr(s,k) (ini.GetValue(s,k,NULL))
51 
52 //=============================================================================
53 // MAKE INI KEYS LIST
54 //=============================================================================
55 void make_ini_item_list(const char *fname)
56 {
57  FILE *ini;
58 
59  char line[ LINE_SIZE ];
60  char string[ LINE_SIZE ];
61  char section[ LINE_SIZE ];//="";
62  char *section_ptr;
63  char *key;
64  char *value;
65  char *tmp;
66  struct Ini_item *prev = NULL;
67 
68  read_ini=(struct Read_ini*)xmalloc(sizeof(struct Read_ini));
69 
70  ini=xfopen(fname,"rt");
71  OLD_ASSERT( ini,"Failed to open the ini file: %s",fname);
72 
73 
74  while( xfgets( line, LINE_SIZE - 2, ini ) != NULL ) {
75  sscanf( line, "%s", string ); // store first substring in the string
76 
77 
78  if (strlen(string)==0) // skips start blank lines
79  continue;
80 
81  // READ SECTION
82  section_ptr = section_test(string);
83  if ( section_ptr ) { // test of new section
84  strcpy(section,section_ptr);
85  continue; // go to next line
86  }
87 
88  if(strchr(line,'=') == NULL) // test of "=" character on the line
89  continue;
90 
91  // CLEAR COMMENTS
92  tmp = strstr(line,"#"); // find comment position
93  if(tmp != NULL){
94  sprintf(tmp,"%s",""); // force ends string on comment position
95  if(strlen(line) == 0) // continue if line contains only comment
96  continue; // go to next line
97  }
98 
99  // READ KEY
100  tmp = xstrtok(line,"="); // read characters before "="
101  sscanf(tmp,"%s",string); // strip spaces
102  if(strlen(string) == 0)
103  continue;
104  else
105  key = xstrcpy(string);
106 
107 
108  //READ VALUE
109  tmp = xstrtok(NULL,"=");
110  tmp = strip_spaces(tmp);
111  if(strlen(tmp) == 0){ //string
112  xfree(key);
113  continue;
114  }
115  else
116  value = xstrcpy(tmp);
117 
118 /*
119  printf("%s\n",section);
120  printf("%s\n",key);
121  printf("%s\n\n",value);
122 */
123 
124  prev = new_item(prev,section,key,value);
125  xfree(key);
126  xfree(value);
127  };
128 };
129 //=============================================================================
130 // STRIP START AND END BLANK CHARACTERS
131 //=============================================================================
132 char *strip_spaces(char *string)
133 {
134  int i;
135  while((string[0] ==' ') || (string[0] =='\t')){
136  string++;
137  }
138  i = strlen(string) - 1;
139  while((string[i] ==' ') || (string[i] =='\t') || (string[i] =='\n') || (string[i] =='\r')){
140  string[i--] = 0;
141  }
142  return string;
143 }
144 //=============================================================================
145 // ADD NEW KEY TO INI-LIST
146 //=============================================================================
147 struct Ini_item *new_item(struct Ini_item *prev,char *section, char *key, char *value)
148 {
149  struct Ini_item *ini_item;
150 
151  if((section != NULL) && (key != NULL) && (value != NULL)){
152  ini_item=(struct Ini_item*)xmalloc(sizeof(struct Ini_item));
153 
154  if(prev == NULL){
155  read_ini->ini_item = ini_item;
156  ini_item->prev = NULL;
157  }
158  else{
159  ini_item->prev = prev;
160  ini_item->next = NULL;
161  prev->next = ini_item;
162  }
163 
164  ini_item->section = xstrcpy(section);
165  ini_item->key = xstrcpy(key);
166  ini_item->value = xstrcpy(value);
167  return ini_item;
168  }
169  else
170  return prev;
171 
172 }
173 //=============================================================================
174 // TEST OF SECTION STRING
175 //=============================================================================
176 char *section_test(char *line)
177 {
178  if(line == NULL) return NULL;
179 
180  if( (line[0] == '[') && (line[strlen(line)-1] == ']') && (strlen(line) > 2))
181  return (xstrtok(line,"[]"));
182  else
183  return (NULL);
184 };
185 
186 /*!
187  * @brief Create new string from selected variable from ini file
188  * @param[in] section Inifile section
189  * @param[in] key Inifile key
190  * @param[in] defval Default value, if key is not found in inifile
191  * @return Ptr to new string with option value from Inifile or to default value
192  */
193 char *OptGetStr(const char *section,const char *key,const char *defval)
194 {
195  xprintf(Err, "OptGetXXX input interface is not supported anymore.\n");
196 
197 
198  const char *rc = NULL;
199  struct Ini_item *ini_item;
200 
201  FOR_INI_ITEMS(ini_item)
202  if( (!strcmp(ini_item->section,section)) && (!strcmp(ini_item->key,key)) ){
203  rc = ini_item->value;
204  break;
205  }
206 
207  if (rc == NULL) {
208  if (defval == NULL)
209  xprintf(UsrErr,"Required parameter: section '%s' key '%s' is not given.\n",section,key);
210  else
211  rc = defval;
212  }
213 
214  return xstrcpy(rc);
215 }
216 
217 //=============================================================================
218 // GET FILE NAME VARIABLE FROM INI FILE
219 //=============================================================================
220 char *OptGetFileName(const char *section,const char *key,const char *defval)
221 {
222 
223 
224  return OptGetStr(section,key,defval);
225 }
226 
227 //=============================================================================
228 // GET INT VARIABLE FROM INI FILE
229 //=============================================================================
230 long int OptGetInt( const char *section,const char *key,const char *defval )
231 {
232  char *str;
233  long int res;
234 
235  str=OptGetStr(section,key,defval);
236  if (sscanf(str,"%ld",&res) == 0) {
237  if (defval == NULL) xprintf(UsrErr,"Can not convert to integer parameter: [%s] %s.\n",section,key);
238  xprintf(PrgErr,"Default value %s of parameter: [%s] %s is not an integer.\n",defval,section,key);
239  }
240 
241  xfree( str );
242  return res;
243 }
244 
245 //=============================================================================
246 // GET DOUBLE VARIABLE FROM INI FILE
247 //=============================================================================
248 double OptGetDbl( const char *section,const char *key,const char *defval )
249 {
250  char *str;
251  double res;
252 
253  str=OptGetStr(section,key,defval);
254  if (sscanf(str,"%lg",&res) == 0) {
255  if (defval == NULL) xprintf(UsrErr,"Can not convert to double parameter: [%s] %s.\n",section,key);
256  if (sscanf(defval,"%lg",&res) == 0)
257  xprintf(PrgErr,"Default value \"%s\" of parameter: [%s] %s is not an double.\n",defval,section,key);
258  }
259 
260  xfree( str );
261  return res;
262 }
263 
264 //=============================================================================
265 // GET BOOL VARIABLE FROM INI FILE
266 //=============================================================================
267 bool OptGetBool( const char *section,const char *key,const char *defval )
268 {
269  char *str;
270  char res=false;
271  str = OptGetStr(section, key, defval);
272 
273  if ( boost::iequals(str, "yes") || boost::iequals(str, "true") || boost::iequals(str, "1") ) res=true;
274  else if ( boost::iequals(str, "no") || boost::iequals(str, "false") || boost::iequals(str, "0") ) res=false;
275  else {
276  xfree(str);
277  if (defval == NULL) xprintf(UsrErr,"Required parameter: [%s] %s is not a boolen.\n",section,key);
278  str=(char *)defval;
279  if ( boost::iequals(str, "yes") || boost::iequals(str, "true") || boost::iequals(str, "1") ) res=true;
280  else if ( boost::iequals(str, "no") || boost::iequals(str, "false") || boost::iequals(str, "0") ) res=false;
281  else xprintf(PrgErr,"Default value \"%s\" of parameter: [%s] %s is not a boolean.\n",defval,section,key);
282  }
283  return res;
284 }
285 /*!
286  * @brief Load options file
287  * @param[in] fname File name
288  */
289 void OptionsInit(const char *fname )
290 {
291  //char *path;
292  //int len;
293 
294  OLD_ASSERT( fname,"NULL file name\n");
295 
296  // take absolute path to the file
297  // this is completly wrong in the case the absolute path is alredy given
298  // since we should remain in the workdir when calling this it is not critical
299  // to hava correct function for path manipulation (see BOOST)
300  /*
301  path=xgetcwd();
302  len=strlen(path)+strlen(fname)+1;
303  if ( len > PATH_MAX )
304  {
305  xprintf(UsrErr, "Path too long\n");
306  }
307  strcpy( options_fname, path ); xfree(path);
308  strcat( options_fname, PATH_SEP );
309  strcat( options_fname, fname );
310 */
311 
312  // initialization of the INI reader
313  make_ini_item_list(fname);
314 
315 }
316 
317 //=============================================================================
318 // GET DOUBLE ARRAY VARIABLE FROM INI FILE
319 //=============================================================================
320 void OptGetDblArray( const char *section,const char *key,const char *defval, std::vector<double> &array)
321 // ArrSize contain number of Array members (length), *Array is the adress of array which should be filled up
322 {
323 
324  char * tmp_str = OptGetStr(section,key,defval);
325  std::string str = tmp_str;
326  free(tmp_str);
327  boost::tokenizer<boost::char_separator<char> > line_tokenizer(str, boost::char_separator<char>("\t "));
328  boost::tokenizer<boost::char_separator<char> >::iterator tok;
329 
330  double value;
331  try {
332  for( tok = line_tokenizer.begin();
333  tok != line_tokenizer.end();
334  ++tok) {
335  value = boost::lexical_cast<double> (*tok);
336  array.push_back(value);
337  }
338  } catch (boost::bad_lexical_cast &) {
339  xprintf(UsrErr, "INI file: Can not convert token `%s` of key `[%s] %s` to double.\n", (*tok).c_str(), section, key);
340  }
341 }
342 
343 
344 //=============================================================================
345 // GET Int ARRAY VARIABLE FROM INI FILE
346 //=============================================================================
347 void OptGetIntArray( const char *section,const char *key,const char *defval, int ArrSize, int *Array)// ArrSize contain number of Array members (length), *Array is the adress of array which should be filled up
348 {
349  char *str;
350  int res;
351  int i;
352 
353  str=OptGetStr(section,key,defval);
354  for(i = 1; i < ArrSize; i++){
355  if (sscanf(str,"%d",&res) == 0) {
356  if (defval == NULL) xprintf(UsrErr,"Can not convert %d. ini-file entry to integer parameter: [%s] %s.\n",i,section,key);
357  if (sscanf(defval,"%d",&res) == 0)
358  xprintf(PrgErr,"Default value \"%s\" of parameter: [%s] %s is not an integer.\n",defval,section,key);
359  }else{
360  *(Array + (i-1)*sizeof(double)) = res;
361  }
362  }
363 
364  free( str );
365  return;
366 }
367 
368 //=============================================================================
369 // GET string ARRAY VARIABLE FROM INI FILE
370 //=============================================================================
371 /*char *OptGetStrArray(const char *section,const char *key, int sb_count, struct TS_lat *dest)
372 {
373  const char **rc = NULL;
374  struct Ini_item *ini_item;
375  int i;
376 
377  FOR_INI_ITEMS(ini_item)
378  if( (!strcmp(ini_item->section,section)) && (!strcmp(ini_item->key,key)) ){
379  for(i=0; i < sb_count; i++)
380  {
381  if(sscanf(ini_item->value,"%s",dest[i].nazev) == NULL)
382  {
383  printf("\nerror during required %d-th parameter initialization occured\n",i);
384  }else{
385  printf("\nthe name of %d-th substance is %s\n",i,dest[i].nazev);
386  }
387  }
388  //
389  *rc = ini_item->value;
390  break;
391  }
392 
393  if (rc == NULL) {
394  if (defval == NULL)
395  xprintf(UsrErr,"Required parameter: [%s] %s is not given.\n",section,key);
396  else
397  *rc = defval;
398  }
399  return xstrcpy(*rc);
400 }*/
401 
struct Ini_item * ini_item
Definition: read_ini.h:32
void OptGetDblArray(const char *section, const char *key, const char *defval, std::vector< double > &array)
Definition: read_ini.cc:320
char * xfgets(char *s, int n, FILE *in)
FGETS WITH ERROR HANDLING and line count.
Definition: xio.cc:563
bool OptGetBool(const char *section, const char *key, const char *defval)
Definition: read_ini.cc:267
char * xstrcpy(const char *src)
MAKE BRAND NEW COPY OF STRING.
Definition: system.cc:280
struct Ini_item * next
Definition: read_ini.h:37
char * value
Definition: read_ini.h:41
I/O functions with filename storing, able to track current line in opened file. All standard stdio fu...
char * OptGetFileName(const char *section, const char *key, const char *defval)
Definition: read_ini.cc:220
static struct Read_ini * read_ini
Definition: read_ini.cc:41
#define OLD_ASSERT(...)
Definition: global_defs.h:128
void OptGetIntArray(const char *section, const char *key, const char *defval, int ArrSize, int *Array)
Definition: read_ini.cc:347
void OptionsInit(const char *fname)
Load options file.
Definition: read_ini.cc:289
#define xprintf(...)
Definition: system.hh:87
#define LINE_SIZE
Definition: xio.h:37
char * section
Definition: read_ini.h:39
static char * section_test(char *section)
Definition: read_ini.cc:176
static struct Ini_item * new_item(struct Ini_item *prev, char *section, char *key, char *value)
Definition: read_ini.cc:147
long int OptGetInt(const char *section, const char *key, const char *defval)
Definition: read_ini.cc:230
double OptGetDbl(const char *section, const char *key, const char *defval)
Definition: read_ini.cc:248
#define FOR_INI_ITEMS(i)
Definition: read_ini.cc:43
char * key
Definition: read_ini.h:40
void * xmalloc(size_t size)
Memory allocation with checking.
Definition: system.cc:198
static void make_ini_item_list(const char *fname)
Definition: read_ini.cc:55
Definition: system.hh:59
Definition: system.hh:59
struct Ini_item * prev
Definition: read_ini.h:38
char * xstrtok(char *s, int position)
STRTOK WITH ERROR HANDLING and whitespace delimiters.
Definition: system.cc:298
Definition: system.hh:59
#define xfree(p)
Definition: system.hh:95
static char * strip_spaces(char *string)
Definition: read_ini.cc:132
FILE * xfopen(const std::string &fname, const char *mode)
Definition: xio.cc:229
char * OptGetStr(const char *section, const char *key, const char *defval)
Create new string from selected variable from ini file.
Definition: read_ini.cc:193