mirror of
https://github.com/jbeder/yaml-cpp.git
synced 2025-09-09 20:51:16 +00:00
99 lines
2.5 KiB
C++
99 lines
2.5 KiB
C++
#include "valueevents.h"
|
|
#include "yaml-cpp/value.h"
|
|
#include "yaml-cpp/eventhandler.h"
|
|
#include "yaml-cpp/mark.h"
|
|
|
|
namespace YAML
|
|
{
|
|
void ValueEvents::AliasManager::RegisterReference(const detail::node& node)
|
|
{
|
|
m_anchorByIdentity.insert(std::make_pair(node.ref(), _CreateNewAnchor()));
|
|
}
|
|
|
|
anchor_t ValueEvents::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;
|
|
}
|
|
|
|
ValueEvents::ValueEvents(const Value& value): m_pMemory(value.m_pMemory), m_root(*value.m_pNode)
|
|
{
|
|
Setup(m_root);
|
|
}
|
|
|
|
void ValueEvents::Setup(const detail::node& node)
|
|
{
|
|
int& refCount = m_refCount[node.ref()];
|
|
refCount++;
|
|
if(refCount > 1)
|
|
return;
|
|
|
|
if(node.type() == ValueType::Sequence) {
|
|
for(detail::const_node_iterator it=node.begin();it!=node.end();++it)
|
|
Setup(**it);
|
|
} else if(node.type() == ValueType::Map) {
|
|
for(detail::const_node_iterator it=node.begin();it!=node.end();++it) {
|
|
Setup(*it->first);
|
|
Setup(*it->second);
|
|
}
|
|
}
|
|
}
|
|
|
|
void ValueEvents::Emit(EventHandler& handler)
|
|
{
|
|
AliasManager am;
|
|
|
|
handler.OnDocumentStart(Mark());
|
|
Emit(m_root, handler, am);
|
|
handler.OnDocumentEnd();
|
|
}
|
|
|
|
void ValueEvents::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 ValueType::Undefined:
|
|
break;
|
|
case ValueType::Null:
|
|
handler.OnNull(Mark(), anchor);
|
|
break;
|
|
case ValueType::Scalar:
|
|
handler.OnScalar(Mark(), "", anchor, node.scalar());
|
|
break;
|
|
case ValueType::Sequence:
|
|
handler.OnSequenceStart(Mark(), "", anchor);
|
|
for(detail::const_node_iterator it=node.begin();it!=node.end();++it)
|
|
Emit(**it, handler, am);
|
|
handler.OnSequenceEnd();
|
|
break;
|
|
case ValueType::Map:
|
|
handler.OnMapStart(Mark(), "", anchor);
|
|
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 ValueEvents::IsAliased(const detail::node& node) const
|
|
{
|
|
RefCount::const_iterator it = m_refCount.find(node.ref());
|
|
return it != m_refCount.end() && it->second > 1;
|
|
}
|
|
}
|