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