nodeevents.cpp 2.47 KB
Newer Older
1
2
3
#include "nodeevents.h"
#include "yaml-cpp/node/node.h"
#include "yaml-cpp/node/impl.h"
Jesse Beder's avatar
Jesse Beder committed
4
5
#include "yaml-cpp/eventhandler.h"
#include "yaml-cpp/mark.h"
6
7
8

namespace YAML
{
9
	void NodeEvents::AliasManager::RegisterReference(const detail::node& node)
Jesse Beder's avatar
Jesse Beder committed
10
11
12
13
	{
		m_anchorByIdentity.insert(std::make_pair(node.ref(), _CreateNewAnchor()));
	}
	
14
	anchor_t NodeEvents::AliasManager::LookupAnchor(const detail::node& node) const
Jesse Beder's avatar
Jesse Beder committed
15
16
17
18
19
20
21
	{
		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
	{
Jesse Beder's avatar
Jesse Beder committed
24
		Setup(m_root);
25
26
	}

27
	void NodeEvents::Setup(const detail::node& node)
28
29
30
31
32
33
	{
		int& refCount = m_refCount[node.ref()];
		refCount++;
		if(refCount > 1)
			return;
		
34
		if(node.type() == NodeType::Sequence) {
Jesse Beder's avatar
Jesse Beder committed
35
			for(detail::const_node_iterator it=node.begin();it!=node.end();++it)
Jesse Beder's avatar
Jesse Beder committed
36
				Setup(**it);
37
		} else if(node.type() == NodeType::Map) {
Jesse Beder's avatar
Jesse Beder committed
38
			for(detail::const_node_iterator it=node.begin();it!=node.end();++it) {
Jesse Beder's avatar
Jesse Beder committed
39
40
				Setup(*it->first);
				Setup(*it->second);
Jesse Beder's avatar
Jesse Beder committed
41
			}
42
43
		}
	}
Jesse Beder's avatar
Jesse Beder committed
44

45
	void NodeEvents::Emit(EventHandler& handler)
Jesse Beder's avatar
Jesse Beder committed
46
47
48
49
50
51
52
53
	{
		AliasManager am;
		
		handler.OnDocumentStart(Mark());
		Emit(m_root, handler, am);
		handler.OnDocumentEnd();
	}

54
	void NodeEvents::Emit(const detail::node& node, EventHandler& handler, AliasManager& am) const
Jesse Beder's avatar
Jesse Beder committed
55
56
57
58
59
60
61
62
63
64
65
66
67
68
	{
		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()) {
69
			case NodeType::Undefined:
Jesse Beder's avatar
Jesse Beder committed
70
				break;
71
			case NodeType::Null:
Jesse Beder's avatar
Jesse Beder committed
72
73
				handler.OnNull(Mark(), anchor);
				break;
74
			case NodeType::Scalar:
Jesse Beder's avatar
Jesse Beder committed
75
76
				handler.OnScalar(Mark(), "", anchor, node.scalar());
				break;
77
			case NodeType::Sequence:
Jesse Beder's avatar
Jesse Beder committed
78
79
80
81
82
				handler.OnSequenceStart(Mark(), "", anchor);
				for(detail::const_node_iterator it=node.begin();it!=node.end();++it)
					Emit(**it, handler, am);
				handler.OnSequenceEnd();
				break;
83
			case NodeType::Map:
Jesse Beder's avatar
Jesse Beder committed
84
85
86
87
88
89
90
91
92
93
				handler.OnMapStart(Mark(), "", 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;
		}
	}

94
	bool NodeEvents::IsAliased(const detail::node& node) const
Jesse Beder's avatar
Jesse Beder committed
95
96
97
98
	{
		RefCount::const_iterator it = m_refCount.find(node.ref());
		return it != m_refCount.end() && it->second > 1;
	}
99
}