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