XGCa
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
NamelistReader.hpp
Go to the documentation of this file.
1 #ifndef NAMELISTREADER_HPP
2 #define NAMELISTREADER_HPP
3 
4 #include <iostream>
5 #include <sstream>
6 #include <fstream>
7 #include <string>
8 #include <vector>
9 #include <algorithm>
10 #include <cctype>
11 
12 namespace NLReader{
13 
14 using namespace std;
15 
16 enum Expect {
23 };
24 
25 enum ReadFrom {
28 };
29 
30 enum Create {
32 };
33 
34 // trim from left
35 inline string& ltrim(string& s, const char* t = " \t\n\r\f\v")
36 {
37  s.erase(0, s.find_first_not_of(t));
38  return s;
39 }
40 
41 // trim from right
42 inline string& rtrim(string& s, const char* t = " \t\n\r\f\v")
43 {
44  s.erase(s.find_last_not_of(t) + 1);
45  return s;
46 }
47 
48 // trim from left & right
49 inline string& trim(string& s, const char* t = " \t\n\r\f\v")
50 {
51  return ltrim(rtrim(s, t), t);
52 }
53 
54 struct Param{
55  string name;
56  bool used;
57  vector<string> values;
58 
59  Param(string name)
60  : name(name), used(false)
61  {}
62 };
63 
64 struct NameList{
65  string name;
66  vector<Param> params;
67 
68  NameList(string name)
69  : name(name)
70  {}
71 
72  void add_param(string word)
73  {
74  params.push_back(Param(word));
75  }
76 
77  void add_value(string word)
78  {
79  params[params.size()-1].values.push_back(word);
80  }
81 };
82 
83 static inline string get_first_word(string& str, int start){
84  for (string::size_type i = start; i < str.size(); i++){
85  if ((str[i]>=48 && str[i]<=57) || (str[i]>=65 && str[i]<=90) ||
86  (str[i]>=97 && str[i]<=122) || str[i]==95){
87  // still in word (0-9, A-Z, a-z, _)
88  } else {
89  // Not in word
90  return str.substr(start, i-start);
91  }
92  }
93  return str.substr(start,str.size()-start);
94 }
95 
96 static inline string get_first_value(string& str, int start){
97  bool in_squote=false;
98  bool in_dquote=false;
99  for (string::size_type i = start; i < str.size(); i++){
100  if (in_dquote==true || in_squote==true){
101  if (str[i]==34) in_dquote=false;
102  if (str[i]==39) in_squote=false;
103  } else {
104  if (str[i]==34) in_dquote=true;
105  if (str[i]==39) in_squote=true;
106  if (str[i]=='!' || str[i]==' ' || str[i]=='\t'|| str[i]=='\r'|| str[i]=='\f'|| str[i]=='\v'){
107  // Not in word
108  return str.substr(start, i-start);
109  }
110  }
111  }
112  return str.substr(start,str.size()-start);
113 }
114 
115 template<typename T>
116 static inline T string_to_param(string& param);
117 
118 template<>
119 bool string_to_param<bool>(string& param){
120  // Make lower case
121  for (int i = 0; i<param.size(); i++)
122  param[i]=tolower(param[i]);
123 
124  if (param==".false."){
125  return false;
126  } else if (param==".true."){
127  return true;
128  } else {
129  printf("Error, couldn't parse %s \n", param.c_str());
130  return false;
131  }
132 }
133 
134 static inline void change_D_to_E(string& param){
135  for (int i = 0; i<param.size(); i++)
136  if (param[i]=='D' || param[i]=='d') param[i]='e';
137 }
138 
139 template<>
140 int string_to_param<int>(string& param){
141  change_D_to_E(param);
142  return stoi(param);
143 }
144 
145 template<>
146 float string_to_param<float>(string& param){
147  change_D_to_E(param);
148  return stof(param);
149 }
150 
151 template<>
152 double string_to_param<double>(string& param){
153  change_D_to_E(param);
154  return stod(param);
155 }
156 
157 template<>
158 string string_to_param<string>(string& param){
159  // Remove the quotes
160  return param.substr(1,param.size()-2);
161 }
162 
164  vector<NameList> namelists;
166  bool use_all;
168 
169  template<class T>
170  void parse_lines(T& newfile, const string& filename){
171  const bool verbose=false;
172  string line;
173  Expect expect = Ampersand;
174  int i_line=0;
175  while(getline(newfile, line)){ //read data from file object and put it into string.
176  i_line++;
177  trim(line); // Remove leading and trailing whitespace
178  for (string::size_type i = 0; i < line.size(); i++){
179  if (line[i]=='!'){
180  // Comment has begun
181  break;
182  }
183  if (expect==Ampersand){
184  if (line[i]=='&'){
185  expect=NLName;
186  }
187  } else if (expect==NLName){
188  string word = get_first_word(line,i);
189  if (word.size()>0){ // Found namelist name
190  expect = ParaNameOrEnd;
191  namelists.push_back(NameList(word));
192  if (verbose) cout << "Found namelist: " << word << "\n";
193  break;
194  }
195  } else if(expect==ParaNameOrEnd){
196  if (line[i]=='/'){ // End of namelist
197  expect=Ampersand;
198  break;
199  }
200 
201  string word = get_first_word(line,i);
202  if (word.size()>0){
203  i+=word.size()-1;
204  expect = Equals;
205  namelists[namelists.size()-1].add_param(word);
206  if (verbose) cout << " Found parameter: " << word << "\n";
207  }
208  } else if(expect==Equals){
209  if (line[i]=='='){
210  expect=Value;
211  }
212  } else if(expect==Value || expect == ValueOrEOL){
213  string word = get_first_value(line,i);
214  if (word.size()>0){
215  i+=word.size()-1;
216  expect = ValueOrEOL;
217  namelists[namelists.size()-1].add_value(word);
218  if (verbose) cout << " Found Value: " << word << "\n";
219  }
220  }
221  }
222  // Got to end of line
223  if (expect==NLName){
224  printf("\nParse failure reading %s at Line %d. Failed to find name of namelist.\n", filename.c_str(), i_line);
225  return;
226  } else if(expect==Equals){
227  printf("\nParse failure reading %s at Line %d. Expected parameter assignment.\n", filename.c_str(), i_line);
228  return;
229  } else if(expect==Value){
230  printf("\nParse failure reading %s at Line %d. Couldn't parse value assignment.\n", filename.c_str(), i_line);
231  return;
232  }
233  // Hit EOL, now expecting next parameter
234  if (expect==ValueOrEOL) expect = ParaNameOrEnd;
235  }
236  }
237 
238  void load(const string& filename){
239  fstream newfile;
240  newfile.open(filename,ios::in); //open a file to perform read operation using file object
241  if (!newfile.is_open()) return; //checking whether the file is open
242 
243  parse_lines(newfile,filename);
244 
245  newfile.close(); //close the file object.
246  }
247 
248  void load_from_string(const string& str){
249  istringstream f(str.c_str());
250 
251  parse_lines(f,"string input");
252  }
253 
254  public:
255 
256  NamelistReader(const string& filename)
257  : namelist_index(-1), use_all(false), modifiable(false)
258  {
259  load(filename);
260  }
261 
262  NamelistReader(const string& str_name, ReadFrom read_from)
263  : namelist_index(-1), use_all(false), modifiable(false)
264  {
265  if (read_from==ReadFromFile){
266  load(str_name);
267  }else{
268  load_from_string(str_name);
269  }
270  }
271 
273  : namelist_index(-1), use_all(false), modifiable(false)
274  {
275  if (create==CreateManually) modifiable = true;
276  }
277 
279  modifiable = true;
280  }
281 
282  void add_namelist(const string& namelist){
283  if (modifiable){
284  namelists.push_back(NameList(namelist));
285  } else {
286  printf("Warning: 'add_namelist' ignored, only valid if NamelistReader is in CreateManually mode");
287  }
288  }
289 
290  void add_to_namelist(const string& param, const string& val){
291  if (modifiable){
292  namelists[namelists.size()-1].add_param(param);
293  namelists[namelists.size()-1].add_value(val);
294  } else {
295  printf("Warning: 'add_to_namelist' ignored, only valid if NamelistReader is in CreateManually mode");
296  }
297  }
298 
299  void add_to_param(const string& val){
300  if (modifiable){
301  namelists[namelists.size()-1].add_value(val);
302  } else {
303  printf("Warning: 'add_to_param' ignored, only valid if NamelistReader is in CreateManually mode");
304  }
305  }
306 
308  int n_unused=0;
309  for (vector<NameList>::iterator nl = namelists.begin(); nl != namelists.end(); ++nl) {
310  for (vector<Param>::iterator param = nl->params.begin(); param != nl->params.end(); ++param ) {
311  if (param->used==false){
312  printf("Warning: '%s' was present in '%s' but was not used.\n",param->name.c_str(), nl->name.c_str());
313  n_unused++;
314  }
315  }
316  }
317  return (n_unused==0);
318  }
319 
320  bool namelist_present(const string& namelist){
321  // Locate the requested namelist
322  vector<NameList>::iterator it = namelists.begin();
323  while (it!=namelists.end()) {
324  if ((*it).name==namelist) break;
325  ++it;
326  }
327  return it != namelists.end();
328  }
329 
330  void use_namelist(const string& namelist){
331  // Locate the requested namelist
332  vector<NameList>::iterator it = namelists.begin();
333  while (it!=namelists.end()) {
334  if ((*it).name==namelist) break;
335  ++it;
336  }
337  if (it != namelists.end()){
338  namelist_index = distance(namelists.begin(), it);
339  }else{
340  printf("\nNamelist '%s' not found in the file!",namelist.c_str());
341  exit(1);
342  }
343  }
344 
345  bool present(const string& param){
346  if (namelist_index==-1){
347  printf("\nNeed to choose which namelist to use with use_namelist(const std::string&)!\n");
348  }
349 
350  // Locate the requested parameter
351  vector<Param>::iterator it = namelists[namelist_index].params.begin();
352  while (it!=namelists[namelist_index].params.end()) {
353  if ((*it).name==param) break;
354  ++it;
355  }
356 
357  return (it != namelists[namelist_index].params.end());
358  }
359 
360  template <typename T>
361  T get(const string& param, const T default_val, int val_ind=0){
362  if (namelist_index==-1){
363  printf("\nNeed to choose which namelist to use with use_namelist(const std::string&)!\n");
364  }
365 
366  // Locate the requested parameter
367  int param_index = -1;
368  vector<Param>::iterator it = namelists[namelist_index].params.begin();
369  while (it!=namelists[namelist_index].params.end()) {
370  if ((*it).name==param) break;
371  ++it;
372  }
373 
374  if (it != namelists[namelist_index].params.end())
375  param_index = distance(namelists[namelist_index].params.begin(), it);
376  else{
377  return default_val;
378  }
379 
380  namelists[namelist_index].params[param_index].used=true;
381 
382  if (val_ind>=0 && val_ind<namelists[namelist_index].params[param_index].values.size()){
383  string str_var = namelists[namelist_index].params[param_index].values[val_ind];
384  return string_to_param<T>(str_var);
385  } else {
386  printf("\nParameter '%s' in namelist '%s' didn't have enough values!",param.c_str(),namelists[namelist_index].name.c_str());
387  exit(1);
388  return default_val;
389  }
390  }
391 
392  template <typename T>
393  T get_required(const string& param, int val_ind=0){
394  if (namelist_index==-1){
395  printf("\nNeed to choose which namelist to use with use_namelist(const std::string&)!\n");
396  }
397 
398  // Locate the requested parameter
399  int param_index = -1;
400  vector<Param>::iterator it = namelists[namelist_index].params.begin();
401  while (it!=namelists[namelist_index].params.end()) {
402  if ((*it).name==param) break;
403  ++it;
404  }
405 
406  if (it != namelists[namelist_index].params.end())
407  param_index = distance(namelists[namelist_index].params.begin(), it);
408  else{
409  printf("\nParameter '%s' not found in namelist '%s'!",param.c_str(),namelists[namelist_index].name.c_str());
410  exit(1);
411  }
412 
413  namelists[namelist_index].params[param_index].used=true;
414 
415  if (val_ind>=0 && val_ind<namelists[namelist_index].params[param_index].values.size()){
416  string str_var = namelists[namelist_index].params[param_index].values[val_ind];
417  return string_to_param<T>(str_var);
418  } else {
419  printf("\nParameter '%s' in namelist '%s' didn't have enough values!",param.c_str(),namelists[namelist_index].name.c_str());
420  exit(1);
421  }
422  }
423 };
424 
425 }
426 #endif
static void change_D_to_E(string &param)
Definition: NamelistReader.hpp:134
void add_value(string word)
Definition: NamelistReader.hpp:77
bool modifiable
Definition: NamelistReader.hpp:167
Definition: NamelistReader.hpp:64
void add_to_param(const string &val)
Definition: NamelistReader.hpp:299
void add_namelist(const string &namelist)
Definition: NamelistReader.hpp:282
void enable_modifications()
Definition: NamelistReader.hpp:278
void load_from_string(const string &str)
Definition: NamelistReader.hpp:248
Definition: NamelistReader.hpp:21
Definition: NamelistReader.hpp:31
Definition: NamelistReader.hpp:20
void load(const string &filename)
Definition: NamelistReader.hpp:238
vector< string > values
Definition: NamelistReader.hpp:57
string name
Definition: NamelistReader.hpp:65
string & rtrim(string &s, const char *t=" \t\n\r\f\v")
Definition: NamelistReader.hpp:42
bool present(const string &param)
Definition: NamelistReader.hpp:345
bool check_all_used()
Definition: NamelistReader.hpp:307
bool use_all
Definition: NamelistReader.hpp:166
Definition: NamelistReader.hpp:163
string & ltrim(string &s, const char *t=" \t\n\r\f\v")
Definition: NamelistReader.hpp:35
Definition: NamelistReader.hpp:18
NamelistReader(const string &filename)
Definition: NamelistReader.hpp:256
int size_type
Definition: col_grid_matrix.hpp:19
Create
Definition: NamelistReader.hpp:30
vector< NameList > namelists
Definition: NamelistReader.hpp:164
bool string_to_param< bool >(string &param)
Definition: NamelistReader.hpp:119
void use_namelist(const string &namelist)
Definition: NamelistReader.hpp:330
Definition: NamelistReader.hpp:27
bool used
Definition: NamelistReader.hpp:56
Definition: NamelistReader.hpp:17
int namelist_index
Definition: NamelistReader.hpp:165
float string_to_param< float >(string &param)
Definition: NamelistReader.hpp:146
NameList(string name)
Definition: NamelistReader.hpp:68
vector< Param > params
Definition: NamelistReader.hpp:66
void parse_lines(T &newfile, const string &filename)
Definition: NamelistReader.hpp:170
NamelistReader(const string &str_name, ReadFrom read_from)
Definition: NamelistReader.hpp:262
void add_to_namelist(const string &param, const string &val)
Definition: NamelistReader.hpp:290
int string_to_param< int >(string &param)
Definition: NamelistReader.hpp:140
static T string_to_param(string &param)
Definition: NamelistReader.hpp:19
string & trim(string &s, const char *t=" \t\n\r\f\v")
Definition: NamelistReader.hpp:49
bool namelist_present(const string &namelist)
Definition: NamelistReader.hpp:320
string name
Definition: NamelistReader.hpp:55
Param(string name)
Definition: NamelistReader.hpp:59
ReadFrom
Definition: NamelistReader.hpp:25
Expect
Definition: NamelistReader.hpp:16
NamelistReader(Create create)
Definition: NamelistReader.hpp:272
double string_to_param< double >(string &param)
Definition: NamelistReader.hpp:152
string string_to_param< string >(string &param)
Definition: NamelistReader.hpp:158
static string get_first_value(string &str, int start)
Definition: NamelistReader.hpp:96
static string get_first_word(string &str, int start)
Definition: NamelistReader.hpp:83
T get_required(const string &param, int val_ind=0)
Definition: NamelistReader.hpp:393
Definition: NamelistReader.hpp:26
subroutine load()
Definition: load.F90:57
Definition: NamelistReader.hpp:54
void add_param(string word)
Definition: NamelistReader.hpp:72
Definition: NamelistReader.hpp:22