From 6e03bebeb0779c31aff577866a1191547d167557 Mon Sep 17 00:00:00 2001 From: Jesse Beder Date: Fri, 9 Sep 2011 23:28:21 -0500 Subject: [PATCH] Implemented (untested) the value builder --- CMakeLists.txt | 5 +- include/yaml-cpp/value/detail/node.h | 3 + include/yaml-cpp/value/detail/node_data.h | 1 + include/yaml-cpp/value/detail/node_ref.h | 3 + src/value/detail/node_data.cpp | 8 ++ src/value/valuebuilder.cpp | 120 ++++++++++++++++++++++ src/value/valuebuilder.h | 54 ++++++++++ 7 files changed, 193 insertions(+), 1 deletion(-) create mode 100644 src/value/valuebuilder.cpp create mode 100644 src/value/valuebuilder.h diff --git a/CMakeLists.txt b/CMakeLists.txt index aef2a0c..cc53944 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -65,7 +65,10 @@ file(GLOB public_headers "include/yaml-cpp/value/[a-zA-Z]*.h" "include/yaml-cpp/value/detail/[a-zA-Z]*.h" ) -file(GLOB private_headers "src/[a-zA-Z]*.h") +file(GLOB private_headers + "src/[a-zA-Z]*.h" + "src/value/[a-zA-Z]*.h" +) if(YAML_CPP_BUILD_CONTRIB) file(GLOB contrib_sources "src/contrib/[a-zA-Z]*.cpp") diff --git a/include/yaml-cpp/value/detail/node.h b/include/yaml-cpp/value/detail/node.h index 48d96f9..006f50c 100644 --- a/include/yaml-cpp/value/detail/node.h +++ b/include/yaml-cpp/value/detail/node.h @@ -44,6 +44,9 @@ namespace YAML // sequence void append(node& node, shared_memory_holder pMemory) { m_pRef->append(node, pMemory); } + void insert(node& key, node& value, shared_memory_holder pMemory) { + m_pRef->insert(key, value, pMemory); + } // indexing template node& get(const Key& key, shared_memory_holder pMemory) const { return static_cast(*m_pRef).get(key, pMemory); } diff --git a/include/yaml-cpp/value/detail/node_data.h b/include/yaml-cpp/value/detail/node_data.h index ad6dfea..8944cdb 100644 --- a/include/yaml-cpp/value/detail/node_data.h +++ b/include/yaml-cpp/value/detail/node_data.h @@ -42,6 +42,7 @@ namespace YAML // sequence void append(node& node, shared_memory_holder pMemory); + void insert(node& key, node& value, shared_memory_holder pMemory); // indexing template node& get(const Key& key, shared_memory_holder pMemory) const; diff --git a/include/yaml-cpp/value/detail/node_ref.h b/include/yaml-cpp/value/detail/node_ref.h index 668ece1..7b2cb98 100644 --- a/include/yaml-cpp/value/detail/node_ref.h +++ b/include/yaml-cpp/value/detail/node_ref.h @@ -41,6 +41,9 @@ namespace YAML // sequence void append(node& node, shared_memory_holder pMemory) { ensure_data_exists(); m_pData->append(node, pMemory); } + void insert(node& key, node& value, shared_memory_holder pMemory) { + ensure_data_exists(); m_pData->insert(key, value, pMemory); + } // indexing template node& get(const Key& key, shared_memory_holder pMemory) const { return m_pData ? static_cast(*m_pData).get(key, pMemory) : pMemory->create_node(); } diff --git a/src/value/detail/node_data.cpp b/src/value/detail/node_data.cpp index 01f8a7f..f851353 100644 --- a/src/value/detail/node_data.cpp +++ b/src/value/detail/node_data.cpp @@ -111,6 +111,14 @@ namespace YAML m_sequence.push_back(&node); } + void node_data::insert(node& key, node& value, shared_memory_holder /* pMemory */) + { + if(m_type != ValueType::Map) + throw std::runtime_error("Can't insert into a non-map node"); + + m_map.push_back(kv_pair(&key, &value)); + } + // indexing node& node_data::get(node& key, shared_memory_holder pMemory) const { diff --git a/src/value/valuebuilder.cpp b/src/value/valuebuilder.cpp new file mode 100644 index 0000000..66f6195 --- /dev/null +++ b/src/value/valuebuilder.cpp @@ -0,0 +1,120 @@ +#include "valuebuilder.h" +#include "yaml-cpp/mark.h" +#include "yaml-cpp/value.h" +#include + +namespace YAML +{ + ValueBuilder::ValueBuilder(): m_pMemory(new detail::memory_holder), m_pRoot(0), m_mapDepth(0) + { + m_anchors.push_back(0); // since the anchors start at 1 + } + + ValueBuilder::~ValueBuilder() + { + } + + void ValueBuilder::OnDocumentStart(const Mark&) + { + } + + void ValueBuilder::OnDocumentEnd() + { + } + + void ValueBuilder::OnNull(const Mark& mark, anchor_t anchor) + { + detail::node& node = Push(anchor); + node.set_null(); + Pop(); + } + + void ValueBuilder::OnAlias(const Mark& /*mark*/, anchor_t anchor) + { + detail::node& node = *m_anchors[anchor]; + m_stack.push_back(&node); + Pop(); + } + + void ValueBuilder::OnScalar(const Mark& mark, const std::string& tag, anchor_t anchor, const std::string& value) + { + detail::node& node = Push(anchor); + node.set_scalar(value); + Pop(); + } + + void ValueBuilder::OnSequenceStart(const Mark& mark, const std::string& tag, anchor_t anchor) + { + detail::node& node = Push(anchor); + node.set_type(ValueType::Sequence); + } + + void ValueBuilder::OnSequenceEnd() + { + Pop(); + } + + void ValueBuilder::OnMapStart(const Mark& mark, const std::string& tag, anchor_t anchor) + { + detail::node& node = Push(anchor); + node.set_type(ValueType::Map); + m_mapDepth++; + } + + void ValueBuilder::OnMapEnd() + { + assert(m_mapDepth > 0); + m_mapDepth--; + Pop(); + } + + detail::node& ValueBuilder::Push(anchor_t anchor) + { + detail::node& top = *m_stack.back(); + + detail::node& node = m_pMemory->create_node(); + m_stack.push_back(&node); + RegisterAnchor(anchor, node); + + if(top.type() == ValueType::Map && m_keys.size() < m_mapDepth) + m_keys.push_back(&node); + + return node; + } + + void ValueBuilder::Pop() + { + assert(!m_stack.empty()); + if(m_stack.size() == 1) { + m_pRoot = m_stack[0]; + m_stack.pop_back(); + return; + } + + detail::node& node = *m_stack.back(); + m_stack.pop_back(); + + detail::node& collection = *m_stack.back(); + + if(collection.type() == ValueType::Sequence) { + collection.append(node, m_pMemory); + } else if(collection.type() == ValueType::Map) { + detail::node& key = *m_keys.back(); + if(&key != &node) { + m_keys.pop_back(); + collection.insert(key, node, m_pMemory); + } + } else { + assert(false); + m_stack.clear(); + } + } + + void ValueBuilder::RegisterAnchor(anchor_t anchor, detail::node& node) + { + if(anchor) { + assert(anchor == m_anchors.size()); + m_anchors.push_back(&node); + } + } +} diff --git a/src/value/valuebuilder.h b/src/value/valuebuilder.h new file mode 100644 index 0000000..6673464 --- /dev/null +++ b/src/value/valuebuilder.h @@ -0,0 +1,54 @@ +#ifndef VALUE_VALUEBUILDER_H_62B23520_7C8E_11DE_8A39_0800200C9A66 +#define VALUE_VALUEBUILDER_H_62B23520_7C8E_11DE_8A39_0800200C9A66 + +#if defined(_MSC_VER) || (defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4 +#pragma once +#endif + +#include "yaml-cpp/eventhandler.h" +#include "yaml-cpp/value/ptr.h" +#include + +namespace YAML +{ + class Value; + + class ValueBuilder: public EventHandler + { + public: + ValueBuilder(); + virtual ~ValueBuilder(); + + virtual void OnDocumentStart(const Mark& mark); + virtual void OnDocumentEnd(); + + virtual void OnNull(const Mark& mark, anchor_t anchor); + virtual void OnAlias(const Mark& mark, anchor_t anchor); + virtual void OnScalar(const Mark& mark, const std::string& tag, anchor_t anchor, const std::string& value); + + virtual void OnSequenceStart(const Mark& mark, const std::string& tag, anchor_t anchor); + virtual void OnSequenceEnd(); + + virtual void OnMapStart(const Mark& mark, const std::string& tag, anchor_t anchor); + virtual void OnMapEnd(); + + private: + detail::node& Push(anchor_t anchor); + void Pop(); + void RegisterAnchor(anchor_t anchor, detail::node& node); + + private: + detail::shared_memory_holder m_pMemory; + detail::node *m_pRoot; + + typedef std::vector Nodes; + Nodes m_stack; + Nodes m_anchors; + + Nodes m_keys; + std::size_t m_mapDepth; + }; +} + +#endif // VALUE_VALUEBUILDER_H_62B23520_7C8E_11DE_8A39_0800200C9A66 +