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>
|
template<class T>
|
||||||
AnyValue& operator=(const std::vector<T>& value);
|
AnyValue& operator=(const std::vector<T>& value);
|
||||||
template<class T>
|
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>
|
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=(const AnyMap& value);
|
||||||
AnyValue& operator=(AnyMap&& value);
|
AnyValue& operator=(AnyMap&& value);
|
||||||
|
|
@ -105,6 +105,9 @@ public:
|
||||||
private:
|
private:
|
||||||
std::string demangle(const std::type_info& type) const;
|
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::string m_key;
|
||||||
std::unique_ptr<boost::any> m_value;
|
std::unique_ptr<boost::any> m_value;
|
||||||
static std::map<std::string, std::string> s_typenames;
|
static std::map<std::string, std::string> s_typenames;
|
||||||
|
|
@ -112,24 +115,24 @@ private:
|
||||||
|
|
||||||
// Implicit conversion to vector<AnyValue>
|
// Implicit conversion to vector<AnyValue>
|
||||||
template<>
|
template<>
|
||||||
const std::vector<AnyValue>& AnyValue::asVector<AnyValue>() const;
|
const std::vector<AnyValue>& AnyValue::asVector<AnyValue>(size_t nMin, size_t nMax) const;
|
||||||
|
|
||||||
template<>
|
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>
|
// Implicit conversion of long int to double if accessed as a vector<double>
|
||||||
template<>
|
template<>
|
||||||
const std::vector<double>& AnyValue::asVector<double>() const;
|
const std::vector<double>& AnyValue::asVector<double>(size_t nMin, size_t nMax) const;
|
||||||
|
|
||||||
template<>
|
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>>
|
// Implicit conversion of long int to double if accessed as a vector<vector<double>>
|
||||||
template<>
|
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<>
|
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
|
//! 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>
|
template<class T>
|
||||||
const std::vector<T> &AnyValue::asVector() const {
|
const std::vector<T> &AnyValue::asVector(size_t nMin, size_t nMax) const {
|
||||||
return as<std::vector<T>>();
|
const auto& v = as<std::vector<T>>();
|
||||||
|
checkSize(v, nMin, nMax);
|
||||||
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
std::vector<T> &AnyValue::asVector() {
|
std::vector<T> &AnyValue::asVector(size_t nMin, size_t nMax) {
|
||||||
return as<std::vector<T>>();
|
auto& v = as<std::vector<T>>();
|
||||||
|
checkSize(v, nMin, nMax);
|
||||||
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
|
|
@ -120,5 +124,20 @@ std::map<std::string, T> AnyValue::asMap() const
|
||||||
return dest;
|
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
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -377,7 +377,7 @@ std::string AnyValue::demangle(const std::type_info& type) const
|
||||||
// Explicit template specializations to allow certain conversions
|
// Explicit template specializations to allow certain conversions
|
||||||
|
|
||||||
template<>
|
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>>()) {
|
if (!is<std::vector<AnyValue>>()) {
|
||||||
std::vector<AnyValue> v;
|
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,
|
// If none of these special cases match, the value won't be replaced,
|
||||||
// and an exception will be thrown.
|
// 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<>
|
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>());
|
const_cast<const AnyValue*>(this)->asVector<AnyValue>());
|
||||||
|
checkSize(v, nMin, nMax);
|
||||||
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<>
|
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>>()) {
|
if (is<std::vector<long int>>()) {
|
||||||
std::vector<double> v;
|
std::vector<double> v;
|
||||||
|
|
@ -420,11 +424,13 @@ const std::vector<double>& AnyValue::asVector<double>() const
|
||||||
}
|
}
|
||||||
*m_value = v;
|
*m_value = v;
|
||||||
}
|
}
|
||||||
return as<std::vector<double>>();
|
const auto& vv = as<std::vector<double>>();
|
||||||
|
checkSize(vv, nMin, nMax);
|
||||||
|
return vv;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<>
|
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>>()) {
|
if (is<std::vector<long int>>()) {
|
||||||
std::vector<double> v;
|
std::vector<double> v;
|
||||||
|
|
@ -433,11 +439,13 @@ std::vector<double>& AnyValue::asVector<double>()
|
||||||
}
|
}
|
||||||
*m_value = v;
|
*m_value = v;
|
||||||
}
|
}
|
||||||
return as<std::vector<double>>();
|
auto& vv = as<std::vector<double>>();
|
||||||
|
checkSize(vv, nMin, nMax);
|
||||||
|
return vv;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<>
|
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>>>()) {
|
if (is<std::vector<std::vector<long int>>>()) {
|
||||||
std::vector<vector_fp> v;
|
std::vector<vector_fp> v;
|
||||||
|
|
@ -449,11 +457,13 @@ const std::vector<vector_fp>& AnyValue::asVector<vector_fp>() const
|
||||||
}
|
}
|
||||||
*m_value = v;
|
*m_value = v;
|
||||||
}
|
}
|
||||||
return as<std::vector<vector_fp>>();
|
const auto& vv = as<std::vector<vector_fp>>();
|
||||||
|
checkSize(vv, nMin, nMax);
|
||||||
|
return vv;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<>
|
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>>>()) {
|
if (is<std::vector<std::vector<long int>>>()) {
|
||||||
std::vector<vector_fp> v;
|
std::vector<vector_fp> v;
|
||||||
|
|
@ -465,7 +475,9 @@ std::vector<vector_fp>& AnyValue::asVector<vector_fp>()
|
||||||
}
|
}
|
||||||
*m_value = v;
|
*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;
|
len_dim += pressure_dependence * reaction_phase_ndim;
|
||||||
quantity_dim -= pressure_dependence;
|
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 A = units.convert(rate_vec[0], Units(1.0, 0, len_dim, -1, 0, 0, quantity_dim));
|
||||||
double b = rate_vec[1].asDouble();
|
double b = rate_vec[1].asDouble();
|
||||||
double Ta = units.convertMolarEnergy(rate_vec[2], "K");
|
double Ta = units.convertMolarEnergy(rate_vec[2], "K");
|
||||||
|
|
@ -671,7 +671,7 @@ void setupPlogReaction(PlogReaction& R, const AnyMap& node,
|
||||||
setupReaction(R, node);
|
setupReaction(R, node);
|
||||||
std::multimap<double, Arrhenius> rates;
|
std::multimap<double, Arrhenius> rates;
|
||||||
for (const auto& rate : node.at("rate-constants").asVector<AnyValue>()) {
|
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"),
|
rates.insert({units.convert(p_rate[0], "Pa"),
|
||||||
readArrhenius(R, p_rate[1], kin, units)});
|
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);
|
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)
|
TEST(AnyMap, getters_with_defaults)
|
||||||
{
|
{
|
||||||
AnyMap m;
|
AnyMap m;
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue