Add optional length check when converting AnyValue to vector
This commit is contained in:
parent
24d1e86440
commit
7a97ff9917
5 changed files with 72 additions and 26 deletions
|
|
@ -86,9 +86,9 @@ public:
|
|||
template<class T>
|
||||
AnyValue& operator=(const std::vector<T>& value);
|
||||
template<class T>
|
||||
const std::vector<T>& asVector() const;
|
||||
const std::vector<T>& asVector(size_t nMin=npos, size_t nMax=npos) const;
|
||||
template<class T>
|
||||
std::vector<T>& asVector();
|
||||
std::vector<T>& asVector(size_t nMin=npos, size_t nMax=npos);
|
||||
|
||||
AnyValue& operator=(const AnyMap& value);
|
||||
AnyValue& operator=(AnyMap&& value);
|
||||
|
|
@ -105,6 +105,9 @@ public:
|
|||
private:
|
||||
std::string demangle(const std::type_info& type) const;
|
||||
|
||||
template<class T>
|
||||
void checkSize(const std::vector<T>& v, size_t nMin, size_t nMax) const;
|
||||
|
||||
std::string m_key;
|
||||
std::unique_ptr<boost::any> m_value;
|
||||
static std::map<std::string, std::string> s_typenames;
|
||||
|
|
@ -112,24 +115,24 @@ private:
|
|||
|
||||
// Implicit conversion to vector<AnyValue>
|
||||
template<>
|
||||
const std::vector<AnyValue>& AnyValue::asVector<AnyValue>() const;
|
||||
const std::vector<AnyValue>& AnyValue::asVector<AnyValue>(size_t nMin, size_t nMax) const;
|
||||
|
||||
template<>
|
||||
std::vector<AnyValue>& AnyValue::asVector<AnyValue>();
|
||||
std::vector<AnyValue>& AnyValue::asVector<AnyValue>(size_t nMin, size_t nMax);
|
||||
|
||||
// Implicit conversion of long int to double if accessed as a vector<double>
|
||||
template<>
|
||||
const std::vector<double>& AnyValue::asVector<double>() const;
|
||||
const std::vector<double>& AnyValue::asVector<double>(size_t nMin, size_t nMax) const;
|
||||
|
||||
template<>
|
||||
std::vector<double>& AnyValue::asVector<double>();
|
||||
std::vector<double>& AnyValue::asVector<double>(size_t nMin, size_t nMax);
|
||||
|
||||
// Implicit conversion of long int to double if accessed as a vector<vector<double>>
|
||||
template<>
|
||||
const std::vector<vector_fp>& AnyValue::asVector<vector_fp>() const;
|
||||
const std::vector<vector_fp>& AnyValue::asVector<vector_fp>(size_t nMin, size_t nMax) const;
|
||||
|
||||
template<>
|
||||
std::vector<vector_fp>& AnyValue::asVector<vector_fp>();
|
||||
std::vector<vector_fp>& AnyValue::asVector<vector_fp>(size_t nMin, size_t nMax);
|
||||
|
||||
|
||||
//! A map of string keys to values whose type can vary at runtime
|
||||
|
|
|
|||
|
|
@ -65,13 +65,17 @@ AnyValue &AnyValue::operator=(const std::vector<T> &value) {
|
|||
}
|
||||
|
||||
template<class T>
|
||||
const std::vector<T> &AnyValue::asVector() const {
|
||||
return as<std::vector<T>>();
|
||||
const std::vector<T> &AnyValue::asVector(size_t nMin, size_t nMax) const {
|
||||
const auto& v = as<std::vector<T>>();
|
||||
checkSize(v, nMin, nMax);
|
||||
return v;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
std::vector<T> &AnyValue::asVector() {
|
||||
return as<std::vector<T>>();
|
||||
std::vector<T> &AnyValue::asVector(size_t nMin, size_t nMax) {
|
||||
auto& v = as<std::vector<T>>();
|
||||
checkSize(v, nMin, nMax);
|
||||
return v;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
|
|
@ -120,5 +124,20 @@ std::map<std::string, T> AnyValue::asMap() const
|
|||
return dest;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void AnyValue::checkSize(const std::vector<T>& v, size_t nMin, size_t nMax) const
|
||||
{
|
||||
if (nMin != npos && nMax == npos && v.size() != nMin) {
|
||||
throw CanteraError("AnyValue::checkSize", "Expected array '{}' "
|
||||
"to have length {}, but found an array of length {}.",
|
||||
m_key, nMin, v.size());
|
||||
} else if (nMin != npos && nMax != npos
|
||||
&& (v.size() < nMin || v.size() > nMax)) {
|
||||
throw CanteraError("AnyValue::checkSize",
|
||||
"Expected array '{}' to have from {} to {} elements, but found an "
|
||||
" array of length {}.", m_key, nMin, nMax, v.size());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -377,7 +377,7 @@ std::string AnyValue::demangle(const std::type_info& type) const
|
|||
// Explicit template specializations to allow certain conversions
|
||||
|
||||
template<>
|
||||
const std::vector<AnyValue>& AnyValue::asVector<AnyValue>() const
|
||||
const std::vector<AnyValue>& AnyValue::asVector<AnyValue>(size_t nMin, size_t nMax) const
|
||||
{
|
||||
if (!is<std::vector<AnyValue>>()) {
|
||||
std::vector<AnyValue> v;
|
||||
|
|
@ -400,18 +400,22 @@ const std::vector<AnyValue>& AnyValue::asVector<AnyValue>() const
|
|||
// If none of these special cases match, the value won't be replaced,
|
||||
// and an exception will be thrown.
|
||||
}
|
||||
return as<std::vector<AnyValue>>();
|
||||
const auto& vv = as<std::vector<AnyValue>>();
|
||||
checkSize(vv, nMin, nMax);
|
||||
return vv;
|
||||
}
|
||||
|
||||
template<>
|
||||
std::vector<AnyValue>& AnyValue::asVector<AnyValue>()
|
||||
std::vector<AnyValue>& AnyValue::asVector<AnyValue>(size_t nMin, size_t nMax)
|
||||
{
|
||||
return const_cast<std::vector<AnyValue>&>(
|
||||
auto& v = const_cast<std::vector<AnyValue>&>(
|
||||
const_cast<const AnyValue*>(this)->asVector<AnyValue>());
|
||||
checkSize(v, nMin, nMax);
|
||||
return v;
|
||||
}
|
||||
|
||||
template<>
|
||||
const std::vector<double>& AnyValue::asVector<double>() const
|
||||
const std::vector<double>& AnyValue::asVector<double>(size_t nMin, size_t nMax) const
|
||||
{
|
||||
if (is<std::vector<long int>>()) {
|
||||
std::vector<double> v;
|
||||
|
|
@ -420,11 +424,13 @@ const std::vector<double>& AnyValue::asVector<double>() const
|
|||
}
|
||||
*m_value = v;
|
||||
}
|
||||
return as<std::vector<double>>();
|
||||
const auto& vv = as<std::vector<double>>();
|
||||
checkSize(vv, nMin, nMax);
|
||||
return vv;
|
||||
}
|
||||
|
||||
template<>
|
||||
std::vector<double>& AnyValue::asVector<double>()
|
||||
std::vector<double>& AnyValue::asVector<double>(size_t nMin, size_t nMax)
|
||||
{
|
||||
if (is<std::vector<long int>>()) {
|
||||
std::vector<double> v;
|
||||
|
|
@ -433,11 +439,13 @@ std::vector<double>& AnyValue::asVector<double>()
|
|||
}
|
||||
*m_value = v;
|
||||
}
|
||||
return as<std::vector<double>>();
|
||||
auto& vv = as<std::vector<double>>();
|
||||
checkSize(vv, nMin, nMax);
|
||||
return vv;
|
||||
}
|
||||
|
||||
template<>
|
||||
const std::vector<vector_fp>& AnyValue::asVector<vector_fp>() const
|
||||
const std::vector<vector_fp>& AnyValue::asVector<vector_fp>(size_t nMin, size_t nMax) const
|
||||
{
|
||||
if (is<std::vector<std::vector<long int>>>()) {
|
||||
std::vector<vector_fp> v;
|
||||
|
|
@ -449,11 +457,13 @@ const std::vector<vector_fp>& AnyValue::asVector<vector_fp>() const
|
|||
}
|
||||
*m_value = v;
|
||||
}
|
||||
return as<std::vector<vector_fp>>();
|
||||
const auto& vv = as<std::vector<vector_fp>>();
|
||||
checkSize(vv, nMin, nMax);
|
||||
return vv;
|
||||
}
|
||||
|
||||
template<>
|
||||
std::vector<vector_fp>& AnyValue::asVector<vector_fp>()
|
||||
std::vector<vector_fp>& AnyValue::asVector<vector_fp>(size_t nMin, size_t nMax)
|
||||
{
|
||||
if (is<std::vector<std::vector<long int>>>()) {
|
||||
std::vector<vector_fp> v;
|
||||
|
|
@ -465,7 +475,9 @@ std::vector<vector_fp>& AnyValue::asVector<vector_fp>()
|
|||
}
|
||||
*m_value = v;
|
||||
}
|
||||
return as<std::vector<vector_fp>>();
|
||||
auto& vv = as<std::vector<vector_fp>>();
|
||||
checkSize(vv, nMin, nMax);
|
||||
return vv;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -314,7 +314,7 @@ Arrhenius readArrhenius(const Reaction& R, const AnyValue& rate,
|
|||
len_dim += pressure_dependence * reaction_phase_ndim;
|
||||
quantity_dim -= pressure_dependence;
|
||||
|
||||
auto& rate_vec = rate.asVector<AnyValue>();
|
||||
auto& rate_vec = rate.asVector<AnyValue>(3);
|
||||
double A = units.convert(rate_vec[0], Units(1.0, 0, len_dim, -1, 0, 0, quantity_dim));
|
||||
double b = rate_vec[1].asDouble();
|
||||
double Ta = units.convertMolarEnergy(rate_vec[2], "K");
|
||||
|
|
@ -671,7 +671,7 @@ void setupPlogReaction(PlogReaction& R, const AnyMap& node,
|
|||
setupReaction(R, node);
|
||||
std::multimap<double, Arrhenius> rates;
|
||||
for (const auto& rate : node.at("rate-constants").asVector<AnyValue>()) {
|
||||
const auto& p_rate = rate.asVector<AnyValue>();
|
||||
const auto& p_rate = rate.asVector<AnyValue>(2);
|
||||
rates.insert({units.convert(p_rate[0], "Pa"),
|
||||
readArrhenius(R, p_rate[1], kin, units)});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -96,6 +96,18 @@ TEST(AnyMap, vector)
|
|||
EXPECT_EQ(m["nested/item"].asVector<double>().size(), (size_t) 4);
|
||||
}
|
||||
|
||||
TEST(AnyMap, vector_length)
|
||||
{
|
||||
AnyMap m;
|
||||
m["foo"] = vector_fp{2.4, 9.6, 14.4, 28.8};
|
||||
// Valid lengths
|
||||
m["foo"].asVector<double>(4);
|
||||
m["foo"].asVector<double>(2, 5);
|
||||
// Invalid lengths
|
||||
EXPECT_THROW(m["foo"].asVector<double>(3), CanteraError);
|
||||
EXPECT_THROW(m["foo"].asVector<double>(5, 8), CanteraError);
|
||||
}
|
||||
|
||||
TEST(AnyMap, getters_with_defaults)
|
||||
{
|
||||
AnyMap m;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue