mirror of https://github.com/axmolengine/axmol.git
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
|