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