diff --git a/include/yaml-cpp/exceptions.h b/include/yaml-cpp/exceptions.h index 9624303..02aeb61 100644 --- a/include/yaml-cpp/exceptions.h +++ b/include/yaml-cpp/exceptions.h @@ -61,6 +61,7 @@ namespace YAML const char * const BAD_DEREFERENCE = "bad dereference"; const char * const BAD_SUBSCRIPT = "operator[] call on a scalar"; const char * const BAD_PUSHBACK = "appending to a non-sequence"; + const char * const BAD_INSERT = "inserting in a non-convertible-to-map"; const char * const UNMATCHED_GROUP_TAG = "unmatched group tag"; const char * const UNEXPECTED_END_SEQ = "unexpected end sequence token"; @@ -178,6 +179,12 @@ namespace YAML : RepresentationException(Mark::null(), ErrorMsg::BAD_PUSHBACK) {} }; + class BadInsert: public RepresentationException { + public: + BadInsert() + : RepresentationException(Mark::null(), ErrorMsg::BAD_INSERT) {} + }; + class EmitterException: public Exception { public: EmitterException(const std::string& msg_) diff --git a/include/yaml-cpp/node/detail/impl.h b/include/yaml-cpp/node/detail/impl.h index e3d17af..b04fc05 100644 --- a/include/yaml-cpp/node/detail/impl.h +++ b/include/yaml-cpp/node/detail/impl.h @@ -118,6 +118,27 @@ namespace YAML return false; } + + // map + template + inline void node_data::force_insert(const Key& key, const Value& value, shared_memory_holder pMemory) + { + switch(m_type) { + case NodeType::Map: + break; + case NodeType::Undefined: + case NodeType::Null: + case NodeType::Sequence: + convert_to_map(pMemory); + break; + case NodeType::Scalar: + throw BadInsert(); + } + + node& k = convert_to_node(key, pMemory); + node& v = convert_to_node(value, pMemory); + insert_map_pair(k, v); + } template inline bool node_data::equals(node& node, const T& rhs, shared_memory_holder pMemory) diff --git a/include/yaml-cpp/node/detail/node.h b/include/yaml-cpp/node/detail/node.h index 846e279..ce3a76d 100644 --- a/include/yaml-cpp/node/detail/node.h +++ b/include/yaml-cpp/node/detail/node.h @@ -115,6 +115,10 @@ namespace YAML } bool remove(node& key, shared_memory_holder pMemory) { return m_pRef->remove(key, pMemory); } + // map + template + void force_insert(const Key& key, const Value& value, shared_memory_holder pMemory){ m_pRef->force_insert(key, value, pMemory); } + private: shared_node_ref m_pRef; typedef std::set nodes; diff --git a/include/yaml-cpp/node/detail/node_data.h b/include/yaml-cpp/node/detail/node_data.h index c0be2b8..7fe05b8 100644 --- a/include/yaml-cpp/node/detail/node_data.h +++ b/include/yaml-cpp/node/detail/node_data.h @@ -56,6 +56,10 @@ namespace YAML node& get(node& key, shared_memory_holder pMemory) const; node& get(node& key, shared_memory_holder pMemory); bool remove(node& key, shared_memory_holder pMemory); + + // map + template + void force_insert(const Key& key, const Value& value, shared_memory_holder pMemory); public: static std::string empty_scalar; diff --git a/include/yaml-cpp/node/detail/node_ref.h b/include/yaml-cpp/node/detail/node_ref.h index d1b06c5..64cdb98 100644 --- a/include/yaml-cpp/node/detail/node_ref.h +++ b/include/yaml-cpp/node/detail/node_ref.h @@ -55,6 +55,10 @@ namespace YAML node& get(node& key, shared_memory_holder pMemory) const { return static_cast(*m_pData).get(key, pMemory); } node& get(node& key, shared_memory_holder pMemory) { return m_pData->get(key, pMemory); } bool remove(node& key, shared_memory_holder pMemory) { return m_pData->remove(key, pMemory); } + + // map + template + void force_insert(const Key& key, const Value& value, shared_memory_holder pMemory) { m_pData->force_insert(key, value, pMemory); } private: shared_node_data m_pData; diff --git a/include/yaml-cpp/node/impl.h b/include/yaml-cpp/node/impl.h index 3b466d5..e25bff0 100644 --- a/include/yaml-cpp/node/impl.h +++ b/include/yaml-cpp/node/impl.h @@ -358,9 +358,16 @@ namespace YAML key.EnsureNodeExists(); return m_pNode->remove(*key.m_pNode, m_pMemory); } + + // map + template + inline void Node::force_insert(const Key& key, const Value& value) + { + EnsureNodeExists(); + m_pNode->force_insert(detail::to_value(key), detail::to_value(value), m_pMemory); + } // free functions - inline bool operator==(const Node& lhs, const Node& rhs) { return lhs.is(rhs); diff --git a/include/yaml-cpp/node/node.h b/include/yaml-cpp/node/node.h index 6fafd26..70acb3e 100644 --- a/include/yaml-cpp/node/node.h +++ b/include/yaml-cpp/node/node.h @@ -78,6 +78,10 @@ namespace YAML const Node operator[](const Node& key) const; Node operator[](const Node& key); bool remove(const Node& key); + + // map + template + void force_insert(const Key& key, const Value& value); private: explicit Node(detail::node& node, detail::shared_memory_holder pMemory); diff --git a/test/new-api/nodetests.cpp b/test/new-api/nodetests.cpp index 54a3e18..556e06b 100644 --- a/test/new-api/nodetests.cpp +++ b/test/new-api/nodetests.cpp @@ -417,6 +417,32 @@ namespace Test YAML_ASSERT(clone == clone[0]); return true; } + + TEST ForceInsertIntoMap() + { + YAML::Node node; + node["a"] = "b"; + node.force_insert("x", "y"); + node.force_insert("a", 5); + YAML_ASSERT(node.size() == 3); + YAML_ASSERT(node.Type() == YAML::NodeType::Map); + bool ab = false; + bool a5 = false; + bool xy = false; + for(YAML::const_iterator it=node.begin();it!=node.end();++it) { + if(it->first.as() == "a") { + if(it->second.as() == "b") + ab = true; + else if(it->second.as() == "5") + a5 = true; + } else if(it->first.as() == "x" && it->second.as() == "y") + xy = true; + } + YAML_ASSERT(ab); + YAML_ASSERT(a5); + YAML_ASSERT(xy); + return true; + } } void RunNodeTest(TEST (*test)(), const std::string& name, int& passed, int& total) { @@ -474,6 +500,7 @@ namespace Test RunNodeTest(&Node::CloneSeq, "clone seq", passed, total); RunNodeTest(&Node::CloneMap, "clone map", passed, total); RunNodeTest(&Node::CloneAlias, "clone alias", passed, total); + RunNodeTest(&Node::ForceInsertIntoMap, "force insert into map", passed, total); std::cout << "Node tests: " << passed << "/" << total << " passed\n"; return passed == total;