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

#include <string>
#include <stdexcept>
#include <iostream>
#include <sstream>
Praetorius, Simon's avatar
Praetorius, Simon committed
7
#include<boost/tokenizer.hpp>
Praetorius, Simon's avatar
Praetorius, Simon committed
8 9
using namespace std;

10 11
namespace AMDiS {

12 13
  /// the small parser for the initfile. see description of 
  /// read(Initfile&,istream&)
14 15 16 17
  struct Parser {
    Parser(const string& line) 
    {
      size_t pos = line.find(':');
18
      if (pos == string::npos) {
Thomas Witkowski's avatar
Thomas Witkowski committed
19 20
// 	throw runtime_error("cannot find the delimiter ':' in line "
// 			    "'" + line + "'");
21
      }
22 23 24 25 26 27
      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)
28
        value = value.substr(0, pos);      
29 30 31 32 33
    }
    string name;
    string value;
  };

34

35
  Initfile* Initfile::singlett = NULL;
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();
    fn_include_list.clear();
    singlett->read(in);	
    singlett->getInternalParameters();
46
  }
47 48 49


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

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


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

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

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


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

Praetorius, Simon's avatar
Praetorius, Simon committed
153

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

    return inputSwap;
168
  }
Praetorius, Simon's avatar
Praetorius, Simon committed
169
  
170

Praetorius, Simon's avatar
Praetorius, Simon committed
171 172 173 174
  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
175
    size_t posVar = inputSwap.find("$(");
Praetorius, Simon's avatar
Praetorius, Simon committed
176 177
    while (posVar != string::npos) {
      size_t posVarBegin, posVarEnd;
Praetorius, Simon's avatar
Praetorius, Simon committed
178 179
      posVarEnd = inputSwap.find_first_of(')',posVar + 2);
      posVarBegin = posVar + 1;
Praetorius, Simon's avatar
Praetorius, Simon committed
180 181 182
      std::string varName = inputSwap.substr(posVarBegin + 1 , posVarEnd - posVarBegin - 1);

      double value = 0.0;
Praetorius, Simon's avatar
Praetorius, Simon committed
183 184
      details::convert(varName, value); // string -> double (using muparser)
      details::convert(value, varName); // double -> string
Praetorius, Simon's avatar
Praetorius, Simon committed
185 186 187 188

      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
189
      posVar = inputSwap.find("$(",posVarBegin);
Praetorius, Simon's avatar
Praetorius, Simon committed
190 191 192 193
    }

    return inputSwap;
  }
194

Praetorius, Simon's avatar
Praetorius, Simon committed
195
  void Initfile::readArgv(std::string parameters, int debugInfo)
196
  {
Praetorius, Simon's avatar
Praetorius, Simon committed
197
    initIntern();
Praetorius, Simon's avatar
Praetorius, Simon committed
198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217
    
    char seperator = ';';
    typedef boost::escaped_list_separator<char> TokenizerFunc;
    typedef boost::tokenizer<TokenizerFunc> Tokenizer;
    TokenizerFunc tokenizerFunc('\\', seperator, '\"');
    Tokenizer tok(parameters, tokenizerFunc);

    // split parameterstring by seperator ";"
    std::vector<std::string> val;
    for (Tokenizer::iterator cell = tok.begin(); cell != tok.end(); ++cell) {
      val.push_back(trim(*cell));
    }
    
    // split each parameter by ":"
    for (size_t i = 0; i < val.size(); i++) {
      int found = val[i].find_first_of(':');
      if (found != static_cast<int>(std::string::npos)) {
	std::string value = trim(val[i].substr(found+1));
	std::string key = trim(val[i].substr(0, found));
	set(key, value, debugInfo);
Praetorius, Simon's avatar
Praetorius, Simon committed
218
      }
219 220 221 222 223 224 225 226 227 228
    }
  }


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

230 231 232
    val = 1;
    get("WAIT", val, 0);
    msgWait = val;
233

234 235 236
    val = 1;
    get("parameter information", val, 0);
    paramInfo = val;
237

238 239 240 241 242 243
    val = 0;
    get("break on missing tag", val, 0);
    breakOnMissingTag = val;

    if (msgInfo == 0)
      paramInfo = 0;
244
  }
245 246 247 248 249 250 251


  /// print all parameters to std::cout
  void Initfile::printParameters() 
  {
    initIntern();
    for (Initfile::iterator it = singlett->begin(); it != singlett->end(); it++)
252
      std::cout << (*it).first << " => " << (*it).second << std::endl;
253
  }
254 255 256 257 258 259


  /// Write data-map to initfile
  void Initfile::write(ostream& out)
  {
    for (Initfile::iterator it = begin() ; it!=end(); it++)
260
      out << (*it).first << ": " << (*it).second << std::endl;	
261 262 263 264 265 266 267 268
  }


  /// Write data-map to initfile
  void Initfile::write(std::string fn) 
  {
    std::ofstream outFile;
    outFile.open(fn.c_str(), std::ios::out);
Thomas Witkowski's avatar
Thomas Witkowski committed
269 270
//     if (!outFile.is_open())
//       throw runtime_error("init-file cannot be opened for writing");
271

272 273
    write(outFile);
  }
274
} // end namespace AMDiS