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