mirror of
https://github.com/jbeder/yaml-cpp.git
synced 2025-09-09 12:41:17 +00:00
- Merged latest changes from the event-api branch.
This commit is contained in:
40
include/anchordict.h
Normal file
40
include/anchordict.h
Normal 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
|
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -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;
|
||||||
|
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -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());
|
||||||
|
pMap->Insert(apKeyNode, apValueNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NodeBuilder::OnMapStart(const Mark& mark, const std::string& tag, anchor_t anchor)
|
Node* NodeBuilder::NewNode()
|
||||||
{
|
|
||||||
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& 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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -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;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -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
|
||||||
|
@@ -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;
|
||||||
|
Reference in New Issue
Block a user