node_data.cpp 5.88 KB
Newer Older
1
2
3
#include "yaml-cpp/node/detail/node_data.h"
#include "yaml-cpp/node/detail/memory.h"
#include "yaml-cpp/node/detail/node.h"
4
#include <sstream>
Jesse Beder's avatar
Jesse Beder committed
5
#include <stdexcept>
Jesse Beder's avatar
Jesse Beder committed
6
7
8
9
10

namespace YAML
{
	namespace detail
	{
11
12
		std::string node_data::empty_scalar;

13
		node_data::node_data(): m_isDefined(false), m_type(NodeType::Null), m_seqSize(0)
Jesse Beder's avatar
Jesse Beder committed
14
15
		{
		}
16

17
18
19
20
21
22
23
		void node_data::mark_defined()
		{
			if(m_type == NodeType::Undefined)
				m_type = NodeType::Null;
			m_isDefined = true;
		}

24
		void node_data::set_type(NodeType::value type)
25
		{
26
			if(type == NodeType::Undefined) {
27
28
29
30
31
32
33
34
35
36
37
38
39
				m_type = type;
				m_isDefined = false;
				return;
			}
			

			m_isDefined = true;
			if(type == m_type)
				return;
			
			m_type = type;
			
			switch(m_type) {
40
				case NodeType::Null:
41
					break;
42
				case NodeType::Scalar:
43
44
					m_scalar.clear();
					break;
45
				case NodeType::Sequence:
46
					reset_sequence();
47
					break;
48
				case NodeType::Map:
49
					reset_map();
50
					break;
51
				case NodeType::Undefined:
52
53
54
55
56
57
58
59
					assert(false);
					break;
			}
		}

		void node_data::set_null()
		{
			m_isDefined = true;
60
			m_type = NodeType::Null;
61
62
63
64
65
		}
		
		void node_data::set_scalar(const std::string& scalar)
		{
			m_isDefined = true;
66
			m_type = NodeType::Scalar;
67
68
69
			m_scalar = scalar;
		}

Jesse Beder's avatar
Jesse Beder committed
70
71
72
		// size/iterator
		std::size_t node_data::size() const
		{
73
74
75
76
77
			if(!m_isDefined)
				return 0;

			switch(m_type) {
				case NodeType::Sequence: compute_seq_size(); return m_seqSize;
78
				case NodeType::Map: compute_map_size(); return m_map.size() - m_undefinedPairs.size();
79
80
81
				default:
					return 0;
			}
Jesse Beder's avatar
Jesse Beder committed
82
83
84
			return 0;
		}
		
85
86
87
88
89
90
91
92
		void node_data::compute_seq_size() const
		{
			while(m_seqSize < m_sequence.size() && m_sequence[m_seqSize]->is_defined())
				m_seqSize++;
		}

		void node_data::compute_map_size() const
		{
93
94
95
96
97
98
99
			kv_pairs::iterator it = m_undefinedPairs.begin();
			while(it != m_undefinedPairs.end()) {
				kv_pairs::iterator jt = boost::next(it);
				if(it->first->is_defined() && it->second->is_defined())
					m_undefinedPairs.erase(it);
				it = jt;
			}
100
101
		}
		
102
		const_node_iterator node_data::begin() const
Jesse Beder's avatar
Jesse Beder committed
103
		{
104
105
106
			if(!m_isDefined)
				return const_node_iterator();
			
Jesse Beder's avatar
Jesse Beder committed
107
			switch(m_type) {
108
109
				case NodeType::Sequence: return const_node_iterator(m_sequence.begin());
				case NodeType::Map: return const_node_iterator(m_map.begin());
110
				default: return const_node_iterator();
Jesse Beder's avatar
Jesse Beder committed
111
112
113
			}
		}
		
114
		node_iterator node_data::begin()
Jesse Beder's avatar
Jesse Beder committed
115
		{
116
117
118
			if(!m_isDefined)
				return node_iterator();

Jesse Beder's avatar
Jesse Beder committed
119
			switch(m_type) {
120
121
				case NodeType::Sequence: return node_iterator(m_sequence.begin());
				case NodeType::Map: return node_iterator(m_map.begin());
122
				default: return node_iterator();
Jesse Beder's avatar
Jesse Beder committed
123
124
125
			}
		}
		
126
		const_node_iterator node_data::end() const
Jesse Beder's avatar
Jesse Beder committed
127
		{
128
129
130
			if(!m_isDefined)
				return const_node_iterator();

Jesse Beder's avatar
Jesse Beder committed
131
			switch(m_type) {
132
133
				case NodeType::Sequence: return const_node_iterator(m_sequence.end());
				case NodeType::Map: return const_node_iterator(m_map.end());
134
				default: return const_node_iterator();
Jesse Beder's avatar
Jesse Beder committed
135
136
137
			}
		}
		
138
		node_iterator node_data::end()
Jesse Beder's avatar
Jesse Beder committed
139
		{
140
141
142
			if(!m_isDefined)
				return node_iterator();

Jesse Beder's avatar
Jesse Beder committed
143
			switch(m_type) {
144
145
				case NodeType::Sequence: return node_iterator(m_sequence.end());
				case NodeType::Map: return node_iterator(m_map.end());
146
				default: return node_iterator();
Jesse Beder's avatar
Jesse Beder committed
147
148
149
150
			}
		}

