11string demangle(
const std::type_info& type);
18 if (
typeid(T) ==
typeid(
double) &&
m_value.type() ==
typeid(
long int)) {
20 const_cast<AnyValue*
>(
this)->
m_value =
static_cast<double>(as<long int>());
21 m_equals = eq_comparer<double>;
22 }
else if (
typeid(T) ==
typeid(string) &&
m_value.type() ==
typeid(double)) {
25 m_equals = eq_comparer<string>;
26 }
else if (
typeid(T) ==
typeid(string) &&
m_value.type() ==
typeid(
long int)) {
28 const_cast<AnyValue*
>(
this)->
m_value = fmt::format(
"{}", as<long int>());
29 m_equals = eq_comparer<string>;
30 }
else if (
typeid(T) ==
typeid(vector<double>)
31 &&
m_value.type() ==
typeid(vector<AnyValue>)) {
33 auto& asAny = as<vector<AnyValue>>();
34 vector<double>
asDouble(asAny.size());
35 for (
size_t i = 0; i < asAny.size(); i++) {
39 m_equals = eq_comparer<vector<double>>;
41 return std::any_cast<const T&>(
m_value);
42 }
catch (std::bad_any_cast&) {
43 if (
m_value.type() ==
typeid(
void)) {
46 "Key '{}' not found or contains no value",
m_key);
50 "Unable to convert '{}' to '{}'.",
54 "Key '{}' contains a '{}',\nnot a '{}'",
64 return const_cast<T&
>(
const_cast<const AnyValue*
>(
this)->as<T>());
69 return m_value.type() ==
typeid(T);
72template<>
bool AnyValue::is<vector<double>>()
const;
76 return m_value.type() ==
typeid(vector<T>);
81 if (
m_value.type() !=
typeid(vector<vector<T>>)) {
85 auto& asMatrix = as<vector<vector<T>>>();
86 if (!asMatrix.size()) {
91 cols = asMatrix[0].size();
93 for (
const auto& row : asMatrix) {
94 if (row.size() != cols) {
102AnyValue &AnyValue::operator=(
const vector<T> &value) {
104 m_equals = eq_comparer<vector<T>>;
110 const auto& v = as<vector<T>>();
111 checkSize(v, nMin, nMax);
117 auto& v = as<vector<T>>();
118 checkSize(v, nMin, nMax);
123AnyValue& AnyValue::operator=(
const std::unordered_map<string, T> items) {
125 m_equals = eq_comparer<AnyMap>;
126 AnyMap& dest = as<AnyMap>();
127 for (
const auto& [key, value] : items) {
134AnyValue& AnyValue::operator=(
const map<string, T> items) {
136 m_equals = eq_comparer<AnyMap>;
137 AnyMap& dest = as<AnyMap>();
138 for (
const auto& [key, value] : items) {
145inline AnyMap& AnyValue::as<AnyMap>() {
149 if (
m_value.type() ==
typeid(
void)) {
151 m_equals = eq_comparer<AnyMap>;
153 return std::any_cast<AnyMap&>(
m_value);
154 }
catch (std::bad_any_cast&) {
155 throw InputFileError(
"AnyValue::as", *
this,
156 "value of key '{}' is a '{}',\nnot an 'AnyMap'.",
165 for (
const auto& item : as<AnyMap>()) {
166 dest[item.first] = item.second.as<T>();
172void AnyValue::checkSize(
const vector<T>& v,
size_t nMin,
size_t nMax)
const
174 if (nMin !=
npos && nMax ==
npos && v.size() != nMin) {
176 "Expected array '{}' to have length {}, but found "
177 "an array of length {}.",
m_key, nMin, v.size());
178 }
else if (nMin !=
npos && nMax !=
npos
179 && (v.size() < nMin || v.size() > nMax)) {
180 throw InputFileError(
"AnyValue::checkSize", *
this,
181 "Expected array '{}' to have from {} to {} elements, but found "
182 "an array of length {}.",
m_key, nMin, nMax, v.size());
186template<
class T,
class U>
189 const auto& lvec = std::any_cast<T>(lhs);
190 const auto& rvec = std::any_cast<U>(rhs);
191 if (lvec.size() != rvec.size()) {
194 return std::equal(lvec.begin(), lvec.end(), rvec.begin());
198template<
class T,
class U>
201 const auto& lvec = std::any_cast<vector<T>>(lhs);
202 const auto& rvec = std::any_cast<vector<U>>(rhs);
203 if (lvec.size() != rvec.size()) {
206 for (
size_t i = 0; i < lvec.size(); i++) {
207 if (!std::equal(lvec[i].begin(), lvec[i].end(), rvec[i].begin())) {
219 typedef vector<double> vd;
220 typedef vector<long int> vi;
221 typedef vector<AnyValue> va;
222 typedef vector<string> vs;
224 auto& ltype = lhs.type();
225 auto& rtype = rhs.type();
227 "AnyValue::eq_comparer",
"Compare function does not match held type");
229 if (ltype == rtype) {
230 return any_cast<T>(lhs) == any_cast<T>(rhs);
231 }
else if (ltype ==
typeid(
double) && rtype ==
typeid(
long int)) {
232 return any_cast<double>(lhs) == any_cast<long int>(rhs);
233 }
else if (ltype ==
typeid(
long int) && rtype ==
typeid(
double)) {
234 return any_cast<long int>(lhs) == any_cast<double>(rhs);
236 }
else if (ltype ==
typeid(vd) && rtype ==
typeid(vi)) {
237 return vector_eq<vd, vi>(lhs, rhs);
238 }
else if (ltype ==
typeid(vi) && rtype ==
typeid(vd)) {
239 return vector_eq<vi, vd>(lhs, rhs);
241 }
else if (ltype ==
typeid(va)) {
242 if (rtype ==
typeid(vd)) {
243 return vector_eq<va, vd>(lhs, rhs);
244 }
else if (rtype ==
typeid(vi)) {
245 return vector_eq<va, vi>(lhs, rhs);
246 }
else if (rtype ==
typeid(vs)) {
247 return vector_eq<va, vs>(lhs, rhs);
249 }
else if (rtype ==
typeid(va)) {
250 if (ltype ==
typeid(vd)) {
251 return vector_eq<vd, va>(lhs, rhs);
252 }
else if (ltype ==
typeid(vi)) {
253 return vector_eq<vi, va>(lhs, rhs);
254 }
else if (ltype ==
typeid(vs)) {
255 return vector_eq<vs, va>(lhs, rhs);
257 }
else if (ltype ==
typeid(vector<vd>) && rtype ==
typeid(vector<vi>)) {
258 return vector2_eq<vd, vi>(lhs, rhs);
259 }
else if (ltype ==
typeid(vector<vi>) && rtype ==
typeid(vector<vd>)) {
260 return vector2_eq<vd, vi>(lhs, rhs);
A wrapper for a variable whose type is determined at runtime.
bool isVector() const
Returns true if the held value is a vector of the specified type, such as vector<double>.
map< string, T > asMap() const
Return the held AnyMap as a map where all of the values have the specified type.
static bool vector2_eq(const std::any &lhs, const std::any &rhs)
Helper function for comparing nested vectors of different (but comparable) types, for example vector<...
bool isMatrix(size_t cols=npos) const
Returns true if the held value is a matrix of the specified type and a consistent number of columns,...
static bool eq_comparer(const std::any &lhs, const std::any &rhs)
Equality comparison function used when lhs is of type T
double & asDouble()
Return the held value as a double, if it is a double or a long int.
string m_key
Key of this value in a parent AnyMap
std::any m_value
The held value.
bool is() const
Returns true if the held value is of the specified type.
const 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 bool vector_eq(const std::any &lhs, const std::any &rhs)
Helper function for comparing vectors of different (but comparable) types, for example vector<double>...
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.
string demangle(const std::type_info &type)
Convert a type name to a human readable string, using boost::core::demangle if available.
Namespace for the Cantera kernel.
const size_t npos
index returned by functions to indicate "no position"