valuebuilder.cpp 2.44 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
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
81
82
83
84
85
86
87
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
#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()
	{
	}
	
	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)
	{
		detail::node& top = *m_stack.back();
		
		detail::node& node = m_pMemory->create_node();
		m_stack.push_back(&node);
		RegisterAnchor(anchor, node);
		
		if(top.type() == ValueType::Map && m_keys.size() < m_mapDepth)
			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);
		}
	}
}