- Merged latest changes from the event-api branch.

This commit is contained in:
rtweeks21
2010-10-16 08:45:41 +00:00
parent 55c8486ee3
commit 3126507ab9
8 changed files with 136 additions and 132 deletions

40
include/anchordict.h Normal file
View File

@@ -0,0 +1,40 @@
#pragma once
#ifndef ANCHORDICT_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define ANCHORDICT_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#include <vector>
#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 T>
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<T> m_data;
};
}
#endif // ANCHORDICT_H_62B23520_7C8E_11DE_8A39_0800200C9A66

View File

@@ -15,7 +15,7 @@ namespace YAML
void GraphBuilderAdapter::OnAlias(const Mark& mark, anchor_t anchor) 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)); DispositionNode(m_builder.AnchorReference(mark, pReffedNode));
} }
@@ -70,7 +70,7 @@ namespace YAML
void GraphBuilderAdapter::RegisterAnchor(anchor_t anchor, void *pNode) void GraphBuilderAdapter::RegisterAnchor(anchor_t anchor, void *pNode)
{ {
if (anchor) { if (anchor) {
m_anchors[anchor] = pNode; m_anchors.Register(anchor, pNode);
} }
} }

View File

@@ -3,6 +3,7 @@
#include <map> #include <map>
#include <stack> #include <stack>
#include "anchordict.h"
#include "eventhandler.h" #include "eventhandler.h"
#include "graphbuilder.h" #include "graphbuilder.h"
@@ -50,7 +51,7 @@ namespace YAML
static int sequenceMarker; static int sequenceMarker;
}; };
typedef std::stack<ContainerFrame> ContainerStack; typedef std::stack<ContainerFrame> ContainerStack;
typedef std::map<anchor_t, void*> AnchorMap; typedef AnchorDict<void*> AnchorMap;
GraphBuilderInterface& m_builder; GraphBuilderInterface& m_builder;
ContainerStack m_containers; ContainerStack m_containers;

View File

@@ -5,6 +5,7 @@
#include "emitfromevents.h" #include "emitfromevents.h"
#include "emitter.h" #include "emitter.h"
#include "eventhandler.h" #include "eventhandler.h"
#include "graphbuilderadapter.h"
#include "iterpriv.h" #include "iterpriv.h"
#include "map.h" #include "map.h"
#include "nodebuilder.h" #include "nodebuilder.h"
@@ -47,7 +48,9 @@ namespace YAML
{ {
std::auto_ptr<Node> pNode(new Node); std::auto_ptr<Node> pNode(new Node);
NodeBuilder nodeBuilder(*pNode); NodeBuilder nodeBuilder(*pNode);
EmitEvents(nodeBuilder); GraphBuilder<NodeBuilder> graphBuilder(nodeBuilder);
GraphBuilderAdapter eventHandler(graphBuilder);
EmitEvents(eventHandler);
return pNode; return pNode;
} }

View File

@@ -6,137 +6,85 @@
namespace YAML 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_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() 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); (void)pParent;
node.InitNull(tag); Node *pNode = NewNode();
Pop(); 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(); (void)pParent;
node.InitAlias(mark, *m_anchors[anchor]); Node *pNode = NewNode();
Pop(); 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); std::auto_ptr<Node> apNode(m_unlinked.pop(pNode));
node.Init(CT_SCALAR, mark, tag); assert(apNode.get());
node.SetData(value); pSequence->Append(apNode);
Pop();
} }
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); (void)pParent;
node.Init(CT_SEQUENCE, mark, tag); Node *pNode = NewNode();
pNode->Init(CT_MAP, mark, tag);
return pNode;
} }
void NodeBuilder::OnSequenceEnd() void NodeBuilder::AssignInMap(Map *pMap, Node *pKeyNode, Node *pValueNode)
{ {
Pop(); std::auto_ptr<Node> apKeyNode(m_unlinked.pop(pKeyNode));
} std::auto_ptr<Node> apValueNode(m_unlinked.pop(pValueNode));
assert(apKeyNode.get() && apValueNode.get());
void NodeBuilder::OnMapStart(const Mark& mark, const std::string& tag, anchor_t anchor) pMap->Insert(apKeyNode, apValueNode);
{
Node& node = Push(anchor);
node.Init(CT_MAP, mark, tag);
m_didPushKey.push(false);
}
void NodeBuilder::OnMapEnd()
{
m_didPushKey.pop();
Pop();
} }
Node& NodeBuilder::Push(anchor_t anchor) Node* NodeBuilder::NewNode()
{
Node& node = Push();
RegisterAnchor(anchor, node);
return node;
}
Node& NodeBuilder::Push()
{ {
if(!m_initializedRoot) { if(!m_initializedRoot) {
m_initializedRoot = true; m_initializedRoot = true;
return m_root; return &m_root;
} }
std::auto_ptr<Node> pNode(new Node); std::auto_ptr<Node> pNode(new Node);
m_stack.push(pNode); Node* pResult = pNode.get();
return m_stack.top(); // Save the pointer in a collection that will free it on exception
} m_unlinked.push(pNode);
return pResult;
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<Node> pNode = m_stack.pop();
Insert(pNode);
}
void NodeBuilder::Insert(std::auto_ptr<Node> 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<Node> 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);
}
} }
} }

