8#include <boost/any.hpp>
9#include <boost/algorithm/string.hpp>
14std::string
demangle(
const std::type_info& type);
21 if (
typeid(T) ==
typeid(
double) &&
m_value->type() ==
typeid(
long int)) {
23 *
m_value =
static_cast<double>(as<long int>());
24 m_equals = eq_comparer<double>;
25 }
else if (
typeid(T) ==
typeid(std::vector<double>)
26 &&
m_value->type() ==
typeid(std::vector<AnyValue>)) {
28 auto& asAny = as<std::vector<AnyValue>>();
30 for (
size_t i = 0; i < asAny.size(); i++) {
34 m_equals = eq_comparer<std::vector<double>>;
36 return boost::any_cast<const T&>(*
m_value);
37 }
catch (boost::bad_any_cast&) {
38 if (
m_value->type() ==
typeid(
void)) {
41 "Key '{}' not found or contains no value",
m_key);
44 "Key '{}' contains a '{}',\nnot a '{}'",
54 return const_cast<T&
>(
const_cast<const AnyValue*
>(
this)->as<T>());
59 return m_value->type() ==
typeid(T);
62template<>
bool AnyValue::is<std::vector<double>>()
const;
65AnyValue &AnyValue::operator=(
const std::vector<T> &value) {
67 m_equals = eq_comparer<std::vector<T>>;
73 const auto& v = as<std::vector<T>>();
74 checkSize(v, nMin, nMax);
80 auto& v = as<std::vector<T>>();
81 checkSize(v, nMin, nMax);
86AnyValue& AnyValue::operator=(
const std::unordered_map<std::string, T> items) {
88 m_equals = eq_comparer<AnyMap>;
89 AnyMap& dest = as<AnyMap>();
90 for (
const auto& item : items) {
91 dest[item.first] = item.second;
97AnyValue& AnyValue::operator=(
const std::map<std::string, T> items) {
99 m_equals = eq_comparer<AnyMap>;
100 AnyMap& dest = as<AnyMap>();
101 for (
const auto& item : items) {
102 dest[item.first] = item.second;
108inline AnyMap& AnyValue::as<AnyMap>() {
112 if (
m_value->type() ==
typeid(
void)) {
114 m_equals = eq_comparer<AnyMap>;
116 return boost::any_cast<AnyMap&>(*
m_value);
117 }
catch (boost::bad_any_cast&) {
118 throw InputFileError(
"AnyValue::as", *
this,
119 "value of key '{}' is a '{}',\nnot an 'AnyMap'.",
127 std::map<std::string, T> dest;
128 for (
const auto& item : as<AnyMap>()) {
129 dest[item.first] = item.second.as<T>();
135void AnyValue::checkSize(
const std::vector<T>& v,
size_t nMin,
size_t nMax)
const
137 if (nMin !=
npos && nMax ==
npos && v.size() != nMin) {
139 "Expected array '{}' to have length {}, but found "
140 "an array of length {}.",
m_key, nMin, v.size());
141 }
else if (nMin !=
npos && nMax !=
npos
142 && (v.size() < nMin || v.size() > nMax)) {
143 throw InputFileError(
"AnyValue::checkSize", *
this,
144 "Expected array '{}' to have from {} to {} elements, but found "
145 "an array of length {}.",
m_key, nMin, nMax, v.size());
149template<
class T,
class U>
152 const auto& lvec = boost::any_cast<T>(lhs);
153 const auto& rvec = boost::any_cast<U>(rhs);
154 if (lvec.size() != rvec.size()) {
157 return std::equal(lvec.begin(), lvec.end(), rvec.begin());
161template<
class T,
class U>
164 const auto& lvec = boost::any_cast<std::vector<T>>(lhs);
165 const auto& rvec = boost::any_cast<std::vector<U>>(rhs);
166 if (lvec.size() != rvec.size()) {
169 for (
size_t i = 0; i < lvec.size(); i++) {
170 if (!std::equal(lvec[i].begin(), lvec[i].end(), rvec[i].begin())) {
181 using boost::any_cast;
183 typedef vector<double> vd;
184 typedef vector<long int> vi;
185 typedef vector<AnyValue> va;
186 typedef vector<std::string> vs;
188 auto& ltype = lhs.type();
189 auto& rtype = rhs.type();
191 "AnyValue::eq_comparer",
"Compare function does not match held type");
193 if (ltype == rtype) {
194 return any_cast<T>(lhs) == any_cast<T>(rhs);
195 }
else if (ltype ==
typeid(
double) && rtype ==
typeid(
long int)) {
196 return any_cast<double>(lhs) == any_cast<long int>(rhs);
197 }
else if (ltype ==
typeid(
long int) && rtype ==
typeid(
double)) {
198 return any_cast<long int>(lhs) == any_cast<double>(rhs);
200 }
else if (ltype ==
typeid(vd) && rtype ==
typeid(vi)) {
201 return vector_eq<vd, vi>(lhs, rhs);
202 }
else if (ltype ==
typeid(vi) && rtype ==
typeid(vd)) {
203 return vector_eq<vi, vd>(lhs, rhs);
205 }
else if (ltype ==
typeid(va)) {
206 if (rtype ==
typeid(vd)) {
207 return vector_eq<va, vd>(lhs, rhs);
208 }
else if (rtype ==
typeid(vi)) {
209 return vector_eq<va, vi>(lhs, rhs);
210 }
else if (rtype ==
typeid(vs)) {
211 return vector_eq<va, vs>(lhs, rhs);
213 }
else if (rtype ==
typeid(va)) {
214 if (ltype ==
typeid(vd)) {
215 return vector_eq<vd, va>(lhs, rhs);
216 }
else if (ltype ==
typeid(vi)) {
217 return vector_eq<vi, va>(lhs, rhs);
218 }
else if (ltype ==
typeid(vs)) {
219 return vector_eq<vs, va>(lhs, rhs);
221 }
else if (ltype ==
typeid(vector<vd>) && rtype ==
typeid(vector<vi>)) {
222 return vector2_eq<vd, vi>(lhs, rhs);
223 }
else if (ltype ==
typeid(vector<vi>) && rtype ==
typeid(vector<vd>)) {
224 return vector2_eq<vd, vi>(lhs, rhs);
A wrapper for a variable whose type is determined at runtime.
std::unique_ptr< boost::any > m_value
The held value.
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.
double & asDouble()
Return the held value as a double, if it is a double or a long int.
static bool eq_comparer(const boost::any &lhs, const boost::any &rhs)
Equality comparison function used when lhs is of type T
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<...
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>...
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.
std::map< std::string, T > asMap() const
Return the held AnyMap as a std::map where all of the values have the specified type.
const T & as() const
Get the value of this key as the specified type.
#define AssertThrowMsg(expr, procedure,...)
Assertion must be true or an error is thrown.
Namespace for the Cantera kernel.
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.
std::string demangle(const std::type_info &type)
Convert a type name to a human readable string, using boost::core::demangle if available.