Initfile.cc 7.73 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
45
  std::set<std::string> Initfile::fn_include_list;


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

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


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

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


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

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

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


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

Praetorius, Simon's avatar
Praetorius, Simon committed
156

157
      // if varname is found in parameter list then replace variable by value
158
      // otherwise throw tagNotFound exception
159
160
161
162
163
      std::string varParam;
      int error_code = checkedGet(varName, varParam);
      if (error_code != 0)
	throw TagNotFoundBreak("required tag '" + varName + "' for variable substitution not found");
      
164
165
166
      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
167
      posVar = inputSwap.find_first_of('$',posVarEnd);
168
169
170
    }

    return inputSwap;
171
  }
172

Praetorius, Simon's avatar
Praetorius, Simon committed
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
  std::string Initfile::variableEvaluation(const std::string& input) const
  {
    std::string whitespaces = " \t\r\f";
    std::string inputSwap = input;
    size_t posVar = inputSwap.find_first_of('$');
    while (posVar != string::npos) {
      size_t posVarBegin, posVarEnd;
      if(inputSwap[posVar+1] == '(') {	// $(expr)
        posVarEnd = inputSwap.find_first_of(')',posVar + 2);
        posVarBegin = posVar + 1;
      } else {
	posVar = inputSwap.find_first_of('$',posVar+1);
	continue;
      }
      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);

      posVar = inputSwap.find_first_of('$');
    }

    return inputSwap;
  }
201
202
203
204
205

  void Initfile::readArgv(int argc, char **argv)
  {
    for (int i = 0; i < argc; i++) {
      if (strcmp("-rs", argv[i]) == 0) {
206
207
        std::string input(argv[i + 1]);
        add("argv->rs", input, 0);
208
209
210
211
212
213
214
215
216
217
218
      }
    }
  }


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

220
221
222
    val = 1;
    get("WAIT", val, 0);
    msgWait = val;
223

224
225
226
    val = 1;
    get("parameter information", val, 0);
    paramInfo = val;
227

228
229
230
231
232
233
    val = 0;
    get("break on missing tag", val, 0);
    breakOnMissingTag = val;

    if (msgInfo == 0)
      paramInfo = 0;
234
  }
235
236
237
238
239
240
241


  /// print all parameters to std::cout
  void Initfile::printParameters() 
  {
    initIntern();
    for (Initfile::iterator it = singlett->begin(); it != singlett->end(); it++)
242
      std::cout << (*it).first << " => " << (*it).second << std::endl;
243
  }
244
245
246
247
248
249


  /// Write data-map to initfile
  void Initfile::write(ostream& out)
  {
    for (Initfile::iterator it = begin() ; it!=end(); it++)
250
      out << (*it).first << ": " << (*it).second << std::endl;	
251
252
253
254
255
256
257
258
259
260
  }


  /// 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");
261

262
263
    write(outFile);
  }
264
} // end namespace AMDiS