node.cpp 4.78 KB
Newer Older
1
#include "yaml-cpp/node.h"
2
#include "aliascontent.h"
3
#include "yaml-cpp/aliasmanager.h"
4
#include "content.h"
5
6
7
#include "yaml-cpp/emitfromevents.h"
#include "yaml-cpp/emitter.h"
#include "yaml-cpp/eventhandler.h"
8
9
10
#include "iterpriv.h"
#include "map.h"
#include "nodebuilder.h"
11
#include "yaml-cpp/nodeproperties.h"
12
#include "scalar.h"
13
#include "scanner.h"
14
#include "sequence.h"
15
#include "tag.h"
16
17
#include "token.h"
#include <cassert>
18
#include <stdexcept>
19
20
21
22
23
24
25
26
27

namespace YAML
{
	// the ordering!
	bool ltnode::operator ()(const Node *pNode1, const Node *pNode2) const
	{
		return *pNode1 < *pNode2;
	}

28
	Node::Node(): m_type(CT_NONE), m_pContent(0), m_alias(false), m_pIdentity(this), m_referenced(false)
Jesse Beder's avatar
Jesse Beder committed
29
30
31
	{
	}

32
33
34
35
36
37
38
39
	Node::~Node()
	{
		Clear();
	}

	void Node::Clear()
	{
		delete m_pContent;
40
		m_type = CT_NONE;
41
42
		m_pContent = 0;
		m_alias = false;
43
44
		m_referenced = false;
		m_tag.clear();
45
	}
Jesse Beder's avatar
Jesse Beder committed
46
47
48
	
	std::auto_ptr<Node> Node::Clone() const
	{
49
50
51
52
		std::auto_ptr<Node> pNode(new Node);
		NodeBuilder nodeBuilder(*pNode);
		EmitEvents(nodeBuilder);
		return pNode;
Jesse Beder's avatar
Jesse Beder committed
53
	}
54

55
	void Node::EmitEvents(EventHandler& eventHandler) const
56
	{
57
58
59
60
61
		eventHandler.OnDocumentStart(m_mark);
		AliasManager am;
		EmitEvents(am, eventHandler);
		eventHandler.OnDocumentEnd();
	}
62

63
64
65
66
67
68
69
70
	void Node::EmitEvents(AliasManager& am, EventHandler& eventHandler) const
	{
		anchor_t anchor = NullAnchor;
		if(m_referenced || m_alias) {
			if(const Node *pOther = am.LookupReference(*this)) {
				eventHandler.OnAlias(m_mark, am.LookupAnchor(*pOther));
				return;
			}
71
			
72
73
			am.RegisterReference(*this);
			anchor = am.LookupAnchor(*this);
74
		}
75
76
77
78
79
80
		
		if(m_pContent)
			m_pContent->EmitEvents(am, eventHandler, m_mark, GetTag(), anchor);
		else
			eventHandler.OnNull(GetTag(), anchor);
	}
81

82
83
84
85
86
87
88
89
90
91
92
93
	void Node::Init(CONTENT_TYPE type, const Mark& mark, const std::string& tag)
	{
		Clear();
		m_mark = mark;
		m_type = type;
		m_tag = tag;
		m_alias = false;
		m_pIdentity = this;
		m_referenced = false;

		switch(type) {
			case CT_SCALAR:
94
95
				m_pContent = new Scalar;
				break;
96
			case CT_SEQUENCE:
97
98
				m_pContent = new Sequence;
				break;
99
			case CT_MAP:
100
101
				m_pContent = new Map;
				break;
Jesse Beder's avatar
Jesse Beder committed
102
			default:
103
				m_pContent = 0;
Jesse Beder's avatar
Jesse Beder committed
104
				break;
105
106
107
		}
	}

108
	void Node::InitNull(const std::string& tag)
109
	{
110
111
112
113
114
		Clear();
		m_tag = tag;
		m_alias = false;
		m_pIdentity = this;
		m_referenced = false;
115
116
	}

117
	void Node::InitAlias(const Mark& mark, const Node& identity)
118
	{
119
120
121
122
123
124
125
126
127
		Clear();
		m_mark = mark;
		m_alias = true;
		m_pIdentity = &identity;
		if(identity.m_pContent) {
			m_pContent = new AliasContent(identity.m_pContent);
			m_type = identity.GetType();
		}
		identity.m_referenced = true;
128
129
	}

130
131
132
133
	void Node::SetData(const std::string& data)
	{
		assert(m_pContent); // TODO: throw
		m_pContent->SetData(data);
134
135
	}

136
	void Node::Append(std::auto_ptr<Node> pNode)
137
	{
138
139
		assert(m_pContent); // TODO: throw
		m_pContent->Append(pNode);
140
	}
141
142
	
	void Node::Insert(std::auto_ptr<Node> pKey, std::auto_ptr<Node> pValue)
143
	{
144
145
		assert(m_pContent); // TODO: throw
		m_pContent->Insert(pKey, pValue);
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
	}

	// begin
	// Returns an iterator to the beginning of this (sequence or map).
	Iterator Node::begin() const
	{
		if(!m_pContent)
			return Iterator();

		std::vector <Node *>::const_iterator seqIter;
		if(m_pContent->GetBegin(seqIter))
			return Iterator(new IterPriv(seqIter));

		std::map <Node *, Node *, ltnode>::const_iterator mapIter;
		if(m_pContent->GetBegin(mapIter))
			return Iterator(new IterPriv(mapIter));

		return Iterator();
	}

	// end
	// . Returns an iterator to the end of this (sequence or map).
	Iterator Node::end() const
	{
		if(!m_pContent)
			return Iterator();

		std::vector <Node *>::const_iterator seqIter;
		if(m_pContent->GetEnd(seqIter))
			return Iterator(new IterPriv(seqIter));

		std::map <Node *, Node *, ltnode>::const_iterator mapIter;
		if(m_pContent->GetEnd(mapIter))
			return Iterator(new IterPriv(mapIter));

		return Iterator();
	}

	// size
	// . Returns the size of this node, if it's a sequence node.
	// . Otherwise, returns zero.
187
	std::size_t Node::size() const
188
189
190
191
192
193
194
	{
		if(!m_pContent)
			return 0;

		return m_pContent->GetSize();
	}

195
	const Node *Node::FindAtIndex(std::size_t i) const
196
197
	{
		if(!m_pContent)
198
199
200
			return 0;
		
		return m_pContent->GetNode(i);
201
202
	}

203
	bool Node::GetScalar(std::string& s) const
204
	{
205
		if(!m_pContent) {
206
207
208
209
			if(m_tag.empty())
				s = "~";
			else
				s = "";
210
211
212
			return true;
		}
		
213
		return m_pContent->GetScalar(s);
214
215
	}

216
	Emitter& operator << (Emitter& out, const Node& node)
217
	{
218
219
		EmitFromEvents emitFromEvents(out);
		node.EmitEvents(emitFromEvents);
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
		return out;
	}

	int Node::Compare(const Node& rhs) const
	{
		// Step 1: no content is the smallest
		if(!m_pContent) {
			if(rhs.m_pContent)
				return -1;
			else
				return 0;
		}
		if(!rhs.m_pContent)
			return 1;

		return m_pContent->Compare(rhs.m_pContent);
	}

	bool operator < (const Node& n1, const Node& n2)
	{
		return n1.Compare(n2) < 0;
	}
}