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