Elaboradar  0.1
config.cpp
1 #include "config.h"
2 #include <unordered_set>
3 #include <fstream>
4 #include <sstream>
5 #include <cstdlib>
6 #include <cctype>
7 
8 using namespace std;
9 
10 namespace elaboradar {
11 
12 namespace {
13 
14 struct ConfigValue
15 {
16  const char* key; // Config key
17  const char* env; // Environment variable name
18  const char* def; // Default value
19 
20  ConfigValue(const char* key, const char* env, const char* def=0)
21  : key(key), env(env), def(def) {}
22 
23 };
24 
25 ConfigValue config_layout[] = {
26  { "file/first_level", "FIRST_LEVEL_FILE" },
27  { "file/vpr_heating", "VPR_HEATING" },
28 };
29 
31 std::string trim(const std::string s)
32 {
33  if (s.empty()) return s;
34 
35  size_t start = 0;
36  size_t end = s.size() - 1;
37  while (start < end && isspace(s[start]))
38  ++start;
39  while (end > start && isspace(s[end]))
40  --end;
41 
42  if (start == end) return string();
43  if (start == 0 && end == s.size() - 1) return s;
44  return s.substr(start, end - start);
45 }
46 
48 bool is_empty(const std::string& line)
49 {
50  for (auto i : line)
51  {
52  if (isspace(i)) continue;
53  if (i == '#') return true;
54  return false;
55  }
56  return true;
57 }
58 
59 }
60 
61 void Config::set_defaults()
62 {
63  for (auto v : config_layout)
64  {
65  if (!v.def) continue;
66  values[v.key] = v.def;
67  }
68 }
69 
70 void Config::read_env()
71 {
72  for (auto v : config_layout)
73  {
74  if (!v.env) continue;
75  const char* val = getenv(v.env);
76  if (val == NULL) continue;
77  values[v.key] = val;
78  }
79 }
80 
81 void Config::read_file(const std::string& fname)
82 {
83  ifstream in(fname);
84  string line;
85  unsigned lineno = 0;
86 
87  // Whitelist of valid keys
88  unordered_set<string> valid_keys;
89  for (auto v : config_layout)
90  valid_keys.insert(v.key);
91 
92  while (getline(in, line))
93  {
94  ++lineno;
95  if (is_empty(line)) continue;
96 
97  size_t pos = line.find('=');
98  if (pos == string::npos)
99  {
100  stringstream s;
101  s << fname << ":" << lineno << ": unparsed line (not empty, a comment or key = value)";
102  throw runtime_error(s.str());
103  }
104  string key = trim(line.substr(0, pos));
105  string val = trim(line.substr(pos+1));
106  if (valid_keys.find(key) == valid_keys.end())
107  {
108  stringstream s;
109  s << fname << ":" << lineno << ": unsupported key '" << key << "'";
110  throw runtime_error(s.str());
111  }
112  values[key] = val;
113  }
114 }
115 
116 bool Config::has(const std::string& key) const
117 {
118  return values.find(key) != values.end();
119 }
120 
121 std::string Config::get(const std::string& key) const
122 {
123  auto res = values.find(key);
124  if (res == values.end()) throw std::runtime_error("configuration key " + key + " not found");
125  return res->second;
126 }
127 
128 std::string Config::get(const std::string& key, const std::string& deflt) const
129 {
130  auto res = values.find(key);
131  if (res == values.end()) return deflt;
132  return res->second;
133 }
134 
135 int Config::get_int(const std::string& key) const
136 {
137  auto res = values.find(key);
138  if (res == values.end()) throw std::runtime_error("configuration key " + key + " not found");
139  return stoi(res->second);
140 }
141 
142 int Config::get_int(const std::string& key, int deflt) const
143 {
144  auto res = values.find(key);
145  if (res == values.end()) return deflt;
146  return stoi(res->second);
147 }
148 
149 double Config::get_double(const std::string& key) const
150 {
151  auto res = values.find(key);
152  if (res == values.end()) throw std::runtime_error("configuration key " + key + " not found");
153  return stod(res->second);
154 }
155 
156 double Config::get_double(const std::string& key, double deflt) const
157 {
158  auto res = values.find(key);
159  if (res == values.end()) return deflt;
160  return stod(res->second);
161 }
162 
163 }
name space generale del programma
Definition: assets.h:28