yaml-cpp

FORK: A YAML parser and emitter in C++
git clone https://git.neptards.moe/neptards/yaml-cpp.git
Log | Files | Refs | README | LICENSE

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