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