aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/libs/yaml-cpp/src/nodeevents.cpp
blob: 726fc13ae6c0dc3cf2d544500601b686ab11a839 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
#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 { 
  AnchorByIdentity::const_iterator 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) { 
  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 (detail::const_node_iterator it = node.begin(); it != node.end(); ++it) 
      Setup(**it); 
  } else if (node.type() == NodeType::Map) { 
    for (detail::const_node_iterator it = node.begin(); it != node.end(); 
         ++it) { 
      Setup(*it->first); 
      Setup(*it->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 (detail::const_node_iterator it = node.begin(); it != node.end(); 
           ++it) 
        Emit(**it, handler, am); 
      handler.OnSequenceEnd(); 
      break; 
    case NodeType::Map: 
      handler.OnMapStart(Mark(), node.tag(), anchor, node.style()); 
      for (detail::const_node_iterator it = node.begin(); it != node.end(); 
           ++it) { 
        Emit(*it->first, handler, am); 
        Emit(*it->second, handler, am); 
      } 
      handler.OnMapEnd(); 
      break; 
  } 
} 
 
bool NodeEvents::IsAliased(const detail::node& node) const { 
  RefCount::const_iterator it = m_refCount.find(node.ref()); 
  return it != m_refCount.end() && it->second > 1; 
} 
}