#include "nodeevents.h" #include "yaml-cpp/eventhandler.h" #include "yaml-cpp/mark.h" #include "yaml-cpp/node/detail/node.h" #include "yaml-cpp/node/detail/node_iterator.h" #include "yaml-cpp/node/node.h" #include "yaml-cpp/node/type.h" namespace YAML { void NodeEvents::AliasManager::RegisterReference(const detail::node& node) { m_anchorByIdentity.insert(std::make_pair(node.ref(), _CreateNewAnchor())); } anchor_t NodeEvents::AliasManager::LookupAnchor( const detail::node& node) const { auto it = m_anchorByIdentity.find(node.ref()); if (it == m_anchorByIdentity.end()) return 0; return it->second; } NodeEvents::NodeEvents(const Node& node) : m_pMemory(node.m_pMemory), m_root(node.m_pNode), m_refCount{} { if (m_root) Setup(*m_root); } void NodeEvents::Setup(const detail::node& node) { int& refCount = m_refCount[node.ref()]; refCount++; if (refCount > 1) return; if (node.type() == NodeType::Sequence) { for (auto element : node) Setup(*element); } else if (node.type() == NodeType::Map) { for (auto element : node) { Setup(*element.first); Setup(*element.second); } } } void NodeEvents::Emit(EventHandler& handler) { AliasManager am; handler.OnDocumentStart(Mark()); if (m_root) Emit(*m_root, handler, am); handler.OnDocumentEnd(); } void NodeEvents::Emit(const detail::node& node, EventHandler& handler, AliasManager& am) const { anchor_t anchor = NullAnchor; if (IsAliased(node)) { anchor = am.LookupAnchor(node); if (anchor) { handler.OnAlias(Mark(), anchor); return; } am.RegisterReference(node); anchor = am.LookupAnchor(node); } switch (node.type()) { case NodeType::Undefined: break; case NodeType::Null: handler.OnNull(Mark(), anchor); break; case NodeType::Scalar: handler.OnScalar(Mark(), node.tag(), anchor, node.scalar()); break; case NodeType::Sequence: handler.OnSequenceStart(Mark(), node.tag(), anchor, node.style()); for (auto element : node) Emit(*element, handler, am); handler.OnSequenceEnd(); break; case NodeType::Map: handler.OnMapStart(Mark(), node.tag(), anchor, node.style()); for (auto element : node) { Emit(*element.first, handler, am); Emit(*element.second, handler, am); } handler.OnMapEnd(); break; } } bool NodeEvents::IsAliased(const detail::node& node) const { auto it = m_refCount.find(node.ref()); return it != m_refCount.end() && it->second > 1; } } // namespace YAML