Initfile.cc 8.24 KB
Newer Older
Praetorius, Simon's avatar
Praetorius, Simon committed
1
2
3
4
5
6
7
8
#include "Initfile.h"

#include <string>
#include <stdexcept>
#include <iostream>
#include <sstream>
using namespace std;

9
10
namespace AMDiS {

11
12
  /// the small parser for the initfile. see description of 
  /// read(Initfile&,istream&)
13
14
15
16
  struct Parser {
    Parser(const string& line) 
    {
      size_t pos = line.find(':');
17
      if (pos == string::npos) {
18
19
	throw runtime_error("cannot find the delimiter ':' in line "
			    "'" + line + "'");
20
      }
21
22
23
24
25
26
      name = line.substr(0, pos);
      value = line.substr(pos + 1, line.length() - (pos + 1));

      // remove everything after the %
      pos = value.find('%');
      if (pos != string::npos)
27
        value = value.substr(0, pos);      
28
29
30
31
32
    }
    string name;
    string value;
  };

33

34
  Initfile* Initfile::singlett = NULL;
35
36
37
38
39
40
41
42
43
44
  std::set<std::string> Initfile::fn_include_list;


  /// initialize singleton object an global parameters
  void Initfile::init(std::string in)
  {
    initIntern();
    fn_include_list.clear();
    singlett->read(in);	
    singlett->getInternalParameters();
45

46
47
    // initialize global strcutures using parameters
    Global::init();
48
  }
49
50
51


  /// Fill an initfile from a file with filename fn
52
  void Initfile::read(std::string fn, bool force)
53
54
  {
    // read file if its not parsed already
55
    if (fn_include_list.find(fn) == fn_include_list.end() || force) {
56
57
58
      std::ifstream inputFile;
      inputFile.open(fn.c_str(), std::ios::in);
      if (!inputFile.is_open())
59
	throw runtime_error("init-file '" + fn + "' cannot be opened for reading");
60

61
62
63
      fn_include_list.insert(fn);
      read(inputFile);
    }
64
  }
65
66
67
68
69


  /// Fill an initfile from an input stream
  void Initfile::read(istream& in) 
  {
70
    unsigned line_length = 512;
71
72
    char swap[line_length];
    in.getline(swap, line_length);
73
    while (in.good() || in.gcount() > 0) {
74
      std::string whitespaces = " \t\r\f\n";
75
76
      std::string sw(swap);
      size_t pos0 = sw.find_first_not_of(whitespaces);
77

78
79
80
81
      if (pos0 != std::string::npos
          && sw[pos0] != '%' 
          && sw[pos0] != '#'
          && sw[pos0] != 0) {
82
83
        // parse line and extract map: tag->value
        Parser parser(sw);
84
        
85
        // add parameter to map after variable replacement
Praetorius, Simon's avatar
Praetorius, Simon committed
86
87
        std::string paramName = variableReplacement(trim(parser.name));
        std::string paramValue = variableReplacement(trim(parser.value));
Praetorius, Simon's avatar
Praetorius, Simon committed
88
89
        paramValue = variableEvaluation(paramValue);
      
90
91
92
93
        operator[](paramName) = paramValue;
        int info = 0;
        get("parameter information", info, 0);
        if (info >= 2)
94
          std::cout << "read [" << paramName << " => " << paramValue << "]\n";
95
96
97
      } else if (pos0 != std::string::npos &&
		 sw[pos0] == '#'  &&
		 static_cast<size_t>(sw.find("#include")) == pos0) {
98
        // include file by '#include "filename"' or '#include <filename>'
99
100
101
102
103
104
        bool forceRead = false;
        int posAdd = 1;
        if (sw[pos0 + std::string("#include").size()] == '!') {
          forceRead = true;
          posAdd++;
        }
105
        size_t pos = sw.find_first_not_of(whitespaces, 
106
          pos0 + std::string("#include").size() + posAdd);
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
        size_t epos = 0;
        std::string fn =  "";
        std::stringstream errorMsg;
        switch (char c= swap[pos++]) {
          case '<':
            c= '>';
          case '\"':
            whitespaces += c;
            epos = sw.find_first_of(whitespaces, pos);
            fn = sw.substr(pos, epos - pos);

            if (sw[epos]!=c) {
              errorMsg << "filename in #include not terminated by " << c;
              throw std::runtime_error(errorMsg.str());
            }
            break;
          default:
            throw std::runtime_error("no filename given for #include");
        }
126
        read(fn, forceRead);
127
      }
128

129
130
      in.getline(swap, line_length);
    }
131
  }
132
133
134
135
136


