mirror of
https://github.com/jbeder/yaml-cpp.git
synced 2025-09-09 20:51:16 +00:00
Merged r444:449 from the node refactoring branch to the trunk
This commit is contained in:
280
src/node.cpp
280
src/node.cpp
@@ -1,33 +1,29 @@
|
||||
#include "yaml-cpp/node.h"
|
||||
#include "aliascontent.h"
|
||||
#include "iterpriv.h"
|
||||
#include "nodebuilder.h"
|
||||
#include "nodeownership.h"
|
||||
#include "scanner.h"
|
||||
#include "tag.h"
|
||||
#include "token.h"
|
||||
#include "yaml-cpp/aliasmanager.h"
|
||||
#include "content.h"
|
||||
#include "yaml-cpp/emitfromevents.h"
|
||||
#include "yaml-cpp/emitter.h"
|
||||
#include "yaml-cpp/eventhandler.h"
|
||||
#include "iterpriv.h"
|
||||
#include "map.h"
|
||||
#include "nodebuilder.h"
|
||||
#include "yaml-cpp/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
|
||||
{
|
||||
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_referenced(false)
|
||||
Node::Node(): m_pOwnership(new NodeOwnership), m_type(NodeType::Null)
|
||||
{
|
||||
}
|
||||
|
||||
Node::Node(NodeOwnership& owner): m_pOwnership(new NodeOwnership(&owner)), m_type(NodeType::Null)
|
||||
{
|
||||
m_pIdentity = this;
|
||||
}
|
||||
|
||||
Node::~Node()
|
||||
@@ -37,14 +33,24 @@ namespace YAML
|
||||
|
||||
void Node::Clear()
|
||||
{
|
||||
delete m_pContent;
|
||||
m_type = CT_NONE;
|
||||
m_pContent = 0;
|
||||
m_alias = false;
|
||||
m_referenced = false;
|
||||
m_pOwnership.reset(new NodeOwnership);
|
||||
m_type = NodeType::Null;
|
||||
m_tag.clear();
|
||||
m_scalarData.clear();
|
||||
m_seqData.clear();
|
||||
m_mapData.clear();
|
||||
}
|
||||
|
||||
bool Node::IsAliased() const
|
||||
{
|
||||
return m_pOwnership->IsAliased(*this);
|
||||
}
|
||||
|
||||
Node& Node::CreateNode()
|
||||
{
|
||||
return m_pOwnership->Create();
|
||||
}
|
||||
|
||||
std::auto_ptr<Node> Node::Clone() const
|
||||
{
|
||||
std::auto_ptr<Node> pNode(new Node);
|
||||
@@ -64,9 +70,10 @@ namespace YAML
|
||||
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));
|
||||
if(IsAliased()) {
|
||||
anchor = am.LookupAnchor(*this);
|
||||
if(anchor) {
|
||||
eventHandler.OnAlias(m_mark, anchor);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -74,93 +81,76 @@ namespace YAML
|
||||
anchor = am.LookupAnchor(*this);
|
||||
}
|
||||
|
||||
if(m_pContent)
|
||||
m_pContent->EmitEvents(am, eventHandler, m_mark, GetTag(), anchor);
|
||||
else
|
||||
eventHandler.OnNull(GetTag(), anchor);
|
||||
switch(m_type) {
|
||||
case NodeType::Null:
|
||||
eventHandler.OnNull(m_mark, anchor);
|
||||
break;
|
||||
case NodeType::Scalar:
|
||||
eventHandler.OnScalar(m_mark, m_tag, anchor, m_scalarData);
|
||||
break;
|
||||
case NodeType::Sequence:
|
||||
eventHandler.OnSequenceStart(m_mark, m_tag, anchor);
|
||||
for(std::size_t i=0;i<m_seqData.size();i++)
|
||||
m_seqData[i]->EmitEvents(am, eventHandler);
|
||||
eventHandler.OnSequenceEnd();
|
||||
break;
|
||||
case NodeType::Map:
|
||||
eventHandler.OnMapStart(m_mark, m_tag, anchor);
|
||||
for(node_map::const_iterator it=m_mapData.begin();it!=m_mapData.end();++it) {
|
||||
it->first->EmitEvents(am, eventHandler);
|
||||
it->second->EmitEvents(am, eventHandler);
|
||||
}
|
||||
eventHandler.OnMapEnd();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void Node::Init(CONTENT_TYPE type, const Mark& mark, const std::string& tag)
|
||||
void Node::Init(NodeType::value 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)
|
||||
void Node::MarkAsAliased()
|
||||
{
|
||||
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);
|
||||
m_pOwnership->MarkAsAliased(*this);
|
||||
}
|
||||
|
||||
void Node::Insert(std::auto_ptr<Node> pKey, std::auto_ptr<Node> pValue)
|
||||
void Node::SetScalarData(const std::string& data)
|
||||
{
|
||||
assert(m_pContent); // TODO: throw
|
||||
m_pContent->Insert(pKey, pValue);
|
||||
assert(m_type == NodeType::Scalar); // TODO: throw?
|
||||
m_scalarData = data;
|
||||
}
|
||||
|
||||
void Node::Append(Node& node)
|
||||
{
|
||||
assert(m_type == NodeType::Sequence); // TODO: throw?
|
||||
m_seqData.push_back(&node);
|
||||
}
|
||||
|
||||
void Node::Insert(Node& key, Node& value)
|
||||
{
|
||||
assert(m_type == NodeType::Map); // TODO: throw?
|
||||
m_mapData[&key] = &value;
|
||||
}
|
||||
|
||||
// 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));
|
||||
|
||||
switch(m_type) {
|
||||
case NodeType::Null:
|
||||
case NodeType::Scalar:
|
||||
return Iterator();
|
||||
case NodeType::Sequence:
|
||||
return Iterator(std::auto_ptr<IterPriv>(new IterPriv(m_seqData.begin())));
|
||||
case NodeType::Map:
|
||||
return Iterator(std::auto_ptr<IterPriv>(new IterPriv(m_mapData.begin())));
|
||||
}
|
||||
|
||||
assert(false);
|
||||
return Iterator();
|
||||
}
|
||||
|
||||
@@ -168,50 +158,62 @@ namespace YAML
|
||||
// . 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));
|
||||
|
||||
switch(m_type) {
|
||||
case NodeType::Null:
|
||||
case NodeType::Scalar:
|
||||
return Iterator();
|
||||
case NodeType::Sequence:
|
||||
return Iterator(std::auto_ptr<IterPriv>(new IterPriv(m_seqData.end())));
|
||||
case NodeType::Map:
|
||||
return Iterator(std::auto_ptr<IterPriv>(new IterPriv(m_mapData.end())));
|
||||
}
|
||||
|
||||
assert(false);
|
||||
return Iterator();
|
||||
}
|
||||
|
||||
// size
|
||||
// . Returns the size of this node, if it's a sequence node.
|
||||
// . Returns the size of a sequence or map node
|
||||
// . Otherwise, returns zero.
|
||||
std::size_t Node::size() const
|
||||
{
|
||||
if(!m_pContent)
|
||||
return 0;
|
||||
|
||||
return m_pContent->GetSize();
|
||||
switch(m_type) {
|
||||
case NodeType::Null:
|
||||
case NodeType::Scalar:
|
||||
return 0;
|
||||
case NodeType::Sequence:
|
||||
return m_seqData.size();
|
||||
case NodeType::Map:
|
||||
return m_mapData.size();
|
||||
}
|
||||
|
||||
assert(false);
|
||||
return 0;
|
||||
}
|
||||
|
||||
const Node *Node::FindAtIndex(std::size_t i) const
|
||||
{
|
||||
if(!m_pContent)
|
||||
return 0;
|
||||
|
||||
return m_pContent->GetNode(i);
|
||||
if(m_type == NodeType::Sequence)
|
||||
return m_seqData[i];
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool Node::GetScalar(std::string& s) const
|
||||
{
|
||||
if(!m_pContent) {
|
||||
if(m_tag.empty())
|
||||
switch(m_type) {
|
||||
case NodeType::Null:
|
||||
s = "~";
|
||||
else
|
||||
s = "";
|
||||
return true;
|
||||
return true;
|
||||
case NodeType::Scalar:
|
||||
s = m_scalarData;
|
||||
return true;
|
||||
case NodeType::Sequence:
|
||||
case NodeType::Map:
|
||||
return false;
|
||||
}
|
||||
|
||||
return m_pContent->GetScalar(s);
|
||||
assert(false);
|
||||
return false;
|
||||
}
|
||||
|
||||
Emitter& operator << (Emitter& out, const Node& node)
|
||||
@@ -223,17 +225,41 @@ namespace YAML
|
||||
|
||||
int Node::Compare(const Node& rhs) const
|
||||
{
|
||||
// Step 1: no content is the smallest
|
||||
if(!m_pContent) {
|
||||
if(rhs.m_pContent)
|
||||
return -1;
|
||||
else
|
||||
if(m_type != rhs.m_type)
|
||||
return rhs.m_type - m_type;
|
||||
|
||||
switch(m_type) {
|
||||
case NodeType::Null:
|
||||
return 0;
|
||||
case NodeType::Scalar:
|
||||
return m_scalarData.compare(rhs.m_scalarData);
|
||||
case NodeType::Sequence:
|
||||
if(m_seqData.size() < rhs.m_seqData.size())
|
||||
return 1;
|
||||
else if(m_seqData.size() > rhs.m_seqData.size())
|
||||
return -1;
|
||||
for(std::size_t i=0;i<m_seqData.size();i++)
|
||||
if(int cmp = m_seqData[i]->Compare(*rhs.m_seqData[i]))
|
||||
return cmp;
|
||||
return 0;
|
||||
case NodeType::Map:
|
||||
if(m_mapData.size() < rhs.m_mapData.size())
|
||||
return 1;
|
||||
else if(m_mapData.size() > rhs.m_mapData.size())
|
||||
return -1;
|
||||
node_map::const_iterator it = m_mapData.begin();
|
||||
node_map::const_iterator jt = rhs.m_mapData.begin();
|
||||
for(;it!=m_mapData.end() && jt!=rhs.m_mapData.end();it++, jt++) {
|
||||
if(int cmp = it->first->Compare(*jt->first))
|
||||
return cmp;
|
||||
if(int cmp = it->second->Compare(*jt->second))
|
||||
return cmp;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
if(!rhs.m_pContent)
|
||||
return 1;
|
||||
|
||||
return m_pContent->Compare(rhs.m_pContent);
|
||||
|
||||
assert(false);
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool operator < (const Node& n1, const Node& n2)
|
||||
|
Reference in New Issue
Block a user