nodeevents.cpp (2607B)
1 #include "nodeevents.h" 2 #include "yaml-cpp/eventhandler.h" 3 #include "yaml-cpp/mark.h" 4 #include "yaml-cpp/node/detail/node.h" 5 #include "yaml-cpp/node/detail/node_iterator.h" 6 #include "yaml-cpp/node/node.h" 7 #include "yaml-cpp/node/type.h" 8 9 namespace YAML { 10 void NodeEvents::AliasManager::RegisterReference(const detail::node& node) { 11 m_anchorByIdentity.insert(std::make_pair(node.ref(), _CreateNewAnchor())); 12 } 13 14 anchor_t NodeEvents::AliasManager::LookupAnchor( 15 const detail::node& node) const { 16 auto it = m_anchorByIdentity.find(node.ref()); 17 if (it == m_anchorByIdentity.end()) 18 return 0; 19 return it->second; 20 } 21 22 NodeEvents::NodeEvents(const Node& node) 23 : m_pMemory(node.m_pMemory), m_root(node.m_pNode), m_refCount{} { 24 if (m_root) 25 Setup(*m_root); 26 } 27 28 void NodeEvents::Setup(const detail::node& node) { 29 int& refCount = m_refCount[node.ref()]; 30 refCount++; 31 if (refCount > 1) 32 return; 33 34 if (node.type() == NodeType::Sequence) { 35 for (auto element : node) 36 Setup(*element); 37 } else if (node.type() == NodeType::Map) { 38 for (auto element : node) { 39 Setup(*element.first); 40 Setup(*element.second); 41 } 42 } 43 } 44 45 void NodeEvents::Emit(EventHandler& handler) { 46 AliasManager am; 47 48 handler.OnDocumentStart(Mark()); 49 if (m_root) 50 Emit(*m_root, handler, am); 51 handler.OnDocumentEnd(); 52 } 53 54 void NodeEvents::Emit(const detail::node& node, EventHandler& handler, 55 AliasManager& am) const { 56 anchor_t anchor = NullAnchor; 57 if (IsAliased(node)) { 58 anchor = am.LookupAnchor(node); 59 if (anchor) { 60 handler.OnAlias(Mark(), anchor); 61 return; 62 } 63 64 am.RegisterReference(node); 65 anchor = am.LookupAnchor(node); 66 } 67 68 switch (node.type()) { 69 case NodeType::Undefined: 70 break; 71 case NodeType::Null: 72 handler.OnNull(Mark(), anchor); 73 break; 74 case NodeType::Scalar: 75 handler.OnScalar(Mark(), node.tag(), anchor, node.scalar()); 76 break; 77 case NodeType::Sequence: 78 handler.OnSequenceStart(Mark(), node.tag(), anchor, node.style()); 79 for (auto element : node) 80 Emit(*element, handler, am); 81 handler.OnSequenceEnd(); 82 break; 83 case NodeType::Map: 84 handler.OnMapStart(Mark(), node.tag(), anchor, node.style()); 85 for (auto element : node) { 86 Emit(*element.first, handler, am); 87 Emit(*element.second, handler, am); 88 } 89 handler.OnMapEnd(); 90 break; 91 } 92 } 93 94 bool NodeEvents::IsAliased(const detail::node& node) const { 95 auto it = m_refCount.find(node.ref()); 96 return it != m_refCount.end() && it->second > 1; 97 } 98 } // namespace YAML