From a32e32b7d7068b3494d1ad420c9b2a79a9c25bfb Mon Sep 17 00:00:00 2001 From: Ray Speth Date: Fri, 21 Dec 2018 17:48:16 -0500 Subject: [PATCH] Remove AnyMap traversal using "/" as a path delimiter This feature was unused, and interfered with the use of "/" as a delimiter for YAML keys indicating keys in other input files. --- include/cantera/base/AnyMap.h | 2 - src/base/AnyMap.cpp | 78 ++++++-------------------------- test/general/test_containers.cpp | 48 ++++++++++---------- 3 files changed, 39 insertions(+), 89 deletions(-) diff --git a/include/cantera/base/AnyMap.h b/include/cantera/base/AnyMap.h index 332a01843..dab7240c1 100644 --- a/include/cantera/base/AnyMap.h +++ b/include/cantera/base/AnyMap.h @@ -166,8 +166,6 @@ std::vector& AnyValue::asVector(size_t nMin, size_t nMax); * // Create a nested AnyMap named "beans" which has a key named "baked" * // whose value is a vector * std::vector v{3.14, 1.59, 2.65}; - * breakfast["beans/baked"] = v; - * // Equivalently: * breakfast["beans"]["baked"] = v; * * // Create a nested AnyMap with values of the same type diff --git a/src/base/AnyMap.cpp b/src/base/AnyMap.cpp index 1847531bc..e32e9ea89 100644 --- a/src/base/AnyMap.cpp +++ b/src/base/AnyMap.cpp @@ -545,50 +545,24 @@ std::vector& AnyValue::asVector(size_t nMin, size_t nMax) AnyValue& AnyMap::operator[](const std::string& key) { - const auto& slash = boost::ifind_first(key, "/"); - if (!slash) { - // Simple key - const auto& iter = m_data.find(key); - if (iter == m_data.end()) { - // Create a new key return it - // NOTE: 'insert' can be replaced with 'emplace' after support for - // G++ 4.7 is dropped. - AnyValue& value = m_data.insert({key, AnyValue()}).first->second; - value.setKey(key); - return value; - } else { - // Return an already-existing item - return iter->second; - } + const auto& iter = m_data.find(key); + if (iter == m_data.end()) { + // Create a new key return it + // NOTE: 'insert' can be replaced with 'emplace' after support for + // G++ 4.7 is dropped. + AnyValue& value = m_data.insert({key, AnyValue()}).first->second; + value.setKey(key); + return value; } else { - // Split the first slash-delimited part of key and recurse - std::string head(key.begin(), slash.begin()); - std::string tail(slash.end(), key.end()); - const auto& iter = m_data.find(head); - if (iter == m_data.end()) { - // Create a new key - AnyValue& value = m_data.insert({head, AnyValue()}).first->second; - value = AnyMap(); - value.setKey(head); - return value.as()[tail]; - } else { - // Return an already existing key - return iter->second.as()[tail]; - } + // Return an already-existing item + return iter->second; } } const AnyValue& AnyMap::at(const std::string& key) const { - const auto& slash = boost::ifind_first(key, "/"); try { - if (!slash) { - return m_data.at(key); - } else { - std::string head(key.begin(), slash.begin()); - std::string tail(slash.end(), key.end()); - return m_data.at(head).as().at(tail); - } + return m_data.at(key); } catch (std::out_of_range& err) { throw CanteraError("AnyMap::at", "Key '{}' not found", key); } @@ -596,39 +570,17 @@ const AnyValue& AnyMap::at(const std::string& key) const bool AnyMap::hasKey(const std::string& key) const { - const auto& slash = boost::ifind_first(key, "/"); - if (!slash) { - return (m_data.find(key) != m_data.end()); - } else { - std::string head(key.begin(), slash.begin()); - std::string tail(slash.end(), key.end()); - if (m_data.find(head) == m_data.end() || !m_data.at(head).is()) { - return false; - } else { - return m_data.at(head).as().hasKey(tail); - } - } + return (m_data.find(key) != m_data.end()); } template const T& AnyMap::get(const std::string& key, const T& default_, std::function getter) const { - const auto& slash = boost::ifind_first(key, "/"); - if (!slash) { - if (m_data.find(key) != m_data.end()) { - return getter(&m_data.at(key)); - } else { - return default_; - } + if (m_data.find(key) != m_data.end()) { + return getter(&m_data.at(key)); } else { - std::string head(key.begin(), slash.begin()); - std::string tail(slash.end(), key.end()); - if (m_data.find(head) == m_data.end() || !m_data.at(head).is()) { - return default_; - } else { - return m_data.at(head).as().get(tail, default_, getter); - } + return default_; } } diff --git a/test/general/test_containers.cpp b/test/general/test_containers.cpp index 02ce1eab5..680dc530b 100644 --- a/test/general/test_containers.cpp +++ b/test/general/test_containers.cpp @@ -27,28 +27,27 @@ TEST(AnyValue, is_moveable) { TEST(AnyMap, paths) { AnyMap m; m["simple"] = "qux"; - m["compound/first"] = "bar"; - m["compound/second"] = "baz"; + m["compound"]["first"] = "bar"; + m["compound"]["second"] = "baz"; m["several"]["layers"]["deep"] = "foo"; EXPECT_TRUE(m.hasKey("simple")); EXPECT_TRUE(m.hasKey("compound")); - EXPECT_TRUE(m.hasKey("compound/first")); EXPECT_TRUE(m["compound"].hasKey("second")); - EXPECT_EQ(m["compound/first"].asString(), "bar"); - EXPECT_EQ(m["compound/second"].as(), "baz"); - EXPECT_EQ(m["several/layers/deep"].asString(), "foo"); + EXPECT_EQ(m["compound"]["first"].asString(), "bar"); + EXPECT_EQ(m["compound"]["second"].as(), "baz"); + EXPECT_EQ(m["several"]["layers"]["deep"].asString(), "foo"); EXPECT_THROW(m.at("missing"), std::exception); EXPECT_FALSE(m.hasKey("missing")); - EXPECT_FALSE(m.hasKey("compound/missing")); + EXPECT_FALSE(m["compound"].hasKey("missing")); EXPECT_THROW(m["missing"].asString(), std::exception); } TEST(AnyMap, map_conversion) { AnyMap m; - m["compound/first"] = "bar"; - m["compound/second"] = "baz"; + m["compound"]["first"] = "bar"; + m["compound"]["second"] = "baz"; auto x = m["compound"].asMap(); EXPECT_EQ(x.size(), (size_t) 2); @@ -57,7 +56,7 @@ TEST(AnyMap, map_conversion) { std::map zz{{"a", 9.0}, {"b", 13.5}}; m["foo"] = zz; - EXPECT_TRUE(m.hasKey("foo/a")); + EXPECT_TRUE(m["foo"].hasKey("a")); EXPECT_DOUBLE_EQ(m["foo"]["b"].asDouble(), 13.5); EXPECT_THROW(m["foo"]["a"].asString(), CanteraError); @@ -79,9 +78,9 @@ TEST(AnyMap, nested) b["qux"] = 0.5; m["baz"] = b; b["late"] = "nope"; // Should have added a copy - EXPECT_EQ(m["baz/foo"].asString(), "bar"); + EXPECT_EQ(m["baz"]["foo"].asString(), "bar"); EXPECT_EQ(m["baz"]["qux"].asDouble(), 0.5); - EXPECT_FALSE(m.hasKey("baz/late")); + EXPECT_FALSE(m["baz"].hasKey("late")); } TEST(AnyMap, vector) @@ -89,11 +88,11 @@ TEST(AnyMap, vector) AnyMap m; vector_fp yy{9.6, 14.4, 28.8}; m["nested"]["item"] = yy; - vector_fp& yref = m["nested/item"].asVector(); + vector_fp& yref = m["nested"]["item"].asVector(); yref.push_back(-1); EXPECT_EQ(yy.size(), (size_t) 3); // Should have added a copy // Should have modified the copy in the map - EXPECT_EQ(m["nested/item"].asVector().size(), (size_t) 4); + EXPECT_EQ(m["nested"]["item"].asVector().size(), (size_t) 4); } TEST(AnyMap, vector_length) @@ -113,7 +112,7 @@ TEST(AnyMap, getters_with_defaults) AnyMap m; std::map zz{{"a", 9.0}, {"b", 13.5}}; m["foo"] = zz; - m["foo/c"] = 4; + m["foo"]["c"] = 4; m["bar"] = "baz"; m["qux"] = false; EXPECT_FALSE(m.getBool("qux", true)); @@ -121,9 +120,10 @@ TEST(AnyMap, getters_with_defaults) EXPECT_EQ(m.getString("missing", "hi"), "hi"); EXPECT_EQ(m.getString("bar", "hi"), "baz"); EXPECT_EQ(m.getInt("missing", 3), 3); - EXPECT_EQ(m.getInt("foo/c", 3), 4); - EXPECT_EQ(m.getDouble("foo/missing", 3), 3); - EXPECT_EQ(m.getDouble("foo/b", 3), 13.5); + auto& f = m["foo"].as(); + EXPECT_EQ(f.getInt("c", 3), 4); + EXPECT_EQ(f.getDouble("missing", 3), 3); + EXPECT_EQ(f.getDouble("b", 3), 13.5); } TEST(AnyMap, conversion_to_double) @@ -189,12 +189,12 @@ TEST(AnyMap, loadYaml) " flag: true\n"); EXPECT_EQ(m["name"].asString(), "NO2"); - EXPECT_EQ(m["composition/N"].asInt(), 1); - EXPECT_EQ(m["thermo/reference-pressure"].asString(), "1 atm"); - EXPECT_EQ(m["thermo/temperature-ranges"].asVector()[0], 200); - EXPECT_EQ(m["transport/geometry"].asString(), "nonlinear"); - EXPECT_TRUE(m["transport/flag"].asBool()); - auto coeffs = m["thermo/data"].asVector(); + EXPECT_EQ(m["composition"]["N"].asInt(), 1); + EXPECT_EQ(m["thermo"]["reference-pressure"].asString(), "1 atm"); + EXPECT_EQ(m["thermo"]["temperature-ranges"].asVector()[0], 200); + EXPECT_EQ(m["transport"]["geometry"].asString(), "nonlinear"); + EXPECT_TRUE(m["transport"]["flag"].asBool()); + auto coeffs = m["thermo"]["data"].asVector(); EXPECT_EQ(coeffs.size(), (size_t) 2); EXPECT_EQ(coeffs[0].size(), (size_t) 7); EXPECT_DOUBLE_EQ(coeffs[1][2], -8.280690600E-07);