1 #include <assert.h>
2 #include <iterator>
3 #include <sstream>
4
5 #include "yaml-cpp/exceptions.h"
6 #include "yaml-cpp/node/detail/memory.h"
7 #include "yaml-cpp/node/detail/node.h" // IWYU pragma: keep
8 #include "yaml-cpp/node/detail/node_data.h"
9 #include "yaml-cpp/node/detail/node_iterator.h"
10 #include "yaml-cpp/node/ptr.h"
11 #include "yaml-cpp/node/type.h"
12
13 namespace YAML {
14 namespace detail {
15
16 std::string node_data::empty_scalar;
17
node_data()18 node_data::node_data()
19 : m_isDefined(false),
20 m_mark(Mark::null_mark()),
21 m_type(NodeType::Null),
22 m_style(EmitterStyle::Default),
23 m_seqSize(0) {}
24
mark_defined()25 void node_data::mark_defined() {
26 if (m_type == NodeType::Undefined)
27 m_type = NodeType::Null;
28 m_isDefined = true;
29 }
30
set_mark(const Mark & mark)31 void node_data::set_mark(const Mark& mark) { m_mark = mark; }
32
set_type(NodeType::value type)33 void node_data::set_type(NodeType::value type) {
34 if (type == NodeType::Undefined) {
35 m_type = type;
36 m_isDefined = false;
37 return;
38 }
39
40 m_isDefined = true;
41 if (type == m_type)
42 return;
43
44 m_type = type;
45
46 switch (m_type) {
47 case NodeType::Null:
48 break;
49 case NodeType::Scalar:
50 m_scalar.clear();
51 break;
52 case NodeType::Sequence:
53 reset_sequence();
54 break;
55 case NodeType::Map:
56 reset_map();
57 break;
58 case NodeType::Undefined:
59 assert(false);
60 break;
61 }
62 }
63
set_tag(const std::string & tag)64 void node_data::set_tag(const std::string& tag) { m_tag = tag; }
65
set_style(EmitterStyle::value style)66 void node_data::set_style(EmitterStyle::value style) { m_style = style; }
67
set_null()68 void node_data::set_null() {
69 m_isDefined = true;
70 m_type = NodeType::Null;
71 }
72
set_scalar(const std::string & scalar)73 void node_data::set_scalar(const std::string& scalar) {
74 m_isDefined = true;
75 m_type = NodeType::Scalar;
76 m_scalar = scalar;
77 }
78
79 // size/iterator
size() const80 std::size_t node_data::size() const {
81 if (!m_isDefined)
82 return 0;
83
84 switch (m_type) {
85 case NodeType::Sequence:
86 compute_seq_size();
87 return m_seqSize;
88 case NodeType::Map:
89 compute_map_size();
90 return m_map.size() - m_undefinedPairs.size();
91 default:
92 return 0;
93 }
94 return 0;
95 }
96
compute_seq_size() const97 void node_data::compute_seq_size() const {
98 while (m_seqSize < m_sequence.size() && m_sequence[m_seqSize]->is_defined())
99 m_seqSize++;
100 }
101
compute_map_size() const102 void node_data::compute_map_size() const {
103 kv_pairs::iterator it = m_undefinedPairs.begin();
104 while (it != m_undefinedPairs.end()) {
105 kv_pairs::iterator jt = std::next(it);
106 if (it->first->is_defined() && it->second->is_defined())
107 m_undefinedPairs.erase(it);
108 it = jt;
109 }
110 }
111
begin() const112 const_node_iterator node_data::begin() const {
113 if (!m_isDefined)
114 return const_node_iterator();
115
116 switch (m_type) {
117 case NodeType::Sequence:
118 return const_node_iterator(m_sequence.begin());
119 case NodeType::Map:
120 return const_node_iterator(m_map.begin(), m_map.end());
121 default:
122 return const_node_iterator();
123 }
124 }
125
begin()126 node_iterator node_data::begin() {
127 if (!m_isDefined)
128 return node_iterator();
129
130 switch (m_type) {
131 case NodeType::Sequence:
132 return node_iterator(m_sequence.begin());
133 case NodeType::Map:
134 return node_iterator(m_map.begin(), m_map.end());
135 default:
136 return node_iterator();
137 }
138 }
139
end() const140 const_node_iterator node_data::end() const {
141 if (!m_isDefined)
142 return const_node_iterator();
143
144 switch (m_type) {
145 case NodeType::Sequence:
146 return const_node_iterator(m_sequence.end());
147 case NodeType::Map:
148 return const_node_iterator(m_map.end(), m_map.end());
149 default:
150 return const_node_iterator();
151 }
152 }
153
end()154 node_iterator node_data::end() {
155 if (!m_isDefined)
156 return node_iterator();
157
158 switch (m_type) {
159 case NodeType::Sequence:
160 return node_iterator(m_sequence.end());
161 case NodeType::Map:
162 return node_iterator(m_map.end(), m_map.end());
163 default:
164 return node_iterator();
165 }
166 }
167
168 // sequence
push_back(node & node,shared_memory_holder)169 void node_data::push_back(node& node, shared_memory_holder /* pMemory */) {
170 if (m_type == NodeType::Undefined || m_type == NodeType::Null) {
171 m_type = NodeType::Sequence;
172 reset_sequence();
173 }
174
175 if (m_type != NodeType::Sequence)
176 throw BadPushback();
177
178 m_sequence.push_back(&node);
179 }
180
insert(node & key,node & value,shared_memory_holder pMemory)181 void node_data::insert(node& key, node& value, shared_memory_holder pMemory) {
182 switch (m_type) {
183 case NodeType::Map:
184 break;
185 case NodeType::Undefined:
186 case NodeType::Null:
187 case NodeType::Sequence:
188 convert_to_map(pMemory);
189 break;
190 case NodeType::Scalar:
191 throw BadSubscript();
192 }
193
194 insert_map_pair(key, value);
195 }
196
197 // indexing
get(node & key,shared_memory_holder) const198 node* node_data::get(node& key, shared_memory_holder /* pMemory */) const {
199 if (m_type != NodeType::Map) {
200 return NULL;
201 }
202
203 for (node_map::const_iterator it = m_map.begin(); it != m_map.end(); ++it) {
204 if (it->first->is(key))
205 return it->second;
206 }
207
208 return NULL;
209 }
210
get(node & key,shared_memory_holder pMemory)211 node& node_data::get(node& key, shared_memory_holder pMemory) {
212 switch (m_type) {
213 case NodeType::Map:
214 break;
215 case NodeType::Undefined:
216 case NodeType::Null:
217 case NodeType::Sequence:
218 convert_to_map(pMemory);
219 break;
220 case NodeType::Scalar:
221 throw BadSubscript();
222 }
223
224 for (node_map::const_iterator it = m_map.begin(); it != m_map.end(); ++it) {
225 if (it->first->is(key))
226 return *it->second;
227 }
228
229 node& value = pMemory->create_node();
230 insert_map_pair(key, value);
231 return value;
232 }
233
remove(node & key,shared_memory_holder)234 bool node_data::remove(node& key, shared_memory_holder /* pMemory */) {
235 if (m_type != NodeType::Map)
236 return false;
237
238 for (node_map::iterator it = m_map.begin(); it != m_map.end(); ++it) {
239 if (it->first->is(key)) {
240 m_map.erase(it);
241 return true;
242 }
243 }
244
245 return false;
246 }
247
reset_sequence()248 void node_data::reset_sequence() {
249 m_sequence.clear();
250 m_seqSize = 0;
251 }
252
reset_map()253 void node_data::reset_map() {
254 m_map.clear();
255 m_undefinedPairs.clear();
256 }
257
insert_map_pair(node & key,node & value)258 void node_data::insert_map_pair(node& key, node& value) {
259 m_map.emplace_back(&key, &value);
260
261 if (!key.is_defined() || !value.is_defined())
262 m_undefinedPairs.emplace_back(&key, &value);
263 }
264
convert_to_map(shared_memory_holder pMemory)265 void node_data::convert_to_map(shared_memory_holder pMemory) {
266 switch (m_type) {
267 case NodeType::Undefined:
268 case NodeType::Null:
269 reset_map();
270 m_type = NodeType::Map;
271 break;
272 case NodeType::Sequence:
273 convert_sequence_to_map(pMemory);
274 break;
275 case NodeType::Map:
276 break;
277 case NodeType::Scalar:
278 assert(false);
279 break;
280 }
281 }
282
convert_sequence_to_map(shared_memory_holder pMemory)283 void node_data::convert_sequence_to_map(shared_memory_holder pMemory) {
284 assert(m_type == NodeType::Sequence);
285
286 reset_map();
287 for (std::size_t i = 0; i < m_sequence.size(); i++) {
288 std::stringstream stream;
289 stream << i;
290
291 node& key = pMemory->create_node();
292 key.set_scalar(stream.str());
293 insert_map_pair(key, *m_sequence[i]);
294 }
295
296 reset_sequence();
297 m_type = NodeType::Map;
298 }
299 }
300 }
301