SST  10.1.0
StructuralSimulationToolkit
params.h
1 // Copyright 2009-2020 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-2020, 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 
31 int main(int argc, char *argv[]);
32 
33 namespace SST {
34 
35 class ConfigGraph;
36 
37 /**
38  * Parameter store.
39  *
40  * Stores key-value pairs as std::strings and provides
41  * a templated find method for finding values and converting
42  * them to arbitrary types (@see find()).
43  */
45 private:
46  struct KeyCompare : std::binary_function<std::string, std::string, bool>
47  {
48  bool operator()(const std::string& X, const std::string& Y) const
49  {
50  const char *x = X.c_str();
51  const char *y = Y.c_str();
52 
53 #define EAT_VAR(A, B) \
54  do { \
55  if ( *x == '%' && (*(x+1) == '(' || *(x+1) == 'd')) { \
56  /* We need to eat off some tokens */ \
57  ++x; \
58  if ( *x == '(' ) { \
59  do { x++; } while ( *x && *x != ')' ); \
60  x++; /* *x should now == 'd' */ \
61  } \
62  if ( *x != 'd' ) goto NO_VARIABLE; \
63  x++; /* Finish eating the variable */ \
64  /* Now, eat of digits of Y */ \
65  while ( *y && isdigit(*y) ) y++; \
66  } \
67  } while(0)
68 
69  do {
70  EAT_VAR(x, y);
71  EAT_VAR(y, x);
72 NO_VARIABLE:
73  if ( *x == *y ) {
74  if ( '\0' == *x ) return false;
75  x++;
76  y++;
77  } else {
78  if ( *x < *y ) return true;
79  return false;
80  }
81  } while ( *x && *y );
82  if ( !(*x) && (*y) ) return true;
83  return false;
84 
85 #undef EAT_VAR
86  }
87  };
88 
89 
90  /** Private utility function to convert a value to the specified
91  * type and check for errors. Key is passed only in case an error
92  * message needs to be generated.
93  *
94  * Type T must be either a basic numeric type (including bool) ,
95  * a std::string, or a class that has a constructor with a std::string
96  * as its only parameter. This class uses SST::Core::from_string to
97  * do the conversion.
98  * @param k - Parameter name
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 convert_value(const std::string& key, const std::string& val) const {
104  try {
105  return SST::Core::from_string<T>(val);
106  }
107  catch ( const std::invalid_argument& e ) {
108  std::string msg = "Params::find(): No conversion for value: key = " + key + ", value = " + val +
109  ". Original error: " + e.what();
110  std::invalid_argument t(msg);
111  throw t;
112  }
113  }
114 
115  /** Private utility function to find a Parameter value in the set,
116  * and return its value as a type T.
117  *
118  * Type T must be either a basic numeric type (including bool) ,
119  * a std::string, or a class that has a constructor with a std::string
120  * as its only parameter. This class uses SST::Core::from_string to
121  * do the conversion.
122  * @param k - Parameter name
123  * @param default_value - Default value to return if parameter isn't found
124  * @param found - set to true if the the parameter was found
125  * @throw std::invalid_argument If value in (key, value) can't be
126  * converted to type T, an invalid_argument exception is thrown.
127  */
128  template <class T>
129  inline T find_impl(const std::string& k, T default_value, bool &found) const {
130  verifyParam(k);
131  // const_iterator i = data.find(getKey(k));
132  const std::string& value = getString(k,found);
133  if ( !found ) {
134  return default_value;
135  }
136  else {
137  return convert_value<T>(k,value);
138  }
139  }
140 
141  /** Find a Parameter value in the set, and return its value as a type T.
142  * Type T must be either a basic numeric type (including bool) ,
143  * a std::string, or a class that has a constructor with a std::string
144  * as its only parameter. This class uses SST::Core::from_string to
145  * do the conversion.
146  * @param k - Parameter name
147  * @param default_value - Default value to return if parameter isn't found,
148  * specified as a string
149  * @param found - set to true if the the parameter was found
150  */
151  template <class T>
152  inline T find_impl(const std::string& k, const std::string& default_value, bool &found) const {
153  verifyParam(k);
154  const std::string& value = getString(k,found);
155  if ( !found ) {
156  try {
157  return SST::Core::from_string<T>(default_value);
158  }
159  catch ( const std::invalid_argument& e ) {
160  std::string msg = "Params::find(): Invalid default value specified: key = " + k + ", value = " + default_value +
161  ". Original error: " + e.what();
162  std::invalid_argument t(msg);
163  throw t;
164  }
165  }
166  else {
167  found = true;
168  try {
169  return SST::Core::from_string<T>(value);
170  }
171  catch ( const std::invalid_argument& e ) {
172  std::string msg = "Params::find(): No conversion for value: key = " + k + ", value = " + value +
173  ". Original error: " + e.what();
174  std::invalid_argument t(msg);
175  throw t;
176  }
177  }
178  }
179 
180  typedef std::map<uint32_t, std::string>::const_iterator const_iterator; /*!< Const Iterator type */
181 
182  const std::string& getString(const std::string& name, bool& found) const;
183 
184  void getArrayTokens(const std::string& value, std::vector<std::string>& tokens) const;
185 
186 public:
187  typedef std::string key_type; /*!< Type of key (string) */
188  typedef std::set<key_type, KeyCompare> KeySet_t; /*!< Type of a set of keys */
189 
190  /**
191  * Enable or disable parameter verification on an instance
192  * of Params. Useful when generating a new set of Params to
193  * pass off to a module.
194  */
195  bool enableVerify(bool enable) { bool old = verify_enabled; verify_enabled = enable; return old; }
196 
197  /**
198  * Enable, on a global scale, parameter verification. Used
199  * after construction of the config graph so that warnings are
200  * not generated during construction.
201  */
202  static void enableVerify() { g_verify_enabled = true; };
203 
204  /** Returns the size of the Params. */
205  size_t size() const;
206  /** Returns true if the Params is empty. (Thus begin() would equal end().) */
207  bool empty() const;
208 
209 
210  /** Create a new, empty Params */
211  Params();
212 
213  /** Create a copy of a Params object */
214  Params(const Params& old);
215 
216  virtual ~Params() { }
217 
218  /**
219  * @brief Assignment operator.
220  * @param old Param to be copied
221  *
222  * All the elements of old are copied,
223  */
224  Params& operator=(const Params& old);
225 
226  /**
227  * Erases all elements.
228  */
229  void clear();
230 
231 
232  /**
233  * @brief Finds the number of elements with given key.
234  * @param k Key of (key, value) pairs to be located.
235  * @return Number of elements with specified key
236  * (either 1 or 0).
237  *
238  */
239  size_t count(const key_type& k);
240 
241  /** Find a Parameter value in the set, and return its value as a type T.
242  * Type T must be either a basic numeric type (including bool) ,
243  * a std::string, or a class that has a constructor with a std::string
244  * as its only parameter. This class uses SST::Core::from_string to
245  * do the conversion.
246  * @param k - Parameter name
247  * @param default_value - Default value to return if parameter isn't found
248  * @param found - set to true if the the parameter was found
249  * @throw std::invalid_argument If value in (key, value) can't be
250  * converted to type T, an invalid_argument exception is thrown.
251  */
252  template <class T>
253  typename std::enable_if<not std::is_same<std::string,T>::value, T>::type
254  find(const std::string& k, T default_value, bool &found) const {
255  return find_impl<T>(k,default_value,found);
256  }
257 
258  /** Find a Parameter value in the set, and return its value as a type T.
259  * Type T must be either a basic numeric type (including bool) ,
260  * a std::string, or a class that has a constructor with a std::string
261  * as its only parameter. This class uses SST::Core::from_string to
262  * 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
266  * @param found - set to true if the the parameter was found
267  */
268  template <class T>
269  T find(const std::string& k, const std::string& default_value, bool &found) const {
270  return find_impl<T>(k,default_value,found);
271  }
272 
273  /** Find a Parameter value in the set, and return its value as a type T.
274  * This version of find is only enabled for bool. This
275  * is required because a string literal will be preferentially
276  * cast to a bool rather than a string. This ensures that
277  * find<bool> works correctly for string literals. This class uses
278  * SST::Core::from_string to do the conversion.
279  * @param k - Parameter name
280  * @param default_value - Default value to return if parameter isn't found,
281  * specified as a string literal
282  */
283  template <class T>
284  typename std::enable_if<std::is_same<bool,T>::value, T>::type
285  find(const std::string& k, const char* default_value, bool &found ) const {
286  if ( nullptr == default_value ) {
287  return find_impl<T>(k, static_cast<T>(0), found);
288  }
289  return find_impl<T>(k, std::string(default_value), found);
290  }
291 
292  /** Find a Parameter value in the set, and return its value as a type T.
293  * Type T must be either a basic numeric type (including bool),
294  * a std::string, or a class that has a constructor with a std::string
295  * as its only parameter. This class uses SST::Core::from_string to
296  * do the conversion.
297  * @param k - Parameter name
298  * @param default_value - Default value to return if parameter isn't found
299  */
300  template <class T>
301  T find(const std::string& k, T default_value ) const {
302  bool tmp;
303  return find_impl<T>(k, default_value, tmp);
304  }
305 
306  /** Find a Parameter value in the set, and return its value as a type T.
307  * Type T must be either a basic numeric type (including bool) ,
308  * a std::string, or a class that has a constructor with a std::string
309  * as its only parameter. This class uses SST::Core::from_string to
310  * 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
314  */
315  template <class T>
316  T find(const std::string& k, const std::string& default_value ) const {
317  bool tmp;
318  return find_impl<T>(k, default_value, tmp);
319  }
320 
321  /** Find a Parameter value in the set, and return its value as a type T.
322  * This version of find is only enabled for bool. This
323  * is required because a string literal will be preferentially
324  * cast to a bool rather than a string. This ensures that
325  * find<bool> works correctly for string literals.This class uses
326  * SST::Core::from_string to do the conversion.
327  * @param k - Parameter name
328  * @param default_value - Default value to return if parameter isn't found,
329  * specified as a string literal
330  */
331  template <class T>
332  typename std::enable_if<std::is_same<bool,T>::value, T>::type
333  find(const std::string& k, const char* default_value ) const {
334  bool tmp;
335  if ( nullptr == default_value ) {
336  return find_impl<T>(k, static_cast<T>(0), tmp);
337  }
338  return find_impl<T>(k, std::string(default_value), tmp);
339  }
340 
341  /** Find a Parameter value in the set, and return its value as a type T.
342  * Type T must be either a basic numeric type (including bool) ,
343  * a std::string, or a class that has a constructor with a std::string
344  * as its only parameter. This class uses SST::Core::from_string to
345  * do the conversion.
346  * @param k - Parameter name
347  */
348  template <class T>
349  T find(const std::string& k) const {
350  bool tmp;
351  T default_value = T();
352  return find_impl<T>(k, default_value, tmp);
353  }
354 
355  /** Find a Parameter value in the set, and return its value as a
356  * type T. Type T must be either a basic numeric type , a
357  * std::string, or a class that has a constructor with a
358  * std::string as its only parameter. This version of find is not
359  * enabled for bool as it conflicts with find<bool>(string key, bool
360  * default_value). This class uses SST::Core::from_string to do
361  * the conversion.
362  * @param k - Parameter name
363  * @param found - set to true if the the parameter was found
364  */
365  template <class T>
366  typename std::enable_if<not std::is_same<bool, T>::value, T>::type
367  find(const std::string& k, bool &found) const {
368  T default_value = T();
369  return find_impl<T>(k, default_value, found);
370  }
371 
372  /** Find a Parameter value in the set, and return its value as a
373  * vector of T's. The array will be appended to
374  * the end of the vector.
375  *
376  * Type T must be either a basic numeric type (including bool) , a
377  * std::string, or a class that has a constructor with a
378  * std::string as its only parameter. This class uses
379  * SST::Core::from_string to do the conversion. The values in the
380  * array must be enclosed in square brackets ( [] ), and be comma
381  * separated (commas in double or single quotes will not be
382  * considered a delimiter). If there are no square brackets, the
383  * entire string will be considered one value and a single item
384  * will be added to the vector.
385  *
386  * More details about parsing the values out of the string:
387  *
388  * Parses a string representing an array of tokens. It is
389  * tailored to the types strings you get when passing a python
390  * list as the param string. When you call addParam() on a python
391  * list in the input file, it will call the str() function on the
392  * list, which creates a string with the following format:
393  * [item1, item2, item3]
394  *
395  * The format of the items depends on where they came from. The
396  * string for the items are generated by calling the repr()
397  * function on them. For strings, this means they will typically
398  * be enclosed in single quotes. It is possible that they end up
399  * enclosed in double quotes if the string itself contains a
400  * single quote. For strings which contain both single and double
401  * quotes, the repr() will create a single quoted string with all
402  * internal single quotes escaped with '\'. Most other items used
403  * in SST do not enclose the string in quotes, though any string
404  * that contains a comma would need to be enclosed in quotes,
405  * since the comma is the delimiter character used. This is not
406  * done automatically, so if you have something that generates a
407  * commma in the string created by repr(), you may need to create
408  * an array string manually. Also, any string that starts with a
409  * quote character, must end with the same quote character.
410  *
411  * Tokens are generated by splitting the string on commas that are
412  * not within quotes (double or single). All whitespace at the
413  * beginning and end of a token is ignored (unless inside quotes).
414  * Once the tokens are generated, any quoted string will have the
415  * front and back quotes removed. The '\' for any escaped quote
416  * of the same type as the front and back is also removed.
417  *
418  * Examples:
419  *
420  * These will produce the same results:
421  * [1, 2, 3, 4, 5]
422  * ['1', '2', '3', '4', '5']
423  *
424  * Examples of strings using double and/or single quotes:
425  * 'This is "a" test' -> This is "a" test
426  * "This is 'a' test" -> This is 'a' test
427  * 'This "is \'a\'" test' -> This "is 'a'" test
428  * 'This "is \"a\"" test' -> This "is \"a\"" test
429  *
430  * @param k - Parameter name
431  * @param vec - vector to append array items to
432  */
433  template <class T>
434  void find_array(const key_type &k, std::vector<T>& vec) const {
435  verifyParam(k);
436 
437  bool found = false;
438  std::string value = getString(k,found);
439  if ( !found ) return;
440  // If string starts with [ and ends with ], it is considered
441  // an array. Otherwise, it is considered a single
442  // value.
443  if ( value.front() != '[' || value.back() != ']' ) {
444  vec.push_back(convert_value<T>(k,value));
445  return;
446  }
447 
448  value = value.substr(1,value.size()-2);
449 
450  // Get the tokens for the array
451  std::vector<std::string> tokens;
452  getArrayTokens(value,tokens);
453 
454  // Convert each token into the proper type and put in output
455  // vector
456  for ( auto& val : tokens ) {
457  vec.push_back(convert_value<T>(k,val));
458  }
459  }
460 
461  /** Checks to see if the value associated with the given key is
462  * considered to be an array. A value is considered to be an
463  * array if it is enclosed in square brackets ([]). No whitespace
464  * before or after the brackets is allowed.
465  *
466  * @param k - Parameter name
467  * @return true if value is an array as described above, false otherwise.
468  */
469  bool is_value_array(const key_type& k) const {
470  bool found = false;
471  std::string value = getString(k,found);
472  if ( !found ) return false;
473  // String should start with [ and end with ]
474  if( (value.find("[") == std::string::npos) ||
475  (value.find("]") == std::string::npos) ){
476  return false;
477  }
478  return true;
479  }
480 
481  /** Print all key/value parameter pairs to specified ostream */
482  void print_all_params(std::ostream &os, const std::string& prefix = "") const;
483  void print_all_params(Output &out, const std::string& prefix = "") const;
484 
485 
486 
487  /** Add a key value pair into the param object.
488  */
489  void insert(const std::string& key, const std::string& value, bool overwrite = true);
490 
491  void insert(const Params& params);
492 
493  std::set<std::string> getKeys() const;
494 
495  /** Returns a new parameter object with parameters that match
496  * the specified prefix.
497  */
498  Params find_prefix_params(const std::string& prefix) const;
499 
500  Params find_scoped_params(const std::string& scope, const char* delims = ".:") const;
501 
502  /**
503  * @param k Key to search for
504  * @return True if the params contains the key, false otherwise
505  */
506  bool contains(const key_type &k);
507 
508  /**
509  * @param keys Set of keys to consider valid to add to the stack
510  * of legal keys
511  */
512  void pushAllowedKeys(const KeySet_t &keys);
513 
514  /**
515  * Removes the most recent set of keys considered allowed
516  */
517  void popAllowedKeys();
518 
519  /**
520  * @param k Key to check for validity
521  * @return True if the key is considered allowed
522  */
523  void verifyParam(const key_type &k) const;
524 
525 
526  /**
527  * Given a Parameter Key ID, return the Name of the matching parameter
528  * @param id Key ID to look up
529  * @return String name of the parameter
530  */
531  static const std::string& getParamName(uint32_t id);
532 
533 
534  void serialize_order(SST::Core::Serialization::serializer &ser) override;
535  ImplementSerializable(SST::Params)
536 
537 private:
538  std::map<uint32_t, std::string> data;
539  std::vector<KeySet_t> allowedKeys;
540  bool verify_enabled;
541  static bool g_verify_enabled;
542 
543  uint32_t getKey(const std::string& str) const;
544  uint32_t getKey(const std::string& str);
545 
546  /* Friend main() because it broadcasts the maps */
547  friend int ::main(int argc, char *argv[]);
548 
549  static std::map<std::string, uint32_t> keyMap;
550  static std::vector<std::string> keyMapReverse;
551  static SST::Core::ThreadSafe::Spinlock keyLock;
552  static uint32_t nextKeyID;
553 
554 
555 };
556 
557 #if 0
558  class UnitAlgebra;
559 
560  #define SST_PARAMS_DECLARE_TEMPLATE_SPECIALIZATION(type) \
561  template<> \
562  type Params::find(const std::string& k, type default_value, bool &found) const; \
563  template<> \
564  type Params::find(const std::string& k, const std::string& default_value, bool &found) const; \
565  template <> \
566  type Params::find(const std::string& k, type default_value ) const; \
567  template <> \
568  type Params::find(const std::string& k, const std::string& default_value ) const; \
569  template <> \
570  type Params::find(const std::string& k) const;
571 
572 
573  SST_PARAMS_DECLARE_TEMPLATE_SPECIALIZATION(int32_t)
574  SST_PARAMS_DECLARE_TEMPLATE_SPECIALIZATION(uint32_t)
575  SST_PARAMS_DECLARE_TEMPLATE_SPECIALIZATION(int64_t)
576  SST_PARAMS_DECLARE_TEMPLATE_SPECIALIZATION(uint64_t)
577  SST_PARAMS_DECLARE_TEMPLATE_SPECIALIZATION(bool)
578  SST_PARAMS_DECLARE_TEMPLATE_SPECIALIZATION(float)
579  SST_PARAMS_DECLARE_TEMPLATE_SPECIALIZATION(double)
580  SST_PARAMS_DECLARE_TEMPLATE_SPECIALIZATION(UnitAlgebra)
581 
582  // std::string has to be special cased because of signature conflicts
583  // SST_PARAMS_DECLARE_TEMPLATE_SPECIALIZATION(std::string)
584  template<>
585  std::string Params::find<std::string>(const std::string& k, const std::string& default_value, bool &found) const;
586 #endif
587 
588 
589 
590 } //namespace SST
591 
592 #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:434
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:301
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
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:254
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:349
static void enableVerify()
Enable, on a global scale, parameter verification.
Definition: params.h:202
size_t count(const key_type &k)
Finds the number of elements with given key.
Definition: params.cc:76
Definition: serializable.h:109
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:195
T find(const std::string &k, const std::string &default_value) const
Find a Parameter value in the set, and return its value as a type T.
Definition: params.h:316
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:367
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:285
Parameter store.
Definition: params.h:44
void popAllowedKeys()
Removes the most recent set of keys considered allowed.
Definition: params.cc:185
T find(const std::string &k, const 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:269
std::set< key_type, KeyCompare > KeySet_t
Definition: params.h:188
std::string key_type
Definition: params.h:187
void verifyParam(const key_type &k) const
Definition: params.cc:191
Params & operator=(const Params &old)
Assignment operator.
Definition: params.cc:61
void insert(const std::string &key, const std::string &value, bool overwrite=true)
Add a key value pair into the param object.
Definition: params.cc:99
Performs Unit math in full precision.
Definition: unitAlgebra.h:107
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:333
bool is_value_array(const key_type &k) const
Checks to see if the value associated with the given key is considered to be an array.
Definition: params.h:469
void print_all_params(std::ostream &os, const std::string &prefix="") const
Print all key/value parameter pairs to specified ostream.
Definition: params.cc:82