99 lines
		
	
	
		
			2.5 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
		
		
			
		
	
	
			99 lines
		
	
	
		
			2.5 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| 
								 | 
							
								#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
							 |