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

nodebuilder.cpp (3224B)


      1 #include <cassert>
      2 
      3 #include "nodebuilder.h"
      4 #include "yaml-cpp/node/detail/node.h"
      5 #include "yaml-cpp/node/impl.h"
      6 #include "yaml-cpp/node/node.h"
      7 #include "yaml-cpp/node/type.h"
      8 
      9 namespace YAML {
     10 struct Mark;
     11 
     12 NodeBuilder::NodeBuilder()
     13     : m_pMemory(new detail::memory_holder),
     14       m_pRoot(nullptr),
     15       m_stack{},
     16       m_anchors{},
     17       m_keys{},
     18       m_mapDepth(0) {
     19   m_anchors.push_back(nullptr);  // since the anchors start at 1
     20 }
     21 
     22 NodeBuilder::~NodeBuilder() = default;
     23 
     24 Node NodeBuilder::Root() {
     25   if (!m_pRoot)
     26     return Node();
     27 
     28   return Node(*m_pRoot, m_pMemory);
     29 }
     30 
     31 void NodeBuilder::OnDocumentStart(const Mark&) {}
     32 
     33 void NodeBuilder::OnDocumentEnd() {}
     34 
     35 void NodeBuilder::OnNull(const Mark& mark, anchor_t anchor) {
     36   detail::node& node = Push(mark, anchor);
     37   node.set_null();
     38   Pop();
     39 }
     40 
     41 void NodeBuilder::OnAlias(const Mark& /* mark */, anchor_t anchor) {
     42   detail::node& node = *m_anchors[anchor];
     43   Push(node);
     44   Pop();
     45 }
     46 
     47 void NodeBuilder::OnScalar(const Mark& mark, const std::string& tag,
     48                            anchor_t anchor, const std::string& value) {
     49   detail::node& node = Push(mark, anchor);
     50   node.set_scalar(value);
     51   node.set_tag(tag);
     52   Pop();
     53 }
     54 
     55 void NodeBuilder::OnSequenceStart(const Mark& mark, const std::string& tag,
     56                                   anchor_t anchor, EmitterStyle::value style) {
     57   detail::node& node = Push(mark, anchor);
     58   node.set_tag(tag);
     59   node.set_type(NodeType::Sequence);
     60   node.set_style(style);
     61 }
     62 
     63 void NodeBuilder::OnSequenceEnd() { Pop(); }
     64 
     65 void NodeBuilder::OnMapStart(const Mark& mark, const std::string& tag,
     66                              anchor_t anchor, EmitterStyle::value style) {
     67   detail::node& node = Push(mark, anchor);
     68   node.set_type(NodeType::Map);
     69   node.set_tag(tag);
     70   node.set_style(style);
     71   m_mapDepth++;
     72 }
     73 
     74 void NodeBuilder::OnMapEnd() {
     75   assert(m_mapDepth > 0);
     76   m_mapDepth--;
     77   Pop();
     78 }
     79 
     80 detail::node& NodeBuilder::Push(const Mark& mark, anchor_t anchor) {
     81   detail::node& node = m_pMemory->create_node();
     82   node.set_mark(mark);
     83   RegisterAnchor(anchor, node);
     84   Push(node);
     85   return node;
     86 }
     87 
     88 void NodeBuilder::Push(detail::node& node) {
     89   const bool needsKey =
     90       (!m_stack.empty() && m_stack.back()->type() == NodeType::Map &&
     91        m_keys.size() < m_mapDepth);
     92 
     93   m_stack.push_back(&node);
     94   if (needsKey)
     95     m_keys.emplace_back(&node, false);
     96 }
     97 
     98 void NodeBuilder::Pop() {
     99   assert(!m_stack.empty());
    100   if (m_stack.size() == 1) {
    101     m_pRoot = m_stack[0];
    102     m_stack.pop_back();
    103     return;
    104   }
    105 
    106   detail::node& node = *m_stack.back();
    107   m_stack.pop_back();
    108 
    109   detail::node& collection = *m_stack.back();
    110 
    111   if (collection.type() == NodeType::Sequence) {
    112     collection.push_back(node, m_pMemory);
    113   } else if (collection.type() == NodeType::Map) {
    114     assert(!m_keys.empty());
    115     PushedKey& key = m_keys.back();
    116     if (key.second) {
    117       collection.insert(*key.first, node, m_pMemory);
    118       m_keys.pop_back();
    119     } else {
    120       key.second = true;
    121     }
    122   } else {
    123     assert(false);
    124     m_stack.clear();
    125   }
    126 }
    127 
    128 void NodeBuilder::RegisterAnchor(anchor_t anchor, detail::node& node) {
    129   if (anchor) {
    130     assert(anchor == m_anchors.size());
    131     m_anchors.push_back(&node);
    132   }
    133 }
    134 }  // namespace YAML