nodebuilder.cpp 2.79 KB
Newer Older
1
#include "nodebuilder.h"
2
#include "yaml-cpp/mark.h"
3
4
#include "yaml-cpp/node/node.h"
#include "yaml-cpp/node/impl.h"
5
6
7
8
#include <cassert>

namespace YAML
{
9
	NodeBuilder::NodeBuilder(): m_pMemory(new detail::memory_holder), m_pRoot(0), m_mapDepth(0)
10
11
12
13
	{
		m_anchors.push_back(0); // since the anchors start at 1
	}
	
14
	NodeBuilder::~NodeBuilder()
15
16
17
	{
	}
	
18
	Node NodeBuilder::Root()
beder's avatar
beder committed
19
20
	{
		if(!m_pRoot)
21
			return Node();
beder's avatar
beder committed
22
		
23
		return Node(*m_pRoot, m_pMemory);
beder's avatar
beder committed
24
25
	}

26
	void NodeBuilder::OnDocumentStart(const Mark&)
27
28
29
	{
	}
	
30
	void NodeBuilder::OnDocumentEnd()
31
32
33
	{
	}
	
34
	void NodeBuilder::OnNull(const Mark& /* mark */, anchor_t anchor)
35
36
37
38
39
40
	{
		detail::node& node = Push(anchor);
		node.set_null();
		Pop();
	}
	
41
	void NodeBuilder::OnAlias(const Mark& /* mark */, anchor_t anchor)
42
43
	{
		detail::node& node = *m_anchors[anchor];
44
		Push(node);
45
46
47
		Pop();
	}
	
48
	void NodeBuilder::OnScalar(const Mark& /* mark */, const std::string& tag, anchor_t anchor, const std::string& value)
49
50
51
	{
		detail::node& node = Push(anchor);
		node.set_scalar(value);
beder's avatar
beder committed
52
		node.set_tag(tag);
53
54
55
		Pop();
	}
	
56
	void NodeBuilder::OnSequenceStart(const Mark& /* mark */, const std::string& tag, anchor_t anchor)
57
58
	{
		detail::node& node = Push(anchor);
beder's avatar
beder committed
59
		node.set_tag(tag);
60
		node.set_type(NodeType::Sequence);
61
62
	}
	
63
	void NodeBuilder::OnSequenceEnd()
64
65
66
67
	{
		Pop();
	}
	
68
	void NodeBuilder::OnMapStart(const Mark& /* mark */, const std::string& tag, anchor_t anchor)
69
70
	{
		detail::node& node = Push(anchor);
71
		node.set_type(NodeType::Map);
beder's avatar
beder committed
72
		node.set_tag(tag);
73
74
75
		m_mapDepth++;
	}
	
76
	void NodeBuilder::OnMapEnd()
77
78
79
80
81
82
	{
		assert(m_mapDepth > 0);
		m_mapDepth--;
		Pop();
	}

83
	detail::node& NodeBuilder::Push(anchor_t anchor)
84
85
86
	{
		detail::node& node = m_pMemory->create_node();
		RegisterAnchor(anchor, node);
87
88
89
90
91
92
93
		Push(node);
		return node;
	}
	
	void NodeBuilder::Push(detail::node& node)
	{
		const bool needsKey = (!m_stack.empty() && m_stack.back()->type() == NodeType::Map && m_keys.size() < m_mapDepth);
94
		
95
		m_stack.push_back(&node);
beder's avatar
beder committed
96
		if(needsKey)
97
			m_keys.push_back(PushedKey(&node, false));
98
99
	}
	
100
	void NodeBuilder::Pop()
101
102
103
104
105
106
107
108
109
110
111
112
113
	{
		assert(!m_stack.empty());
		if(m_stack.size() == 1) {
			m_pRoot = m_stack[0];
			m_stack.pop_back();
			return;
		}
		
		detail::node& node = *m_stack.back();
		m_stack.pop_back();

		detail::node& collection = *m_stack.back();
		
114
		if(collection.type() == NodeType::Sequence) {
115
			collection.push_back(node, m_pMemory);
116
		} else if(collection.type() == NodeType::Map) {
117
118
			assert(!m_keys.empty());
			PushedKey& key = m_keys.back();
119
120
			if(key.second) {
				collection.insert(*key.first, node, m_pMemory);
121
				m_keys.pop_back();
122
123
			} else {
				key.second = true;
124
125
126
127
128
129
130
			}
		} else {
			assert(false);
			m_stack.clear();
		}
	}

131
	void NodeBuilder::RegisterAnchor(anchor_t anchor, detail::node& node)
132
133
134
135
136
137
138
	{
		if(anchor) {
			assert(anchor == m_anchors.size());
			m_anchors.push_back(&node);
		}
	}
}