SST  8.0.0
StructuralSimulationToolkit
params.h
1 // Copyright 2009-2018 NTESS. Under the terms
2 // of Contract DE-NA0003525 with NTESS, the U.S.
3 // Government retains certain rights in this software.
4 //
5 // Copyright (c) 2009-2018, NTESS
6 // All rights reserved.
7 //
8 // This file is part of the SST software package. For license
9 // information, see the LICENSE file in the top level directory of the
10 // distribution.
11 
12 #ifndef SST_CORE_PARAM_H
13 #define SST_CORE_PARAM_H
14 
15 #include <sst/core/output.h>
16 #include <sst/core/from_string.h>
17 
18 #include <cassert>
19 #include <inttypes.h>
20 #include <iostream>
21 #include <sstream>
22 #include <map>
23 #include <stack>
24 #include <stdlib.h>
25 #include <utility>
26 #include <sst/core/threadsafe.h>
27 
28 #include <sst/core/serialization/serializable.h>
29 #include <sst/core/serialization/serializer.h>
30 #include <sst/core/output.h>
31 
32 int main(int argc, char *argv[]);
33 
34 namespace SST {
35 
36 class ConfigGraph;
37 
38 /**
39  * Parameter store.
40  *
41  * Stores key-value pairs as std::strings and provides
42  * a templated find method for finding values and converting
43  * them to arbitrary types (@see find()).
44  */
46 private:
47  struct KeyCompare : std::binary_function<std::string, std::string, bool>
48  {
49  bool operator()(const std::string& X, const std::string& Y) const
50  {
51  const char *x = X.c_str();
52  const char *y = Y.c_str();
53 
54 #define EAT_VAR(A, B) \
55  do { \
56  if ( *x == '%' && (*(x+1) == '(' || *(x+1) == 'd')) { \
57  /* We need to eat off some tokens */ \
58  ++x; \
59  if ( *x == '(' ) { \
60  do { x++; } while ( *x && *x != ')' ); \
61  x++; /* *x should now == 'd' */ \
62  } \
63  if ( *x != 'd' ) goto NO_VARIABLE; \
64  x++; /* Finish eating the variable */ \
65  /* Now, eat of digits of Y */ \
66  while ( *y && isdigit(*y) ) y++; \
67  } \
68  } while(0)
69 
70  do {
71  EAT_VAR(x, y);
72  EAT_VAR(y, x);
73 NO_VARIABLE:
74  if ( *x == *y ) {
75  if ( '\0' == *x ) return false;
76  x++;
77  y++;
78  } else {
79  if ( *x < *y ) return true;
80  return false;
81  }
82  } while ( *x && *y );
83  if ( !(*x) && (*y) ) return true;
84  return false;
85 
86 #undef EAT_VAR
87  }
88  };
89 
90  typedef std::map<uint32_t, std::string>::const_iterator const_iterator; /*!< Const Iterator type */
91 
92 public:
93  typedef std::string key_type; /*!< Type of key (string) */
94  typedef std::set<key_type, KeyCompare> KeySet_t; /*!< Type of a set of keys */
95 
96  /**
97  * Enable or disable parameter verification on an instance
98  * of Params. Useful when generating a new set of Params to
99  * pass off to a module.
100  */
101  bool enableVerify(bool enable) { bool old = verify_enabled; verify_enabled = enable; return old; }
102 
103  /**
104  * Enable, on a global scale, parameter verification. Used
105  * after construction of the config graph so that warnings are
106  * not generated during construction.
107  */
108  static void enableVerify() { g_verify_enabled = true; };
109 
110  /** Returns the size of the Params. */
111  size_t size() const { return data.size(); }
112  /** Returns true if the Params is empty. (Thus begin() would equal end().) */
113  bool empty() const { return data.empty(); }
114 
115 
116  /** Create a new, empty Params */
117  Params() : data(), verify_enabled(true) { }
118 
119  /** Create a copy of a Params object */
120  Params(const Params& old) : data(old.data), allowedKeys(old.allowedKeys), verify_enabled(old.verify_enabled) { }
121 
122  virtual ~Params() { }
123 
124  /**
125  * @brief Assignment operator.
126  * @param old Param to be copied
127  *
128  * All the elements of old are copied,
129  */
130  Params& operator=(const Params& old) {
131  data = old.data;
132  verify_enabled = old.verify_enabled;
133  allowedKeys = old.allowedKeys;
134  return *this;
135  }
136 
137  /**
138  * Erases all elements.
139  */
140  void clear() { data.clear(); }
141 
142 
143  /**
144  * @brief Finds the number of elements with given key.
145  * @param k Key of (key, value) pairs to be located.
146  * @return Number of elements with specified key
147  * (either 1 or 0).
148  *
149  */
150  size_t count(const key_type& k) { return data.count(getKey(k)); }
151 
152  /** Find a Parameter value in the set, and return its value as a type T.
153  * Type T must be either a basic numeric type (including bool) ,
154  * a std::string, or a class that has a constructor with a std::string
155  * as its only parameter. This class uses SST::Core::from_string to
156  * do the conversion.
157  * @param k - Parameter name
158  * @param default_value - Default value to return if parameter isn't found
159  * @param found - set to true if the the parameter was found
160  * @throw std::invalid_argument If value in (key, value) can't be
161  * converted to type T, an invalid_argument exception is thrown.
162  */
163  template <class T>
164  T find(const std::string &k, T default_value, bool &found) const {
165  verifyParam(k);
166  const_iterator i = data.find(getKey(k));
167  if (i == data.end()) {
168  found = false;
169  return default_value;
170  } else {
171  found = true;
172  try {
173  return SST::Core::from_string<T>(i->second);
174  }
175  catch ( const std::invalid_argument& e ) {
176  std::string msg = "Params::find(): No conversion for value: key = " + k + ", value = " + i->second +
177  ". Original error: " + e.what();
178  std::invalid_argument t(msg);
179  throw t;
180  }
181  }
182  }
183 
184  /** Find a Parameter value in the set, and return its value as a type T.
185  * Type T must be either a basic numeric type (including bool) ,
186  * a std::string, or a class that has a constructor with a std::string
187  * as its only parameter. This class uses SST::Core::from_string to
188  * do the conversion.
189  * @param k - Parameter name
190  * @param default_value - Default value to return if parameter isn't found,
191  * specified as a string
192  * @param found - set to true if the the parameter was found
193  */
194  template <class T>
195  T find(const std::string &k, std::string default_value, bool &found) const {
196  verifyParam(k);
197  const_iterator i = data.find(getKey(k));
198  if (i == data.end()) {
199  found = false;
200  try {
201  return SST::Core::from_string<T>(default_value);
202  }
203  catch ( const std::invalid_argument& e ) {
204  std::string msg = "Params::find(): Invalid default value specified: key = " + k + ", value = " + i->second +
205  ". Original error: " + e.what();
206  std::invalid_argument t(msg);
207  throw t;
208  }
209  } else {
210  found = true;
211  try {
212  return SST::Core::from_string<T>(i->second);
213  }
214  catch ( const std::invalid_argument& e ) {
215  std::string msg = "Params::find(): No conversion for value: key = " + k + ", value = " + i->second +
216  ". Original error: " + e.what();
217  std::invalid_argument t(msg);
218  throw t;
219  }
220  }
221  }
222 
223  /** Find a Parameter value in the set, and return its value as a type T.
224  * Type T must be either a basic numeric type (including bool),
225  * a std::string, or a class that has a constructor with a std::string
226  * as its only parameter. This class uses SST::Core::from_string to
227  * do the conversion.
228  * @param k - Parameter name
229  * @param default_value - Default value to return if parameter isn't found
230  */
231  template <class T>
232  T find(const std::string &k, T default_value ) const {
233  bool tmp;
234  return find<T>(k, default_value, tmp);
235  }
236 
237  /** Find a Parameter value in the set, and return its value as a type T.
238  * Type T must be either a basic numeric type (including bool) ,
239  * a std::string, or a class that has a constructor with a std::string
240  * as its only parameter. This class uses SST::Core::from_string to
241  * do the conversion.
242  * @param k - Parameter name
243  * @param default_value - Default value to return if parameter isn't found,
244  * specified as a string
245  */
246  template <class T>
247  T find(const std::string &k, std::string default_value ) const {
248  bool tmp;
249  return find<T>(k, default_value, tmp);
250  }
251 
252  /** Find a Parameter value in the set, and return its value as a type T.
253  * Type T must be either a basic numeric type (including bool) ,
254  * a std::string, or a class that has a constructor with a std::string
255  * as its only parameter. This class uses SST::Core::from_string to
256  * do the conversion.
257  * @param k - Parameter name
258  */
259  template <class T>
260  T find(const std::string &k) const {
261  bool tmp;
262  T default_value = T();
263  return find(k, default_value, tmp);
264  }
265 
266  /** Find a Parameter value in the set, and return its value as a type T.
267  * Type T must be either a basic numeric type (including bool) ,
268  * a std::string, or a class that has a constructor with a std::string
269  * as its only parameter. This class uses SST::Core::from_string to
270  * do the conversion.
271  * @param k - Parameter name
272  * @param found - set to true if the the parameter was found
273  */
274  template <class T>
275  T find(const std::string &k, bool &found) const {
276  T default_value = T();
277  return find(k, default_value, found);
278  }
279 
280  /** Find a Parameter value in the set, and return its value as a
281  * vector of T's. The array will be appended to
282  * the end of the vector.
283  * Type T must be either a basic numeric type (including bool) ,
284  * a std::string, or a class that has a constructor with a std::string
285  * as its only parameter. This class uses SST::Core::from_string to
286  * do the conversion.
287  *
288  * @param k - Parameter name
289  * @param vec - vector to append array items to
290  */
291  template <class T>
292  void find_array(const key_type &k, std::vector<T>& vec) const {
293  verifyParam(k);
294  const_iterator i = data.find(getKey(k));
295  if ( i == data.end()) {
296  return;
297  }
298  std::string value = i->second;
299  // String should start with [ and end with ], we need to cut
300  // these out
301  // Test the value for correct [...] formatting
302  if( (value.find("[") == std::string::npos) ||
303  (value.find("]") == std::string::npos) ){
304  std::string msg =
305  "Params::find_array(): Invalid formatting: String must be enclosed by brackets [str]";
306  std::invalid_argument t(msg);
307  throw t;
308  }
309  value = value.substr(0,value.size()-1);
310  value = value.substr(1);
311 
312  std::stringstream ss(value);
313 
314  while( ss.good() ) {
315  std::string substr;
316  getline( ss, substr, ',' );
317  // vec.push_back(strtol(substr.c_str(), NULL, 0));
318  try {
319  vec.push_back(SST::Core::from_string<T>(substr));
320  }
321  catch ( const std::invalid_argument& e ) {
322  std::string msg = "Params::find(): No conversion for value: key = " + k + ", value = " + substr +
323  ". Original error: " + e.what();
324  std::invalid_argument t(msg);
325  throw t;
326  }
327  }
328  }
329 
330  /** Print all key/value parameter pairs to specified ostream */
331  void print_all_params(std::ostream &os, std::string prefix = "") const {
332  for (const_iterator i = data.begin() ; i != data.end() ; ++i) {
333  os << prefix << "key=" << keyMapReverse[i->first] << ", value=" << i->second << std::endl;
334  }
335  }
336 
337  void print_all_params(Output &out, std::string prefix = "") const {
338  for (const_iterator i = data.begin() ; i != data.end() ; ++i) {
339  out.output("%s%s = %s\n", prefix.c_str(), keyMapReverse[i->first].c_str(), i->second.c_str());
340  }
341  }
342 
343 
344 
345  /** Add a key value pair into the param object.
346  */
347  void insert(std::string key, std::string value, bool overwrite = true) {
348  if ( overwrite ) {
349  data[getKey(key)] = value;
350  }
351  else {
352  uint32_t id = getKey(key);
353  data.insert(std::make_pair(id, value));
354  }
355  }
356 
357  void insert(const Params& params) {
358  data.insert(params.data.begin(), params.data.end());
359  }
360 
361  std::set<std::string> getKeys() const {
362  std::set<std::string> ret;
363  for (const_iterator i = data.begin() ; i != data.end() ; ++i) {
364  ret.insert(keyMapReverse[i->first]);
365  }
366  return ret;
367  }
368 
369  /** Returns a new parameter object with parameters that match
370  * the specified prefix.
371  */
372  Params find_prefix_params(std::string prefix) const {
373  Params ret;
374  ret.enableVerify(false);
375  for (const_iterator i = data.begin() ; i != data.end() ; ++i) {
376  std::string key = keyMapReverse[i->first].substr(0, prefix.length());
377  if (key == prefix) {
378  ret.insert(keyMapReverse[i->first].substr(prefix.length()), i->second);
379  }
380  }
381  ret.allowedKeys = allowedKeys;
382  ret.enableVerify(verify_enabled);
383 
384  return ret;
385  }
386 
387 
388  /**
389  * @param k Key to search for
390  * @return True if the params contains the key, false otherwise
391  */
392  bool contains(const key_type &k) {
393  return data.find(getKey(k)) != data.end();
394  }
395 
396  /**
397  * @param keys Set of keys to consider valid to add to the stack
398  * of legal keys
399  */
400  void pushAllowedKeys(const KeySet_t &keys) {
401  allowedKeys.push_back(keys);
402  }
403 
404  /**
405  * Removes the most recent set of keys considered allowed
406  */
407  void popAllowedKeys() {
408  allowedKeys.pop_back();
409  }
410 
411  /**
412  * @param k Key to check for validity
413  * @return True if the key is considered allowed
414  */
415  void verifyParam(const key_type &k) const {
416  if ( !g_verify_enabled || !verify_enabled ) return;
417 
418  for ( std::vector<KeySet_t>::const_reverse_iterator ri = allowedKeys.rbegin() ; ri != allowedKeys.rend() ; ++ri ) {
419  if ( ri->find(k) != ri->end() ) return;
420  }
421 
422 #ifdef USE_PARAM_WARNINGS
423  SST::Output outXX("ParamWarning: ", 0, 0, Output::STDERR);
424  outXX.output(CALL_INFO, "Warning: Parameter \"%s\" is undocumented.\n", k.c_str());
425 #endif
426  }
427 
428 
429  /**
430  * Given a Parameter Key ID, return the Name of the matching parameter
431  * @param id Key ID to look up
432  * @return String name of the parameter
433  */
434  static const std::string& getParamName(uint32_t id)
435  {
436  return keyMapReverse[id];
437  }
438 
439 
440  void serialize_order(SST::Core::Serialization::serializer &ser) override {
441  ser & data;
442  }
443 
444  ImplementSerializable(SST::Params)
445 
446 private:
447  std::map<uint32_t, std::string> data;
448  std::vector<KeySet_t> allowedKeys;
449  bool verify_enabled;
450  static bool g_verify_enabled;
451 
452  uint32_t getKey(const std::string &str) const
453  {
454  std::lock_guard<SST::Core::ThreadSafe::Spinlock> lock(keyLock);
455  std::map<std::string, uint32_t>::iterator i = keyMap.find(str);
456  if ( i == keyMap.end() ) {
457  return (uint32_t)-1;
458  }
459  return i->second;
460  }
461 
462  uint32_t getKey(const std::string &str)
463  {
464  std::lock_guard<SST::Core::ThreadSafe::Spinlock> lock(keyLock);
465  std::map<std::string, uint32_t>::iterator i = keyMap.find(str);
466  if ( i == keyMap.end() ) {
467  uint32_t id = nextKeyID++;
468  keyMap.insert(std::make_pair(str, id));
469  keyMapReverse.push_back(str);
470  assert(keyMapReverse.size() == nextKeyID);
471  return id;
472  }
473  return i->second;
474  }
475 
476  /* Friend main() because it broadcasts the maps */
477  friend int ::main(int argc, char *argv[]);
478 
479  static std::map<std::string, uint32_t> keyMap;
480  static std::vector<std::string> keyMapReverse;
481  static SST::Core::ThreadSafe::Spinlock keyLock;
482  static uint32_t nextKeyID;
483 
484 
485 };
486 
487 } //namespace SST
488 
489 #endif //SST_CORE_PARAMS_H
Output object provides consistent method for outputting data to stdout, stderr and/or sst debug file...
Definition: output.h:54
Params(const Params &old)
Create a copy of a Params object.
Definition: params.h:120
This class is basically a wrapper for objects to declare the order in which their members should be s...
Definition: serializer.h:35
void find_array(const key_type &k, std::vector< T > &vec) const
Find a Parameter value in the set, and return its value as a vector of T&#39;s.
Definition: params.h:292
T find(const std::string &k, T default_value) const
Find a Parameter value in the set, and return its value as a type T.
Definition: params.h:232
T find(const std::string &k, std::string default_value, bool &found) const
Find a Parameter value in the set, and return its value as a type T.
Definition: params.h:195
void pushAllowedKeys(const KeySet_t &keys)
Definition: params.h:400
bool contains(const key_type &k)
Definition: params.h:392
Params find_prefix_params(std::string prefix) const
Returns a new parameter object with parameters that match the specified prefix.
Definition: params.h:372
void insert(std::string key, std::string value, bool overwrite=true)
Add a key value pair into the param object.
Definition: params.h:347
T find(const std::string &k, std::string default_value) const
Find a Parameter value in the set, and return its value as a type T.
Definition: params.h:247
Params & operator=(const Params &old)
Assignment operator.
Definition: params.h:130
T find(const std::string &k) const
Find a Parameter value in the set, and return its value as a type T.
Definition: params.h:260
static void enableVerify()
Enable, on a global scale, parameter verification.
Definition: params.h:108
void print_all_params(std::ostream &os, std::string prefix="") const
Print all key/value parameter pairs to specified ostream.
Definition: params.h:331
size_t count(const key_type &k)
Finds the number of elements with given key.
Definition: params.h:150
Definition: serializable.h:109
bool empty() const
Returns true if the Params is empty.
Definition: params.h:113
void clear()
Erases all elements.
Definition: params.h:140
static const std::string & getParamName(uint32_t id)
Given a Parameter Key ID, return the Name of the matching parameter.
Definition: params.h:434
Params()
Create a new, empty Params.
Definition: params.h:117
T find(const std::string &k, T default_value, bool &found) const
Find a Parameter value in the set, and return its value as a type T.
Definition: params.h:164
bool enableVerify(bool enable)
Enable or disable parameter verification on an instance of Params.
Definition: params.h:101
void output(uint32_t line, const char *file, const char *func, const char *format,...) const
Output the message with formatting as specified by the format parameter.
Definition: output.h:184
Definition: output.h:62
Definition: threadsafe.h:127
size_t size() const
Returns the size of the Params.
Definition: params.h:111
T find(const std::string &k, bool &found) const
Find a Parameter value in the set, and return its value as a type T.
Definition: params.h:275
Parameter store.
Definition: params.h:45
void popAllowedKeys()
Removes the most recent set of keys considered allowed.
Definition: params.h:407
std::set< key_type, KeyCompare > KeySet_t
Definition: params.h:94
std::string key_type
Definition: params.h:93
void verifyParam(const key_type &k) const
Definition: params.h:415