Files
yaml-cpp/src/node.cpp
2010-10-18 06:45:03 +00:00

243 lines
4.7 KiB
C++

#include "node.h"
#include "aliascontent.h"
#include "aliasmanager.h"
#include "content.h"
#include "emitfromevents.h"
#include "emitter.h"
#include "eventhandler.h"
#include "iterpriv.h"
#include "map.h"
#include "nodebuilder.h"
#include "nodeproperties.h"
#include "scalar.h"
#include "scanner.h"
#include "sequence.h"
#include "tag.h"
#include "token.h"
#include <cassert>
#include <stdexcept>
namespace YAML
{
// the ordering!
bool ltnode::operator ()(const Node *pNode1, const Node *pNode2) const
{
return *pNode1 < *pNode2;
}
Node::Node(): m_type(CT_NONE), m_pContent(0), m_alias(false), m_pIdentity(this), m_referenced(false)
{
}
Node::~Node()
{
Clear();
}
void Node::Clear()
{
delete m_pContent;
m_type = CT_NONE;
m_pContent = 0;
m_alias = false;
m_referenced = false;
m_tag.clear();
}
std::auto_ptr<Node> Node::Clone() const
{
std::auto_ptr<Node> pNode(new Node);
NodeBuilder nodeBuilder(*pNode);
EmitEvents(nodeBuilder);
return pNode;
}
void Node::EmitEvents(EventHandler& eventHandler) const
{
eventHandler.OnDocumentStart(m_mark);
AliasManager am;
EmitEvents(am, eventHandler);
eventHandler.OnDocumentEnd();
}
void Node::EmitEvents(AliasManager& am, EventHandler& eventHandler) const
{
anchor_t anchor = NullAnchor;
if(m_referenced || m_alias) {
if(const Node *pOther = am.LookupReference(*this)) {
eventHandler.OnAlias(m_mark, am.LookupAnchor(*pOther));
return;
}
am.RegisterReference(*this);
anchor = am.LookupAnchor(*this);
}
if(m_pContent)
m_pContent->EmitEvents(am, eventHandler, m_mark, GetTag(), anchor);
else
eventHandler.OnNull(GetTag(), anchor);
}
void Node::Init(CONTENT_TYPE type, const Mark& mark, const std::string& tag)
{
Clear();
m_mark = mark;
m_type = type;
m_tag = tag;
m_alias = false;
m_pIdentity = this;
m_referenced = false;
switch(type) {
case CT_SCALAR:
m_pContent = new Scalar;
break;
case CT_SEQUENCE:
m_pContent = new Sequence;
break;
case CT_MAP:
m_pContent = new Map;
break;
default:
m_pContent = 0;
break;
}
}
void Node::InitNull(const std::string& tag)
{
Clear();
m_tag = tag;
m_alias = false;
m_pIdentity = this;
m_referenced = false;
}
void Node::InitAlias(const Mark& mark, const Node& identity)
{
Clear();
m_mark = mark;
m_alias = true;
m_pIdentity = &identity;
if(identity.m_pContent) {
m_pContent = new AliasContent(identity.m_pContent);
m_type = identity.GetType();
}
identity.m_referenced = true;
}
void Node::SetData(const std::string& data)
{
assert(m_pContent); // TODO: throw
m_pContent->SetData(data);
}
void Node::Append(std::auto_ptr<Node> pNode)
{
assert(m_pContent); // TODO: throw
m_pContent->Append(pNode);
}
void Node::Insert(std::auto_ptr<Node> pKey, std::auto_ptr<Node> pValue)
{
assert(m_pContent); // TODO: throw
m_pContent->Insert(pKey, pValue);
}
// begin
// Returns an iterator to the beginning of this (sequence or map).
Iterator Node::begin() const
{
if(!m_pContent)
return Iterator();
std::vector <Node *>::const_iterator seqIter;
if(m_pContent->GetBegin(seqIter))
return Iterator(new IterPriv(seqIter));
std::map <Node *, Node *, ltnode>::const_iterator mapIter;
if(m_pContent->GetBegin(mapIter))
return Iterator(new IterPriv(mapIter));
return Iterator();
}
// end
// . Returns an iterator to the end of this (sequence or map).
Iterator Node::end() const
{
if(!m_pContent)
return Iterator();
std::vector <Node *>::const_iterator seqIter;
if(m_pContent->GetEnd(seqIter))
return Iterator(new IterPriv(seqIter));
std::map <Node *, Node *, ltnode>::const_iterator mapIter;
if(m_pContent->GetEnd(mapIter))
return Iterator(new IterPriv(mapIter));
return Iterator();
}
// size
// . Returns the size of this node, if it's a sequence node.
// . Otherwise, returns zero.
std::size_t Node::size() const
{
if(!m_pContent)
return 0;
return m_pContent->GetSize();
}
const Node *Node::FindAtIndex(std::size_t i) const
{
if(!m_pContent)
return 0;
return m_pContent->GetNode(i);
}
bool Node::GetScalar(std::string& s) const
{
if(!m_pContent) {
if(m_tag.empty())
s = "~";
else
s = "";
return true;
}
return m_pContent->GetScalar(s);
}
Emitter& operator << (Emitter& out, const Node& node)
{
EmitFromEvents emitFromEvents(out);
node.EmitEvents(emitFromEvents);
return out;
}
int Node::Compare(const Node& rhs) const
{
// Step 1: no content is the smallest
if(!m_pContent) {
if(rhs.m_pContent)
return -1;
else
return 0;
}
if(!rhs.m_pContent)
return 1;
return m_pContent->Compare(rhs.m_pContent);
}
bool operator < (const Node& n1, const Node& n2)
{
return n1.Compare(n2) < 0;
}
}