		// sequence
Jesse Beder's avatar
Jesse Beder committed
151
152
		void node_data::append(node& node, shared_memory_holder /* pMemory */)
		{
153
154
			if(m_type == NodeType::Undefined || m_type == NodeType::Null) {
				m_type = NodeType::Sequence;
155
				reset_sequence();
156
157
			}
			
158
			if(m_type != NodeType::Sequence)
Jesse Beder's avatar
Jesse Beder committed
159
160
161
162
163
				throw std::runtime_error("Can't append to a non-sequence node");
			
			m_sequence.push_back(&node);
		}

164
		void node_data::insert(node& key, node& value, shared_memory_holder pMemory)
165
		{
166
167
			if(m_type == NodeType::Undefined || m_type == NodeType::Null) {
				m_type = NodeType::Map;
168
				reset_map();
169
170
171
172
			} else if(m_type == NodeType::Sequence) {
				convert_sequence_to_map(pMemory);
			}

173
			if(m_type != NodeType::Map)
174
175
				throw std::runtime_error("Can't insert into a non-map node");

176
			insert_map_pair(key, value);
177
178
		}

179
		// indexing
180
		node& node_data::get(node& key, shared_memory_holder pMemory) const
181
		{
182
			if(m_type != NodeType::Map)
183
				return pMemory->create_node();
184
185
			
			for(node_map::const_iterator it=m_map.begin();it!=m_map.end();++it) {
186
				if(it->first->is(key))
187
					return *it->second;
188
189
			}
			
190
			return pMemory->create_node();
191
192
		}
		
193
		node& node_data::get(node& key, shared_memory_holder pMemory)
194
195
		{
			switch(m_type) {
196
197
198
199
				case NodeType::Undefined:
				case NodeType::Null:
				case NodeType::Scalar:
					m_type = NodeType::Map;
200
					reset_map();
201
					break;
202
				case NodeType::Sequence:
203
					convert_sequence_to_map(pMemory);
204
					break;
205
				case NodeType::Map:
206
207
208
209
					break;
			}

			for(node_map::const_iterator it=m_map.begin();it!=m_map.end();++it) {
210
				if(it->first->is(key))
211
					return *it->second;
212
213
			}
			
214
			node& value = pMemory->create_node();
215
			insert_map_pair(key, value);
216
			return value;
217
218
		}
		
219
		bool node_data::remove(node& key, shared_memory_holder /* pMemory */)
220
		{
221
			if(m_type != NodeType::Map)
222
223
224
				return false;

			for(node_map::iterator it=m_map.begin();it!=m_map.end();++it) {
225
				if(it->first->is(key)) {
226
227
228
229
230
231
232
233
					m_map.erase(it);
					return true;
				}
			}
			
			return false;
		}

234
235
236
237
238
239
240
241
242
		void node_data::reset_sequence()
		{
			m_sequence.clear();
			m_seqSize = 0;
		}

		void node_data::reset_map()
		{
			m_map.clear();
243
244
245
246
247
248
249
250
			m_undefinedPairs.clear();
		}

		void node_data::insert_map_pair(node& key, node& value)
		{
			m_map[&key] = &value;
			if(!key.is_defined() || !value.is_defined())
				m_undefinedPairs.push_back(kv_pair(&key, &value));
251
252
		}

253
		void node_data::convert_sequence_to_map(shared_memory_holder pMemory)
254
		{
255
			assert(m_type == NodeType::Sequence);
256
257

			reset_map();
258
259
260
261
			for(std::size_t i=0;i<m_sequence.size();i++) {
				std::stringstream stream;
				stream << i;

262
263
				node& key = pMemory->create_node();
				key.set_scalar(stream.str());
264
				insert_map_pair(key, *m_sequence[i]);
265
266
			}
			
267
			reset_sequence();
268
			m_type = NodeType::Map;
269
		}
Jesse Beder's avatar
Jesse Beder committed
270
271
	}
}