From 3126507ab99138d7ea8568381169f6244e64fedf Mon Sep 17 00:00:00 2001 From: rtweeks21 Date: Sat, 16 Oct 2010 08:45:41 +0000 Subject: [PATCH] - Merged latest changes from the event-api branch. --- include/anchordict.h | 40 ++++++++++ src/graphbuilderadapter.cpp | 4 +- src/graphbuilderadapter.h | 3 +- src/node.cpp | 5 +- src/nodebuilder.cpp | 142 ++++++++++++------------------------ src/nodebuilder.h | 48 ++++++------ src/parser.cpp | 2 +- src/ptr_stack.h | 24 +++++- 8 files changed, 136 insertions(+), 132 deletions(-) create mode 100644 include/anchordict.h diff --git a/include/anchordict.h b/include/anchordict.h new file mode 100644 index 0000000..24e1f4b --- /dev/null +++ b/include/anchordict.h @@ -0,0 +1,40 @@ +#pragma once + +#ifndef ANCHORDICT_H_62B23520_7C8E_11DE_8A39_0800200C9A66 +#define ANCHORDICT_H_62B23520_7C8E_11DE_8A39_0800200C9A66 + +#include + +#include "anchor.h" + +namespace YAML +{ + /// AnchorDict + /// . An object that stores and retrieves values correlating to anchor_t + /// values. + /// . Efficient implementation that can make assumptions about how anchor_t + /// values are assigned by the Parser class. + template + class AnchorDict + { + public: + void Register(anchor_t anchor, T value) + { + if (anchor > m_data.size()) + { + m_data.resize(anchor); + } + m_data[anchor - 1] = value; + } + + T Get(anchor_t anchor) const + { + return m_data[anchor - 1]; + } + + private: + std::vector m_data; + }; +} + +#endif // ANCHORDICT_H_62B23520_7C8E_11DE_8A39_0800200C9A66 diff --git a/src/graphbuilderadapter.cpp b/src/graphbuilderadapter.cpp index 74b7e22..6431a45 100644 --- a/src/graphbuilderadapter.cpp +++ b/src/graphbuilderadapter.cpp @@ -15,7 +15,7 @@ namespace YAML void GraphBuilderAdapter::OnAlias(const Mark& mark, anchor_t anchor) { - void *pReffedNode = m_anchors[anchor]; + void *pReffedNode = m_anchors.Get(anchor); DispositionNode(m_builder.AnchorReference(mark, pReffedNode)); } @@ -70,7 +70,7 @@ namespace YAML void GraphBuilderAdapter::RegisterAnchor(anchor_t anchor, void *pNode) { if (anchor) { - m_anchors[anchor] = pNode; + m_anchors.Register(anchor, pNode); } } diff --git a/src/graphbuilderadapter.h b/src/graphbuilderadapter.h index 5b4aa3a..f2ae142 100644 --- a/src/graphbuilderadapter.h +++ b/src/graphbuilderadapter.h @@ -3,6 +3,7 @@ #include #include +#include "anchordict.h" #include "eventhandler.h" #include "graphbuilder.h" @@ -50,7 +51,7 @@ namespace YAML static int sequenceMarker; }; typedef std::stack ContainerStack; - typedef std::map AnchorMap; + typedef AnchorDict AnchorMap; GraphBuilderInterface& m_builder; ContainerStack m_containers; diff --git a/src/node.cpp b/src/node.cpp index 757b798..a9b97c8 100644 --- a/src/node.cpp +++ b/src/node.cpp @@ -5,6 +5,7 @@ #include "emitfromevents.h" #include "emitter.h" #include "eventhandler.h" +#include "graphbuilderadapter.h" #include "iterpriv.h" #include "map.h" #include "nodebuilder.h" @@ -47,7 +48,9 @@ namespace YAML { std::auto_ptr pNode(new Node); NodeBuilder nodeBuilder(*pNode); - EmitEvents(nodeBuilder); + GraphBuilder graphBuilder(nodeBuilder); + GraphBuilderAdapter eventHandler(graphBuilder); + EmitEvents(eventHandler); return pNode; } diff --git a/src/nodebuilder.cpp b/src/nodebuilder.cpp index 7da7d16..f72fba1 100644 --- a/src/nodebuilder.cpp +++ b/src/nodebuilder.cpp @@ -6,137 +6,85 @@ namespace YAML { - NodeBuilder::NodeBuilder(Node& root): m_root(root), m_initializedRoot(false), m_finished(false) + NodeBuilder::NodeBuilder(Node& root): m_root(root), m_initializedRoot(false) { m_root.Clear(); - m_anchors.push_back(0); // since the anchors start at 1 + } + + NodeBuilder::NodeBuilder(const NodeBuilder& o): m_root(o.m_root), m_initializedRoot(o.m_initializedRoot) + { } NodeBuilder::~NodeBuilder() { } - void NodeBuilder::OnDocumentStart(const Mark&) + Node *NodeBuilder::NewNull(const std::string& tag, Node *pParent) { + (void)pParent; + Node *pNode = NewNode(); + pNode->InitNull(tag); + return pNode; } - void NodeBuilder::OnDocumentEnd() + Node *NodeBuilder::AnchorReference(const Mark& mark, Node *pNode) { - assert(m_finished); + Node *pAlias = NewNode(); + pAlias->InitAlias(mark, *pNode); + return pAlias; } - void NodeBuilder::OnNull(const std::string& tag, anchor_t anchor) + Node *NodeBuilder::NewScalar(const Mark& mark, const std::string& tag, Node *pParent, const std::string& value) { - Node& node = Push(anchor); - node.InitNull(tag); - Pop(); + (void)pParent; + Node *pNode = NewNode(); + pNode->Init(CT_SCALAR, mark, tag); + pNode->SetData(value); + return pNode; } - void NodeBuilder::OnAlias(const Mark& mark, anchor_t anchor) + NodeBuilder::Sequence *NodeBuilder::NewSequence(const Mark& mark, const std::string& tag, Node *pParent) { - Node& node = Push(); - node.InitAlias(mark, *m_anchors[anchor]); - Pop(); + (void)pParent; + Node *pNode = NewNode(); + pNode->Init(CT_SEQUENCE, mark, tag); + return pNode; } - void NodeBuilder::OnScalar(const Mark& mark, const std::string& tag, anchor_t anchor, const std::string& value) + void NodeBuilder::AppendToSequence(Sequence *pSequence, Node *pNode) { - Node& node = Push(anchor); - node.Init(CT_SCALAR, mark, tag); - node.SetData(value); - Pop(); + std::auto_ptr apNode(m_unlinked.pop(pNode)); + assert(apNode.get()); + pSequence->Append(apNode); } - void NodeBuilder::OnSequenceStart(const Mark& mark, const std::string& tag, anchor_t anchor) + NodeBuilder::Map *NodeBuilder::NewMap(const Mark& mark, const std::string& tag, Node* pParent) { - Node& node = Push(anchor); - node.Init(CT_SEQUENCE, mark, tag); + (void)pParent; + Node *pNode = NewNode(); + pNode->Init(CT_MAP, mark, tag); + return pNode; } - void NodeBuilder::OnSequenceEnd() + void NodeBuilder::AssignInMap(Map *pMap, Node *pKeyNode, Node *pValueNode) { - Pop(); - } - - void NodeBuilder::OnMapStart(const Mark& mark, const std::string& tag, anchor_t anchor) - { - Node& node = Push(anchor); - node.Init(CT_MAP, mark, tag); - m_didPushKey.push(false); - } - - void NodeBuilder::OnMapEnd() - { - m_didPushKey.pop(); - Pop(); + std::auto_ptr apKeyNode(m_unlinked.pop(pKeyNode)); + std::auto_ptr apValueNode(m_unlinked.pop(pValueNode)); + assert(apKeyNode.get() && apValueNode.get()); + pMap->Insert(apKeyNode, apValueNode); } - Node& NodeBuilder::Push(anchor_t anchor) - { - Node& node = Push(); - RegisterAnchor(anchor, node); - return node; - } - - Node& NodeBuilder::Push() + Node* NodeBuilder::NewNode() { if(!m_initializedRoot) { m_initializedRoot = true; - return m_root; + return &m_root; } std::auto_ptr pNode(new Node); - m_stack.push(pNode); - return m_stack.top(); - } - - Node& NodeBuilder::Top() - { - return m_stack.empty() ? m_root : m_stack.top(); - } - - void NodeBuilder::Pop() - { - assert(!m_finished); - if(m_stack.empty()) { - m_finished = true; - return; - } - - std::auto_ptr pNode = m_stack.pop(); - Insert(pNode); - } - - void NodeBuilder::Insert(std::auto_ptr pNode) - { - Node& node = Top(); - switch(node.GetType()) { - case CT_SEQUENCE: - node.Append(pNode); - break; - case CT_MAP: - assert(!m_didPushKey.empty()); - if(m_didPushKey.top()) { - assert(!m_pendingKeys.empty()); - - std::auto_ptr pKey = m_pendingKeys.pop(); - node.Insert(pKey, pNode); - m_didPushKey.top() = false; - } else { - m_pendingKeys.push(pNode); - m_didPushKey.top() = true; - } - break; - default: - assert(false); - } - } - - void NodeBuilder::RegisterAnchor(anchor_t anchor, const Node& node) - { - if(anchor) { - assert(anchor == m_anchors.size()); - m_anchors.push_back(&node); - } + Node* pResult = pNode.get(); + // Save the pointer in a collection that will free it on exception + m_unlinked.push(pNode); + return pResult; } } diff --git a/src/nodebuilder.h b/src/nodebuilder.h index 004aaad..beb8ede 100644 --- a/src/nodebuilder.h +++ b/src/nodebuilder.h @@ -3,55 +3,49 @@ #ifndef NODEBUILDER_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #define NODEBUILDER_H_62B23520_7C8E_11DE_8A39_0800200C9A66 -#include "eventhandler.h" -#include "ptr_stack.h" #include #include #include +#include + +#include "ptr_stack.h" namespace YAML { class Node; + class Mark; - class NodeBuilder: public EventHandler + class NodeBuilder { public: + typedef YAML::Node Node; + typedef YAML::Node Map; + typedef YAML::Node Sequence; + explicit NodeBuilder(Node& root); + NodeBuilder(const NodeBuilder& o); virtual ~NodeBuilder(); - virtual void OnDocumentStart(const Mark& mark); - virtual void OnDocumentEnd(); + Node *NewNull(const std::string& tag, Node *pParent); + Node *AnchorReference(const Mark& mark, Node *pNode); + Node *NewScalar(const Mark& mark, const std::string& tag, Node *pParent, const std::string& value); - virtual void OnNull(const std::string& tag, 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); + Sequence *NewSequence(const Mark& mark, const std::string& tag, Node *pParent); + void AppendToSequence(Sequence *pSequence, Node *pNode); + void SequenceComplete(Sequence *pSequence) {(void)pSequence;} - 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(); + Map *NewMap(const Mark& mark, const std::string& tag, Node *pParent); + void AssignInMap(Map *pMap, Node *pKeyNode, Node *pValueNode); + void MapComplete(Map *pMap) {(void)pMap;} private: - Node& Push(anchor_t anchor); - Node& Push(); - Node& Top(); - void Pop(); - - void Insert(std::auto_ptr pNode); - void RegisterAnchor(anchor_t anchor, const Node& node); + Node* NewNode(); private: Node& m_root; bool m_initializedRoot; - bool m_finished; - ptr_stack m_stack; - ptr_stack m_pendingKeys; - std::stack m_didPushKey; - - typedef std::vector Anchors; - Anchors m_anchors; + ptr_stack m_unlinked; }; } diff --git a/src/parser.cpp b/src/parser.cpp index f557b9b..1840d43 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -75,7 +75,7 @@ namespace YAML bool Parser::GetNextDocument(Node& document) { NodeBuilder builder(document); - return HandleNextDocument(builder); + return BuildNextDocumentGraph(builder); } // ParseDirectives diff --git a/src/ptr_stack.h b/src/ptr_stack.h index cfe6fac..9cb282f 100644 --- a/src/ptr_stack.h +++ b/src/ptr_stack.h @@ -3,11 +3,14 @@ #ifndef PTR_STACK_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #define PTR_STACK_H_62B23520_7C8E_11DE_8A39_0800200C9A66 +#include #include #include +#include "noncopyable.h" + template -class ptr_stack +class ptr_stack : private YAML::noncopyable { public: ptr_stack() {} @@ -22,13 +25,28 @@ public: std::size_t size() const { return m_data.size(); } bool empty() const { return m_data.empty(); } - void push(std::auto_ptr t) { m_data.push_back(t.release()); } + void push(std::auto_ptr t) { + // Make sure that the space is available before releasing the + // auto_ptr to it. NULL can be deleted safely. + m_data.push_back(NULL); + m_data.back() = t.release(); + } std::auto_ptr pop() { std::auto_ptr t(m_data.back()); m_data.pop_back(); return t; } - T& top() { return *m_data.back(); } + std::auto_ptr pop(T* val) { + typename std::vector::reverse_iterator itVal = + std::find(m_data.rbegin(), m_data.rend(), val); + std::auto_ptr t; + if (itVal != m_data.rend()) { + t.reset(*itVal); + m_data.erase((itVal + 1).base()); + } + return t; + } + T& top() const { return *m_data.back(); } private: std::vector m_data;