View File

@@ -3,55 +3,49 @@
#ifndef NODEBUILDER_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #ifndef NODEBUILDER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define NODEBUILDER_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #define NODEBUILDER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#include "eventhandler.h"
#include "ptr_stack.h"
#include <map> #include <map>
#include <memory> #include <memory>
#include <stack> #include <stack>
#include <string>
#include "ptr_stack.h"
namespace YAML namespace YAML
{ {
class Node; class Node;
class Mark;
class NodeBuilder: public EventHandler class NodeBuilder
{ {
public: public:
typedef YAML::Node Node;
typedef YAML::Node Map;
typedef YAML::Node Sequence;
explicit NodeBuilder(Node& root); explicit NodeBuilder(Node& root);
NodeBuilder(const NodeBuilder& o);
virtual ~NodeBuilder(); virtual ~NodeBuilder();
virtual void OnDocumentStart(const Mark& mark); Node *NewNull(const std::string& tag, Node *pParent);
virtual void OnDocumentEnd(); 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); Sequence *NewSequence(const Mark& mark, const std::string& tag, Node *pParent);
virtual void OnAlias(const Mark& mark, anchor_t anchor); void AppendToSequence(Sequence *pSequence, Node *pNode);
virtual void OnScalar(const Mark& mark, const std::string& tag, anchor_t anchor, const std::string& value); void SequenceComplete(Sequence *pSequence) {(void)pSequence;}
virtual void OnSequenceStart(const Mark& mark, const std::string& tag, anchor_t anchor); Map *NewMap(const Mark& mark, const std::string& tag, Node *pParent);
virtual void OnSequenceEnd(); void AssignInMap(Map *pMap, Node *pKeyNode, Node *pValueNode);
void MapComplete(Map *pMap) {(void)pMap;}
virtual void OnMapStart(const Mark& mark, const std::string& tag, anchor_t anchor);
virtual void OnMapEnd();
private: private:
Node& Push(anchor_t anchor); Node* NewNode();
Node& Push();
Node& Top();
void Pop();
void Insert(std::auto_ptr<Node> pNode);
void RegisterAnchor(anchor_t anchor, const Node& node);
private: private:
Node& m_root; Node& m_root;
bool m_initializedRoot; bool m_initializedRoot;
bool m_finished;
ptr_stack<Node> m_stack; ptr_stack<Node> m_unlinked;
ptr_stack<Node> m_pendingKeys;
std::stack<bool> m_didPushKey;
typedef std::vector<const Node *> Anchors;
Anchors m_anchors;
}; };
} }

View File

@@ -75,7 +75,7 @@ namespace YAML
bool Parser::GetNextDocument(Node& document) bool Parser::GetNextDocument(Node& document)
{ {
NodeBuilder builder(document); NodeBuilder builder(document);
return HandleNextDocument(builder); return BuildNextDocumentGraph(builder);
} }
// ParseDirectives // ParseDirectives

View File

@@ -3,11 +3,14 @@
#ifndef PTR_STACK_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #ifndef PTR_STACK_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define PTR_STACK_H_62B23520_7C8E_11DE_8A39_0800200C9A66 #define PTR_STACK_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#include <algorithm>
#include <memory> #include <memory>
#include <vector> #include <vector>
#include "noncopyable.h"
template <typename T> template <typename T>
class ptr_stack class ptr_stack : private YAML::noncopyable
{ {
public: public:
ptr_stack() {} ptr_stack() {}
@@ -22,13 +25,28 @@ public:
std::size_t size() const { return m_data.size(); } std::size_t size() const { return m_data.size(); }
bool empty() const { return m_data.empty(); } bool empty() const { return m_data.empty(); }
void push(std::auto_ptr<T> t) { m_data.push_back(t.release()); } void push(std::auto_ptr<T> 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<T> pop() { std::auto_ptr<T> pop() {
std::auto_ptr<T> t(m_data.back()); std::auto_ptr<T> t(m_data.back());
m_data.pop_back(); m_data.pop_back();
return t; return t;
} }
T& top() { return *m_data.back(); } std::auto_ptr<T> pop(T* val) {
typename std::vector<T*>::reverse_iterator itVal =
std::find(m_data.rbegin(), m_data.rend(), val);
std::auto_ptr<T> 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: private:
std::vector<T*> m_data; std::vector<T*> m_data;