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