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 static inline string lower_case_copy(const string& str){
116  // Make copy
117  string lc_str = str;
118 
119  // Make lower case
120  for (int i = 0; i<lc_str.size(); i++)
121  lc_str[i]=tolower(lc_str[i]);
122 
123  return lc_str;
124 }
125 
126 template<typename T>
127 static inline T string_to_param(string& param);
128 
129 template<>
130 bool string_to_param<bool>(string& param){
131  // Make lower case copy
132  const string lc_param = lower_case_copy(param);
133 
134  if (lc_param==".false."){
135  return false;
136  } else if (lc_param==".true."){
137  return true;
138  } else {
139  printf("Error, couldn't parse %s \n", param.c_str());
140  return false;
141  }
142 }
143 
144 static inline void change_D_to_E(string& param){
145  for (int i = 0; i<param.size(); i++)
146  if (param[i]=='D' || param[i]=='d') param[i]='e';
147 }
148 
149 template<>
150 int string_to_param<int>(string& param){
151  change_D_to_E(param);
152  return stoi(param);
153 }
154 
155 template<>
156 float string_to_param<float>(string& param){
157  change_D_to_E(param);
158  return stof(param);
159 }
160 
161 template<>
162 double string_to_param<double>(string& param){
163  change_D_to_E(param);
164  return stod(param);
165 }
166 
167 template<>
168 string string_to_param<string>(string& param){
169  // Remove the quotes
170  return param.substr(1,param.size()-2);
171 }
172 
173 
174 template<typename T>
175 int find_case_insensitive_name_match(vector<T>& vec, const string& str){
176  // Make lower case version
177  const string lc_str = lower_case_copy(str);
178 
179  // Locate the requested parameter
180  typename vector<T>::iterator it = vec.begin();
181  while (it!=vec.end()) {
182  if (lower_case_copy((*it).name)==str) break;
183  ++it;
184  }
185 
186  if (it != vec.end())
187  return distance(vec.begin(), it);
188  else{
189  return -1;
190  }
191 }
192 
194  vector<NameList> namelists;
196  bool use_all;
198 
199  template<class T>
200  void parse_lines(T& newfile, const string& filename){
201  const bool verbose=false;
202  string line;
203  Expect expect = Ampersand;
204  int i_line=0;
205  while(getline(newfile, line)){ //read data from file object and put it into string.
206  i_line++;
207  trim(line); // Remove leading and trailing whitespace
208  for (string::size_type i = 0; i < line.size(); i++){
209  if (line[i]=='!'){
210  // Comment has begun
211  break;
212  }
213  if (expect==Ampersand){
214  if (line[i]=='&'){
215  expect=NLName;
216  }
217  } else if (expect==NLName){
218  string word = get_first_word(line,i);
219  if (word.size()>0){ // Found namelist name
220  expect = ParaNameOrEnd;
221  namelists.push_back(NameList(word));
222  if (verbose) cout << "Found namelist: " << word << "\n";
223  break;
224  }
225  } else if(expect==ParaNameOrEnd){
226  if (line[i]=='/'){ // End of namelist
227  expect=Ampersand;
228  break;
229  }
230 
231  string word = get_first_word(line,i);
232  if (word.size()>0){
233  i+=word.size()-1;
234  expect = Equals;
235  namelists[namelists.size()-1].add_param(word);
236  if (verbose) cout << " Found parameter: " << word << "\n";
237  }
238  } else if(expect==Equals){
239  if (line[i]=='='){
240  expect=Value;
241  }
242  } else if(expect==Value || expect == ValueOrEOL){
243  string word = get_first_value(line,i);
244  if (word.size()>0){
245  i+=word.size()-1;
246  expect = ValueOrEOL;
247  namelists[namelists.size()-1].add_value(word);
248  if (verbose) cout << " Found Value: " << word << "\n";
249  }
250  }
251  }
252  // Got to end of line
253  if (expect==NLName){
254  printf("\nParse failure reading %s at Line %d. Failed to find name of namelist.\n", filename.c_str(), i_line);
255  return;
256  } else if(expect==Equals){
257  printf("\nParse failure reading %s at Line %d. Expected parameter assignment.\n", filename.c_str(), i_line);
258  return;
259  } else if(expect==Value){
260  printf("\nParse failure reading %s at Line %d. Couldn't parse value assignment.\n", filename.c_str(), i_line);
261  return;
262  }
263  // Hit EOL, now expecting next parameter
264  if (expect==ValueOrEOL) expect = ParaNameOrEnd;
265  }
266  }
267 
268  void load(const string& filename){
269  fstream newfile;
270  newfile.open(filename,ios::in); //open a file to perform read operation using file object
271  if (!newfile.is_open()) return; //checking whether the file is open
272 
273  parse_lines(newfile,filename);
274 
275  newfile.close(); //close the file object.
276  }
277 
278  void load_from_string(const string& str){
279  istringstream f(str.c_str());
280 
281  parse_lines(f,"string input");
282  }
283 
284  public:
285 
286  NamelistReader(const string& filename)
287  : namelist_index(-1), use_all(false), modifiable(false)
288  {
289  load(filename);
290  }
291 
292  NamelistReader(const string& str_name, ReadFrom read_from)
293  : namelist_index(-1), use_all(false), modifiable(false)
294  {
295  if (read_from==ReadFromFile){
296  load(str_name);
297  }else{
298  load_from_string(str_name);
299  }
300  }
301 
303  : namelist_index(-1), use_all(false), modifiable(false)
304  {
305  if (create==CreateManually) modifiable = true;
306  }
307 
309  modifiable = true;
310  }
311 
312  void add_namelist(const string& namelist){
313  if (modifiable){
314  namelists.push_back(NameList(namelist));
315  namelist_index = namelists.size()-1; // Focus to the new namelist
316  } else {
317  printf("Warning: 'add_namelist' ignored, only valid if NamelistReader is in CreateManually mode");
318  }
319  }
320 
321  void add_to_namelist(const string& param, const string& val){
322  if (modifiable){
323  namelists[namelist_index].add_param(param);
324  namelists[namelist_index].add_value(val);
325  } else {
326  printf("Warning: 'add_to_namelist' ignored, only valid if NamelistReader is in CreateManually mode");
327  }
328  }
329 
330  void add_to_param(const string& val){
331  if (modifiable){
332  namelists[namelist_index].add_value(val);
333  } else {
334  printf("Warning: 'add_to_param' ignored, only valid if NamelistReader is in CreateManually mode");
335  }
336  }
337 
339  int n_unused=0;
340  for (vector<NameList>::iterator nl = namelists.begin(); nl != namelists.end(); ++nl) {
341  for (vector<Param>::iterator param = nl->params.begin(); param != nl->params.end(); ++param ) {
342  if (param->used==false){
343  printf("Warning: '%s' was present in '%s' but was not used.\n",param->name.c_str(), nl->name.c_str());
344  n_unused++;
345  }
346  }
347  }
348  return (n_unused==0);
349  }
350 
351  bool namelist_present(const string& namelist){
352  return (find_case_insensitive_name_match(namelists, namelist)!=-1);
353  }
354 
355  void use_namelist(const string& namelist){
356  namelist_index = find_case_insensitive_name_match(namelists, namelist);
357  if(namelist_index==-1){
358  printf("\nNamelist '%s' not found in the file!",namelist.c_str());
359  exit(1);
360  }
361  }
362 
363  bool present(const string& param){
364  if (namelist_index==-1){
365  printf("\nNeed to choose which namelist to use with use_namelist(const std::string&)!\n");
366  }
367 
368  // Locate the requested parameter
369  return (find_case_insensitive_name_match(namelists[namelist_index].params, param)!=-1);
370  }
371 
372  template <typename T>
373  T get(const string& param, const T default_val, int val_ind=0){
374  if (namelist_index==-1){
375  printf("\nNeed to choose which namelist to use with use_namelist(const std::string&)!\n");
376  }
377 
378  // Locate the requested parameter
379  int param_index = find_case_insensitive_name_match(namelists[namelist_index].params, param);
380  if(param_index==-1){
381  return default_val;
382  }
383 
384  namelists[namelist_index].params[param_index].used=true;
385 
386  if (val_ind>=0 && val_ind<namelists[namelist_index].params[param_index].values.size()){
387  string str_var = namelists[namelist_index].params[param_index].values[val_ind];
388  return string_to_param<T>(str_var);
389  } else {
390  printf("\nParameter '%s' in namelist '%s' didn't have enough values!",param.c_str(),namelists[namelist_index].name.c_str());
391  exit(1);
392  return default_val;
393  }
394  }
395 
396  template <typename T>
397  T get_required(const string& param, int val_ind=0){
398  if (namelist_index==-1){
399  printf("\nNeed to choose which namelist to use with use_namelist(const std::string&)!\n");
400  }
401 
402  // Locate the requested parameter
403  int param_index = find_case_insensitive_name_match(namelists[namelist_index].params, param);
404  if(param_index==-1){
405  printf("\nParameter '%s' not found in namelist '%s'!",param.c_str(),namelists[namelist_index].name.c_str());
406  exit(1);
407  }
408 
409  namelists[namelist_index].params[param_index].used=true;
410 
411  if (val_ind>=0 && val_ind<namelists[namelist_index].params[param_index].values.size()){
412  string str_var = namelists[namelist_index].params[param_index].values[val_ind];
413  return string_to_param<T>(str_var);
414  } else {
415  printf("\nParameter '%s' in namelist '%s' didn't have enough values!",param.c_str(),namelists[namelist_index].name.c_str());
416  exit(1);
417  }
418  }
419 };
420 
421 }
422 #endif
static void change_D_to_E(string &param)
Definition: NamelistReader.hpp:144
void add_value(string word)
Definition: NamelistReader.hpp:77
bool modifiable
Definition: NamelistReader.hpp:197
Definition: NamelistReader.hpp:64
void add_to_param(const string &val)
Definition: NamelistReader.hpp:330
void add_namelist(const string &namelist)
Definition: NamelistReader.hpp:312
void enable_modifications()
Definition: NamelistReader.hpp:308
void load_from_string(const string &str)
Definition: NamelistReader.hpp:278
Definition: NamelistReader.hpp:21
Definition: NamelistReader.hpp:31
Definition: NamelistReader.hpp:20
void load(const string &filename)
Definition: NamelistReader.hpp:268
vector< string > values
Definition: NamelistReader.hpp:57
string name
Definition: NamelistReader.hpp:65
int find_case_insensitive_name_match(vector< T > &vec, const string &str)
Definition: NamelistReader.hpp:175
string & rtrim(string &s, const char *t=" \t\n\r\f\v")
Definition: NamelistReader.hpp:42
bool present(const string &param)
Definition: NamelistReader.hpp:363
bool check_all_used()
Definition: NamelistReader.hpp:338
bool use_all
Definition: NamelistReader.hpp:196
Definition: NamelistReader.hpp:193
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:286
int size_type
Definition: col_grid_matrix.hpp:19
Create
Definition: NamelistReader.hpp:30
vector< NameList > namelists
Definition: NamelistReader.hpp:194
bool string_to_param< bool >(string &param)
Definition: NamelistReader.hpp:130
void use_namelist(const string &namelist)
Definition: NamelistReader.hpp:355
Definition: NamelistReader.hpp:27
bool used
Definition: NamelistReader.hpp:56
Definition: NamelistReader.hpp:17
int namelist_index
Definition: NamelistReader.hpp:195
float string_to_param< float >(string &param)
Definition: NamelistReader.hpp:156
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:200
NamelistReader(const string &str_name, ReadFrom read_from)
Definition: NamelistReader.hpp:292
void add_to_namelist(const string &param, const string &val)
Definition: NamelistReader.hpp:321
int string_to_param< int >(string &param)
Definition: NamelistReader.hpp:150
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:351
string name
Definition: NamelistReader.hpp:55
Param(string name)
Definition: NamelistReader.hpp:59
ReadFrom
Definition: NamelistReader.hpp:25
Expect
Definition: NamelistReader.hpp:16
static string lower_case_copy(const string &str)
Definition: NamelistReader.hpp:115
NamelistReader(Create create)
Definition: NamelistReader.hpp:302
double string_to_param< double >(string &param)
Definition: NamelistReader.hpp:162
string string_to_param< string >(string &param)
Definition: NamelistReader.hpp:168
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:397
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