CGRA-ME
ConfigStore.h
Go to the documentation of this file.
1 /*******************************************************************************
2  * The software programs comprising "CGRA-ME" and the documentation provided
3  * with them are copyright by its authors and the University of Toronto. Only
4  * non-commercial, not-for-profit use of this software is permitted without ex-
5  * plicit permission. This software is provided "as is" with no warranties or
6  * guarantees of support. See the LICENCE for more details. You should have re-
7  * ceived a copy of the full licence along with this software. If not, see
8  * <http://cgra-me.ece.utoronto.ca/license/>.
9  ******************************************************************************/
10 
11 #ifndef __CONFIG_STORE_H___
12 #define __CONFIG_STORE_H___
13 
15 
16 #include <iomanip>
17 #include <iostream>
18 #include <map>
19 #include <string>
20 
21 template<typename S1, typename S2>
22 bool equalsIgnoreCase(const S1& s1, const S2& s2) {
23  auto i1 = begin(s1);
24  auto i2 = begin(s2);
25  for (; i1 != end(s1) && i2 != end(s2); ++i1, ++i2) {
26  if (std::tolower(*i1) != std::tolower(*i2)) {
27  return false;
28  }
29  }
30 
31  return i1 == end(s1) && i2 == end(s2);
32 }
33 
34 template<typename S>
35 bool isTruthString(const S& s) {
36  for (const char* test : { "on", "true", "yes"}) {
37  if (equalsIgnoreCase(s, std::string(test))) {
38  return true;
39  }
40  }
41  return false;
42 }
43 
44 template<typename S>
45 bool isFarceString(const S& s) {
46  for (const char* test : { "off", "false", "no"}) {
47  if (equalsIgnoreCase(s, std::string(test))) {
48  return true;
49  }
50  }
51  return false;
52 }
53 
54 inline const char* makeBoolString(bool v) { return v ? "true" : "false"; }
55 
57  std::string impl;
58 
59  template<typename T, typename std::enable_if_t<std::is_integral<T>::value && not std::is_same<bool,T>::value, bool> = true>
60  ImplicitlyToString(const T& number) : impl(std::to_string(number)) { }
61  template<typename T, typename std::enable_if_t<std::is_floating_point<T>::value, bool> = true>
62  ImplicitlyToString(const T& number) : impl(std::to_string(number)) { }
63 
64  ImplicitlyToString(std::string s) : impl(std::move(s)) { }
65  ImplicitlyToString(const char* s) : ImplicitlyToString(std::string(s)) { }
66 
67  template<typename T, typename std::enable_if_t<std::is_same<bool,T>::value, bool> = true>
68  ImplicitlyToString(const T& b) : impl(makeBoolString(b)) { }
69 };
70 
76 class ConfigStore {
77 public:
78  using BackingStore = std::map<std::string, std::string>;
79 
80  ConfigStore() = default;
81 
83  : backing_store(std::move(src))
84  { }
85 
86 
104  ConfigStore(std::initializer_list<std::pair<std::string, ImplicitlyToString>> ilist)
105  : backing_store()
106  {
107  for (auto& kv : ilist) {
108  addString(kv.first, kv.second.impl); // cannot move. initializer_list forces copy
109  }
110  }
111 
112  ConfigStore(const ConfigStore&) = default;
113  ConfigStore& operator=(const ConfigStore&) = default;
114  ConfigStore(ConfigStore&&) = default;
115  ConfigStore& operator=(ConfigStore&&) = default;
116 
120  bool addString(std::string key, std::string value) { return backing_store.emplace(std::move(key), std::move(value)).second; }
121  bool addInt(std::string key, long long value) { return addString(std::move(key), std::to_string(value)); }
122  bool addReal(std::string key, double value) { return addString(std::move(key), std::to_string(value)); }
123  bool addBool(std::string key, bool value) { return addString(std::move(key), makeBoolString(value)); }
124 
128  void setString(std::string key, std::string value) { insert_or_assign(backing_store, std::move(key), std::move(value)); }
129  void setInt(std::string key, long long value) { setString(std::move(key), std::to_string(value)); }
130  void setReal(std::string key, double value) { setString(std::move(key), std::to_string(value)); }
131  void setBool(std::string key, bool value) { setString(std::move(key), makeBoolString(value)); }
132 
136  const std::string& getString(const std::string& key) const {
137  try {
138  return backing_store.at(key);
139  } catch (const std::out_of_range& oor) {
140  throw std::out_of_range(
141  "ConfigStore accessed with non-existent key `" + key + "'. Original exception's .what() = `" + oor.what() + "'"
142  );
143  }
144  }
145 
146  long long getInt(const std::string& key) const {
147  const auto& value = getString(key);
148  std::size_t final_pos = 0;
149  auto result = std::stoll(value, &final_pos);
150  if (final_pos != value.size()) {
151  throw makeIncompleteConversionException(key, value);
152  }
153  return result;
154  }
155 
156  double getReal(const std::string& key) const {
157  const auto& value = getString(key);
158  std::size_t final_pos = 0;
159  auto result = std::stod(value, &final_pos);
160  if (final_pos != value.size()) {
161  throw makeIncompleteConversionException(key, value);
162  }
163  return result;
164  }
165 
166  bool getBool(const std::string& key) const {
167  const auto& value = getString(key);
168  if (isTruthString(value)) {
169  return true;
170  }
171  if (isFarceString(value)) {
172  return false;
173  }
174 
175  return getInt(key) != 0;
176  }
177 
181  const std::string& getStringOr(const std::string& key, const std::string& otherwise) const {
182  if (hasKey(key)) { return getString(key); }
183  else { return otherwise; }
184  }
185 
186  std::string getStringOr(const std::string& key, std::string&& otherwise) const {
187  if (hasKey(key)) { return getString(key); }
188  else { return std::move(otherwise); }
189  }
190 
191  long long getIntOr(const std::string& key, long long otherwise) const {
192  if (hasKey(key)) { return getInt(key); }
193  else { return otherwise; }
194  }
195 
196  double getRealOr(const std::string& key, double otherwise) const {
197  if (hasKey(key)) { return getInt(key); }
198  else { return otherwise; }
199  }
200 
201  bool getBoolOr(const std::string& key, bool otherwise) const {
202  if (hasKey(key)) { return getBool(key); }
203  else { return otherwise; }
204  }
205 
209  bool hasKey(const std::string& key) const {
210  return backing_store.find(key) != backing_store.end();
211  }
212 
213  auto begin() const { return backing_store.begin(); }
214  auto end() const { return backing_store.end(); }
215  bool empty() const { return backing_store.empty(); }
216 
217  bool operator==(const ConfigStore& rhs) const {
218  return this->backing_store == rhs.backing_store;
219  }
220  bool operator!=(const ConfigStore& rhs) const { return not (*this == rhs); }
221 
225  friend std::ostream& operator<<(std::ostream& os, const ConfigStore& cs) {
226  std::ptrdiff_t max_key_length = 0;
227  for (const auto& key_and_value : cs.backing_store) {
228  max_key_length = std::max(max_key_length, (std::ptrdiff_t)key_and_value.first.size());
229  }
230 
231  os << "{\n";
232  for (const auto& key_and_value : cs.backing_store) {
233  os << std::setw(max_key_length + 2) << key_and_value.first << " = " << key_and_value.second << '\n';
234  }
235  os << '}';
236  return os;
237  }
238 
239 private:
240  std::invalid_argument makeIncompleteConversionException(const std::string& key, const std::string& value) const {
241  return std::invalid_argument("value `" + value + "' at key `" + key + "' could not be completely converted");
242  }
243 
245 };
246 
247 
251 inline ConfigStore& add_all(ConfigStore& into, const ConfigStore& from) { for (auto& kv : from) { into.addString(kv.first, kv.second); } return into; }
252 inline ConfigStore& set_all(ConfigStore& into, const ConfigStore& from) { for (auto& kv : from) { into.setString(kv.first, kv.second); } return into; }
253 
257 inline ConfigStore& override_all(ConfigStore& into, const ConfigStore& from) {
258  for (auto& kv : from) {
259  if (not into.hasKey(kv.first)) { throw std::out_of_range(
260  "attempted to override non-existent key " + kv.first + " with value " + kv.second
261  );}
262  into.setString(kv.first, kv.second);
263  }
264  return into;
265 }
266 
267 // variadic lvalue overloads
268 template<typename... CSes> ConfigStore& add_all (ConfigStore& into, const ConfigStore& from1, const CSes&... froms) { add_all(into, from1); (void)(int[]){(add_all(into, froms),0)...}; return into; }
269 template<typename... CSes> ConfigStore& set_all (ConfigStore& into, const ConfigStore& from1, const CSes&... froms) { set_all(into, from1); (void)(int[]){(set_all(into, froms),0)...}; return into; }
270 template<typename... CSes> ConfigStore& override_all(ConfigStore& into, const ConfigStore& from1, const CSes&... froms) { override_all(into, from1); (void)(int[]){(override_all(into, froms),0)...}; return into; }
271 
272 // variadic rvalue overloads
273 template<typename... CSes> ConfigStore add_all (ConfigStore&& into, const ConfigStore& from1, const CSes&... froms) { return add_all(into, from1, froms...); }
274 template<typename... CSes> ConfigStore set_all (ConfigStore&& into, const ConfigStore& from1, const CSes&... froms) { return set_all(into, from1, froms...); }
275 template<typename... CSes> ConfigStore override_all(ConfigStore&& into, const ConfigStore& from1, const CSes&... froms) { return override_all(into, from1, froms...); }
276 
277 // These always operate on (and return) a copy
278 template<typename... CSes> ConfigStore with_added (ConfigStore into, const ConfigStore& from1, const CSes&... froms) { return add_all(std::move(into), from1, froms...); }
279 template<typename... CSes> ConfigStore with_set (ConfigStore into, const ConfigStore& from1, const CSes&... froms) { return set_all(std::move(into), from1, froms...); }
280 template<typename... CSes> ConfigStore with_overridden(ConfigStore into, const ConfigStore& from1, const CSes&... froms) { return override_all(std::move(into), from1, froms...); }
281 
285 inline ConfigStore getEntriesForPrefix(const ConfigStore& cs, const std::string& prefix) {
286  ConfigStore result;
287  for (const auto& kv : cs) {
288  if (kv.first.substr(0, prefix.size()) == prefix) {
289  result.setString(kv.first.substr(prefix.size()), kv.second);
290  }
291  }
292  return result;
293 }
294 
298 inline ConfigStore addPrefix(const ConfigStore& cs, const std::string& prefix) {
299  ConfigStore result;
300  for (const auto& kv : cs) {
301  result.setString(prefix + kv.first, kv.second);
302  }
303  return result;
304 }
305 
306 
310 template<typename Filter>
311 auto filterKeys(const ConfigStore& cs, Filter&& f) -> decltype(f(std::string()), ConfigStore()) {
312  ConfigStore result;
313  for (const auto& kv : cs) {
314  if (std::forward<Filter>(f)(kv.first)) {
315  result.addString(kv.first, kv.second);
316  }
317  }
318  return result;
319 }
320 
324 template<typename Filter>
325 auto filterKeys(const ConfigStore& cs, Filter&& f) -> decltype(f(std::string(),std::string()), ConfigStore()) {
326  ConfigStore result;
327  for (const auto& kv : cs) {
328  if (std::forward<Filter>(f)(kv.first, kv.second)) {
329  result.addString(kv.first, kv.second);
330  }
331  }
332  return result;
333 }
334 
335 #endif /* __CONFIG_STORE_H___ */
ConfigStore::operator<<
friend std::ostream & operator<<(std::ostream &os, const ConfigStore &cs)
Definition: ConfigStore.h:225
ConfigStore::addReal
bool addReal(std::string key, double value)
Definition: ConfigStore.h:122
isTruthString
bool isTruthString(const S &s)
Definition: ConfigStore.h:35
with_added
ConfigStore with_added(ConfigStore into, const ConfigStore &from1, const CSes &... froms)
Definition: ConfigStore.h:278
ConfigStore::setString
void setString(std::string key, std::string value)
Definition: ConfigStore.h:128
ConfigStore::getBoolOr
bool getBoolOr(const std::string &key, bool otherwise) const
Definition: ConfigStore.h:201
ConfigStore::operator=
ConfigStore & operator=(const ConfigStore &)=default
begin
auto begin(const SingleItemImmutableSet< VertexID > &siis)
Definition: Collections.h:137
ConfigStore::getRealOr
double getRealOr(const std::string &key, double otherwise) const
Definition: ConfigStore.h:196
ConfigStore::operator!=
bool operator!=(const ConfigStore &rhs) const
Definition: ConfigStore.h:220
ConfigStore::setInt
void setInt(std::string key, long long value)
Definition: ConfigStore.h:129
override_all
ConfigStore & override_all(ConfigStore &into, const ConfigStore &from)
Definition: ConfigStore.h:257
ConfigStore::addInt
bool addInt(std::string key, long long value)
Definition: ConfigStore.h:121
equalsIgnoreCase
bool equalsIgnoreCase(const S1 &s1, const S2 &s2)
Definition: ConfigStore.h:22
ConfigStore
Definition: ConfigStore.h:76
makeBoolString
const char * makeBoolString(bool v)
Definition: ConfigStore.h:54
ImplicitlyToString::ImplicitlyToString
ImplicitlyToString(const T &b)
Definition: ConfigStore.h:68
with_overridden
ConfigStore with_overridden(ConfigStore into, const ConfigStore &from1, const CSes &... froms)
Definition: ConfigStore.h:280
ConfigStore::end
auto end() const
Definition: ConfigStore.h:214
ConfigStore::makeIncompleteConversionException
std::invalid_argument makeIncompleteConversionException(const std::string &key, const std::string &value) const
Definition: ConfigStore.h:240
to_string
const std::string & to_string(const OpGraphOpCode &opcode)
Definition: OpGraph.cpp:111
ConfigStore::getStringOr
const std::string & getStringOr(const std::string &key, const std::string &otherwise) const
Definition: ConfigStore.h:181
ConfigStore::empty
bool empty() const
Definition: ConfigStore.h:215
ConfigStore::ConfigStore
ConfigStore(std::initializer_list< std::pair< std::string, ImplicitlyToString >> ilist)
Flexible constructor that converts everything value it is given to a string.
Definition: ConfigStore.h:104
ConfigStore::hasKey
bool hasKey(const std::string &key) const
Definition: ConfigStore.h:209
ConfigStore::addString
bool addString(std::string key, std::string value)
Definition: ConfigStore.h:120
add_all
ConfigStore & add_all(ConfigStore &into, const ConfigStore &from)
Add (or set) all keys from from in into.
Definition: ConfigStore.h:251
ConfigStore::setBool
void setBool(std::string key, bool value)
Definition: ConfigStore.h:131
ImplicitlyToString::ImplicitlyToString
ImplicitlyToString(const T &number)
Definition: ConfigStore.h:60
ConfigStore::getStringOr
std::string getStringOr(const std::string &key, std::string &&otherwise) const
Definition: ConfigStore.h:186
ImplicitlyToString::ImplicitlyToString
ImplicitlyToString(const char *s)
Definition: ConfigStore.h:65
isFarceString
bool isFarceString(const S &s)
Definition: ConfigStore.h:45
ImplicitlyToString
Definition: ConfigStore.h:56
ConfigStore::ConfigStore
ConfigStore(BackingStore src)
Definition: ConfigStore.h:82
filterKeys
auto filterKeys(const ConfigStore &cs, Filter &&f) -> decltype(f(std::string()), ConfigStore())
Definition: ConfigStore.h:311
ConfigStore::ConfigStore
ConfigStore()=default
ImplicitlyToString::ImplicitlyToString
ImplicitlyToString(std::string s)
Definition: ConfigStore.h:64
addPrefix
ConfigStore addPrefix(const ConfigStore &cs, const std::string &prefix)
Definition: ConfigStore.h:298
Collections.h
end
auto end(const SingleItemImmutableSet< VertexID > &siis)
Definition: Collections.h:138
ConfigStore::getIntOr
long long getIntOr(const std::string &key, long long otherwise) const
Definition: ConfigStore.h:191
set_all
ConfigStore & set_all(ConfigStore &into, const ConfigStore &from)
Definition: ConfigStore.h:252
ConfigStore::operator==
bool operator==(const ConfigStore &rhs) const
Definition: ConfigStore.h:217
ConfigStore::backing_store
BackingStore backing_store
Definition: ConfigStore.h:244
ConfigStore::getString
const std::string & getString(const std::string &key) const
Definition: ConfigStore.h:136
with_set
ConfigStore with_set(ConfigStore into, const ConfigStore &from1, const CSes &... froms)
Definition: ConfigStore.h:279
ConfigStore::addBool
bool addBool(std::string key, bool value)
Definition: ConfigStore.h:123
ImplicitlyToString::impl
std::string impl
Definition: ConfigStore.h:57
ConfigStore::begin
auto begin() const
Definition: ConfigStore.h:213
getEntriesForPrefix
ConfigStore getEntriesForPrefix(const ConfigStore &cs, const std::string &prefix)
Definition: ConfigStore.h:285
ConfigStore::getInt
long long getInt(const std::string &key) const
Definition: ConfigStore.h:146
ConfigStore::getReal
double getReal(const std::string &key) const
Definition: ConfigStore.h:156
insert_or_assign
auto insert_or_assign(ASSOCIATIVE_COLLECTION &assoc_collection, KEY &&key, VALUE &&value)
Definition: Collections.h:358
ConfigStore::setReal
void setReal(std::string key, double value)
Definition: ConfigStore.h:130
ConfigStore::getBool
bool getBool(const std::string &key) const
Definition: ConfigStore.h:166
ConfigStore::BackingStore
std::map< std::string, std::string > BackingStore
Definition: ConfigStore.h:78