valuebuilder.cpp 2.57 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include "valuebuilder.h"
#include "yaml-cpp/mark.h"
#include "yaml-cpp/value.h"
#include <cassert>

namespace YAML
{
	ValueBuilder::ValueBuilder(): m_pMemory(new detail::memory_holder), m_pRoot(0), m_mapDepth(0)
	{
		m_anchors.push_back(0); // since the anchors start at 1
	}
	
	ValueBuilder::~ValueBuilder()
	{
	}
	
17
18
19
20
21
22
23
24
	Value ValueBuilder::Root()
	{
		if(!m_pRoot)
			return Value();
		
		return Value(*m_pRoot, m_pMemory);
	}

25
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
51
52
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
	void ValueBuilder::OnDocumentStart(const Mark&)
	{
	}
	
	void ValueBuilder::OnDocumentEnd()
	{
	}
	
	void ValueBuilder::OnNull(const Mark& mark, anchor_t anchor)
	{
		detail::node& node = Push(anchor);
		node.set_null();
		Pop();
	}
	
	void ValueBuilder::OnAlias(const Mark& /*mark*/, anchor_t anchor)
	{
		detail::node& node = *m_anchors[anchor];
		m_stack.push_back(&node);
		Pop();
	}
	
	void ValueBuilder::OnScalar(const Mark& mark, const std::string& tag, anchor_t anchor, const std::string& value)
	{
		detail::node& node = Push(anchor);
		node.set_scalar(value);
		Pop();
	}
	
	void ValueBuilder::OnSequenceStart(const Mark& mark, const std::string& tag, anchor_t anchor)
	{
		detail::node& node = Push(anchor);
		node.set_type(ValueType::Sequence);
	}
	
	void ValueBuilder::OnSequenceEnd()
	{
		Pop();
	}
	
	void ValueBuilder::OnMapStart(const Mark& mark, const std::string& tag, anchor_t anchor)
	{
		detail::node& node = Push(anchor);
		node.set_type(ValueType::Map);
		m_mapDepth++;
	}
	
	void ValueBuilder::OnMapEnd()
	{
		assert(m_mapDepth > 0);
		m_mapDepth--;
		Pop();
	}

	detail::node& ValueBuilder::Push(anchor_t anchor)
	{
81
		const bool needsKey = (!m_stack.empty() && m_stack.back()->type() == ValueType::Map && m_keys.size() < m_mapDepth);
82
83
84
85
86
		
		detail::node& node = m_pMemory->create_node();
		m_stack.push_back(&node);
		RegisterAnchor(anchor, node);
		
87
		if(needsKey)
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
			m_keys.push_back(&node);
		
		return node;
	}
	
	void ValueBuilder::Pop()
	{
		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();
		
		if(collection.type() == ValueType::Sequence) {
			collection.append(node, m_pMemory);
		} else if(collection.type() == ValueType::Map) {
			detail::node& key = *m_keys.back();
			if(&key != &node) {
				m_keys.pop_back();
				collection.insert(key, node, m_pMemory);
			}
		} else {
			assert(false);
			m_stack.clear();
		}
	}

	void ValueBuilder::RegisterAnchor(anchor_t anchor, detail::node& node)
	{
		if(anchor) {
			assert(anchor == m_anchors.size());
			m_anchors.push_back(&node);
		}
	}
}