nodeevents.cpp 2.55 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include "nodeevents.h"
#include "yaml-cpp/node/node.h"
#include "yaml-cpp/node/impl.h"
#include "yaml-cpp/eventhandler.h"
#include "yaml-cpp/mark.h"

namespace YAML
{
	void NodeEvents::AliasManager::RegisterReference(const detail::node& node)
	{
		m_anchorByIdentity.insert(std::make_pair(node.ref(), _CreateNewAnchor()));
	}
	
	anchor_t NodeEvents::AliasManager::LookupAnchor(const detail::node& node) const
	{
		AnchorByIdentity::const_iterator it = m_anchorByIdentity.find(node.ref());
		if(it == m_anchorByIdentity.end())
			return 0;
		return it->second;
	}

22
	NodeEvents::NodeEvents(const Node& node): m_pMemory(node.m_pMemory), m_root(node.m_pNode)
23
	{
24
25
        if(m_root)
            Setup(*m_root);
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
	}

	void NodeEvents::Setup(const detail::node& node)
	{
		int& refCount = m_refCount[node.ref()];
		refCount++;
		if(refCount > 1)
			return;
		
		if(node.type() == NodeType::Sequence) {
			for(detail::const_node_iterator it=node.begin();it!=node.end();++it)
				Setup(**it);
		} else if(node.type() == NodeType::Map) {
			for(detail::const_node_iterator it=node.begin();it!=node.end();++it) {
				Setup(*it->first);
				Setup(*it->second);
			}
		}
	}

	void NodeEvents::Emit(EventHandler& handler)
	{
		AliasManager am;
		
		handler.OnDocumentStart(Mark());
51
52
        if(m_root)
            Emit(*m_root, handler, am);
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
		handler.OnDocumentEnd();
	}

	void NodeEvents::Emit(const detail::node& node, EventHandler& handler, AliasManager& am) const
	{
		anchor_t anchor = NullAnchor;
		if(IsAliased(node)) {
			anchor = am.LookupAnchor(node);
			if(anchor) {
				handler.OnAlias(Mark(), anchor);
				return;
			}
			
			am.RegisterReference(node);
			anchor = am.LookupAnchor(node);
		}
		
		switch(node.type()) {
			case NodeType::Undefined:
				break;
			case NodeType::Null:
				handler.OnNull(Mark(), anchor);
				break;
			case NodeType::Scalar:
				handler.OnScalar(Mark(), node.tag(), anchor, node.scalar());
				break;
			case NodeType::Sequence:
				handler.OnSequenceStart(Mark(), node.tag(), anchor);
				for(detail::const_node_iterator it=node.begin();it!=node.end();++it)
					Emit(**it, handler, am);
				handler.OnSequenceEnd();
				break;
			case NodeType::Map:
				handler.OnMapStart(Mark(), node.tag(), anchor);
				for(detail::const_node_iterator it=node.begin();it!=node.end();++it) {
					Emit(*it->first, handler, am);
					Emit(*it->second, handler, am);
				}
				handler.OnMapEnd();
				break;
		}
	}

	bool NodeEvents::IsAliased(const detail::node& node) const
	{
		RefCount::const_iterator it = m_refCount.find(node.ref());
		return it != m_refCount.end() && it->second > 1;
	}
}