Cantera 2.6.0
AnyMap.h
Go to the documentation of this file.
1//! @file AnyMap.h
2
3// This file is part of Cantera. See License.txt in the top-level directory or
4// at https://cantera.org/license.txt for license and copyright information.
5
6#ifndef CT_ANYMAP_H
7#define CT_ANYMAP_H
8
11#include "cantera/base/Units.h"
12
13#include <unordered_map>
14#include <functional>
15
16namespace boost
17{
18class any;
19}
20
21namespace YAML
22{
23class Emitter;
24Emitter& operator<<(Emitter& out, const Cantera::AnyMap& rhs);
25Emitter& operator<<(Emitter& out, const Cantera::AnyValue& rhs);
26}
27
28namespace Cantera
29{
30
31//! Base class defining common data possessed by both AnyMap and AnyValue
32//! objects.
33class AnyBase {
34public:
35 AnyBase();
36 virtual ~AnyBase() {};
37
38 //! For values which are derived from an input file, set the line and column
39 //! of this value in that file. Used for providing context for some error
40 //! messages.
41 void setLoc(int line, int column);
42
43 //! Get a value from the metadata applicable to the AnyMap tree containing
44 //! this node.
45 const AnyValue& getMetadata(const std::string& key) const;
46
47protected:
48 //! The line where this value occurs in the input file. Set to -1 for values
49 //! that weren't created from an input file.
50 int m_line;
51
52 //! If m_line >= 0, the column where this value occurs in the input file.
53 //! If m_line == -1, a value used for determining output ordering
55
56 //! Metadata relevant to an entire AnyMap tree, such as information about
57 // the input file used to create it
58 shared_ptr<AnyMap> m_metadata;
59
60 friend class InputFileError;
61 friend void warn_deprecated(const std::string& source, const AnyBase& node,
62 const std::string& message);
63};
64
65class AnyMap;
66
67//! A wrapper for a variable whose type is determined at runtime
68/*!
69 * Instances of AnyValue are used as values in an AnyMap. Values are converted
70 * to a concrete type using the templated as() method or convenience methods
71 * such as asString() and asDouble(). See AnyMap for usage examples.
72 *
73 * Elements are set using assignment, and the assignment operator has been
74 * overloaded for specific types so that only those types are allowed to be
75 * used in an AnyValue. The allowed types are:
76 * - AnyMap
77 * - `double`
78 * - `long int`
79 * - `bool`
80 * - `std::string`
81 * - `std::vector` of any of the above
82 */
83class AnyValue : public AnyBase
84{
85public:
86 AnyValue();
87 ~AnyValue();
88 AnyValue(AnyValue const& other);
89 AnyValue(AnyValue&& other);
90 AnyValue& operator=(AnyValue const& other);
91 AnyValue& operator=(AnyValue&& other);
92
93 bool operator==(const AnyValue& other) const;
94 bool operator!=(const AnyValue& other) const;
95
96 //! If this AnyValue is an AnyMap, return the value stored in `key`.
97 AnyValue& operator[](const std::string& key);
98 const AnyValue& operator[](const std::string& key) const;
99
100 //! Returns `true` if this AnyValue is an AnyMap and that map contains
101 //! a key with the given name.
102 bool hasKey(const std::string& key) const;
103
104 //! Set the name of the key storing this value in an AnyMap. Used for
105 //! providing informative error messages in class InputFileError.
106 void setKey(const std::string& key);
107
108 //! Propagate metadata to any child elements
109 void propagateMetadata(shared_ptr<AnyMap>& file);
110
111 //! Get the value of this key as the specified type.
112 template<class T>
113 const T& as() const;
114
115 template<class T>
116 T& as();
117
118 //! Returns the type of the held value.
119 const std::type_info& type() const;
120
121 //! Returns a string specifying the type of the held value.
122 std::string type_str() const;
123
124 //! Return boolean indicating whether AnyValue is empty.
125 bool empty() const;
126
127 //! Returns `true` if the held value is of the specified type.
128 template<class T>
129 bool is() const;
130
131 //! Returns `true` if the held value is a scalar type (such as `double`, `long
132 //! int`, `string`, or `bool`).
133 bool isScalar() const;
134
135 explicit AnyValue(const std::string& value);
136 explicit AnyValue(const char* value);
137 AnyValue& operator=(const std::string& value);
138 AnyValue& operator=(const char* value);
139 //! Return the held value, if it is a string
140 const std::string& asString() const;
141 bool operator==(const std::string& other) const;
142 bool operator!=(const std::string& other) const;
143 friend bool operator==(const std::string& lhs, const AnyValue& rhs);
144 friend bool operator!=(const std::string& lhs, const AnyValue& rhs);
145
146 //! @name Quantity conversions
147 //! Assign a quantity consisting of one or more values and their
148 //! corresponding units, which will be converted to a target unit system
149 //! when the applyUnits() function is later called on the root of the
150 //! AnyMap.
151 //! @{
152
153 //! Assign a scalar quantity with units as a string, for example
154 //! `{3.0, "m^2"}`. If the `is_act_energy` flag is set to `true`, the units
155 //! will be converted using the special rules for activation energies.
156 void setQuantity(double value, const std::string& units, bool is_act_energy=false);
157
158 //! Assign a scalar quantity with units as a Units object, for cases where
159 //! the units vary and are determined dynamically, such as reaction
160 //! pre-exponential factors
161 void setQuantity(double value, const Units& units);
162
163 //! Assign a vector where all the values have the same units
164 void setQuantity(const vector_fp& values, const std::string& units);
165
166 typedef std::function<void(AnyValue&, const UnitSystem&)> unitConverter;
167
168 //! Assign a value of any type where the unit conversion requires a
169 //! different behavior besides scaling all values by the same factor
170 void setQuantity(const AnyValue& value, const unitConverter& converter);
171 //! @} end group quantity conversions
172
173 explicit AnyValue(double value);
174 AnyValue& operator=(double value);
175 //! Return the held value as a `double`, if it is a `double` or a `long
176 //! int`.
177 double& asDouble();
178 const double& asDouble() const;
179 bool operator==(const double& other) const;
180 bool operator!=(const double& other) const;
181 friend bool operator==(const double& lhs, const AnyValue& rhs);
182 friend bool operator!=(const double& lhs, const AnyValue& rhs);
183
184 explicit AnyValue(bool value);
185 AnyValue& operator=(bool value);
186 //! Return the held value, if it is a `bool`.
187 bool& asBool();
188 const bool& asBool() const;
189
190 explicit AnyValue(long int value);
191 explicit AnyValue(int value);
192 AnyValue& operator=(long int value);
193 AnyValue& operator=(int value);
194 //! Return the held value, if it is a `long int`.
195 long int& asInt();
196 const long int& asInt() const;
197 bool operator==(const long int& other) const;
198 bool operator!=(const long int& other) const;
199 bool operator==(const int& other) const;
200 bool operator!=(const int& other) const;
201 friend bool operator==(const long int& lhs, const AnyValue& rhs);
202 friend bool operator!=(const long int& lhs, const AnyValue& rhs);
203 friend bool operator==(const int& lhs, const AnyValue& rhs);
204 friend bool operator!=(const int& lhs, const AnyValue& rhs);
205
206 template<class T>
207 AnyValue& operator=(const std::vector<T>& value);
208 //! Return the held value, if it is a vector of type `T`. If called with one
209 //! argument, requires the vector to be of the specified size. If called
210 //! with two arguments, requires the vector to be within the range specified
211 //! by the two values, inclusive.
212 template<class T>
213 const std::vector<T>& asVector(size_t nMin=npos, size_t nMax=npos) const;
214 template<class T>
215 std::vector<T>& asVector(size_t nMin=npos, size_t nMax=npos);
216
217 explicit AnyValue(const AnyMap& value);
218 AnyValue& operator=(const AnyMap& value);
219 AnyValue& operator=(AnyMap&& value);
220
221 template<class T>
222 AnyValue& operator=(const std::unordered_map<std::string, T> items);
223
224 template<class T>
225 AnyValue& operator=(const std::map<std::string, T> items);
226
227 //! Return the held `AnyMap` as a `std::map` where all of the values have
228 //! the specified type.
229 template<class T>
230 std::map<std::string, T> asMap() const;
231
232 //! Access a `vector<AnyMap>` as a mapping using the value of `name` from
233 //! each item as the key in the new mapping.
234 /*!
235 * For example, for the list:
236 * ```
237 * [{name: O2, weight: 32}, {name: CH4, weight: 16}]
238 * ```
239 * calling `asMap("name")` will create a map with keys ``O2`` and ``CH4``.
240 */
241 std::unordered_map<std::string, const AnyMap*> asMap(const std::string& name) const;
242 std::unordered_map<std::string, AnyMap*> asMap(const std::string& name);
243
244 //! Treating the value as `vector<AnyMap>`, return the item where the given
245 //! key has the specified value.
246 /*!
247 * If value is the empty string, returns the first item in the list.
248 *
249 * If the contained type is just `AnyMap` rather than `vector<AnyMap>`, it
250 * will be treated as a vector of length 1.
251 *
252 * If the value does not exist but the `create` flag is set to true, a new
253 * map with that key and value will be created and returned.
254 */
255 AnyMap& getMapWhere(const std::string& key, const std::string& value, bool create=false);
256 const AnyMap& getMapWhere(const std::string& key, const std::string& value) const;
257
258 //! Returns `true` when getMapWhere() would succeed
259 bool hasMapWhere(const std::string& key, const std::string& value) const;
260
261 //! Return values used to determine the sort order when outputting to YAML
262 std::pair <int, int> order() const;
263
264 //! @see AnyMap::applyUnits(const UnitSystem&)
265 void applyUnits(shared_ptr<UnitSystem>& units);
266
267 //! @see AnyMap::setFlowStyle
268 void setFlowStyle(bool flow=true);
269
270private:
271 template<class T>
272 void checkSize(const std::vector<T>& v, size_t nMin, size_t nMax) const;
273
274 //! Key of this value in a parent `AnyMap`
275 std::string m_key;
276
277 //! The held value
278 std::unique_ptr<boost::any> m_value;
279
280 typedef bool (*Comparer)(const boost::any&, const boost::any&);
281
282 //! Equality comparison function used when *lhs* is of type *T*
283 template <typename T>
284 static bool eq_comparer(const boost::any& lhs, const boost::any& rhs);
285
286 //! Helper function for comparing vectors of different (but comparable)
287 //! types, for example `vector<double>` and `vector<long int>`
288 template<class T, class U>
289 static bool vector_eq(const boost::any& lhs, const boost::any& rhs);
290
291 //! Helper function for comparing nested vectors of different (but
292 //! comparable) types, for example `vector<vector<double>>` and
293 //! `vector<vector<long int>>`
294 template<class T, class U>
295 static bool vector2_eq(const boost::any& lhs, const boost::any& rhs);
296
297 mutable Comparer m_equals;
298
299 friend YAML::Emitter& YAML::operator<<(YAML::Emitter& out, const AnyValue& rhs);
300};
301
302//! Implicit conversion to vector<AnyValue>
303template<>
304const std::vector<AnyValue>& AnyValue::asVector<AnyValue>(size_t nMin, size_t nMax) const;
305
306template<>
307std::vector<AnyValue>& AnyValue::asVector<AnyValue>(size_t nMin, size_t nMax);
308
309//! Implicit conversion of long int to double if accessed as a vector<double>
310template<>
311const std::vector<double>& AnyValue::asVector<double>(size_t nMin, size_t nMax) const;
312
313template<>
314std::vector<double>& AnyValue::asVector<double>(size_t nMin, size_t nMax);
315
316//! Implicit conversion of long int to double if accessed as a vector<vector<double>>
317template<>
318const std::vector<vector_fp>& AnyValue::asVector<vector_fp>(size_t nMin, size_t nMax) const;
319
320template<>
321std::vector<vector_fp>& AnyValue::asVector<vector_fp>(size_t nMin, size_t nMax);
322
323//! Implicit conversion of AnyMap to a vector<AnyMap> of length 1, or an empty
324//! vector<AnyValue> an empty vector<AnyMap>
325template<>
326const std::vector<AnyMap>& AnyValue::asVector<AnyMap>(size_t nMin, size_t nMax) const;
327
328template<>
329std::vector<AnyMap>& AnyValue::asVector<AnyMap>(size_t nMin, size_t nMax);
330
331//! A map of string keys to values whose type can vary at runtime
332/*!
333 * Values in an AnyMap are held by instances of AnyValue. Instances of AnyMap
334 * can be nested to form a tree.
335 *
336 * ## Setting elements
337 *
338 * ```
339 * AnyMap breakfast;
340 * breakfast["spam"] = 123.4; // Creates a value of type 'double'
341 * breakfast["eggs"] = "scrambled"; // Creates a value of type 'std::string'
342 *
343 * // Create a nested AnyMap named "beans" which has a key named "baked"
344 * // whose value is a vector<double>
345 * std::vector<double> v{3.14, 1.59, 2.65};
346 * breakfast["beans"]["baked"] = v;
347 *
348 * // Create a nested AnyMap with values of the same type
349 * std::map<std::string, double> breads{{"wheat", 4.0}, {"white", 2.5}};
350 * breakfast["toast"] = breads;
351 * // Equivalent to:
352 * breakfast["toast"]["wheat"] = 4.0
353 * breakfast["toast"]["white"] = 2.5
354 * ```
355 *
356 * ## Accessing elements
357 *
358 * ```
359 * double val1 = breakfast["spam"].asDouble();
360 * std::string val2 = breakfast["eggs"].asString();
361 * vector_fp val3 = breakfast["beans"]["baked"].asVector<double>();
362 *
363 * std::map<std::string, double> = breakfast["toast"].asMap<double>();
364 * ```
365 *
366 * ## Checking for elements
367 *
368 * ```
369 * try {
370 * breakfast["waffle"].asDouble();
371 * } except (std::exception& err) {
372 * // Exception will be thrown.
373 * // 'breakfast' will have an empty key named 'waffle' unless 'breakfast'
374 * // is a 'const AnyMap'.
375 * }
376 *
377 * try {
378 * breakfast.at("grits").asDouble();
379 * } except (std::exception& err) {
380 * // Exception will be thrown and no new key will be added
381 * }
382 *
383 * if (breakfast.hasKey("grits")) {
384 * // do something with this entry
385 * }
386 * ```
387 *
388 * ## Checking element types
389 *
390 * ```
391 * if (breakfast["sausage"].is<vector<double>>()) {
392 * // access using asVector<double>
393 * } else if (breakfast["sausage"].type() == typeid(vector<std::string>)) {
394 * // access using asVector<std::string>
395 * }
396 * ```
397 */
398class AnyMap : public AnyBase
399{
400public:
401 AnyMap();
402
403 //! Create an AnyMap from a YAML file.
404 /*!
405 * Searches the directory containing the optionally-specified parent file
406 * first, followed by the current working directory and the Cantera include
407 * path.
408 */
409 static AnyMap fromYamlFile(const std::string& name,
410 const std::string& parent_name="");
411
412 //! Create an AnyMap from a string containing a YAML document
413 static AnyMap fromYamlString(const std::string& yaml);
414
415 std::string toYamlString() const;
416
417 //! Get the value of the item stored in `key`.
418 AnyValue& operator[](const std::string& key);
419 const AnyValue& operator[](const std::string& key) const;
420
421 //! Used to create a new item which will be populated from a YAML input
422 //! string, where the item with `key` occurs at the specified line and
423 //! column within the string.
424 AnyValue& createForYaml(const std::string& key, int line, int column);
425
426 //! Get the value of the item stored in `key`. Raises an exception if the
427 //! value does not exist.
428 const AnyValue& at(const std::string& key) const;
429
430 //! Return boolean indicating whether AnyMap is empty.
431 bool empty() const;
432
433 //! Returns `true` if the map contains an item named `key`.
434 bool hasKey(const std::string& key) const;
435
436 //! Erase the value held by `key`.
437 void erase(const std::string& key);
438
439 //! Erase all items in the mapping
440 void clear();
441
442 //! Add items from `other` to this AnyMap. If keys in `other` also exist in
443 //! this AnyMap, the `keepExisting` option determines which item is used.
444 void update(const AnyMap& other, bool keepExisting=true);
445
446 //! Return a string listing the keys in this AnyMap, for use in error
447 //! messages, for example
448 std::string keys_str() const;
449
450 //! Set a metadata value that applies to this AnyMap and its children.
451 //! Mainly for internal use in reading or writing from files.
452 void setMetadata(const std::string& key, const AnyValue& value);
453
454 //! Copy metadata including input line/column from an existing AnyMap
455 void copyMetadata(const AnyMap& other);
456
457 //! Propagate metadata to any child elements
458 void propagateMetadata(shared_ptr<AnyMap>& file);
459
460 //! If `key` exists, return it as a `bool`, otherwise return `default_`.
461 bool getBool(const std::string& key, bool default_) const;
462
463 //! If `key` exists, return it as a `long int`, otherwise return `default_`.
464 long int getInt(const std::string& key, long int default_) const;
465
466 //! If `key` exists, return it as a `double`, otherwise return `default_`.
467 double getDouble(const std::string& key, double default_) const;
468
469 //! If `key` exists, return it as a `string`, otherwise return `default_`.
470 const std::string& getString(const std::string& key,
471 const std::string& default_) const;
472
473 //! Convert the item stored by the given `key` to the units specified in
474 //! `units`. If the stored value is a double, convert it using the default
475 //! units. If the input is a string, treat this as a dimensioned value, such
476 //! as '988 kg/m^3' and convert from the specified units.
477 double convert(const std::string& key, const std::string& units) const;
478 double convert(const std::string& key, const Units& units) const;
479
480 //! Convert the item stored by the given `key` to the units specified in
481 //! `units`. If the stored value is a double, convert it using the default
482 //! units. If the input is a string, treat this as a dimensioned value, such
483 //! as '988 kg/m^3' and convert from the specified units. If the key is
484 //! missing, the `default_` value is returned.
485 double convert(const std::string& key, const std::string& units,
486 double default_) const;
487
488 //! Convert a vector of dimensional values
489 /*!
490 * For each item in the vector, if the stored value is a double, convert it
491 * using the default units. If the value is a string, treat it as a
492 * dimensioned value, such as '988 kg/m^3', and convert from the specified
493 * units.
494 *
495 * @param key Location of the vector in this AnyMap
496 * @param units Units to convert to
497 * @param nMin Minimum allowed length of the vector. If `nMax` is not
498 * specified, this is also taken to be the maximum length. An exception
499 * is thrown if this condition is not met.
500 * @param nMax Maximum allowed length of the vector. An exception is
501 * thrown if this condition is not met.
502 */
503 vector_fp convertVector(const std::string& key, const std::string& units,
504 size_t nMin=npos, size_t nMax=npos) const;
505
506 //! Defined to allow use with range-based for loops. Iteration automatically
507 //! skips over keys that start and end with double underscores.
508 class Iterator {
509 public:
510 Iterator() {}
511 Iterator(const std::unordered_map<std::string, AnyValue>::const_iterator& start,
512 const std::unordered_map<std::string, AnyValue>::const_iterator& stop);
513
514 const std::pair<const std::string, AnyValue>& operator*() const {
515 return *m_iter;
516 }
517 const std::pair<const std::string, AnyValue>* operator->() const {
518 return &*m_iter;
519 }
520 bool operator!=(const Iterator& right) const {
521 return m_iter != right.m_iter;
522 }
523 Iterator& operator++();
524
525 private:
526 std::unordered_map<std::string, AnyValue>::const_iterator m_iter;
527 std::unordered_map<std::string, AnyValue>::const_iterator m_stop;
528 };
529
530 //! Defined to allow use with range-based for loops
531 Iterator begin() const {
532 return Iterator(m_data.begin(), m_data.end());
533 }
534
535 //! Defined to allow use with range-based for loops
536 Iterator end() const {
537 return Iterator(m_data.end(), m_data.end());
538 }
539
540 class OrderedIterator;
541
542 //! Proxy for iterating over an AnyMap in the defined output ordering.
543 //! See ordered().
545 public:
546 OrderedProxy() {}
547 OrderedProxy(const AnyMap& data);
548 OrderedIterator begin() const;
549 OrderedIterator end() const;
550
551 typedef std::vector<std::pair<
552 std::pair<int, int>,
553 const std::pair<const std::string, AnyValue>*>> OrderVector;
554 private:
555 const AnyMap* m_data;
556 OrderVector m_ordered;
557 std::unique_ptr<std::pair<const std::string, AnyValue>> m_units;
558 };
559
560 //! Defined to allow the OrderedProxy class to be used with range-based
561 //! for loops.
563 public:
564 OrderedIterator() {}
565 OrderedIterator(const OrderedProxy::OrderVector::const_iterator& start,
566 const OrderedProxy::OrderVector::const_iterator& stop);
567
568 const std::pair<const std::string, AnyValue>& operator*() const {
569 return *m_iter->second;
570 }
571 const std::pair<const std::string, AnyValue>* operator->() const {
572 return &(*m_iter->second);
573 }
574 bool operator!=(const OrderedIterator& right) const {
575 return m_iter != right.m_iter;
576 }
577 OrderedIterator& operator++() { ++m_iter; return *this; }
578
579 private:
580 OrderedProxy::OrderVector::const_iterator m_iter;
581 OrderedProxy::OrderVector::const_iterator m_stop;
582 };
583
584 // Return a proxy object that allows iteration in an order determined by the
585 // order of insertion, the location in an input file, and rules specified by
586 // the addOrderingRules() method.
587 OrderedProxy ordered() const { return OrderedProxy(*this); }
588
589 //! Returns the number of elements in this map
590 size_t size() const {
591 return m_data.size();
592 };
593
594 bool operator==(const AnyMap& other) const;
595 bool operator!=(const AnyMap& other) const;
596
597 //! Return the default units that should be used to convert stored values
598 const UnitSystem& units() const { return *m_units; }
599
600 //! Use the supplied UnitSystem to set the default units, and recursively
601 //! process overrides from nodes named `units`.
602 /*!
603 * If a `units` node is present in a map that contains other keys, the
604 * specified units are taken to be the defaults for that map. If the map
605 * contains only a `units` node, and is the first item in a list of maps,
606 * then the specified units are taken to be the defaults for all the maps in
607 * the list.
608 *
609 * After being processed, the `units` nodes are removed. This function is
610 * called automatically by the fromYamlFile() and fromYamlString()
611 * constructors.
612 *
613 * @warning This function is an experimental part of the %Cantera API and
614 * may be changed or removed without notice.
615 */
616 void applyUnits();
617
618 //! @see applyUnits(const UnitSystem&)
619 void applyUnits(shared_ptr<UnitSystem>& units);
620
621 //! Set the unit system for this AnyMap. The applyUnits() method should be
622 //! called on the root AnyMap object after all desired calls to setUnits()
623 //! in the tree have been made.
624 void setUnits(const UnitSystem& units);
625
626 //! Use "flow" style when outputting this AnyMap to YAML
627 void setFlowStyle(bool flow=true);
628
629 //! Add global rules for setting the order of elements when outputting
630 //! AnyMap objects to YAML
631 /*!
632 * Enables specifying keys that should appear at either the beginning
633 * or end of the generated YAML mapping. Only programmatically-added keys
634 * are rearranged. Keys which come from YAML input retain their existing
635 * ordering, and are output after programmatically-added keys.
636 *
637 * This function should be called exactly once for any given spec that
638 * is to be added. To facilitate this, the method returns a bool so that
639 * it can be called as part of initializing a static variable. To avoid
640 * spurious compiler warnings about unused variables, the following
641 * structure can be used:
642 *
643 * ```
644 * static bool reg = AnyMap::addOrderingRules("Reaction",
645 * {{"head", "equation"}, {"tail", "duplicate"}});
646 * if (reg) {
647 * reactionMap["__type__"] = "Reaction";
648 * }
649 * ```
650 *
651 * @param objectType Apply rules to maps where the hidden `__type__` key
652 * has the corresponding value.
653 * @param specs A list of rule specifications. Each rule consists of
654 * two strings. The first string is either "head" or "tail", and the
655 * second string is the name of a key
656 * @returns ``true``, to facilitate static initialization
657 */
658 static bool addOrderingRules(const std::string& objectType,
659 const std::vector<std::vector<std::string>>& specs);
660
661 //! Remove the specified file from the input cache if it is present
662 static void clearCachedFile(const std::string& filename);
663
664private:
665 //! The stored data
666 std::unordered_map<std::string, AnyValue> m_data;
667
668 //! The default units that are used to convert stored values
669 std::shared_ptr<UnitSystem> m_units;
670
671 //! Cache for previously-parsed input (YAML) files. The key is the full path
672 //! to the file, and the second element of the value is the last-modified
673 //! time for the file, which is used to enable change detection.
674 static std::unordered_map<std::string, std::pair<AnyMap, int>> s_cache;
675
676 //! Information about fields that should appear first when outputting to
677 //! YAML. Keys in this map are matched to `__type__` keys in AnyMap
678 //! objects, and values are a list of field names.
679 static std::unordered_map<std::string, std::vector<std::string>> s_headFields;
680
681 //! Information about fields that should appear last when outputting to
682 //! YAML. Keys in this map are matched to `__type__` keys in AnyMap
683 //! objects, and values are a list of field names.
684 static std::unordered_map<std::string, std::vector<std::string>> s_tailFields;
685
686 friend class AnyValue;
687 friend YAML::Emitter& YAML::operator<<(YAML::Emitter& out, const AnyMap& rhs);
688};
689
690// Define begin() and end() to allow use with range-based for loops
691AnyMap::Iterator begin(const AnyValue& v);
692AnyMap::Iterator end(const AnyValue& v);
693
694//! Error thrown for problems processing information contained in an AnyMap or
695//! AnyValue.
696/*!
697 * This class uses the file, line, and column information stored in an AnyMap
698 * or AnyValue to provide an error message including context lines for the
699 * original user input.
700 */
702{
703public:
704 //! Indicate an error occurring in `procedure` while using information from
705 //! `node`. The `message` and `args` are processed as in the CanteraError
706 //! class.
707 template <typename... Args>
708 InputFileError(const std::string& procedure, const AnyBase& node,
709 const std::string& message, const Args&... args)
710 : CanteraError(
711 procedure,
712 formatError(fmt::format(message, args...),
713 node.m_line, node.m_column, node.m_metadata))
714 {
715 }
716
717 //! Indicate an error occurring in `procedure` while using information from
718 //! `node1` and `node2`. The `message` and `args` are processed as in the
719 //! CanteraError class.
720 template <typename... Args>
721 InputFileError(const std::string& procedure, const AnyBase& node1,
722 const AnyBase& node2, const std::string& message,
723 const Args&... args)
724 : CanteraError(
725 procedure,
726 formatError2(fmt::format(message, args...),
727 node1.m_line, node1.m_column, node1.m_metadata,
728 node2.m_line, node2.m_column, node2.m_metadata))
729 {
730 }
731
732
733 virtual std::string getClass() const {
734 return "InputFileError";
735 }
736protected:
737 static std::string formatError(const std::string& message,
738 int line, int column,
739 const shared_ptr<AnyMap>& metadata);
740 static std::string formatError2(const std::string& message,
741 int line1, int column1, const shared_ptr<AnyMap>& metadata1,
742 int line2, int column2, const shared_ptr<AnyMap>& metadata2);
743};
744
745//! A deprecation warning for syntax in an input file
746void warn_deprecated(const std::string& source, const AnyBase& node,
747 const std::string& message);
748
749}
750
751#ifndef CANTERA_API_NO_BOOST
753#endif
754
755#endif
Header for unit conversion utilities, which are used to translate user input from input files (See In...
Base class defining common data possessed by both AnyMap and AnyValue objects.
Definition: AnyMap.h:33
const AnyValue & getMetadata(const std::string &key) const
Get a value from the metadata applicable to the AnyMap tree containing this node.
Definition: AnyMap.cpp:577
int m_column
If m_line >= 0, the column where this value occurs in the input file.
Definition: AnyMap.h:54
void setLoc(int line, int column)
For values which are derived from an input file, set the line and column of this value in that file.
Definition: AnyMap.cpp:571
int m_line
The line where this value occurs in the input file.
Definition: AnyMap.h:50
friend void warn_deprecated(const std::string &source, const AnyBase &node, const std::string &message)
A deprecation warning for syntax in an input file.
Definition: AnyMap.cpp:1901
shared_ptr< AnyMap > m_metadata
Metadata relevant to an entire AnyMap tree, such as information about.
Definition: AnyMap.h:58
Defined to allow use with range-based for loops.
Definition: AnyMap.h:508
Defined to allow the OrderedProxy class to be used with range-based for loops.
Definition: AnyMap.h:562
Proxy for iterating over an AnyMap in the defined output ordering.
Definition: AnyMap.h:544
A map of string keys to values whose type can vary at runtime.
Definition: AnyMap.h:399
AnyValue & operator[](const std::string &key)
Get the value of the item stored in key.
Definition: AnyMap.cpp:1341
Iterator begin() const
Defined to allow use with range-based for loops.
Definition: AnyMap.h:531
size_t size() const
Returns the number of elements in this map.
Definition: AnyMap.h:590
std::unordered_map< std::string, AnyValue > m_data
The stored data.
Definition: AnyMap.h:666
vector_fp convertVector(const std::string &key, const std::string &units, size_t nMin=npos, size_t nMax=npos) const
Convert a vector of dimensional values.
Definition: AnyMap.cpp:1528
const AnyValue & at(const std::string &key) const
Get the value of the item stored in key.
Definition: AnyMap.cpp:1391
void copyMetadata(const AnyMap &other)
Copy metadata including input line/column from an existing AnyMap.
Definition: AnyMap.cpp:1465
static std::unordered_map< std::string, std::vector< std::string > > s_tailFields
Information about fields that should appear last when outputting to YAML.
Definition: AnyMap.h:684
std::shared_ptr< UnitSystem > m_units
The default units that are used to convert stored values.
Definition: AnyMap.h:669
double convert(const std::string &key, const std::string &units) const
Convert the item stored by the given key to the units specified in units.
Definition: AnyMap.cpp:1508
AnyValue & createForYaml(const std::string &key, int line, int column)
Used to create a new item which will be populated from a YAML input string, where the item with key o...
Definition: AnyMap.cpp:1377
const UnitSystem & units() const
Return the default units that should be used to convert stored values.
Definition: AnyMap.h:598
Iterator end() const
Defined to allow use with range-based for loops.
Definition: AnyMap.h:536
bool empty() const
Return boolean indicating whether AnyMap is empty.
Definition: AnyMap.cpp:1401
void applyUnits()
Use the supplied UnitSystem to set the default units, and recursively process overrides from nodes na...
Definition: AnyMap.cpp:1665
const std::string & getString(const std::string &key, const std::string &default_) const
If key exists, return it as a string, otherwise return default_.
Definition: AnyMap.cpp:1502
static std::unordered_map< std::string, std::vector< std::string > > s_headFields
Information about fields that should appear first when outputting to YAML.
Definition: AnyMap.h:679
bool getBool(const std::string &key, bool default_) const
If key exists, return it as a bool, otherwise return default_.
Definition: AnyMap.cpp:1487
static void clearCachedFile(const std::string &filename)
Remove the specified file from the input cache if it is present.
Definition: AnyMap.cpp:1719
static AnyMap fromYamlFile(const std::string &name, const std::string &parent_name="")
Create an AnyMap from a YAML file.
Definition: AnyMap.cpp:1743
long int getInt(const std::string &key, long int default_) const
If key exists, return it as a long int, otherwise return default_.
Definition: AnyMap.cpp:1497
void erase(const std::string &key)
Erase the value held by key.
Definition: AnyMap.cpp:1411
double getDouble(const std::string &key, double default_) const
If key exists, return it as a double, otherwise return default_.
Definition: AnyMap.cpp:1492
static bool addOrderingRules(const std::string &objectType, const std::vector< std::vector< std::string > > &specs)
Add global rules for setting the order of elements when outputting AnyMap objects to YAML.
Definition: AnyMap.cpp:1702
void setFlowStyle(bool flow=true)
Use "flow" style when outputting this AnyMap to YAML.
Definition: AnyMap.cpp:1698
void propagateMetadata(shared_ptr< AnyMap > &file)
Propagate metadata to any child elements.
Definition: AnyMap.cpp:1445
std::string keys_str() const
Return a string listing the keys in this AnyMap, for use in error messages, for example.
Definition: AnyMap.cpp:1430
static std::unordered_map< std::string, std::pair< AnyMap, int > > s_cache
Cache for previously-parsed input (YAML) files.
Definition: AnyMap.h:674
void clear()
Erase all items in the mapping.
Definition: AnyMap.cpp:1416
static AnyMap fromYamlString(const std::string &yaml)
Create an AnyMap from a string containing a YAML document.
Definition: AnyMap.cpp:1727
bool hasKey(const std::string &key) const
Returns true if the map contains an item named key.
Definition: AnyMap.cpp:1406
void update(const AnyMap &other, bool keepExisting=true)
Add items from other to this AnyMap.
Definition: AnyMap.cpp:1421
void setMetadata(const std::string &key, const AnyValue &value)
Set a metadata value that applies to this AnyMap and its children.
Definition: AnyMap.cpp:1453
void setUnits(const UnitSystem &units)
Set the unit system for this AnyMap.
Definition: AnyMap.cpp:1686
A wrapper for a variable whose type is determined at runtime.
Definition: AnyMap.h:84
AnyValue & operator[](const std::string &key)
If this AnyValue is an AnyMap, return the value stored in key.
Definition: AnyMap.cpp:644
bool hasMapWhere(const std::string &key, const std::string &value) const
Returns true when getMapWhere() would succeed.
Definition: AnyMap.cpp:1063
void setKey(const std::string &key)
Set the name of the key storing this value in an AnyMap.
Definition: AnyMap.cpp:658
std::unique_ptr< boost::any > m_value
The held value.
Definition: AnyMap.h:278
const std::string & asString() const
Return the held value, if it is a string.
Definition: AnyMap.cpp:716
void setQuantity(double value, const std::string &units, bool is_act_energy=false)
Assign a scalar quantity with units as a string, for example {3.0, "m^2"}.
Definition: AnyMap.cpp:746
bool & asBool()
Return the held value, if it is a bool.
Definition: AnyMap.cpp:848
bool empty() const
Return boolean indicating whether AnyValue is empty.
Definition: AnyMap.cpp:684
const std::vector< T > & asVector(size_t nMin=npos, size_t nMax=npos) const
Return the held value, if it is a vector of type T.
Definition: AnyMap.inl.h:72
long int & asInt()
Return the held value, if it is a long int.
Definition: AnyMap.cpp:880
void applyUnits(shared_ptr< UnitSystem > &units)
Definition: AnyMap.cpp:1091
const std::type_info & type() const
Returns the type of the held value.
Definition: AnyMap.cpp:660
double & asDouble()
Return the held value as a double, if it is a double or a long int.
Definition: AnyMap.cpp:801
static bool eq_comparer(const boost::any &lhs, const boost::any &rhs)
Equality comparison function used when lhs is of type T
Definition: AnyMap.inl.h:179
bool isScalar() const
Returns true if the held value is a scalar type (such as double, long int, string,...
Definition: AnyMap.cpp:688
std::string type_str() const
Returns a string specifying the type of the held value.
Definition: AnyMap.cpp:680
static bool vector2_eq(const boost::any &lhs, const boost::any &rhs)
Helper function for comparing nested vectors of different (but comparable) types, for example vector<...
Definition: AnyMap.inl.h:162
std::pair< int, int > order() const
Return values used to determine the sort order when outputting to YAML.
Definition: AnyMap.cpp:1086
void setFlowStyle(bool flow=true)
Definition: AnyMap.cpp:1188
void propagateMetadata(shared_ptr< AnyMap > &file)
Propagate metadata to any child elements.
Definition: AnyMap.cpp:664
static bool vector_eq(const boost::any &lhs, const boost::any &rhs)
Helper function for comparing vectors of different (but comparable) types, for example vector<double>...
Definition: AnyMap.inl.h:150
std::string m_key
Key of this value in a parent AnyMap
Definition: AnyMap.h:275
bool is() const
Returns true if the held value is of the specified type.
Definition: AnyMap.inl.h:58
AnyMap & getMapWhere(const std::string &key, const std::string &value, bool create=false)
Treating the value as vector<AnyMap>, return the item where the given key has the specified value.
Definition: AnyMap.cpp:1012
bool hasKey(const std::string &key) const
Returns true if this AnyValue is an AnyMap and that map contains a key with the given name.
Definition: AnyMap.cpp:654
std::map< std::string, T > asMap() const
Return the held AnyMap as a std::map where all of the values have the specified type.
Definition: AnyMap.inl.h:125
const T & as() const
Get the value of this key as the specified type.
Definition: AnyMap.inl.h:19
Base class for exceptions thrown by Cantera classes.
Definition: ctexceptions.h:61
Error thrown for problems processing information contained in an AnyMap or AnyValue.
Definition: AnyMap.h:702
virtual std::string getClass() const
Method overridden by derived classes to indicate their type.
Definition: AnyMap.h:733
InputFileError(const std::string &procedure, const AnyBase &node, const std::string &message, const Args &... args)
Indicate an error occurring in procedure while using information from node.
Definition: AnyMap.h:708
InputFileError(const std::string &procedure, const AnyBase &node1, const AnyBase &node2, const std::string &message, const Args &... args)
Indicate an error occurring in procedure while using information from node1 and node2.
Definition: AnyMap.h:721
Unit conversion utility.
Definition: Units.h:161
A representation of the units associated with a dimensional quantity.
Definition: Units.h:30
This file contains definitions of constants, types and terms that are used in internal routines and a...
Definitions for the classes that are thrown when Cantera experiences an error condition (also contain...
Namespace for the Cantera kernel.
Definition: AnyMap.h:29
const size_t npos
index returned by functions to indicate "no position"
Definition: ct_defs.h:192
void warn_deprecated(const std::string &source, const AnyBase &node, const std::string &message)
A deprecation warning for syntax in an input file.
Definition: AnyMap.cpp:1901
std::vector< double > vector_fp
Turn on the use of stl vectors for the basic array type within cantera Vector of doubles.
Definition: ct_defs.h:184
Versions 6.2.0 and 6.2.1 of fmtlib do not include this define before they include windows....
Definition: fmt.h:31