SST  9.1.0
StructuralSimulationToolkit
params.h
1 // Copyright 2009-2019 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-2019, 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 
91  /** Find a Parameter value in the set, and return its value as a type T.
92  * Type T must be either a basic numeric type (including bool) ,
93  * a std::string, or a class that has a constructor with a std::string
94  * as its only parameter. This class uses SST::Core::from_string to
95  * do the conversion.
96  * @param k - Parameter name
97  * @param default_value - Default value to return if parameter isn't found
98  * @param found - set to true if the the parameter was found
99  * @throw std::invalid_argument If value in (key, value) can't be
100  * converted to type T, an invalid_argument exception is thrown.
101  */
102  template <class T>
103  inline T find_impl(const std::string &k, T default_value, bool &found) const {
104  verifyParam(k);
105  // const_iterator i = data.find(getKey(k));
106  const std::string& value = getString(k,found);
107  // if (i == data.end()) {
108  // found = false;
109  if ( !found ) {
110  return default_value;
111  }
112  else {
113  // found = true;
114  try {
115  // return SST::Core::from_string<T>(i->second);
116  return SST::Core::from_string<T>(value);
117  }
118  catch ( const std::invalid_argument& e ) {
119  std::string msg = "Params::find(): No conversion for value: key = " + k + ", value = " + value +
120  ". Original error: " + e.what();
121  std::invalid_argument t(msg);
122  throw t;
123  }
124  }
125  }
126 
127  /** Find a Parameter value in the set, and return its value as a type T.
128  * Type T must be either a basic numeric type (including bool) ,
129  * a std::string, or a class that has a constructor with a std::string
130  * as its only parameter. This class uses SST::Core::from_string to
131  * do the conversion.
132  * @param k - Parameter name
133  * @param default_value - Default value to return if parameter isn't found,
134  * specified as a string
135  * @param found - set to true if the the parameter was found
136  */
137  template <class T>
138  inline T find_impl(const std::string &k, std::string default_value, bool &found) const {
139  verifyParam(k);
140  const std::string& value = getString(k,found);
141  if ( !found ) {
142  try {
143  return SST::Core::from_string<T>(default_value);
144  }
145  catch ( const std::invalid_argument& e ) {
146  std::string msg = "Params::find(): Invalid default value specified: key = " + k + ", value = " + default_value +
147  ". Original error: " + e.what();
148  std::invalid_argument t(msg);
149  throw t;
150  }
151  }
152  else {
153  found = true;
154  try {
155  return SST::Core::from_string<T>(value);
156  }
157  catch ( const std::invalid_argument& e ) {
158  std::string msg = "Params::find(): No conversion for value: key = " + k + ", value = " + value +
159  ". Original error: " + e.what();
160  std::invalid_argument t(msg);
161  throw t;
162  }
163  }
164  }
165 
166  typedef std::map<uint32_t, std::string>::const_iterator const_iterator; /*!< Const Iterator type */
167 
168  const std::string& getString(const std::string& name, bool& found) const;
169 
170 public:
171  typedef std::string key_type; /*!< Type of key (string) */
172  typedef std::set<key_type, KeyCompare> KeySet_t; /*!< Type of a set of keys */
173 
174  /**
175  * Enable or disable parameter verification on an instance
176  * of Params. Useful when generating a new set of Params to
177  * pass off to a module.
178  */
179  bool enableVerify(bool enable) { bool old = verify_enabled; verify_enabled = enable; return old; }
180 
181  /**
182  * Enable, on a global scale, parameter verification. Used
183  * after construction of the config graph so that warnings are
184  * not generated during construction.
185  */
186  static void enableVerify() { g_verify_enabled = true; };
187 
188  /** Returns the size of the Params. */
189  size_t size() const;
190  /** Returns true if the Params is empty. (Thus begin() would equal end().) */
191  bool empty() const;
192 
193 
194  /** Create a new, empty Params */
195  Params();
196 
197  /** Create a copy of a Params object */
198  Params(const Params& old);
199 
200  virtual ~Params() { }
201 
202  /**
203  * @brief Assignment operator.
204  * @param old Param to be copied
205  *
206  * All the elements of old are copied,
207  */
208  Params& operator=(const Params& old);
209 
210  /**
211  * Erases all elements.
212  */
213  void clear();
214 
215 
216  /**
217  * @brief Finds the number of elements with given key.
218  * @param k Key of (key, value) pairs to be located.
219  * @return Number of elements with specified key
220  * (either 1 or 0).
221  *
222  */
223  size_t count(const key_type& k);
224 
225  /** Find a Parameter value in the set, and return its value as a type T.
226  * Type T must be either a basic numeric type (including bool) ,
227  * a std::string, or a class that has a constructor with a std::string
228  * as its only parameter. This class uses SST::Core::from_string to
229  * do the conversion.
230  * @param k - Parameter name
231  * @param default_value - Default value to return if parameter isn't found
232  * @param found - set to true if the the parameter was found
233  * @throw std::invalid_argument If value in (key, value) can't be
234  * converted to type T, an invalid_argument exception is thrown.
235  */
236  template <class T>
237  typename std::enable_if<not std::is_same<std::string,T>::value, T>::type
238  find(const std::string &k, T default_value, bool &found) const {
239  return find_impl<T>(k,default_value,found);
240  }
241 
242  /** Find a Parameter value in the set, and return its value as a type T.
243  * Type T must be either a basic numeric type (including bool) ,
244  * a std::string, or a class that has a constructor with a std::string
245  * as its only parameter. This class uses SST::Core::from_string to
246  * do the conversion.
247  * @param k - Parameter name
248  * @param default_value - Default value to return if parameter isn't found,
249  * specified as a string
250  * @param found - set to true if the the parameter was found
251  */
252  template <class T>
253  T find(const std::string &k, std::string default_value, bool &found) const {
254  return find_impl<T>(k,default_value,found);
255  }
256 
257  /** Find a Parameter value in the set, and return its value as a type T.
258  * This version of find is only enabled for bool. This
259  * is required because a string literal will be preferentially
260  * cast to a bool rather than a string. This ensures that
261  * find<bool> works correctly for string literals. This class uses
262  * SST::Core::from_string to do the conversion.
263  * @param k - Parameter name
264  * @param default_value - Default value to return if parameter isn't found,
265  * specified as a string literal
266  */
267  template <class T>
268  typename std::enable_if<std::is_same<bool,T>::value, T>::type
269  find(const std::string &k, const char* default_value, bool &found ) const {
270  if ( 0 == default_value ) {
271  return find_impl<T>(k, static_cast<T>(0), found);
272  }
273  return find_impl<T>(k, std::string(default_value), found);
274  }
275 
276  /** Find a Parameter value in the set, and return its value as a type T.
277  * Type T must be either a basic numeric type (including bool),
278  * a std::string, or a class that has a constructor with a std::string
279  * as its only parameter. This class uses SST::Core::from_string to
280  * do the conversion.
281  * @param k - Parameter name
282  * @param default_value - Default value to return if parameter isn't found
283  */
284  template <class T>
285  T find(const std::string &k, T default_value ) const {
286  bool tmp;
287  return find_impl<T>(k, default_value, tmp);
288  }
289 
290  /** Find a Parameter value in the set, and return its value as a type T.
291  * Type T must be either a basic numeric type (including bool) ,
292  * a std::string, or a class that has a constructor with a std::string
293  * as its only parameter. This class uses SST::Core::from_string to
294  * do the conversion.
295  * @param k - Parameter name
296  * @param default_value - Default value to return if parameter isn't found,
297  * specified as a string
298  */
299  template <class T>
300  T find(const std::string &k, std::string default_value ) const {
301  bool tmp;
302  return find_impl<T>(k, default_value, tmp);
303  }
304 
305  /** Find a Parameter value in the set, and return its value as a type T.
306  * This version of find is only enabled for bool. This
307  * is required because a string literal will be preferentially
308  * cast to a bool rather than a string. This ensures that
309  * find<bool> works correctly for string literals.This class uses
310  * SST::Core::from_string to do the conversion.
311  * @param k - Parameter name
312  * @param default_value - Default value to return if parameter isn't found,
313  * specified as a string literal
314  */
315  template <class T>
316  typename std::enable_if<std::is_same<bool,T>::value, T>::type
317  find(const std::string &k, const char* default_value ) const {
318  bool tmp;
319  if ( 0 == default_value ) {
320  return find_impl<T>(k, static_cast<T>(0), tmp);
321  }
322  return find_impl<T>(k, std::string(default_value), tmp);
323  }
324 
325  /** Find a Parameter value in the set, and return its value as a type T.
326  * Type T must be either a basic numeric type (including bool) ,
327  * a std::string, or a class that has a constructor with a std::string
328  * as its only parameter. This class uses SST::Core::from_string to
329  * do the conversion.
330  * @param k - Parameter name
331  */
332  template <class T>
333  T find(const std::string &k) const {
334  bool tmp;
335  T default_value = T();
336  return find_impl<T>(k, default_value, tmp);
337  }
338 
339  /** Find a Parameter value in the set, and return its value as a
340  * type T. Type T must be either a basic numeric type , a
341  * std::string, or a class that has a constructor with a
342  * std::string as its only parameter. This version of find is not
343  * enabled for bool as it conflicts with find<bool>(string key, bool
344  * default_value). This class uses SST::Core::from_string to do
345  * the conversion.
346  * @param k - Parameter name
347  * @param found - set to true if the the parameter was found
348  */
349  template <class T>
350  typename std::enable_if<not std::is_same<bool, T>::value, T>::type
351  find(const std::string &k, bool &found) const {
352  T default_value = T();
353  return find_impl<T>(k, default_value, found);
354  }
355 
356  /** Find a Parameter value in the set, and return its value as a
357  * vector of T's. The array will be appended to
358  * the end of the vector.
359  * Type T must be either a basic numeric type (including bool) ,
360  * a std::string, or a class that has a constructor with a std::string
361  * as its only parameter. This class uses SST::Core::from_string to
362  * do the conversion.
363  *
364  * @param k - Parameter name
365  * @param vec - vector to append array items to
366  */
367  template <class T>
368  void find_array(const key_type &k, std::vector<T>& vec) const {
369  verifyParam(k);
370  // const_iterator i = data.find(getKey(k));
371  // if ( i == data.end()) {
372  // return;
373  // }
374  // std::string value = i->second;
375  bool found = false;
376  std::string value = getString(k,found);
377  if ( !found ) return;
378  // String should start with [ and end with ], we need to cut
379  // these out
380  // Test the value for correct [...] formatting
381  if( (value.find("[") == std::string::npos) ||
382  (value.find("]") == std::string::npos) ){
383  std::string msg =
384  "Params::find_array(): Invalid formatting: String must be enclosed by brackets [str]";
385  std::invalid_argument t(msg);
386  throw t;
387  }
388  value = value.substr(0,value.size()-1);
389  value = value.substr(1);
390 
391  std::stringstream ss(value);
392 
393  while( ss.good() ) {
394  std::string substr;
395  getline( ss, substr, ',' );
396  // vec.push_back(strtol(substr.c_str(), NULL, 0));
397  try {
398  vec.push_back(SST::Core::from_string<T>(substr));
399  }
400  catch ( const std::invalid_argument& e ) {
401  std::string msg = "Params::find(): No conversion for value: key = " + k + ", value = " + substr +
402  ". Original error: " + e.what();
403  std::invalid_argument t(msg);
404  throw t;
405  }
406  }
407  }
408 
409  /** Print all key/value parameter pairs to specified ostream */
410  void print_all_params(std::ostream &os, std::string prefix = "") const;
411  void print_all_params(Output &out, std::string prefix = "") const;
412 
413 
414 
415  /** Add a key value pair into the param object.
416  */
417  void insert(std::string key, std::string value, bool overwrite = true);
418 
419  void insert(const Params& params);
420 
421  std::set<std::string> getKeys() const;
422 
423  /** Returns a new parameter object with parameters that match
424  * the specified prefix.
425  */
426  Params find_prefix_params(const std::string& prefix) const;
427 
428  Params find_scoped_params(const std::string& scope, const char* delims = ".:") const;
429 
430  /**
431  * @param k Key to search for
432  * @return True if the params contains the key, false otherwise
433  */
434  bool contains(const key_type &k);
435 
436  /**
437  * @param keys Set of keys to consider valid to add to the stack
438  * of legal keys
439  */
440  void pushAllowedKeys(const KeySet_t &keys);
441 
442  /**
443  * Removes the most recent set of keys considered allowed
444  */
445  void popAllowedKeys();
446 
447  /**
448  * @param k Key to check for validity
449  * @return True if the key is considered allowed
450  */
451  void verifyParam(const key_type &k) const;
452 
453 
454  /**
455  * Given a Parameter Key ID, return the Name of the matching parameter
456  * @param id Key ID to look up
457  * @return String name of the parameter
458  */
459  static const std::string& getParamName(uint32_t id);
460 
461 
462  void serialize_order(SST::Core::Serialization::serializer &ser) override;
463  ImplementSerializable(SST::Params)
464 
465 private:
466  std::map<uint32_t, std::string> data;
467  std::vector<KeySet_t> allowedKeys;
468  bool verify_enabled;
469  static bool g_verify_enabled;
470 
471  uint32_t getKey(const std::string &str) const;
472  uint32_t getKey(const std::string &str);
473 
474  /* Friend main() because it broadcasts the maps */
475  friend int ::main(int argc, char *argv[]);
476 
477  static std::map<std::string, uint32_t> keyMap;
478  static std::vector<std::string> keyMapReverse;
479  static SST::Core::ThreadSafe::Spinlock keyLock;
480  static uint32_t nextKeyID;
481 
482 
483 };
484 
485 #if 0
486  class UnitAlgebra;
487 
488  #define SST_PARAMS_DECLARE_TEMPLATE_SPECIALIZATION(type) \
489  template<> \
490  type Params::find(const std::string &k, type default_value, bool &found) const; \
491  template<> \
492  type Params::find(const std::string &k, std::string default_value, bool &found) const; \
493  template <> \
494  type Params::find(const std::string &k, type default_value ) const; \
495  template <> \
496  type Params::find(const std::string &k, std::string default_value ) const; \
497  template <> \
498  type Params::find(const std::string &k) const;
499 
500 
501  SST_PARAMS_DECLARE_TEMPLATE_SPECIALIZATION(int32_t)
502  SST_PARAMS_DECLARE_TEMPLATE_SPECIALIZATION(uint32_t)
503  SST_PARAMS_DECLARE_TEMPLATE_SPECIALIZATION(int64_t)
504  SST_PARAMS_DECLARE_TEMPLATE_SPECIALIZATION(uint64_t)
505  SST_PARAMS_DECLARE_TEMPLATE_SPECIALIZATION(bool)
506  SST_PARAMS_DECLARE_TEMPLATE_SPECIALIZATION(float)
507  SST_PARAMS_DECLARE_TEMPLATE_SPECIALIZATION(double)
508  SST_PARAMS_DECLARE_TEMPLATE_SPECIALIZATION(UnitAlgebra)
509 
510  // std::string has to be special cased because of signature conflicts
511  // SST_PARAMS_DECLARE_TEMPLATE_SPECIALIZATION(std::string)
512  template<>
513  std::string Params::find<std::string>(const std::string &k, std::string default_value, bool &found) const;
514 #endif
515 
516 
517 
518 } //namespace SST
519 
520 #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
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:368
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:285
Params find_prefix_params(const std::string &prefix) const
Returns a new parameter object with parameters that match the specified prefix.
Definition: params.cc:156
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:253
void pushAllowedKeys(const KeySet_t &keys)
Definition: params.cc:179
bool contains(const key_type &k)
Definition: params.cc:173
std::enable_if< not std::is_same< std::string, T >::value, T >::type 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:238
void insert(std::string key, std::string value, bool overwrite=true)
Add a key value pair into the param object.
Definition: params.cc:99
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:300
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:333
static void enableVerify()
Enable, on a global scale, parameter verification.
Definition: params.h:186
void print_all_params(std::ostream &os, std::string prefix="") const
Print all key/value parameter pairs to specified ostream.
Definition: params.cc:82
size_t count(const key_type &k)
Finds the number of elements with given key.
Definition: params.cc:76
Definition: serializable.h:110
bool empty() const
Returns true if the Params is empty.
Definition: params.cc:44
static const std::string & getParamName(uint32_t id)
Given a Parameter Key ID, return the Name of the matching parameter.
Definition: params.cc:206
void clear()
Erases all elements.
Definition: params.cc:69
Params()
Create a new, empty Params.
Definition: params.cc:49
bool enableVerify(bool enable)
Enable or disable parameter verification on an instance of Params.
Definition: params.h:179
std::enable_if< not std::is_same< bool, T >::value, T >::type 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:351
Definition: threadsafe.h:127
size_t size() const
Returns the size of the Params.
Definition: params.cc:38
std::enable_if< std::is_same< bool, T >::value, T >::type find(const std::string &k, const char *default_value, bool &found) const
Find a Parameter value in the set, and return its value as a type T.
Definition: params.h:269
Parameter store.
Definition: params.h:45
void popAllowedKeys()
Removes the most recent set of keys considered allowed.
Definition: params.cc:185
std::set< key_type, KeyCompare > KeySet_t
Definition: params.h:172
std::string key_type
Definition: params.h:171
void verifyParam(const key_type &k) const
Definition: params.cc:191
Params & operator=(const Params &old)
Assignment operator.
Definition: params.cc:61
Performs Unit math in full precision.
Definition: unitAlgebra.h:104
std::enable_if< std::is_same< bool, T >::value, T >::type find(const std::string &k, const char *default_value) const
Find a Parameter value in the set, and return its value as a type T.
Definition: params.h:317