XGCa
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator 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 
278  void add_namelist(const string& namelist){
279  if (modifiable){
280  namelists.push_back(NameList(namelist));
281  } else {
282  printf("Warning: 'add_namelist' ignored, only valid if NamelistReader is in CreateManually mode");
283  }
284  }
285 
286  void add_to_namelist(const string& param, const string& val){
287  if (modifiable){
288  namelists[namelists.size()-1].add_param(param);
289  namelists[namelists.size()-1].add_value(val);
290  } else {
291  printf("Warning: 'add_to_namelist' ignored, only valid if NamelistReader is in CreateManually mode");
292  }
293  }
294 
296  int n_unused=0;
297  for (vector<NameList>::iterator nl = namelists.begin(); nl != namelists.end(); ++nl) {
298  for (vector<Param>::iterator param = nl->params.begin(); param != nl->params.end(); ++param ) {
299  if (param->used==false){
300  printf("Warning: '%s' was present in '%s' but was not used.\n",param->name.c_str(), nl->name.c_str());
301  n_unused++;
302  }
303  }
304  }
305  return (n_unused==0);
306  }
307 
308  void use_namelist(const string& namelist){
309  // Locate the requested namelist
310  vector<NameList>::iterator it = namelists.begin();
311  while (it!=namelists.end()) {
312  if ((*it).name==namelist) break;
313  ++it;
314  }
315  if (it != namelists.end())
316  namelist_index = distance(namelists.begin(), it);
317  else
318  printf("\nNamelist '%s' not found in the file!",namelist.c_str());
319  }
320 
321  bool present(const string& param){
322  if (namelist_index==-1){
323  printf("\nNeed to choose which namelist to use with use_namelist(const std::string&)!\n");
324  }
325 
326  // Locate the requested parameter
327  vector<Param>::iterator it = namelists[namelist_index].params.begin();
328  while (it!=namelists[namelist_index].params.end()) {
329  if ((*it).name==param) break;
330  ++it;
331  }
332 
333  return (it != namelists[namelist_index].params.end());
334  }
335 
336  template <typename T>
337  T get(const string& param, const T default_val, int val_ind=0){
338  if (namelist_index==-1){
339  printf("\nNeed to choose which namelist to use with use_namelist(const std::string&)!\n");
340  }
341 
342  // Locate the requested parameter
343  int param_index = -1;
344  vector<Param>::iterator it = namelists[namelist_index].params.begin();
345  while (it!=namelists[namelist_index].params.end()) {
346  if ((*it).name==param) break;
347  ++it;
348  }
349 
350  if (it != namelists[namelist_index].params.end())
351  param_index = distance(namelists[namelist_index].params.begin(), it);
352  else{
353  return default_val;
354  }
355 
356  namelists[namelist_index].params[param_index].used=true;
357 
358  if (val_ind>=0 && val_ind<namelists[namelist_index].params[param_index].values.size()){
359  string str_var = namelists[namelist_index].params[param_index].values[val_ind];
360  return string_to_param<T>(str_var);
361  } else {
362  printf("\nParameter '%s' in namelist '%s' didn't have enough values!",param.c_str(),namelists[namelist_index].name.c_str());
363  exit(1);
364  return default_val;
365  }
366  }
367 
368  template <typename T>
369  T get_required(const string& param, int val_ind=0){
370  if (namelist_index==-1){
371  printf("\nNeed to choose which namelist to use with use_namelist(const std::string&)!\n");
372  }
373 
374  // Locate the requested parameter
375  int param_index = -1;
376  vector<Param>::iterator it = namelists[namelist_index].params.begin();
377  while (it!=namelists[namelist_index].params.end()) {
378  if ((*it).name==param) break;
379  ++it;
380  }
381 
382  if (it != namelists[namelist_index].params.end())
383  param_index = distance(namelists[namelist_index].params.begin(), it);
384  else{
385  printf("\nParameter '%s' not found in namelist '%s'!",param.c_str(),namelists[namelist_index].name.c_str());
386  exit(1);
387  }
388 
389  namelists[namelist_index].params[param_index].used=true;
390 
391  if (val_ind>=0 && val_ind<namelists[namelist_index].params[param_index].values.size()){
392  string str_var = namelists[namelist_index].params[param_index].values[val_ind];
393  return string_to_param<T>(str_var);
394  } else {
395  printf("\nParameter '%s' in namelist '%s' didn't have enough values!",param.c_str(),namelists[namelist_index].name.c_str());
396  exit(1);
397  }
398  }
399 };
400 
401 }
402 #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_namelist(const string &namelist)
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:321
bool check_all_used()
Definition: NamelistReader.hpp:295
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
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:308
Definition: NamelistReader.hpp:27
bool used
Definition: NamelistReader.hpp:56
Definition: NamelistReader.hpp:17
int namelist_index
Definition: NamelistReader.hpp:165
subroutine load(grid, psn, spall)
Definition: load.F90:7
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:286
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
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:369
Definition: NamelistReader.hpp:26
Definition: NamelistReader.hpp:54
void add_param(string word)
Definition: NamelistReader.hpp:72
Definition: NamelistReader.hpp:22