Coverage Report

Created: 2025-08-28 06:18

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