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()
	{
	}
	
beder's avatar
beder committed
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)
	{
beder's avatar
beder committed
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);
		
beder's avatar
beder committed
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);
		}
	}
}