LORENE
read_variable.C
1//======================================================================
2// some general-purpose routines for config-file reading
3//======================================================================
4
5/*
6 * Copyright (c) 2003 Reinhard Prix
7 *
8 * This file is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This file is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with LORENE; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 *
22 */
23char read_variable_C[] = "$Header: /cvsroot/Lorene/C++/Source/Non_class_members/Utilities/read_variable.C,v 1.10 2014/10/13 08:53:32 j_novak Exp $";
24
25#include <cstdlib>
26#include <cstring>
27#include <cstdio>
28#include <cctype>
29
30#include "headcpp.h"
31#include "utilitaires.h"
32
33namespace Lorene {
34
35/*----------------------------------------------------------------------
36 * load_file: does just that plus takes care of memory allocation
37 *
38 * !!!!! --> don't forget to free the data after use !!!!!
39 *
40 * returns NULL on error
41 *----------------------------------------------------------------------*/
42char *load_file (const char *fname)
43{
44 FILE *fp;
45 char *data;
46 size_t size, read_size;
47
48 if( (fp = fopen (fname, "r")) == NULL)
49 {
50 cout << "ERROR: Could not open config-file: '" << fname << "'\n";
51 return (NULL);
52 }
53
54 size = FS_filelength (fp);
55
56 // Now read in the raw data
57 data = static_cast<char*> (MyMalloc (size+10));
58 read_size = fread ( data, 1, size, fp);
59 data [read_size] = '\0'; // properly terminate as string!
60
61 fclose (fp);
62
63 return (data);
64
65} // load_file()
66
67/*----------------------------------------------------------------------
68 * char *read_file_buffered (fname)
69 *
70 * just a buffer for load_file: if fname is NULL or the same as last one,
71 * then return buffered copy, otherwise free old one and get a new one
72 *
73 * ----------------------------------------------------------------------*/
74char *
75load_file_buffered (const char *fname)
76{
77 static char *prev_fname = NULL;
78 static char *data = NULL;
79
80 if (!fname) // fname=NULL: return buffered copy
81 return (data);
82
83 if ( prev_fname && !strcmp(prev_fname, fname) ) // fname=prev_name: return buffered copy
84 return (data);
85
86 // we're dealing with a new file here, so read it in properly
87 if (data) // free old data
88 free(data);
89
90 data = load_file (fname);
91
92 return (data);
93
94} // load_file_buffered()
95
96
97#define ERR -1
98#define OK 0
99#define FMT_STRING "string" // reading in strings needs some special treatment
100
101/*----------------------------------------------------------------------
102 * parser for config-files: can read config-variables of the form
103 * VARIABLE [=: \t] VALUE
104 * everything else is ignored as comments
105 *
106 * RETURN: -1 if VARIABLE was not found or could not be read,
107 * 0 if found&read
108 * ----------------------------------------------------------------------*/
109int
110read_variable (const char *fname, const char *var_name, char *fmt, void *varp)
111{
112 char *found = NULL;
113 char *seek, *pos, *bol;
114 int ret;
115 int before, after;
116 char *data;
117 int len;
118
119 if ( (data = load_file_buffered (fname)) == NULL )
120 return ERR;
121
122 seek = data;
123 while (!found)
124 {
125 if ( (pos = strstr(seek, var_name)) == NULL)
126 break; // we didn't find anything
127 seek = pos + strlen (var_name); // move data-pointer beyond current position in case we continue
128
129 // make sure we didn't just find a substring:
130 if (pos > data)
131 before = *(pos-1);
132 else
133 before = 0;
134
135 after = *(pos+strlen(var_name));
136
137 if ( isalnum(before) || isalnum(after) || (before == '_') || (after == '_') )
138 continue;
139
140 // find beginning of this line: bol
141 bol = (pos > data) ? pos - 1 : data;
142 while ( (bol > data) && (*bol != '\n') )
143 bol --;
144 if ( *bol == '\n' ) bol++;
145
146 // don't allow anything but whitespace before variable-name
147 if (pos > bol)
148 if ( strspn(bol, " \t") != static_cast<size_t>(pos - bol) )
149 continue; // must have been a commentary ...
150
151 found = pos; // ok, that's it
152 }
153
154 if (!found)
155 {
156 cout << "ERROR: variable " << var_name << " was not found in config-file!\n";
157 return (ERR);
158 }
159
160 found += strlen (var_name);
161
162 // skip {space,tab,=,:}
163 found += strspn(found, " \t=:");
164
165 // now read the value into the variable
166
167 // reading a string needs some special treatment:
168 if ( !strcmp(fmt, FMT_STRING) )
169 {
170 if ( *found == '"') // skip quotes
171 {
172 if ( (pos = strchr(found+1, '"')) == NULL ) // find delimiting quotes
173 {
174 cout << "ERROR: no closing quotes found \n";
175 return (ERR);
176 }
177 found ++;
178 } /* if quoted string */
179 else
180 {
181 if ( (pos = strchr (found, '\n')) == NULL) // end of line?
182 pos = data + strlen(data); // end of file
183 } /* if not quoted */
184
185 // NOTE: varp here is supposed to be a pointer to char* !!
186 char **cstr = static_cast<char**>(varp);
187 len = int(pos - found); // length of string excluding \0
188 (*cstr) = static_cast<char*>(MyMalloc(len+1));
189 strncpy ((*cstr), found, len);
190 (*cstr)[len] = '\0';
191 ret = 1;
192 } /* if fmt == string */
193 else // the default case is just sscanf...
194 ret = sscanf (found, fmt, varp);
195
196
197 if ( (ret == 0) || (ret == EOF) )
198 {
199 cout << "WARNING: Variable " << var_name <<" was not readable using the format '"<<fmt<<"'\n";
200 return (ERR);
201 }
202
203 return (OK);
204
205} // read_variable
206
207/* ----------------------------------------------------------------------
208 * specialize to a few common types:
209 *----------------------------------------------------------------------*/
210int
211read_variable (const char *fname, const char *var_name, int &var)
212{
213 int ret = read_variable(fname, var_name, const_cast<char*>("%d"), &var);
214
215 cout << "DEBUG: " << var_name << " = " << var <<endl;
216
217 return (ret);
218}
219
220int
221read_variable (const char *fname, const char *var_name, bool &var)
222{
223 int buf;
224 int ret = read_variable(fname, var_name, const_cast<char*>("%d"), &buf);
225
226 var = static_cast<bool>(buf);
227
228 cout << "DEBUG: " << var_name << " = " << var <<endl;
229
230 return (ret);
231}
232
233int
234read_variable (const char *fname, const char *var_name, double &var)
235{
236 int ret = read_variable(fname, var_name, const_cast<char*>("%lf"), &var);
237
238 cout << "DEBUG: " << var_name << " = " << var <<endl;
239
240 return (ret);
241}
242
243int
244read_variable (const char *fname, const char *var_name, char **str)
245{
246 char *cstr;
247
248 if (*str != NULL)
249 {
250 cout << "ERROR: return-string needs to be NULL in read_variable()\n";
251 return (ERR);
252 }
253
254 int ret = read_variable(fname, var_name, const_cast<char*>(FMT_STRING), &cstr);
255
256 if ((ret == OK) && cstr)
257 *str = cstr;
258
259 cout << "DEBUG: " << var_name << " = " << *str <<endl;
260
261 return (ret);
262
263}
264
265
266
267/*----------------------------------------------------------------------
268 * FS_filelength().. (taken from quake2)
269 * contrary to stat() this fct is nice and portable,
270 *----------------------------------------------------------------------*/
271int
273{
274 int pos;
275 int end;
276
277 pos = int(ftell (f));
278 fseek (f, 0, SEEK_END);
279 end = int(ftell (f));
280 fseek (f, pos, SEEK_SET);
281
282 return end;
283}
284
285/*@Function============================================================
286@Desc: This function works like malloc, except that it also checks for
287 success and terminates in case of "out of memory", so we dont
288 need to do this always in the code.
289
290@Ret:
291* $Function----------------------------------------------------------*/
292void *
294{
295 void *Mptr = NULL;
296
297 // make Gnu-compatible even if on a broken system:
298 if (bytes == 0)
299 bytes = 1;
300
301 if ((Mptr = calloc (1, bytes)) == NULL)
302 {
303 cout << "MyMalloc("<< bytes << ") did not succeed! Terminating...\n";
304 exit (-1);
305 }
306
307 return (Mptr);
308
309} // void* MyMalloc
310
311}
Time evolution with partial storage (*** under development ***).
Definition evolution.h:371
char * load_file_buffered(char *fname)
Returns pointer to data from a file using a buffer.
char * load_file(char *fname)
Read file into memory and returns pointer to data.
int FS_filelength(FILE *f)
A portable routine to determine the length of a file.
void * MyMalloc(long bytes)
'Improved' malloc that sets memory to 0 and also auto-terminates on error.
int read_variable(const char *fname, const char *var_name, char *fmt, void *varp)
Reads a variable from file.
Lorene prototypes.
Definition app_hor.h:64