8 #include "cantera/base/yaml.h"
10 #ifdef CT_USE_DEMANGLE
11 #include <boost/core/demangle.hpp>
14 #include <boost/algorithm/string.hpp>
17 #include <unordered_set>
19 namespace ba = boost::algorithm;
23 std::mutex yaml_cache_mutex;
25 bool isFloat(
const std::string& val)
29 std::string str = ba::trim_copy(val);
37 if (ch ==
'+' || ch ==
'-') {
39 if (str.size() == 1) {
43 for (
size_t i = istart; i < str.size(); i++) {
46 }
else if (ch ==
'.') {
54 }
else if (ch ==
'e' || ch ==
'E') {
56 if (numExp > 1 || i == str.size() - 1) {
60 if (ch ==
'+' || ch ==
'-') {
61 if (i + 1 == str.size() - 1) {
73 bool isInt(
const std::string& val)
75 std::string str = ba::trim_copy(val);
81 if (ch ==
'+' || ch ==
'-') {
83 if (str.size() == 1) {
87 for (
size_t i = istart; i < str.size(); i++) {
88 if (!isdigit(str[i])) {
95 bool isBool(
const std::string& val) {
96 std::string str = ba::trim_copy(val);
97 return (val ==
"true" || val ==
"True" || val ==
"false" || val ==
"False");
100 enum class Type : char {
110 Type operator|(Type lhs, Type rhs)
112 return Type(
static_cast<char>(lhs) |
static_cast<char>(rhs));
115 Type elementTypes(
const YAML::Node& node)
118 Type types = Type::Unknown;
119 for (
const auto& el : node) {
121 types = types | Type::Map;
122 }
else if (el.IsSequence()) {
123 types = types | Type::Sequence;
124 }
else if (el.IsScalar()) {
125 std::string nodestr = el.as<std::string>();
126 if (isInt(nodestr)) {
127 types = types | Type::Integer;
128 }
else if (isFloat(nodestr)) {
129 types = types | Type::Double;
130 }
else if (isBool(nodestr)) {
131 types = types | Type::Bool;
133 types = types | Type::String;
154 target.
setLoc(node.Mark().line, node.Mark().column);
155 if (node.IsSequence()) {
157 target[
"items"] = node.as<
AnyValue>();
159 }
else if (!node.IsMap()) {
160 std::string text = YAML::Dump(node);
161 if (text.size() > 300) {
165 "YAML node is not a map. Node begins with:\n'''\n{}\n'''", text);
167 for (
const auto& child : node) {
168 std::string key = child.first.as<std::string>();
169 const auto& loc = child.second.Mark();
170 target[key].
setLoc(loc.line, loc.column);
171 if (child.second.IsMap()) {
172 target[key] = child.second.as<
AnyMap>();
174 target[key] = child.second.as<
AnyValue>();
175 target[key].setKey(key);
189 target.
setLoc(node.Mark().line, node.Mark().column);
190 if (node.IsScalar()) {
192 std::string nodestr = node.as<std::string>();
193 if (node.Tag() ==
"!") {
198 }
else if (isInt(nodestr)) {
200 target = node.
as<
long int>();
201 }
catch (YAML::BadConversion&) {
205 target = node.
as<
double>();
207 }
else if (isFloat(nodestr)) {
209 }
else if (isBool(nodestr)) {
210 target = node.
as<
bool>();
215 }
else if (node.IsSequence()) {
217 Type types = elementTypes(node);
218 if (types == Type::Integer) {
219 target = node.
as<std::vector<long int>>();
220 }
else if (types == (Type::Integer | Type::Double) || types == Type::Double) {
222 }
else if (types == Type::String) {
223 target = node.
as<std::vector<std::string>>();
224 }
else if (types == Type::Bool) {
225 target = node.
as<std::vector<bool>>();
226 }
else if (types == Type::Map) {
227 target = node.
as<std::vector<AnyMap>>();
228 }
else if (types == Type::Sequence) {
230 Type subtypes = Type::Unknown;
231 for (
const auto& el : node) {
232 subtypes = subtypes | elementTypes(el);
234 if (subtypes == Type::Integer) {
235 target = node.
as<std::vector<std::vector<long int>>>();
236 }
else if (subtypes == (Type::Integer | Type::Double) || subtypes == Type::Double) {
237 target = node.
as<std::vector<std::vector<double>>>();
238 }
else if (types == Type::String) {
239 target = node.
as<std::vector<std::vector<std::string>>>();
240 }
else if (types == Type::Bool) {
241 target = node.
as<std::vector<std::vector<bool>>>();
243 target = node.
as<std::vector<AnyValue>>();
247 target = node.
as<std::vector<AnyValue>>();
250 }
else if (node.IsMap()) {
253 }
else if (node.IsNull()) {
267 {
typeid(double).name(),
"double"},
268 {
typeid(
long int).name(),
"long int"},
269 {
typeid(std::string).name(),
"string"},
270 {
typeid(std::vector<double>).name(),
"vector<double>"},
271 {
typeid(
AnyMap).name(),
"AnyMap"},
274 std::unordered_map<std::string, std::pair<AnyMap, int>>
AnyMap::s_cache;
302 , m_value(new boost::any{})
303 , m_equals(eq_comparer<size_t>)
306 AnyValue::~AnyValue() =
default;
308 AnyValue::AnyValue(
AnyValue const& other)
311 , m_value(new boost::any{*other.m_value})
312 , m_equals(other.m_equals)
316 AnyValue::AnyValue(
AnyValue&& other)
318 , m_key(std::move(other.m_key))
319 , m_value(std::move(other.m_value))
320 , m_equals(std::move(other.m_equals))
325 if (
this == &other) {
328 AnyBase::operator=(*
this);
331 m_equals = other.m_equals;
336 if (
this == &other) {
339 AnyBase::operator=(std::move(other));
342 m_equals = std::move(other.m_equals);
346 bool AnyValue::operator==(
const AnyValue& other)
const
351 bool AnyValue::operator!=(
const AnyValue& other)
const
358 return as<AnyMap>()[key];
363 return as<AnyMap>().at(key);
367 return (is<AnyMap>() && as<AnyMap>().
hasKey(key));
381 }
else if (
is<std::vector<AnyValue>>()) {
382 for (
auto& item : asVector<AnyValue>()) {
385 }
else if (
is<std::vector<AnyMap>>()) {
386 for (
auto& item : asVector<AnyMap>()) {
393 return demangle(
type());
397 return is<double>() || is<long int>() || is<std::string>() || is<bool>();
402 AnyValue::AnyValue(
const std::string& value)
403 : m_value(new boost::any{value})
404 , m_equals(eq_comparer<std::string>)
407 AnyValue::AnyValue(
const char* value)
408 : m_value(new boost::any{std::string(value)})
409 , m_equals(eq_comparer<std::string>)
412 AnyValue &AnyValue::operator=(
const std::string &value) {
414 m_equals = eq_comparer<std::string>;
418 AnyValue &AnyValue::operator=(
const char *value) {
420 m_equals = eq_comparer<std::string>;
425 return as<std::string>();
428 bool AnyValue::operator==(
const std::string& other)
const
430 if (
m_value->type() ==
typeid(std::string)) {
431 return boost::any_cast<std::string>(*
m_value) == other;
437 bool AnyValue::operator!=(
const std::string& other)
const
439 return !(*
this == other);
442 bool operator==(
const std::string& lhs,
const AnyValue& rhs)
447 bool operator!=(
const std::string& lhs,
const AnyValue& rhs)
454 AnyValue::AnyValue(
double value)
455 : m_value(new boost::any{value})
456 , m_equals(eq_comparer<double>)
459 AnyValue &AnyValue::operator=(
double value) {
461 m_equals = eq_comparer<double>;
473 bool AnyValue::operator==(
const double& other)
const
475 if (
m_value->type() ==
typeid(
double)) {
476 return boost::any_cast<double>(*
m_value) == other;
477 }
else if (
m_value->type() ==
typeid(
long int)) {
478 return boost::any_cast<long int>(*
m_value) == other;
484 bool AnyValue::operator!=(
const double& other)
const
486 return !(*
this == other);
489 bool operator==(
const double& lhs,
const AnyValue& rhs)
494 bool operator!=(
const double& lhs,
const AnyValue& rhs)
501 AnyValue::AnyValue(
bool value)
502 : m_value(new boost::any{value})
503 , m_equals(eq_comparer<bool>)
506 AnyValue &AnyValue::operator=(
bool value) {
508 m_equals = eq_comparer<bool>;
522 AnyValue::AnyValue(
long int value)
523 : m_value(new boost::any{value})
524 , m_equals(eq_comparer<long int>)
527 AnyValue::AnyValue(
int value)
528 : m_value(new boost::any{static_cast<long int>(value)})
529 , m_equals(eq_comparer<long int>)
532 AnyValue &AnyValue::operator=(
long int value) {
534 m_equals = eq_comparer<long int>;
538 AnyValue &AnyValue::operator=(
int value) {
539 *
m_value =
static_cast<long int>(value);
540 m_equals = eq_comparer<long int>;
545 return as<long int>();
549 return as<long int>();
552 bool AnyValue::operator==(
const long int& other)
const
554 if (
m_value->type() ==
typeid(
long int)) {
555 return boost::any_cast<long int>(*
m_value) == other;
556 }
else if (
m_value->type() ==
typeid(
double)) {
557 return boost::any_cast<double>(*
m_value) == other;
563 bool AnyValue::operator!=(
const long int& other)
const
565 return !(*
this == other);
568 bool AnyValue::operator==(
const int& other)
const
570 return *
this ==
static_cast<long int>(other);
573 bool AnyValue::operator!=(
const int& other)
const
575 return *
this !=
static_cast<long int>(other);
578 bool operator==(
const long int& lhs,
const AnyValue& rhs)
583 bool operator!=(
const long int& lhs,
const AnyValue& rhs)
588 bool operator==(
const int& lhs,
const AnyValue& rhs)
593 bool operator!=(
const int& lhs,
const AnyValue& rhs)
600 AnyValue::AnyValue(
const AnyMap& value)
601 : m_value(new boost::any{value})
602 , m_equals(eq_comparer<
AnyMap>)
607 m_equals = eq_comparer<AnyMap>;
613 m_equals = eq_comparer<AnyMap>;
618 const std::string& name)
const
620 std::unordered_map<std::string, const AnyMap*> mapped;
621 for (
const auto& item : asVector<AnyMap>()) {
622 auto key = item[name].asString();
623 if (mapped.count(key)) {
625 "Duplicate key '{}'", key);
627 mapped.emplace(std::make_pair(key, &item));
632 std::unordered_map<std::string, AnyMap*>
AnyValue::asMap(
const std::string& name)
634 std::unordered_map<std::string, AnyMap*> mapped;
635 for (
auto& item : asVector<AnyMap>()) {
636 auto key = item.at(name).asString();
637 if (mapped.count(key)) {
639 "Duplicate key '{}'", key);
641 mapped.emplace(std::make_pair(key, &item));
648 if (
is<std::vector<AnyMap>>()) {
650 return asVector<AnyMap>().
at(0);
652 for (
auto& item : asVector<AnyMap>()) {
653 if (item.hasKey(key) && item[key] == value) {
658 "List does not contain a map where '{}' = '{}'", key, value);
659 }
else if (is<AnyMap>()) {
660 if (value ==
"" || (
hasKey(key) && as<AnyMap>()[key] == value)) {
664 "Map does not contain a key where '{}' = '{}'", key, value);
666 }
else if (is<void>()) {
668 "Key '{}' not found",
m_key);
671 "Element is not a mapping or list of mappings");
678 if (
is<std::vector<AnyMap>>()) {
680 return asVector<AnyMap>().
at(0);
682 for (
auto& item : asVector<AnyMap>()) {
683 if (item.hasKey(key) && item[key] == value) {
689 auto& vec = asVector<AnyMap>();
692 vec.push_back(std::move(child));
696 "List does not contain a map where '{}' = '{}'", key, value);
698 }
else if (is<AnyMap>()) {
699 if (value ==
"" || (
hasKey(key) && as<AnyMap>()[key] == value)) {
703 newChild[key] = value;
704 std::vector<AnyMap> nodes{std::move(as<AnyMap>()), std::move(newChild)};
705 operator=(std::move(nodes));
706 return asVector<AnyMap>().back();
709 "Map does not contain a key where '{}' = '{}'", key, value);
711 }
else if (is<void>() && create) {
714 operator=(std::move(child));
716 }
else if (is<void>()) {
718 "Key '{}' not found",
m_key);
721 "Element is not a mapping or list of mappings");
727 if (
is<std::vector<AnyMap>>()) {
731 for (
auto& item : asVector<AnyMap>()) {
732 if (item.hasKey(key) && item[key] == value) {
737 }
else if (is<AnyMap>()) {
738 if (value ==
"" || (
hasKey(key) && as<AnyMap>()[key] == value)) {
752 as<AnyMap>().applyUnits(units);
753 }
else if (
is<std::vector<AnyMap>>()) {
754 auto& list = as<std::vector<AnyMap>>();
755 if (list.size() && list[0].hasKey(
"units") && list[0].size() == 1) {
759 newUnits.
setDefaults(list[0][
"units"].asMap<std::string>());
760 list[0].m_data.erase(
"units");
761 for (
auto& item : list) {
763 if (item.size() == 1 && item.hasKey(
"units")) {
765 "Found units entry as not the first item in a list.");
767 item.applyUnits(newUnits);
770 list.erase(list.begin());
773 for (
auto& item : list) {
775 if (item.size() == 1 && item.hasKey(
"units")) {
777 "Found units entry as not the first item in a list.");
779 item.applyUnits(units);
786 std::string AnyValue::demangle(
const std::type_info& type)
const
791 #ifdef CT_USE_DEMANGLE
792 return boost::core::demangle(
type.name());
802 const std::vector<AnyValue>& AnyValue::asVector<AnyValue>(
size_t nMin,
size_t nMax)
const
804 if (!
is<std::vector<AnyValue>>()) {
805 std::vector<AnyValue> v;
806 if (
is<std::vector<double>>()) {
807 for (
const auto& el : asVector<double>()) {
811 }
else if (
is<std::vector<long int>>()) {
812 for (
const auto& el : asVector<long int>()) {
816 }
else if (
is<std::vector<std::string>>()) {
817 for (
const auto& el : asVector<std::string>()) {
825 const auto& vv = as<std::vector<AnyValue>>();
826 m_equals = eq_comparer<std::vector<AnyValue>>;
827 checkSize(vv, nMin, nMax);
832 std::vector<AnyValue>& AnyValue::asVector<AnyValue>(
size_t nMin,
size_t nMax)
834 auto& v =
const_cast<std::vector<AnyValue>&
>(
835 const_cast<const AnyValue*
>(
this)->asVector<AnyValue>());
836 checkSize(v, nMin, nMax);
841 const std::vector<double>& AnyValue::asVector<double>(
size_t nMin,
size_t nMax)
const
843 if (
is<std::vector<long int>>()) {
844 std::vector<double> v;
845 for (
const auto& el : asVector<long int>()) {
850 const auto& vv = as<std::vector<double>>();
851 m_equals = eq_comparer<std::vector<double>>;
852 checkSize(vv, nMin, nMax);
857 std::vector<double>& AnyValue::asVector<double>(
size_t nMin,
size_t nMax)
859 if (
is<std::vector<long int>>()) {
860 std::vector<double> v;
861 for (
const auto& el : asVector<long int>()) {
866 auto& vv = as<std::vector<double>>();
867 m_equals = eq_comparer<std::vector<double>>;
868 checkSize(vv, nMin, nMax);
873 const std::vector<vector_fp>& AnyValue::asVector<vector_fp>(
size_t nMin,
size_t nMax)
const
875 if (
is<std::vector<std::vector<long int>>>()) {
876 std::vector<vector_fp> v;
877 for (
const auto& outer :
asVector<std::vector<long int>>()) {
879 for (
const auto& inner : outer) {
880 v.back().push_back(inner);
885 const auto& vv = as<std::vector<vector_fp>>();
886 m_equals = eq_comparer<std::vector<vector_fp>>;
887 checkSize(vv, nMin, nMax);
892 std::vector<vector_fp>& AnyValue::asVector<vector_fp>(
size_t nMin,
size_t nMax)
894 if (
is<std::vector<std::vector<long int>>>()) {
895 std::vector<vector_fp> v;
896 for (
const auto& outer :
asVector<std::vector<long int>>()) {
898 for (
const auto& inner : outer) {
899 v.back().push_back(inner);
904 auto& vv = as<std::vector<vector_fp>>();
905 m_equals = eq_comparer<std::vector<vector_fp>>;
906 checkSize(vv, nMin, nMax);
911 const std::vector<AnyMap>& AnyValue::asVector<AnyMap>(
size_t nMin,
size_t nMax)
const
914 std::vector<AnyMap> v;
915 v.push_back(std::move(as<AnyMap>()));
917 }
else if (
is<std::vector<AnyValue>>() && asVector<AnyValue>().empty()) {
918 *
m_value = std::vector<AnyMap>();
920 const auto& vv = as<std::vector<AnyMap>>();
921 checkSize(vv, nMin, nMax);
926 std::vector<AnyMap>& AnyValue::asVector<AnyMap>(
size_t nMin,
size_t nMax)
929 std::vector<AnyMap> v;
930 v.push_back(std::move(as<AnyMap>()));
932 }
else if (
is<std::vector<AnyValue>>() && asVector<AnyValue>().empty()) {
933 *
m_value = std::vector<AnyMap>();
935 auto& vv = as<std::vector<AnyMap>>();
936 checkSize(vv, nMin, nMax);
944 const auto& iter =
m_data.find(key);
945 if (iter ==
m_data.end()) {
968 }
catch (std::out_of_range&) {
970 "Key '{}' not found.\nExisting keys: {}", key,
keys_str());
978 }
catch (std::out_of_range&) {
980 "Key '{}' not found.\nExisting keys: {}", key,
keys_str());
1001 fmt::memory_buffer b;
1002 auto iter = this->
begin();
1003 if (iter != this->
end()) {
1004 format_to(b,
"{}", iter->first);
1007 while (iter != this->
end()) {
1008 format_to(b,
", {}", iter->first);
1011 return to_string(b);
1017 for (
auto& item :
m_data) {
1030 (*m_metadata)[key] = value;
1036 return (
hasKey(key)) ?
m_data.at(key).asBool() : default_;
1041 return (
hasKey(key)) ?
m_data.at(key).asDouble() : default_;
1046 return (
hasKey(key)) ?
m_data.at(key).asInt() : default_;
1050 const std::string& default_)
const
1052 return (
hasKey(key)) ?
m_data.at(key).asString() : default_;
1066 double default_)
const
1076 size_t nMin,
size_t nMax)
const
1078 return units().
convert(
at(key).asVector<AnyValue>(nMin, nMax), dest);
1081 AnyMap::Iterator::Iterator(
1082 const std::unordered_map<std::string, AnyValue>::const_iterator& start,
1083 const std::unordered_map<std::string, AnyValue>::const_iterator& stop)
1087 while (m_iter != m_stop
1088 && ba::starts_with(m_iter->first,
"__")
1089 && ba::ends_with(m_iter->first,
"__")) {
1097 while (m_iter != m_stop
1098 && ba::starts_with(m_iter->first,
"__")
1099 && ba::ends_with(m_iter->first,
"__")) {
1105 bool AnyMap::operator==(
const AnyMap& other)
const
1109 for (
auto& item : *
this) {
1110 if (!other.
hasKey(item.first)) {
1115 for (
auto & item : other) {
1116 if (!
hasKey(item.first) || item.second !=
at(item.first)) {
1123 bool AnyMap::operator!=(
const AnyMap& other)
const
1135 for (
auto& item :
m_data) {
1136 item.second.applyUnits(
m_units);
1143 YAML::Node node = YAML::Load(yaml);
1144 amap = node.as<
AnyMap>();
1145 }
catch (YAML::Exception& err) {
1147 fake.
setLoc(err.mark.line, err.mark.column);
1157 const std::string& parent_name)
1159 std::string fullName;
1161 size_t islash = parent_name.find_last_of(
"/\\");
1162 if (islash !=
npos) {
1163 std::string parent_path = parent_name.substr(0, islash);
1164 if (std::ifstream(parent_path +
"/" + name).good()) {
1165 fullName = parent_path +
"/" + name;
1169 if (fullName.empty()) {
1175 int mtime = get_modified_time(fullName);
1176 std::unique_lock<std::mutex> lock(yaml_cache_mutex);
1177 auto iter =
s_cache.find(fullName);
1178 if (iter !=
s_cache.end() && iter->second.second == mtime) {
1179 return iter->second.first;
1182 if (!std::ifstream(fullName).good()) {
1183 throw CanteraError(
"AnyMap::fromYamlFile",
"Input file '{}' not found "
1184 "on the Cantera search path.", name);
1188 auto& cache_item =
s_cache[fullName];
1189 cache_item.second = mtime;
1191 YAML::Node node = YAML::LoadFile(fullName);
1192 cache_item.first = node.as<
AnyMap>();
1195 }
catch (YAML::Exception& err) {
1198 fake.
setLoc(err.mark.line, err.mark.column);
1205 cache_item.first[
"__file__"] = fullName;
1207 if (cache_item.first.hasKey(
"deprecated")) {
1212 return cache_item.first;
1224 void formatInputFile(fmt::memory_buffer& b,
const shared_ptr<AnyMap>& metadata,
1225 const std::string& filename,
int lineno,
int column,
int lineno2=-1,
int column2=-1)
1227 if (lineno2 == -1) {
1232 format_to(b,
"| Line |\n");
1233 if (!metadata->hasKey(
"file-contents")) {
1235 std::stringstream buffer;
1236 buffer << infile.rdbuf();
1237 (*metadata)[
"file-contents"] = buffer.str();
1242 std::stringstream contents((*metadata)[
"file-contents"].asString());
1243 while (std::getline(contents, line)) {
1244 if (i == lineno || i == lineno2) {
1245 format_to(b,
"> {: 5d} > {}\n", i+1, line);
1246 format_to(b,
"{:>{}}\n",
"^", column + 11);
1248 }
else if ((lineno + 4 > i && lineno < i + 6) ||
1249 (lineno2 + 4 > i && lineno2 < i + 6)) {
1250 if (lastShown >= 0 && i - lastShown > 1) {
1251 format_to(b,
"...\n");
1253 format_to(b,
"| {: 5d} | {}\n", i+1, line);
1261 std::string InputFileError::formatError(
const std::string& message,
1262 int lineno,
int column,
1263 const shared_ptr<AnyMap>& metadata)
1268 std::string filename = metadata->getString(
"filename",
"input string");
1270 fmt::memory_buffer b;
1271 format_to(b,
"Error on line {} of {}:\n{}\n", lineno+1, filename, message);
1272 formatInputFile(b, metadata, filename, lineno, column);
1273 return to_string(b);
1276 std::string InputFileError::formatError2(
const std::string& message,
1277 int line1,
int column1,
1278 const shared_ptr<AnyMap>& metadata1,
1279 int line2,
int column2,
1280 const shared_ptr<AnyMap>& metadata2)
1282 if (!metadata1 || !metadata2) {
1285 std::string filename1 = metadata1->getString(
"filename",
"input string");
1286 std::string filename2 = metadata2->getString(
"filename",
"input string");
1288 fmt::memory_buffer b;
1289 if (filename1 == filename2) {
1290 format_to(b,
"Error on lines {} and {} of {}:\n",
1291 std::min(line1, line2) + 1, std::max(line1, line2) + 1,
1293 format_to(b,
"{}\n", message);
1294 formatInputFile(b, metadata1, filename1, line1, column1, line2, column2);
1296 format_to(b,
"Error on line {} of {} and line {} of {}:\n{}\n",
1297 line1+1, filename1, line2+1, filename2, message);
1298 formatInputFile(b, metadata1, filename1, line1, column1);
1300 formatInputFile(b, metadata2, filename2, line2, column2);
1303 return to_string(b);
Base class defining common data possessed by both AnyMap and AnyValue objects.
const AnyValue & getMetadata(const std::string &key) const
Get a value from the metadata applicable to the AnyMap tree containing this node.
int m_column
Column where this node occurs in the input file.
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.
int m_line
Line where this node occurs in the input file.
shared_ptr< AnyMap > m_metadata
Metadata relevant to an entire AnyMap tree, such as information about.
Defined to allow use with range-based for loops.
A map of string keys to values whose type can vary at runtime.
AnyValue & operator[](const std::string &key)
Get the value of the item stored in key.
Iterator begin() const
Defined to allow use with range-based for loops.
std::unordered_map< std::string, AnyValue > m_data
The stored data.
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.
const AnyValue & at(const std::string &key) const
Get the value of the item stored in key.
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.
UnitSystem m_units
The default units that are used to convert stored values.
Iterator end() const
Defined to allow use with range-based for loops.
const std::string & getString(const std::string &key, const std::string &default_) const
If key exists, return it as a string, otherwise return default_.
bool getBool(const std::string &key, bool default_) const
If key exists, return it as a bool, otherwise return default_.
static AnyMap fromYamlFile(const std::string &name, const std::string &parent_name="")
Create an AnyMap from a YAML file.
long int getInt(const std::string &key, long int default_) const
If key exists, return it as a long int, otherwise return default_.
void erase(const std::string &key)
Erase the value held by key.
double getDouble(const std::string &key, double default_) const
If key exists, return it as a double, otherwise return default_.
void propagateMetadata(shared_ptr< AnyMap > &file)
Propagate metadata to any child elements.
std::string keys_str() const
Return a string listing the keys in this AnyMap, e.g.
static std::unordered_map< std::string, std::pair< AnyMap, int > > s_cache
Cache for previously-parsed input (YAML) files.
void clear()
Erase all items in the mapping.
static AnyMap fromYamlString(const std::string &yaml)
Create an AnyMap from a string containing a YAML document.
bool hasKey(const std::string &key) const
Returns true if the map contains an item named key.
const UnitSystem & units() const
Return the default units that should be used to convert stored values.
void applyUnits(const UnitSystem &units)
Use the supplied UnitSystem to set the default units, and recursively process overrides from nodes na...
void setMetadata(const std::string &key, const AnyValue &value)
Set a metadata value that applies to this AnyMap and its children.
A wrapper for a variable whose type is determined at runtime.
AnyValue & operator[](const std::string &key)
If this AnyValue is an AnyMap, return the value stored in key.
bool hasMapWhere(const std::string &key, const std::string &value) const
Returns true when getMapWhere() would succeed.
void setKey(const std::string &key)
Set the name of the key storing this value in an AnyMap.
std::unique_ptr< boost::any > m_value
The held value.
const std::string & asString() const
Return the held value, if it is a string.
bool & asBool()
Return the held value, if it is a bool.
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.
static std::map< std::string, std::string > s_typenames
Human-readable names for some common types, for use when boost::demangle is not available.
long int & asInt()
Return the held value, if it is a long int.
const std::type_info & type() const
Returns the type of the held value.
double & asDouble()
Return the held value as a double, if it is a double or a long int.
bool isScalar() const
Returns true if the held value is a scalar type (e.g.
std::string type_str() const
Returns a string specifying the type of the held value.
void propagateMetadata(shared_ptr< AnyMap > &file)
Propagate metadata to any child elements.
std::string m_key
Key of this value in a parent AnyMap
bool is() const
Returns true if the held value is of the specified type.
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.
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.
std::map< std::string, T > asMap() const
Return the held AnyMap as a std::map where all of the values have the specified type.
void applyUnits(const UnitSystem &units)
const T & as() const
Get the value of this key as the specified type.
Base class for exceptions thrown by Cantera classes.
An error indicating that an unimplemented function has been called.
double convert(double value, const std::string &src, const std::string &dest) const
Convert value from the units of src to the units of dest.
void setDefaults(std::initializer_list< std::string > units)
Set the default units to convert from when explicit units are not provided.
A representation of the units associated with a dimensional quantity.
const size_t npos
index returned by functions to indicate "no position"
std::vector< double > vector_fp
Turn on the use of stl vectors for the basic array type within cantera Vector of doubles.
Namespace for the Cantera kernel.
doublereal fpValue(const std::string &val)
Translate a string into one doublereal value.
Contains declarations for string manipulation functions within Cantera.