3 #ifndef CT_ANYMAP_INL_H
4 #define CT_ANYMAP_INL_H
8 #include <boost/any.hpp>
9 #include <boost/algorithm/string.hpp>
19 if (
typeid(T) ==
typeid(
double) &&
m_value->type() ==
typeid(
long int)) {
21 *
m_value =
static_cast<double>(as<long int>());
22 m_equals = eq_comparer<double>;
24 return boost::any_cast<const T&>(*
m_value);
25 }
catch (boost::bad_any_cast&) {
26 if (
m_value->type() ==
typeid(
void)) {
29 "Key '{}' not found or contains no value",
m_key);
32 "Key '{}' contains a '{}',\nnot a '{}'",
41 if (
typeid(T) ==
typeid(
double) &&
m_value->type() ==
typeid(
long int)) {
43 *
m_value =
static_cast<double>(as<long int>());
44 m_equals = eq_comparer<double>;
46 return boost::any_cast<T&>(*
m_value);
47 }
catch (boost::bad_any_cast&) {
48 if (
m_value->type() ==
typeid(
void)) {
50 throw InputFileError(
"AnyValue::as", *
this,
51 "Key '{}' not found or contains no value",
m_key);
53 throw InputFileError(
"AnyValue::as", *
this,
54 "Key '{}' contains a '{}',\nnot a '{}'",
62 return m_value->type() ==
typeid(T);
66 AnyValue &AnyValue::operator=(
const std::vector<T> &value) {
68 m_equals = eq_comparer<std::vector<T>>;
74 const auto& v = as<std::vector<T>>();
75 checkSize(v, nMin, nMax);
81 auto& v = as<std::vector<T>>();
82 checkSize(v, nMin, nMax);
87 AnyValue& AnyValue::operator=(
const std::unordered_map<std::string, T> items) {
89 m_equals = eq_comparer<AnyMap>;
90 AnyMap& dest = as<AnyMap>();
91 for (
const auto& item : items) {
92 dest[item.first] = item.second;
98 AnyValue& AnyValue::operator=(
const std::map<std::string, T> items) {
100 m_equals = eq_comparer<AnyMap>;
101 AnyMap& dest = as<AnyMap>();
102 for (
const auto& item : items) {
103 dest[item.first] = item.second;
109 inline AnyMap& AnyValue::as<AnyMap>() {
113 if (
m_value->type() ==
typeid(
void)) {
115 m_equals = eq_comparer<AnyMap>;
117 return boost::any_cast<AnyMap&>(*
m_value);
118 }
catch (boost::bad_any_cast&) {
119 throw InputFileError(
"AnyValue::as", *
this,
120 "value of key '{}' is a '{}',\nnot an 'AnyMap'.",
128 std::map<std::string, T> dest;
129 for (
const auto& item : as<AnyMap>()) {
130 dest[item.first] = item.second.as<T>();
136 void AnyValue::checkSize(
const std::vector<T>& v,
size_t nMin,
size_t nMax)
const
138 if (nMin !=
npos && nMax ==
npos && v.size() != nMin) {
140 "Expected array '{}' to have length {}, but found "
141 "an array of length {}.",
m_key, nMin, v.size());
142 }
else if (nMin !=
npos && nMax !=
npos
143 && (v.size() < nMin || v.size() > nMax)) {
144 throw InputFileError(
"AnyValue::checkSize", *
this,
145 "Expected array '{}' to have from {} to {} elements, but found "
146 "an array of length {}.",
m_key, nMin, nMax, v.size());
150 template<
class T,
class U>
153 const auto& lvec = boost::any_cast<T>(lhs);
154 const auto& rvec = boost::any_cast<U>(rhs);
155 if (lvec.size() != rvec.size()) {
158 return std::equal(lvec.begin(), lvec.end(), rvec.begin());
162 template<
class T,
class U>
165 const auto& lvec = boost::any_cast<std::vector<T>>(lhs);
166 const auto& rvec = boost::any_cast<std::vector<U>>(rhs);
167 if (lvec.size() != rvec.size()) {
170 for (
size_t i = 0; i < lvec.size(); i++) {
171 if (!std::equal(lvec[i].begin(), lvec[i].end(), rvec[i].begin())) {
182 using boost::any_cast;
184 typedef vector<double> vd;
185 typedef vector<long int> vi;
186 typedef vector<AnyValue> va;
187 typedef vector<std::string> vs;
189 auto& ltype = lhs.type();
190 auto& rtype = rhs.type();
192 "AnyValue::eq_comparer",
"Compare function does not match held type");
194 if (ltype == rtype) {
195 return any_cast<T>(lhs) == any_cast<T>(rhs);
196 }
else if (ltype ==
typeid(
double) && rtype ==
typeid(
long int)) {
197 return any_cast<double>(lhs) == any_cast<long int>(rhs);
198 }
else if (ltype ==
typeid(
long int) && rtype ==
typeid(
double)) {
199 return any_cast<long int>(lhs) == any_cast<double>(rhs);
201 }
else if (ltype ==
typeid(vd) && rtype ==
typeid(vi)) {
202 return vector_eq<vd, vi>(lhs, rhs);
203 }
else if (ltype ==
typeid(vi) && rtype ==
typeid(vd)) {
204 return vector_eq<vi, vd>(lhs, rhs);
206 }
else if (ltype ==
typeid(va)) {
207 if (rtype ==
typeid(vd)) {
208 return vector_eq<va, vd>(lhs, rhs);
209 }
else if (rtype ==
typeid(vi)) {
210 return vector_eq<va, vi>(lhs, rhs);
211 }
else if (rtype ==
typeid(vs)) {
212 return vector_eq<va, vs>(lhs, rhs);
214 }
else if (rtype ==
typeid(va)) {
215 if (ltype ==
typeid(vd)) {
216 return vector_eq<vd, va>(lhs, rhs);
217 }
else if (ltype ==
typeid(vi)) {
218 return vector_eq<vi, va>(lhs, rhs);
219 }
else if (ltype ==
typeid(vs)) {
220 return vector_eq<vs, va>(lhs, rhs);
222 }
else if (ltype ==
typeid(vector<vd>) && rtype ==
typeid(vector<vi>)) {
223 return vector2_eq<vd, vi>(lhs, rhs);
224 }
else if (ltype ==
typeid(vector<vi>) && rtype ==
typeid(vector<vd>)) {
225 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.
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, e....
static bool vector_eq(const boost::any &lhs, const boost::any &rhs)
Helper function for comparing vectors of different (but comparable) types, e.g.
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.
const size_t npos
index returned by functions to indicate "no position"
Namespace for the Cantera kernel.