mirror of
https://github.com/jbeder/yaml-cpp.git
synced 2025-09-09 20:51:16 +00:00
Implemented value events emitter
This commit is contained in:
@@ -1,14 +1,29 @@
|
|||||||
#include "valueevents.h"
|
#include "valueevents.h"
|
||||||
#include "yaml-cpp/value.h"
|
#include "yaml-cpp/value.h"
|
||||||
|
#include "yaml-cpp/eventhandler.h"
|
||||||
|
#include "yaml-cpp/mark.h"
|
||||||
|
|
||||||
namespace YAML
|
namespace YAML
|
||||||
{
|
{
|
||||||
ValueEvents::ValueEvents(const Value& value): m_pMemory(value.m_pMemory), m_root(*value.m_pNode)
|
void ValueEvents::AliasManager::RegisterReference(const detail::node& node)
|
||||||
{
|
{
|
||||||
Visit(m_root);
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ValueEvents::Visit(const detail::node& node)
|
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()];
|
int& refCount = m_refCount[node.ref()];
|
||||||
refCount++;
|
refCount++;
|
||||||
@@ -17,12 +32,67 @@ namespace YAML
|
|||||||
|
|
||||||
if(node.type() == ValueType::Sequence) {
|
if(node.type() == ValueType::Sequence) {
|
||||||
for(detail::const_node_iterator it=node.begin();it!=node.end();++it)
|
for(detail::const_node_iterator it=node.begin();it!=node.end();++it)
|
||||||
Visit(**it);
|
Setup(**it);
|
||||||
} else if(node.type() == ValueType::Map) {
|
} else if(node.type() == ValueType::Map) {
|
||||||
for(detail::const_node_iterator it=node.begin();it!=node.end();++it) {
|
for(detail::const_node_iterator it=node.begin();it!=node.end();++it) {
|
||||||
Visit(*it->first);
|
Setup(*it->first);
|
||||||
Visit(*it->second);
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -13,14 +13,36 @@
|
|||||||
namespace YAML
|
namespace YAML
|
||||||
{
|
{
|
||||||
class Value;
|
class Value;
|
||||||
|
class EventHandler;
|
||||||
|
|
||||||
class ValueEvents
|
class ValueEvents
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ValueEvents(const Value& value);
|
ValueEvents(const Value& value);
|
||||||
|
|
||||||
|
void Emit(EventHandler& handler);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void Visit(const detail::node& node);
|
class AliasManager {
|
||||||
|
public:
|
||||||
|
AliasManager(): m_curAnchor(0) {}
|
||||||
|
|
||||||
|
void RegisterReference(const detail::node& node);
|
||||||
|
anchor_t LookupAnchor(const detail::node& node) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
anchor_t _CreateNewAnchor() { return ++m_curAnchor; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
typedef std::map<const detail::node_ref*, anchor_t> AnchorByIdentity;
|
||||||
|
AnchorByIdentity m_anchorByIdentity;
|
||||||
|
|
||||||
|
anchor_t m_curAnchor;
|
||||||
|
};
|
||||||
|
|
||||||
|
void Setup(const detail::node& node);
|
||||||
|
void Emit(const detail::node& node, EventHandler& handler, AliasManager& am) const;
|
||||||
|
bool IsAliased(const detail::node& node) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
detail::shared_memory_holder m_pMemory;
|
detail::shared_memory_holder m_pMemory;
|
||||||
|
Reference in New Issue
Block a user