SST  15.1.0
StructuralSimulationToolkit
params.h
1 // Copyright 2009-2025 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-2025, 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/from_string.h"
16 #include "sst/core/serialization/serializable.h"
17 #include "sst/core/serialization/serializer.h"
18 #include "sst/core/threadsafe.h"
19 
20 #include <cassert>
21 #include <cstddef>
22 #include <cstdint>
23 #include <inttypes.h>
24 #include <iostream>
25 #include <map>
26 #include <mutex>
27 #include <set>
28 #include <sstream>
29 #include <stack>
30 #include <stdexcept>
31 #include <stdlib.h>
32 #include <string>
33 #include <type_traits>
34 #include <utility>
35 #include <vector>
36 
37 int main(int argc, char* argv[]);
38 
39 namespace SST {
40 
41 class ConfigGraph;
42 class ConfigComponent;
43 class ConfigPortModule;
44 class Output;
45 class SSTModelDescription;
46 
47 namespace Core {
48 class ConfigGraphOutput;
49 } // namespace Core
50 
51 /**
52  * Parameter store.
53  *
54  * Stores key-value pairs as std::strings and provides
55  * a templated find method for finding values and converting
56  * them to arbitrary types (@see find()).
57  *
58  * NOTE: Params objects should only be used for simulation
59  * initialization, a Params object should not be used as part of an
60  * event, as serialization of Params objects only works correctly as
61  * part of ConfigGraph serialization.
62  */
63 class Params
64 {
65 private:
66  struct KeyCompare
67  {
68  bool operator()(const std::string& X, const std::string& Y) const
69  {
70  const char* x = X.c_str();
71  const char* y = Y.c_str();
72 
73 #define EAT_VAR(A, B) \
74  do { \
75  if ( *x == '%' && (*(x + 1) == '(' || *(x + 1) == 'd') ) { \
76  /* We need to eat off some tokens */ \
77  ++x; \
78  if ( *x == '(' ) { \
79  do { \
80  x++; \
81  } while ( *x && *x != ')' ); \
82  x++; /* *x should now == 'd' */ \
83  } \
84  if ( *x != 'd' ) goto NO_VARIABLE; \
85  x++; /* Finish eating the variable */ \
86  /* Now, eat of digits of Y */ \
87  while ( *y && isdigit(*y) ) \
88  y++; \
89  } \
90  } while ( 0 )
91 
92  do {
93  EAT_VAR(x, y);
94  EAT_VAR(y, x);
95 NO_VARIABLE:
96  if ( *x == *y ) {
97  if ( '\0' == *x ) return false;
98  x++;
99  y++;
100  }
101  else {
102  if ( *x < *y ) return true;
103  return false;
104  }
105  } while ( *x && *y );
106  if ( !(*x) && (*y) ) return true;
107  return false;
108 
109 #undef EAT_VAR
110  }
111  };
112 
113  /** Private utility function to convert a value to the specified
114  * type and check for errors. Key is passed only in case an error
115  * message needs to be generated.
116  *
117  * Type T must be either a basic numeric type (including bool) ,
118  * a std::string, or a class that has a constructor with a std::string
119  * as its only parameter. This class uses SST::Core::from_string to
120  * do the conversion.
121  * @param k - Parameter name
122  * @throw std::invalid_argument If value in (key, value) can't be
123  * converted to type T, an invalid_argument exception is thrown.
124  */
125  template <class T>
126  inline T convert_value(const std::string& key, const std::string& val) const
127  {
128  try {
129  return SST::Core::from_string<T>(val);
130  }
131  catch ( const std::invalid_argument& e ) {
132  std::string msg = "Params::find(): No conversion for value: key = " + key + ", value = " + val +
133  ". Original error: " + e.what();
134  std::invalid_argument t(msg);
135  throw t;
136  }
137  }
138 
139  /** Private utility function to find a Parameter value in the set,
140  * and return its value as a type T.
141  *
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  * @param found - set to true if the the parameter was found
149  * @throw std::invalid_argument If value in (key, value) can't be
150  * converted to type T, an invalid_argument exception is thrown.
151  */
152  template <class T>
153  inline T find_impl(const std::string& k, T default_value, bool& found) const
154  {
155  verifyKey(k);
156  // const_iterator i = data.find(getKey(k));
157  const std::string& value = getString(k, found);
158  if ( !found ) {
159  return default_value;
160  }
161  else {
162  return convert_value<T>(k, value);
163  }
164  }
165 
166  /** Find a Parameter value in the set, and return its value as a type T.
167  * Type T must be either a basic numeric type (including bool) ,
168  * a std::string, or a class that has a constructor with a std::string
169  * as its only parameter. This class uses SST::Core::from_string to
170  * do the conversion.
171  * @param k - Parameter name
172  * @param default_value - Default value to return if parameter isn't found,
173  * specified as a string
174  * @param found - set to true if the the parameter was found
175  */
176  template <class T>
177  inline T find_impl(const std::string& k, const std::string& default_value, bool& found) const
178  {
179  verifyKey(k);
180  const std::string& value = getString(k, found);
181  if ( !found ) {
182  try {
183  return SST::Core::from_string<T>(default_value);
184  }
185  catch ( const std::invalid_argument& e ) {
186  std::string msg = "Params::find(): Invalid default value specified: key = " + k +
187  ", value = " + default_value + ". Original error: " + e.what();
188  std::invalid_argument t(msg);
189  throw t;
190  }
191  }
192  else {
193  found = true;
194  try {
195  return SST::Core::from_string<T>(value);
196  }
197  catch ( const std::invalid_argument& e ) {
198  std::string msg = "Params::find(): No conversion for value: key = " + k + ", value = " + value +
199  ". Original error: " + e.what();
200  std::invalid_argument t(msg);
201  throw t;
202  }
203  }
204  }
205 
206  using const_iterator = std::map<uint32_t, std::string>::const_iterator; /*!< Const Iterator type */
207 
208  const std::string& getString(const std::string& name, bool& found) const;
209 
210  /**
211  Private function to clean up a token. It will remove leading
212  and trailing whitespace, leading and trailing quotes (single or
213  double), and the backslash (\) character before escaped quotes
214  of the same type as a leading quote.
215 
216  The format of the items depends on where they came from. The
217  string for the items are generated by calling the repr()
218  function on them. For strings, this means they will typically
219  be enclosed in single quotes. It is possible that they end up
220  enclosed in double quotes if the string itself contains a
221  single quote. For strings which contain both single and double
222  quotes, the repr() will create a single quoted string with all
223  internal single quotes escaped with '\'. Also, any string that
224  starts with a quote character, must end with the same quote
225  character.
226 
227  Examples of strings using double and/or single quotes:
228  'This is "a" test' -> This is "a" test
229  "This is 'a' test" -> This is 'a' test
230  'This "is \'a\'" test' -> This "is 'a'" test
231  'This "is \"a\"" test' -> This "is \"a\"" test
232  */
233  void cleanToken(std::string& token) const;
234 
235  /**
236  Private function for creating tokens from a delimited list.
237  Delimiters inside of quotes (single or double) are ignored.
238  */
239  void getDelimitedTokens(const std::string& value, char delim, std::vector<std::string>& tokens) const;
240 
241 public:
242  using key_type = std::string; /*!< Type of key (string) */
243  using KeySet_t = std::set<key_type, KeyCompare>; /*!< Type of a set of keys */
244 
245  /**
246  * Enable or disable parameter verification on an instance
247  * of Params. Useful when generating a new set of Params to
248  * pass off to a module.
249  *
250  * @return returns the previous state of the flag
251  */
252  bool enableVerify(bool enable)
253  {
254  bool old = verify_enabled;
255  verify_enabled = enable;
256  return old;
257  }
258 
259  /**
260  * Enable, on a global scale, parameter verification. Used
261  * after construction of the config graph so that warnings are
262  * not generated during construction.
263  */
264  static void enableVerify()
265  {
266  g_verify_enabled = true;
267  };
268 
269  /**
270  * Returns the size of the Params. This will count both local and
271  * shared params.
272  *
273  * @return number of key/value pairs in this Params object
274  */
275  size_t size() const;
276  /**
277  * Returns true if the Params is empty. Checks both local and
278  * shared param sets.
279  *
280  * @return true if this Params object is empty, false otherwise
281  */
282  bool empty() const;
283 
284  /** Create a new, empty Params */
285  Params();
286 
287  /** Create a copy of a Params object */
288  Params(const Params& old);
289 
290  ~Params() {}
291 
292  /**
293  * @brief Assignment operator.
294  * @param old Param to be copied
295  *
296  * All the elements of old are copied, This will also copy
297  * over any references to shared param sets
298  */
299  Params& operator=(const Params& old);
300 
301  /**
302  * Erases all elements, including deleting reference to shared
303  * param sets.
304  */
305  void clear();
306 
307  /**
308  * @brief Finds the number of elements with given key.
309  *
310  * The call will check both local and shared params, but will
311  * still only report one instance if the given key is found in
312  * both the local and shared param sets.
313  *
314  * @param k Key of (key, value) pairs to be located.
315  * @return Number of elements with specified key
316  * (either 1 or 0).
317  *
318  */
319  size_t count(const key_type& k) const;
320 
321  /** Find a Parameter value in the set, and return its value as a type T.
322  * Type T must be either a basic numeric type (including bool) ,
323  * a std::string, or a class that has a constructor with a std::string
324  * as its only parameter. This class uses SST::Core::from_string to
325  * do the conversion.
326  * @param k - Parameter name
327  * @param default_value - Default value to return if parameter isn't found
328  * @param found - set to true if the the parameter was found
329  * @throw std::invalid_argument If value in (key, value) can't be
330  * converted to type T, an invalid_argument exception is thrown.
331  */
332  template <class T>
333  std::enable_if_t<!std::is_same_v<std::string, T>, T> find(const std::string& k, T default_value, bool& found) const
334  {
335  return find_impl<T>(k, default_value, found);
336  }
337 
338  /** Find a Parameter value in the set, and return its value as a type T.
339  * Type T must be either a basic numeric type (including bool) ,
340  * a std::string, or a class that has a constructor with a std::string
341  * as its only parameter. This class uses SST::Core::from_string to
342  * do the conversion.
343  * @param k - Parameter name
344  * @param default_value - Default value to return if parameter isn't found,
345  * specified as a string
346  * @param found - set to true if the the parameter was found
347  */
348  template <class T>
349  T find(const std::string& k, const std::string& default_value, bool& found) const
350  {
351  return find_impl<T>(k, default_value, found);
352  }
353 
354  /** Find a Parameter value in the set, and return its value as a type T.
355  * This version of find is only enabled for bool. This
356  * is required because a string literal will be preferentially
357  * cast to a bool rather than a string. This ensures that
358  * find<bool> works correctly for string literals. This class uses
359  * SST::Core::from_string to do the conversion.
360  * @param k - Parameter name
361  * @param default_value - Default value to return if parameter isn't found,
362  * specified as a string literal
363  */
364  template <class T>
365  std::enable_if_t<std::is_same_v<bool, T>, T> find(
366  const std::string& k, const char* default_value, bool& found) const
367  {
368  if ( nullptr == default_value ) {
369  return find_impl<T>(k, static_cast<T>(0), found);
370  }
371  return find_impl<T>(k, std::string(default_value), found);
372  }
373 
374  /** Find a Parameter value in the set, and return its value as a type T.
375  * Type T must be either a basic numeric type (including bool),
376  * a std::string, or a class that has a constructor with a std::string
377  * as its only parameter. This class uses SST::Core::from_string to
378  * do the conversion.
379  * @param k - Parameter name
380  * @param default_value - Default value to return if parameter isn't found
381  */
382  template <class T>
383  T find(const std::string& k, T default_value) const
384  {
385  bool tmp;
386  return find_impl<T>(k, default_value, tmp);
387  }
388 
389  /** Find a Parameter value in the set, and return its value as a type T.
390  * Type T must be either a basic numeric type (including bool) ,
391  * a std::string, or a class that has a constructor with a std::string
392  * as its only parameter. This class uses SST::Core::from_string to
393  * do the conversion.
394  * @param k - Parameter name
395  * @param default_value - Default value to return if parameter isn't found,
396  * specified as a string
397  */
398  template <class T>
399  T find(const std::string& k, const std::string& default_value) const
400  {
401  bool tmp;
402  return find_impl<T>(k, default_value, tmp);
403  }
404 
405  /** Find a Parameter value in the set, and return its value as a type T.
406  * This version of find is only enabled for bool. This
407  * is required because a string literal will be preferentially
408  * cast to a bool rather than a string. This ensures that
409  * find<bool> works correctly for string literals.This class uses
410  * SST::Core::from_string to do the conversion.
411  * @param k - Parameter name
412  * @param default_value - Default value to return if parameter isn't found,
413  * specified as a string literal
414  */
415  template <class T>
416  std::enable_if_t<std::is_same_v<bool, T>, T> find(const std::string& k, const char* default_value) const
417  {
418  bool tmp;
419  if ( nullptr == default_value ) {
420  return find_impl<T>(k, static_cast<T>(0), tmp);
421  }
422  return find_impl<T>(k, std::string(default_value), tmp);
423  }
424 
425  /** Find a Parameter value in the set, and return its value as a type T.
426  * Type T must be either a basic numeric type (including bool) ,
427  * a std::string, or a class that has a constructor with a std::string
428  * as its only parameter. This class uses SST::Core::from_string to
429  * do the conversion.
430  * @param k - Parameter name
431  */
432  template <class T>
433  T find(const std::string& k) const
434  {
435  bool tmp;
436  T default_value = T();
437  return find_impl<T>(k, default_value, tmp);
438  }
439 
440  /** Find a Parameter value in the set, and return its value as a
441  * type T. Type T must be either a basic numeric type , a
442  * std::string, or a class that has a constructor with a
443  * std::string as its only parameter. This version of find is not
444  * enabled for bool as it conflicts with find<bool>(string key, bool
445  * default_value). This class uses SST::Core::from_string to do
446  * the conversion.
447  * @param k - Parameter name
448  * @param found - set to true if the the parameter was found
449  */
450  template <class T>
451  std::enable_if_t<!std::is_same_v<bool, T>, T> find(const std::string& k, bool& found) const
452  {
453  T default_value = T();
454  return find_impl<T>(k, default_value, found);
455  }
456 
457  /** Find a Parameter value in the set, and return its value as a
458  * vector of T's. The array will be appended to
459  * the end of the vector.
460  *
461  * Type T must be either a basic numeric type (including bool) , a
462  * std::string, or a class that has a constructor with a
463  * std::string as its only parameter. This class uses
464  * SST::Core::from_string to do the conversion. The values in the
465  * array must be enclosed in square brackets ( [] ), and be comma
466  * separated (commas in double or single quotes will not be
467  * considered a delimiter). If there are no square brackets, the
468  * entire string will be considered one value and a single item
469  * will be added to the vector.
470  *
471  * More details about parsing the values out of the string:
472  *
473  * Parses a string representing an array of tokens. It is
474  * tailored to the types strings you get when passing a python
475  * list as the param string. When you call addParam() on a python
476  * list in the input file, it will call the str() function on the
477  * list, which creates a string with the following format:
478  * [item1, item2, item3]
479  *
480  * The format of the items depends on where they came from. The
481  * string for the items are generated by calling the repr()
482  * function on them. For strings, this means they will typically
483  * be enclosed in single quotes. It is possible that they end up
484  * enclosed in double quotes if the string itself contains a
485  * single quote. For strings which contain both single and double
486  * quotes, the repr() will create a single quoted string with all
487  * internal single quotes escaped with '\'. Most other items used
488  * in SST do not enclose the string in quotes, though any string
489  * that contains a comma would need to be enclosed in quotes,
490  * since the comma is the delimiter character used. This is not
491  * done automatically, so if you have something that generates a
492  * commma in the string created by repr(), you may need to create
493  * an array string manually. Also, any string that starts with a
494  * quote character, must end with the same quote character.
495  *
496  * Tokens are generated by splitting the string on commas that are
497  * not within quotes (double or single). All whitespace at the
498  * beginning and end of a token is ignored (unless inside quotes).
499  * Once the tokens are generated, any quoted string will have the
500  * front and back quotes removed. The '\' for any escaped quote
501  * of the same type as the front and back is also removed.
502  *
503  * Examples:
504  *
505  * These will produce the same results:
506  * [1, 2, 3, 4, 5]
507  * ['1', '2', '3', '4', '5']
508  *
509  * Examples of strings using double and/or single quotes:
510  * 'This is "a" test' -> This is "a" test
511  * "This is 'a' test" -> This is 'a' test
512  * 'This "is \'a\'" test' -> This "is 'a'" test
513  * 'This "is \"a\"" test' -> This "is \"a\"" test
514  *
515  * @param k - Parameter name
516  * @param vec - vector to append array items to
517  */
518  template <class T>
519  void find_array(const key_type& k, std::vector<T>& vec) const
520  {
521  verifyKey(k);
522 
523  bool found = false;
524  std::string value = getString(k, found);
525  if ( !found ) return;
526  // If string starts with [ and ends with ], it is considered
527  // an array. Otherwise, it is considered a single
528  // value.
529  if ( value.front() != '[' || value.back() != ']' ) {
530  vec.push_back(convert_value<T>(k, value));
531  return;
532  }
533 
534  value = value.substr(1, value.size() - 2);
535 
536  // Get the tokens for the array
537  std::vector<std::string> tokens;
538  getDelimitedTokens(value, ',', tokens);
539 
540  // Clean up the tokens
541  for ( auto& str : tokens ) {
542  cleanToken(str);
543  }
544 
545  // Convert each token into the proper type and put in output
546  // vector
547  for ( auto& val : tokens ) {
548  vec.push_back(convert_value<T>(k, val));
549  }
550  }
551 
552  /** Find a Parameter value in the set, and return its value as a
553  * set of T's. The items will be added to the passed in set.
554  *
555  * Type T must be either a basic numeric type (including bool), a
556  * std::string, or a class that has a constructor with a
557  * std::string as its only parameter. This class uses
558  * SST::Core::from_string to do the conversion. The values in the
559  * set must be enclosed in curly braces ( {} ), and be comma
560  * separated (commas in double or single quotes will not be
561  * considered a delimiter). If there are no curly braces, the
562  * entire string will be considered one value and a single item
563  * will be added to the set.
564  *
565  * More details about parsing the values out of the string:
566  *
567  * Parses a string representing a set of tokens. It is
568  * tailored to the types strings you get when passing a python
569  * set as the param string. When you call addParam() on a python
570  * set in the input file, it will call the str() function on the
571  * set, which creates a string with the following format:
572  * {item1, item2, item3}
573  *
574  * The format of the items depends on where they came from. The
575  * string for the items are generated by calling the repr()
576  * function on them. For strings, this means they will typically
577  * be enclosed in single quotes. It is possible that they end up
578  * enclosed in double quotes if the string itself contains a
579  * single quote. For strings which contain both single and double
580  * quotes, the repr() will create a single quoted string with all
581  * internal single quotes escaped with '\'. Most other items used
582  * in SST do not enclose the string in quotes, though any string
583  * that contains a comma would need to be enclosed in quotes,
584  * since the comma is the delimiter character used. This is not
585  * done automatically, so if you have something that generates a
586  * commma in the string created by repr(), you may need to create
587  * an array string manually. Also, any string that starts with a
588  * quote character, must end with the same quote character.
589  *
590  * Tokens are generated by splitting the string on commas that are
591  * not within quotes (double or single). All whitespace at the
592  * beginning and end of a token is ignored (unless inside quotes).
593  * Once the tokens are generated, any quoted string will have the
594  * front and back quotes removed. The '\' for any escaped quote
595  * of the same type as the front and back is also removed.
596  *
597  * Examples:
598  *
599  * These will produce the same results:
600  * {1, 2, 3, 4, 5}
601  * {'1', '2', '3', '4', '5'}
602  *
603  * Examples of strings using double and/or single quotes:
604  * 'This is "a" test' -> This is "a" test
605  * "This is 'a' test" -> This is 'a' test
606  * 'This "is \'a\'" test' -> This "is 'a'" test
607  * 'This "is \"a\"" test' -> This "is \"a\"" test
608  *
609  * @param k - Parameter name
610  * @param set - set to add items to (new items will overwrite old
611  * items)
612  */
613  template <class T>
614  void find_set(const key_type& k, std::set<T>& set) const
615  {
616  verifyKey(k);
617 
618  bool found = false;
619  std::string value = getString(k, found);
620  if ( !found ) return;
621 
622  // Python 2 seems to have a slightly different format when
623  // str() is called on sets: set([a, b, c]). We need to change
624  // this to the expected format.
625  if ( value.find("set([") == 0 ) {
626  // Need to convert formats
627 
628  // take a substring with space at beginning and end to add
629  // {}
630  value = value.substr(4, value.length() - 5);
631  value[0] = '{';
632  value[value.length() - 1] = '}';
633  }
634 
635  // If string starts with { and ends with }, it is considered
636  // a set. Otherwise, it is considered a single
637  // value.
638  if ( value.front() != '{' || value.back() != '}' ) {
639  set.insert(convert_value<T>(k, value));
640  return;
641  }
642 
643  value = value.substr(1, value.size() - 2);
644 
645  // Get the tokens for the array
646  std::vector<std::string> tokens;
647  getDelimitedTokens(value, ',', tokens);
648 
649  // Clean up the tokens
650  for ( auto& str : tokens ) {
651  cleanToken(str);
652  }
653 
654  // Convert each token into the proper type and put in output
655  // vector
656  for ( auto& val : tokens ) {
657  set.insert(convert_value<T>(k, val));
658  }
659  }
660 
661  /** Find a Parameter value in the set, and return its value as a
662  * map<keyT,valT>. The items will be added to the passed in map.
663  *
664  * Types keyT and valT must be either a basic numeric type
665  * (including bool), a std::string, or a class that has a
666  * constructor with a std::string as its only parameter. This
667  * class uses SST::Core::from_string to do the conversion. The
668  * values in the map must be enclosed in curly braces ( {} ), the
669  * key/value pairs must be comma separated (commas in double or
670  * single quotes will not be considered a delimiter) and the key
671  * and value in the pairs must be separated by a colon (colons in
672  * double or single quotes will not be considered a delimiter).
673  * If there are no curly braces, the function will throw an
674  * std::invalid_argument exception without adding anything to the
675  * map.
676  *
677  * More details about parsing the values out of the string:
678  *
679  * Parses a string representing a set of tokens. It is
680  * tailored to the types strings you get when passing a python
681  * set as the param string. When you call addParam() on a python
682  * set in the input file, it will call the str() function on the
683  * set, which creates a string with the following format:
684  * {key1 : value1, key2 : value2, key3 : value3}
685  *
686  * The format of each item depends on where it came from. The
687  * string for the items are generated by calling the repr()
688  * function on them. For strings, this means they will typically
689  * be enclosed in single quotes. It is possible that they end up
690  * enclosed in double quotes if the string itself contains a
691  * single quote. For strings which contain both single and double
692  * quotes, the repr() will create a single quoted string with all
693  * internal single quotes escaped with '\'. Most other items used
694  * in SST do not enclose the string in quotes, though any string
695  * that contains a comma would need to be enclosed in quotes,
696  * since the comma is the delimiter character used. This is not
697  * done automatically, so if you have something that generates a
698  * commma in the string created by repr(), you may need to create
699  * an array string manually. Also, any string that starts with a
700  * quote character, must end with the same quote character.
701  *
702  * Tokens are generated by splitting the string on commas that are
703  * not within quotes (double or single). All whitespace at the
704  * beginning and end of a token is ignored (unless inside quotes).
705  * Once the tokens are generated, any quoted string will have the
706  * front and back quotes removed. The '\' for any escaped quote
707  * of the same type as the front and back is also removed.
708  *
709  * Examples:
710  *
711  * These will produce the same results:
712  * {"one" : 1, "two" : 2, "three" : 3, "Four" : 4}
713  * {"one" :'1', "two" : '2', "three" : '3', "four" : '4'}
714  *
715  * Examples of strings using double and/or single quotes:
716  * 'This is "a" test' -> This is "a" test
717  * "This is 'a' test" -> This is 'a' test
718  * 'This "is \'a\'" test' -> This "is 'a'" test
719  * 'This "is \"a\"" test' -> This "is \"a\"" test
720  *
721  * @param k - Parameter name
722  * @param map - map to add items to (new items will overwrite old
723  * items)
724  */
725  template <class keyT, class valT>
726  void find_map(const key_type& k, std::map<keyT, valT>& map) const
727  {
728  verifyKey(k);
729 
730  bool found = false;
731  std::string value = getString(k, found);
732  if ( !found ) return;
733  // If string starts with { and ends with }, it is considered
734  // a map. Otherwise, we will throw an exception.
735  if ( value.front() != '{' || value.back() != '}' ) {
736  std::string msg = "Invalid format for parameter to be parsed as a map: " + value;
737 
738  // Throw exception
739  throw std::invalid_argument(msg);
740  }
741 
742  value = value.substr(1, value.size() - 2);
743 
744  // Get the tokens
745  std::vector<std::string> tokens;
746  getDelimitedTokens(value, ',', tokens);
747 
748  // Now, we need to convert each of these to a key/value pair
749  // separated by a colon
750  std::vector<std::string> kvpair;
751  for ( auto& x : tokens ) {
752  kvpair.clear();
753  getDelimitedTokens(x, ':', kvpair);
754 
755  if ( kvpair.size() != 2 ) {
756  std::string msg = "Invalid format for map key/value pair: " + x;
757 
758  // throw exception
759  throw std::invalid_argument(msg);
760  }
761 
762  // Clean up the tokens
763  cleanToken(kvpair[0]);
764  cleanToken(kvpair[1]);
765 
766  // Insert into map, overwriting what might already be there
767  map[convert_value<keyT>(k, kvpair[0])] = convert_value<valT>(k, kvpair[1]);
768  }
769  }
770 
771  /** Checks to see if the value associated with the given key is
772  * considered to be an array. A value is considered to be an
773  * array if it is enclosed in square brackets ([]). No whitespace
774  * before or after the brackets is allowed.
775  *
776  * @param k - Parameter name
777  * @return true if value is an array as described above, false otherwise.
778  */
779  bool is_value_array(const key_type& k) const
780  {
781  bool found = false;
782  std::string value = getString(k, found);
783  if ( !found ) return false;
784  // String should start with [ and end with ]
785  if ( (value.find("[") == std::string::npos) || (value.find("]") == std::string::npos) ) {
786  return false;
787  }
788  return true;
789  }
790 
791  /** Print all key/value parameter pairs to specified ostream */
792  void print_all_params(std::ostream& os, const std::string& prefix = "") const;
793  /** Print all key/value parameter pairs to specified ostream */
794  void print_all_params(Output& out, const std::string& prefix = "") const;
795  /** Return a string version of all key/value parameter pairs */
796  std::string toString(const std::string& prefix = "") const;
797 
798  /**
799  * Add a key/value pair into the param object.
800  *
801  * @param key key to add to the map
802  *
803  * @param value value to add to the map
804  *
805  * @param overwrite controls whether the key/value pair will
806  * overwrite an existing pair in the set
807  */
808  void insert(const std::string& key, const std::string& value, bool overwrite = true);
809 
810  /**
811  * Add contents of input Params object to current Params object.
812  * This will also add any pointers to shared param sets after the
813  * existing pointers to shared param sets in this object.
814  *
815  * @param params Params object that should added to current object
816  */
817  void insert(const Params& params);
818 
819  /**
820  Get all the keys contained in the Params object. This will
821  give both local and shared params.
822  */
823  std::set<std::string> getKeys() const;
824 
825  /**
826  * Returns a new parameter object with parameters that match the
827  * specified scoped prefix (scopes are separated with "." The
828  * keys will be stripped of the "scope." prefix.
829  *
830  * Function will search both local and shared params, but all
831  * params will be copied into the local space of the new Params
832  * object.
833  *
834  * @param scope Scope to search (anything prefixed with "scope."
835  * will be included in the return Params object
836  *
837  * @return New Params object with the found scoped params.
838  */
839  Params get_scoped_params(const std::string& scope) const;
840 
841  /**
842  * Search the container for a particular key. This will search
843  * both local and shared params.
844  *
845  * @param k Key to search for
846  * @return True if the params contains the key, false otherwise
847  */
848  bool contains(const key_type& k) const;
849 
850  /**
851  * @param keys Set of keys to consider valid to add to the stack
852  * of legal keys
853  */
854  void pushAllowedKeys(const std::vector<std::string>& keys);
855 
856  /**
857  * Removes the most recent set of keys considered allowed
858  */
859  void popAllowedKeys();
860 
861  void serialize_order(SST::Core::Serialization::serializer& ser);
862 
863 private:
864  //// Functions used by model descriptions and config graph
865  //// outputters (classes that use it are friended below)
866  friend class SST::ConfigGraph;
867  friend class SST::ConfigComponent;
868  friend class SST::ConfigPortModule;
869  friend class SST::Core::ConfigGraphOutput;
870  friend class SST::SSTModelDescription;
871 
872  /**
873  * @param k Key to check for validity
874  * @return True if the key is considered allowed
875  */
876  void verifyParam(const key_type& k) const;
877 
878  /**
879  * Adds a shared param set to be looked at in this Params object
880  * if the key isn't found locally. It will search the shared sets
881  * in the order they were inserted and return immediately after
882  * finding the key in one of the sets.
883  *
884  * @param set set to add to the search list for this object
885  */
886  void addSharedParamSet(const std::string& set);
887 
888  /**
889  * Adds a key/value pair to the specified shared set
890  *
891  * @param set shared set to add the key/value pair to
892  *
893  * @param key key to add to the map
894  *
895  * @param value value to add to the map
896  *
897  * @param overwrite controls whether the key/value pair will
898  * overwrite an existing pair in the set
899  */
900  static void insert_shared(
901  const std::string& set, const key_type& key, const key_type& value, bool overwrite = true);
902 
903  /**
904  * Get a named shared parameter set.
905  *
906  * @param name Name of the set to get
907  *
908  * @return returns a copy of the reqeusted shared param set
909  *
910  */
911  static std::map<std::string, std::string> getSharedParamSet(const std::string& name);
912 
913  /**
914  * Get a vector of the names of available shared parameter sets.
915  *
916  * @return returns a vector of the names of available shared param
917  * sets
918  *
919  */
920  static std::vector<std::string> getSharedParamSetNames();
921 
922  /**
923  * Get a vector of the local keys
924  *
925  * @return returns a vector of the local keys in this Params
926  * object
927  *
928  */
929  std::vector<std::string> getLocalKeys() const;
930 
931  /**
932  * Get a vector of the shared param sets this Params object is
933  * subscribed to
934  *
935  * @return returns a vector of the shared param sets his Params
936  * object is subscribed to
937  *
938  */
939  std::vector<std::string> getSubscribedSharedParamSets() const;
940 
941 
942  // Private functions used by Params
943  /**
944  * @param k Key to check for validity
945  * @return True if the key is considered allowed
946  */
947  void verifyKey(const key_type& k) const;
948 
949 
950  // Private data
951  std::map<uint32_t, std::string> my_data;
952  std::vector<std::map<uint32_t, std::string>*> data;
953  std::vector<KeySet_t> allowedKeys;
954  bool verify_enabled;
955  static bool g_verify_enabled;
956 
957  static uint32_t getKey(const std::string& str);
958 
959  /**
960  * Given a Parameter Key ID, return the Name of the matching parameter
961  * @param id Key ID to look up
962  * @return String name of the parameter
963  */
964  static const std::string& getParamName(uint32_t id);
965 
966  /* Friend main() because it broadcasts the maps */
967  friend int ::main(int argc, char* argv[]);
968  /* Friend simulation because it checkpoints the maps */
969  friend class Simulation_impl;
970 
971  static std::map<std::string, uint32_t> keyMap;
972  static std::vector<std::string> keyMapReverse;
973  static std::recursive_mutex keyLock;
974  static SST::Core::ThreadSafe::Spinlock sharedLock;
975  static uint32_t nextKeyID;
976 
977  static std::map<std::string, std::map<uint32_t, std::string>> shared_params;
978 };
979 
980 #if 0
981  class UnitAlgebra;
982 
983 #define SST_PARAMS_DECLARE_TEMPLATE_SPECIALIZATION(type) \
984  template <> \
985  type Params::find(const std::string& k, type default_value, bool& found) const; \
986  template <> \
987  type Params::find(const std::string& k, const std::string& default_value, bool& found) const; \
988  template <> \
989  type Params::find(const std::string& k, type default_value) const; \
990  template <> \
991  type Params::find(const std::string& k, const std::string& default_value) const; \
992  template <> \
993  type Params::find(const std::string& k) const;
994 
995 
996  SST_PARAMS_DECLARE_TEMPLATE_SPECIALIZATION(int32_t)
997  SST_PARAMS_DECLARE_TEMPLATE_SPECIALIZATION(uint32_t)
998  SST_PARAMS_DECLARE_TEMPLATE_SPECIALIZATION(int64_t)
999  SST_PARAMS_DECLARE_TEMPLATE_SPECIALIZATION(uint64_t)
1000  SST_PARAMS_DECLARE_TEMPLATE_SPECIALIZATION(bool)
1001  SST_PARAMS_DECLARE_TEMPLATE_SPECIALIZATION(float)
1002  SST_PARAMS_DECLARE_TEMPLATE_SPECIALIZATION(double)
1003  SST_PARAMS_DECLARE_TEMPLATE_SPECIALIZATION(UnitAlgebra)
1004 
1005  // std::string has to be special cased because of signature conflicts
1006  // SST_PARAMS_DECLARE_TEMPLATE_SPECIALIZATION(std::string)
1007  template<>
1008  std::string Params::find<std::string>(const std::string& k, const std::string& default_value, bool &found) const;
1009 #endif
1010 
1011 } // namespace SST
1012 
1013 #endif // SST_CORE_PARAMS_H
Output object provides consistent method for outputting data to stdout, stderr and/or sst debug file...
Definition: output.h:57
This class is basically a wrapper for objects to declare the order in which their members should be s...
Definition: serializer.h:42
void print_all_params(std::ostream &os, const std::string &prefix="") const
Print all key/value parameter pairs to specified ostream.
Definition: params.cc:105
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:383
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:399
Outputs configuration data to a specified file path.
Definition: configGraphOutput.h:61
Represents the configuration of a generic component.
Definition: configGraph.h:381
std::enable_if_t<!std::is_same_v< bool, T >, 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:451
A Configuration Graph A graph representing Components and Links.
Definition: configGraph.h:585
Class that represents a PortModule in ConfigGraph.
Definition: configGraph.h:348
Definition: action.cc:18
static void enableVerify()
Enable, on a global scale, parameter verification.
Definition: params.h:264
bool contains(const key_type &k) const
Search the container for a particular key.
Definition: params.cc:233
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:519
void clear()
Erases all elements, including deleting reference to shared param sets.
Definition: params.cc:86
void pushAllowedKeys(const std::vector< std::string > &keys)
Definition: params.cc:242
std::enable_if_t< std::is_same_v< bool, T >, T > 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:416
Params()
Create a new, empty Params.
Definition: params.cc:58
bool enableVerify(bool enable)
Enable or disable parameter verification on an instance of Params.
Definition: params.h:252
Main control class for a SST Simulation.
Definition: simulation_impl.h:122
std::string toString(const std::string &prefix="") const
Return a string version of all key/value parameter pairs.
Definition: params.cc:147
Params get_scoped_params(const std::string &scope) const
Returns a new parameter object with parameters that match the specified scoped prefix (scopes are sep...
Definition: params.cc:211
std::set< std::string > getKeys() const
Get all the keys contained in the Params object.
Definition: params.cc:198
Definition: threadsafe.h:135
std::enable_if_t< std::is_same_v< bool, T >, T > 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:365
void find_set(const key_type &k, std::set< T > &set) const
Find a Parameter value in the set, and return its value as a set of T&#39;s.
Definition: params.h:614
std::enable_if_t<!std::is_same_v< std::string, T >, 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:333
std::set< key_type, KeyCompare > KeySet_t
Definition: params.h:243
Parameter store.
Definition: params.h:63
void popAllowedKeys()
Removes the most recent set of keys considered allowed.
Definition: params.cc:252
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:349
void find_map(const key_type &k, std::map< keyT, valT > &map) const
Find a Parameter value in the set, and return its value as a map<keyT,valT>.
Definition: params.h:726
Base class for Model Generation.
Definition: sstmodel.h:29
size_t count(const key_type &k) const
Finds the number of elements with given key.
Definition: params.cc:94
bool empty() const
Returns true if the Params is empty.
Definition: params.cc:53
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:433
size_t size() const
Returns the size of the Params.
Definition: params.cc:47
Params & operator=(const Params &old)
Assignment operator.
Definition: params.cc:75
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:779
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:171
std::string key_type
Definition: params.h:242