nodeevents.cpp 2.59 KB
Newer Older
1
2
3
#include "nodeevents.h"
#include "yaml-cpp/eventhandler.h"
#include "yaml-cpp/mark.h"
Jesse Beder's avatar
Jesse Beder committed
4
5
6
7
#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"
8

Jesse Beder's avatar
Jesse Beder committed
9
10
11
12
13
namespace YAML {
void NodeEvents::AliasManager::RegisterReference(const detail::node& node) {
  m_anchorByIdentity.insert(std::make_pair(node.ref(), _CreateNewAnchor()));
}

Jesse Beder's avatar
Jesse Beder committed
14
15
anchor_t NodeEvents::AliasManager::LookupAnchor(
    const detail::node& node) const {
Jesse Beder's avatar
Jesse Beder committed
16
17
18
19
20
21
22
  AnchorByIdentity::const_iterator it = m_anchorByIdentity.find(node.ref());
  if (it == m_anchorByIdentity.end())
    return 0;
  return it->second;
}

NodeEvents::NodeEvents(const Node& node)
23
    : m_pMemory(node.m_pMemory), m_root(node.m_pNode), m_refCount{} {
Jesse Beder's avatar
Jesse Beder committed
24
25
26
27
28
29
30
31
32
  if (m_root)
    Setup(*m_root);
}

void NodeEvents::Setup(const detail::node& node) {
  int& refCount = m_refCount[node.ref()];
  refCount++;
  if (refCount > 1)
    return;
33

Jesse Beder's avatar
Jesse Beder committed
34
  if (node.type() == NodeType::Sequence) {
35
36
    for (auto element : node)
      Setup(*element);
Jesse Beder's avatar
Jesse Beder committed
37
  } else if (node.type() == NodeType::Map) {
38
39
40
    for (auto element : node) {
      Setup(*element.first);
      Setup(*element.second);
Jesse Beder's avatar
Jesse Beder committed
41
42
43
44
45
46
47
48
49
50
51
52
    }
  }
}

void NodeEvents::Emit(EventHandler& handler) {
  AliasManager am;

  handler.OnDocumentStart(Mark());
  if (m_root)
    Emit(*m_root, handler, am);
  handler.OnDocumentEnd();
}
53

Jesse Beder's avatar
Jesse Beder committed
54
55
56
57
58
59
60
61
62
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;
    }
63

Jesse Beder's avatar
Jesse Beder committed
64
65
66
    am.RegisterReference(node);
    anchor = am.LookupAnchor(node);
  }
67

Jesse Beder's avatar
Jesse Beder committed
68
69
70
71
72
73
74
75
76
77
  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:
78
      handler.OnSequenceStart(Mark(), node.tag(), anchor, node.style());
79
80
      for (auto element : node)
        Emit(*element, handler, am);
Jesse Beder's avatar
Jesse Beder committed
81
82
83
      handler.OnSequenceEnd();
      break;
    case NodeType::Map:
84
      handler.OnMapStart(Mark(), node.tag(), anchor, node.style());
85
86
87
      for (auto element : node) {
        Emit(*element.first, handler, am);
        Emit(*element.second, handler, am);
Jesse Beder's avatar
Jesse Beder committed
88
89
90
91
92
      }
      handler.OnMapEnd();
      break;
  }
}
93

Jesse Beder's avatar
Jesse Beder committed
94
95
96
97
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;
}
98
}  // namespace YAML