InitfileParser.cpp 5.09 KB
Newer Older
Praetorius, Simon's avatar
Praetorius, Simon committed
1
#include <config.h>
2
3

#include "InitfileParser.hpp"
4

5
#include <amdis/Output.hpp>
6
7
#include <amdis/common/Filesystem.hpp>
#include <amdis/common/String.hpp>
8
9
10

namespace AMDiS {

11
void InitfileParser::readInitfile(std::string const& fn, Dune::ParameterTree& pt, bool overwrite)
12
{
13
  test_exit(filesystem::exists(fn), "Init-file '{}' cannot be opened for reading", fn);
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40

  // read file if its not parsed already
  auto ins = includeList().insert(fn);
  if (ins.second) {
    std::ifstream in(fn.c_str());
    readInitfile(in, pt, overwrite);
  }
}


void InitfileParser::readInitfile(std::istream& in, Dune::ParameterTree& pt, bool overwrite)
{
  std::string swap;
  std::getline(in, swap);
  while (in.good() || swap.size() > 0) {
    std::string whitespaces = " \t\r\f\n";
    std::string delimiter = "\r\n";
    std::string sw(swap);
    std::size_t pos0 = sw.find_first_not_of(whitespaces);

    if (pos0 != std::string::npos
        && sw[pos0] != '%'
        && sw[pos0] != '#'
        && sw[pos0] != 0)
    {
      // parse line and extract map: tag->value
      std::size_t pos = sw.find(':');
41
      test_exit(pos != std::string::npos, "Cannot find the delimiter ':' in line '{}'", sw);
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67

      std::string name = sw.substr(0, pos);
      std::string value = sw.substr(pos + 1, sw.length() - (pos + 1));

      // remove everything after the %
      pos = value.find('%');
      if (pos != std::string::npos)
        value = value.substr(0, pos);

      // add parameter to map after variable replacement
      std::string paramName = replaceVariable(pt, trim(name));
      std::string paramValue = replaceVariable(pt, trim(value));
      paramValue = replaceExpression(pt, paramValue);

      // add parameter to parametertree
      if (overwrite || ! pt.hasKey(paramName))
        pt[paramName] = paramValue;
    }
    else if (pos0 != std::string::npos &&
             sw[pos0] == '#'  &&
             std::size_t(sw.find("#include")) == pos0)
    {
      // include file by '#include "filename"' or '#include <filename>'
      std::size_t pos = sw.find_first_not_of(whitespaces, pos0 + std::string("#include").size() + 1);
      std::size_t epos = 0;
      std::string fn =  "";
68
69
      std::map<char,char> closing = { {'<','>'}, {'\"', '\"'} };

70
71
72
      switch (char c = swap[pos++]) {
        case '<':
        case '\"':
73
          delimiter += closing[c];
74
75
76
          epos = sw.find_first_of(delimiter, pos);
          fn = sw.substr(pos, epos - pos);

77
          test_exit(sw[epos]==c, "Filename in #include not terminated by {}.", std::to_string(c));
78
79
          break;
        default:
80
          error_exit("No filename given for #include");
81
82
83
84
85
86
87
88
89
90
91
      }

      readInitfile(fn, pt, overwrite);
    }

    swap.clear();
    std::getline(in, swap);
  }
}


92
std::string InitfileParser::replaceVariable(Dune::ParameterTree const& pt, std::string const& input)
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
{
  std::string whitespaces = " \t\r\f";
  std::string allowedChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_";
  std::string inputSwap = input;
  std::size_t posVar = inputSwap.find_first_of('$');
  while (posVar != std::string::npos) {
    std::size_t posVarBegin, posVarEnd;
    if (inputSwap[posVar+1] == '{') {						// ${var_name}
      posVarEnd = inputSwap.find_first_of('}',posVar + 2);
      posVarBegin = posVar + 1;
    } else if (inputSwap[posVar+1] != '(' && inputSwap[posVar+1] != '[') { // $var_name
      posVarEnd = inputSwap.find_first_not_of(allowedChars, posVar + 1);
      posVarBegin = posVar;
    } else {
      posVar = inputSwap.find_first_of('$',posVar+1);
      continue;
    }

    std::string varName = inputSwap.substr(posVarBegin + 1 , posVarEnd - posVarBegin - 1);

    // if varname is found in parameter list then replace variable by value
    // otherwise throw tagNotFound exception
115
116
    test_exit(pt.hasKey(varName),
      "Required tag '{}' for variable substitution not found", varName);
117
118
119
120
121
122
123
124
125
126
127
128
129

    std::string varParam = pt[varName];

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

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

  return inputSwap;
}


Praetorius, Simon's avatar
Praetorius, Simon committed
130
std::string InitfileParser::replaceExpression(Dune::ParameterTree const& /*pt*/, std::string const& input)
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
{
#if 0
  std::string whitespaces = " \t\r\f";
  std::string inputSwap = input;
  std::size_t posVar = inputSwap.find("$(");
  while (posVar != std::string::npos) {
    size_t posVarBegin, posVarEnd;
    posVarEnd = inputSwap.find_first_of(')',posVar + 2);
    posVarBegin = posVar + 1;
    std::string varName = inputSwap.substr(posVarBegin + 1 , posVarEnd - posVarBegin - 1);

    double value = 0.0;
    detail::convert(varName, value); // string -> double (using muparser)
    detail::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("$(",posVarBegin);
  }

  return inputSwap;
#else

  // currently no evaluation implemented.
  return input;
#endif
}

} // end namespace AMDiS