The Sparta Modeling Framework
Loading...
Searching...
No Matches
FeatureConfiguration.hpp
Go to the documentation of this file.
1// <FeatureConfiguration.h> -*- C++ -*-
2
3
10#pragma once
11
12#include "sparta/simulation/ParameterTree.hpp"
16
17#include <iostream>
18#include <fstream>
19#include <memory>
20
21#include <boost/lexical_cast.hpp>
22
23namespace sparta {
24namespace app {
25
28{
29public:
30 void setFeatureValue(const std::string & name, const unsigned int value) {
31 feature_values_.create(name)->setValue(
32 boost::lexical_cast<std::string>(value));
33 }
34
35 unsigned int getFeatureValue(const std::string & feature_name) const {
36 auto feature = feature_values_.tryGet(feature_name);
37 if (feature == nullptr || !feature->hasValue()) {
38 return 0;
39 }
40 return std::stoi(feature->getValue());
41 }
42
43 bool isFeatureValueSet(const std::string & feature_name) const {
44 return (feature_values_.tryGet(feature_name) != nullptr);
45 }
46
100 {
101 public:
106 void setOptionsFromYamlFile(const std::string & yaml_opts_fname)
107 {
108 std::ifstream fin(yaml_opts_fname);
109 if (!fin) {
110 std::cout << " [feature] Warning: No options file named '"
111 << yaml_opts_fname << "' found." << std::endl;
112 return;
113 }
114
115 std::vector<std::vector<std::string>> str_vectors;
116 utils::split_lines_around_tokens(fin, str_vectors, ":");
117 for (auto & strvec : str_vectors) {
118 sparta_assert(strvec.size() == 2);
119 std::string & option_name = strvec[0];
120 std::string & option_value = strvec[1];
121 option_name = sparta::utils::strip_whitespace(option_name);
122 option_value = sparta::utils::strip_whitespace(option_value);
123 feature_options_.set(option_name, option_value, false);
124 }
125 }
126
147 template <typename T,
148 typename = typename std::enable_if<
149 std::is_trivial<T>::value, T>::type>
151 const std::string & option_name,
152 const T default_value) const
153 {
154 auto option = feature_options_.tryGet(option_name);
155 if (option == nullptr || !option->hasValue()) {
156 return default_value;
157 }
158
159 const std::string & opt_value_str = option->getValue();
160 try {
161 const double opt_value = boost::lexical_cast<double>(opt_value_str);
162 return static_cast<T>(opt_value);
163 } catch (const boost::bad_lexical_cast &) {
164 }
165
166 //We could get here if there was an option yaml file like this:
167 //
168 // myFoo: 4.6
169 // myBar: helloWorld
170 //
171 //And the call site looked like this:
172 //
173 // auto opt_value = feature_opts->getOptionValue<double>("myBar", 3.14);
174 //
175 //The myBar option data type is string, but the call site specified
176 //a double template argument.
177 return default_value;
178 }
179
183 template <typename T,
184 typename = typename std::enable_if<
185 std::is_same<T, std::string>::value, T>::type>
186 std::string getOptionValue(
187 const std::string & option_name,
188 const T default_value) const
189 {
190 auto option = feature_options_.tryGet(option_name);
191 if (option == nullptr || !option->hasValue()) {
192 return default_value;
193 }
194 return option->getValue();
195 }
196
197 private:
198 ParameterTree feature_options_;
199 };
200
204 void setFeatureOptionsFromFile(const std::string & feature_name,
205 const std::string & yaml_opts_fname)
206 {
207 auto iter = feature_options_.find(feature_name);
208 if (iter == feature_options_.end()) {
209 std::unique_ptr<FeatureOptions> opts(new FeatureOptions);
210 opts->setOptionsFromYamlFile(yaml_opts_fname);
211 feature_options_[feature_name] = std::move(opts);
212 return;
213 }
214 iter->second->setOptionsFromYamlFile(yaml_opts_fname);
215 }
216
230 const FeatureOptions * getFeatureOptions(const std::string & feature_name) const {
231 auto iter = feature_options_.find(feature_name);
232 if (iter != feature_options_.end()) {
233 return iter->second.get();
234 }
235 return &null_feature_options_;
236 }
237
238private:
239 ParameterTree feature_values_;
240 std::unordered_map<std::string, std::unique_ptr<FeatureOptions>> feature_options_;
241 FeatureOptions null_feature_options_;
242};
243
244} // namespace app
245
249template <typename T>
250typename std::enable_if<
251 std::is_same<T, app::FeatureConfiguration>::value,
252bool>::type
254 const T & cfg,
255 const std::string & feature_name,
256 const unsigned int feature_value)
257{
258 return cfg.getFeatureValue(feature_name) == feature_value;
259}
260
263template <typename T>
264typename std::enable_if<
266bool>::type
268 const std::string & feature_name,
269 const unsigned int feature_value)
270{
271 return cfg ? IsFeatureValueEqualTo(*cfg, feature_name, feature_value) :
272 (feature_value == 0);
273}
274
277template <typename T>
278typename std::enable_if<
279 std::is_same<T, app::FeatureConfiguration>::value,
280bool>::type
282 const T & cfg,
283 const std::string & feature_name)
284{
285 return cfg.getFeatureValue(feature_name) > 0;
286}
287
291template <typename T>
292typename std::enable_if<
294bool>::type
296 const T & cfg,
297 const std::string & feature_name)
298{
299 return cfg ? IsFeatureValueEnabled(*cfg, feature_name) : false;
300}
301
304template <typename T>
305typename std::enable_if<
306 std::is_same<T, app::FeatureConfiguration>::value,
307const app::FeatureConfiguration::FeatureOptions*>::type
308GetFeatureOptions(const T & cfg,
309 const std::string & feature_name)
310{
311 return cfg.getFeatureOptions(feature_name);
312}
313
316template <typename T>
317typename std::enable_if<
319const app::FeatureConfiguration::FeatureOptions*>::type
321 const T & cfg,
322 const std::string & feature_name)
323{
324 return cfg ? GetFeatureOptions(*cfg, feature_name) : nullptr;
325}
326
327} // namespace sparta
Contains a collection implementation of various compile-time metaprogramming and Type-Detection APIs ...
#define sparta_assert(...)
Simple variadic assertion that will throw a sparta_exception if the condition fails.
Exception class for all of Sparta.
Cool string utilities.
void setValue(const std::string &val, bool required=true, const std::string &origin="")
Set a value on this node directly.
Virtual Parameter Tree. This represents a tree of parameters read from some source but does not neces...
Node * create(const std::string &path, bool required=false)
Add a node to the tree, with proper priority.
bool set(const std::string &path, const std::string &value, bool required, const std::string &origin="")
Add a parameter to the tree, replacing any existing parameter.
const Node * tryGet(const std::string &path, const bool must_be_leaf=true) const
Try to get a node if it exists. Returns nullptr it it does not.
void setOptionsFromYamlFile(const std::string &yaml_opts_fname)
std::string getOptionValue(const std::string &option_name, const T default_value) const
T getOptionValue(const std::string &option_name, const T default_value) const
Collection of named feature values.
const FeatureOptions * getFeatureOptions(const std::string &feature_name) const
void setFeatureOptionsFromFile(const std::string &feature_name, const std::string &yaml_opts_fname)
Macros for handling exponential backoff.
std::enable_if< std::is_same< T, app::FeatureConfiguration >::value, bool >::type IsFeatureValueEqualTo(const T &cfg, const std::string &feature_name, const unsigned int feature_value)
std::enable_if< std::is_same< T, app::FeatureConfiguration >::value, constapp::FeatureConfiguration::FeatureOptions * >::type GetFeatureOptions(const T &cfg, const std::string &feature_name)
std::enable_if< std::is_same< T, app::FeatureConfiguration >::value, bool >::type IsFeatureValueEnabled(const T &cfg, const std::string &feature_name)
This templated struct lets us know about whether the datatype is actually an ordinary object or point...