  std::string Initfile::variableReplacement(const std::string& input) const
  {
    std::string whitespaces = " \t\r\f";
Praetorius, Simon's avatar
Praetorius, Simon committed
137
    std::string allowedChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_";
138
139
140
141
    std::string inputSwap = input; 
    size_t posVar = inputSwap.find_first_of('$');
    while (posVar != string::npos) {
      size_t posVarBegin, posVarEnd;
Praetorius, Simon's avatar
Praetorius, Simon committed
142
      if(inputSwap[posVar+1] == '{') {						// ${var_name}
143
144
        posVarEnd = inputSwap.find_first_of('}',posVar + 2);
        posVarBegin = posVar + 1;
Praetorius, Simon's avatar
Praetorius, Simon committed
145
146
      } else if (inputSwap[posVar+1] != '(' && inputSwap[posVar+1] != '[') {
        posVarEnd = inputSwap.find_first_not_of(allowedChars, posVar + 1);
147
        posVarBegin = posVar;
Praetorius, Simon's avatar
Praetorius, Simon committed
148
149
150
      } else {
	posVar = inputSwap.find_first_of('$',posVar+1);
	continue;
151
      }
Praetorius, Simon's avatar
Praetorius, Simon committed
152
      
153
      std::string varName = inputSwap.substr(posVarBegin + 1 , posVarEnd - posVarBegin - 1);
154

Praetorius, Simon's avatar
Praetorius, Simon committed
155

156
      // if varname is found in parameter list then replace variable by value
157
      // otherwise throw tagNotFound exception
158
159
160
161
162
      std::string varParam;
      int error_code = checkedGet(varName, varParam);
      if (error_code != 0)
	throw TagNotFoundBreak("required tag '" + varName + "' for variable substitution not found");
      
163
164
165
      std::string replaceName = inputSwap.substr(posVar , posVarEnd - posVar + (posVarBegin - posVar));
      inputSwap.replace(inputSwap.find(replaceName), replaceName.length(), varParam);

Praetorius, Simon's avatar
Praetorius, Simon committed
166
      posVar = inputSwap.find_first_of('$',posVarBegin);
167
168
169
    }

    return inputSwap;
170
  }
171

Praetorius, Simon's avatar
Praetorius, Simon committed
172
173
174
175
  std::string Initfile::variableEvaluation(const std::string& input) const
  {
    std::string whitespaces = " \t\r\f";
    std::string inputSwap = input;
Praetorius, Simon's avatar
Praetorius, Simon committed
176
    size_t posVar = inputSwap.find("$(");
Praetorius, Simon's avatar
Praetorius, Simon committed
177
178
    while (posVar != string::npos) {
      size_t posVarBegin, posVarEnd;
Praetorius, Simon's avatar
Praetorius, Simon committed
179
180
      posVarEnd = inputSwap.find_first_of(')',posVar + 2);
      posVarBegin = posVar + 1;
Praetorius, Simon's avatar
Praetorius, Simon committed
181
182
183
184
185
186
187
188
189
      std::string varName = inputSwap.substr(posVarBegin + 1 , posVarEnd - posVarBegin - 1);

      double value = 0.0;
      InitfileInternal::convert(varName, value); // string -> double (using muparser)
      InitfileInternal::convert(value, varName); // double -> string

      std::string replaceName = inputSwap.substr(posVar , posVarEnd - posVar + (posVarBegin - posVar));
      inputSwap.replace(inputSwap.find(replaceName), replaceName.length(), varName);

Praetorius, Simon's avatar
Praetorius, Simon committed
190
      posVar = inputSwap.find("$(",posVarBegin);
Praetorius, Simon's avatar
Praetorius, Simon committed
191
192
193
194
    }

    return inputSwap;
  }
195
196
197

  void Initfile::readArgv(int argc, char **argv)
  {
Praetorius, Simon's avatar
Praetorius, Simon committed
198
    initIntern();
199
200
    for (int i = 0; i < argc; i++) {
      if (strcmp("-rs", argv[i]) == 0) {
201
202
        std::string input(argv[i + 1]);
        add("argv->rs", input, 0);
203
      }
Praetorius, Simon's avatar
Praetorius, Simon committed
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
      else if (strcmp("-parameters", argv[i]) == 0) {
        std::string input(argv[i + 1]);
	int found = input.find_first_of(';');

	std::vector<std::string> parameters;
	while (found != static_cast<int>(std::string::npos)) {
	  if (found > 2) {
	    parameters.push_back(input.substr(0, found).c_str());
	  }
	  input = input.substr(found + 1);
	  found = input.find_first_of(';');
	}
	if (input.length() > 2)
	  parameters.push_back(input.c_str());

	for (size_t i = 0; i < parameters.size(); i++) {
	  int found = input.find_first_of(':');
	  if (found != static_cast<int>(std::string::npos)) {
	    std::string value = input.substr(found+1);
	    set(input.substr(0, found), value, 0);
	  }
	}
	
      }
228
229
230
231
232
233
234
235
236
237
    }
  }


  /// read standard values for output and information of parameter-values
  void Initfile::getInternalParameters() 
  {
    int val = 0;
    get("level of information", val, 0);
    msgInfo = val;
238

239
240
241
    val = 1;
    get("WAIT", val, 0);
    msgWait = val;
242

243
244
245
    val = 1;
    get("parameter information", val, 0);
    paramInfo = val;
246

247
248
249
250
251
252
    val = 0;
    get("break on missing tag", val, 0);
    breakOnMissingTag = val;

    if (msgInfo == 0)
      paramInfo = 0;
253
  }
254
255
256
257
258
259
260


  /// print all parameters to std::cout
  void Initfile::printParameters() 
  {
    initIntern();
    for (Initfile::iterator it = singlett->begin(); it != singlett->end(); it++)
261
      std::cout << (*it).first << " => " << (*it).second << std::endl;
262
  }
263
264
265
266
267
268


  /// Write data-map to initfile
  void Initfile::write(ostream& out)
  {
    for (Initfile::iterator it = begin() ; it!=end(); it++)
269
      out << (*it).first << ": " << (*it).second << std::endl;	
270
271
272
273
274
275
276
277
278
279
  }


  /// Write data-map to initfile
  void Initfile::write(std::string fn) 
  {
    std::ofstream outFile;
    outFile.open(fn.c_str(), std::ios::out);
    if (!outFile.is_open())
      throw runtime_error("init-file cannot be opened for writing");
280

281
282
    write(outFile);
  }
283
} // end namespace AMDiS