Skip to content

Commit

Permalink
Merged aliases branch into trunk, changes r100:150
Browse files Browse the repository at this point in the history
  • Loading branch information
jbeder committed May 22, 2009
1 parent 9d0e0c6 commit b3a5a51
Show file tree
Hide file tree
Showing 13 changed files with 308 additions and 18 deletions.
2 changes: 2 additions & 0 deletions include/exceptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ namespace YAML
const std::string CHAR_IN_ANCHOR = "illegal character found while scanning anchor";
const std::string ZERO_INDENT_IN_BLOCK = "cannot set zero indentation for a block scalar";
const std::string CHAR_IN_BLOCK = "unexpected character in block scalar";
const std::string AMBIGUOUS_ANCHOR = "cannot assign the same alias to multiple nodes";
const std::string UNKNOWN_ANCHOR = "the referenced anchor is not defined";

const std::string INVALID_SCALAR = "invalid scalar";
const std::string KEY_NOT_FOUND = "key not found";
Expand Down
7 changes: 7 additions & 0 deletions include/node.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,11 @@ namespace YAML
const Node& operator [] (unsigned u) const;
const Node& operator [] (int i) const;

// for anchors/aliases
const Node *Identity() const { return m_pIdentity; }
bool IsAlias() const { return m_alias; }
bool IsReferenced() const { return m_referenced; }

// insertion
friend std::ostream& operator << (std::ostream& out, const Node& node);

Expand All @@ -89,6 +94,8 @@ namespace YAML
std::string m_anchor, m_tag;
Content *m_pContent;
bool m_alias;
const Node *m_pIdentity;
mutable bool m_referenced;
};

// templated things we need to keep inline in the header
Expand Down
2 changes: 1 addition & 1 deletion src/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
set(FILES content.cpp iterator.cpp node.cpp parserstate.cpp
set(FILES alias.cpp content.cpp iterator.cpp node.cpp parserstate.cpp
scalar.cpp scanscalar.cpp sequence.cpp stream.cpp
exp.cpp map.cpp parser.cpp regex.cpp scanner.cpp
scantoken.cpp simplekey.cpp)
Expand Down
125 changes: 125 additions & 0 deletions src/alias.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
#include "crt.h"
#include "alias.h"
#include <iostream>

namespace YAML
{
Alias::Alias(Content* pNodeContent)
: m_pRef(pNodeContent)
{
}

void Alias::Parse(Scanner *pScanner, const ParserState& state)
{
}

void Alias::Write(std::ostream& out, int indent, bool startedLine, bool onlyOneCharOnLine)
{
out << "\n";
}

bool Alias::GetBegin(std::vector <Node *>::const_iterator& i) const
{
return m_pRef->GetBegin(i);
}

bool Alias::GetBegin(std::map <Node *, Node *, ltnode>::const_iterator& i) const
{
return m_pRef->GetBegin(i);
}

bool Alias::GetEnd(std::vector <Node *>::const_iterator& i) const
{
return m_pRef->GetEnd(i);
}

bool Alias::GetEnd(std::map <Node *, Node *, ltnode>::const_iterator& i) const
{
return m_pRef->GetEnd(i);
}

Node* Alias::GetNode(unsigned n) const
{
return m_pRef->GetNode(n);
}

unsigned Alias::GetSize() const
{
return m_pRef->GetSize();
}

bool Alias::IsScalar() const
{
return m_pRef->IsScalar();
}

bool Alias::IsMap() const
{
return m_pRef->IsMap();
}

bool Alias::IsSequence() const
{
return m_pRef->IsSequence();
}

bool Alias::Read(std::string& v) const
{
return m_pRef->Read(v);
}

bool Alias::Read(int& v) const
{
return m_pRef->Read(v);
}

bool Alias::Read(unsigned& v) const
{
return m_pRef->Read(v);
}

bool Alias::Read(long& v) const
{
return m_pRef->Read(v);
}

bool Alias::Read(float& v) const
{
return m_pRef->Read(v);
}

bool Alias::Read(double& v) const
{
return m_pRef->Read(v);
}

bool Alias::Read(char& v) const
{
return m_pRef->Read(v);
}

bool Alias::Read(bool& v) const
{
return m_pRef->Read(v);
}

int Alias::Compare(Content *pContent)
{
return m_pRef->Compare(pContent);
}

int Alias::Compare(Scalar *pScalar)
{
return m_pRef->Compare(pScalar);
}

int Alias::Compare(Sequence *pSequence)
{
return m_pRef->Compare(pSequence);
}

int Alias::Compare(Map *pMap)
{
return m_pRef->Compare(pMap);
}
}
42 changes: 42 additions & 0 deletions src/alias.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
#pragma once

#include "content.h"

namespace YAML
{
class Alias : public Content
{
public:
Alias(Content *pNodeContent);

virtual void Parse(Scanner* pScanner, const ParserState& state);
virtual void Write(std::ostream& out, int indent, bool startedLine, bool onlyOneCharOnLine);

virtual bool GetBegin(std::vector <Node *>::const_iterator&) const;
virtual bool GetBegin(std::map <Node *, Node *, ltnode>::const_iterator&) const;
virtual bool GetEnd(std::vector <Node *>::const_iterator&) const;
virtual bool GetEnd(std::map <Node *, Node *, ltnode>::const_iterator&) const;
virtual Node* GetNode(unsigned) const;
virtual unsigned GetSize() const;
virtual bool IsScalar() const;
virtual bool IsMap() const;
virtual bool IsSequence() const;

virtual bool Read(std::string&) const;
virtual bool Read(int&) const;
virtual bool Read(unsigned&) const;
virtual bool Read(long&) const;
virtual bool Read(float&) const;
virtual bool Read(double&) const;
virtual bool Read(char&) const;
virtual bool Read(bool&) const;

virtual int Compare(Content *);
virtual int Compare(Scalar *);
virtual int Compare(Sequence *);
virtual int Compare(Map *);

private:
Content* m_pRef;
};
}
70 changes: 54 additions & 16 deletions src/node.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@
#include "scalar.h"
#include "sequence.h"
#include "map.h"
#include "alias.h"
#include "iterpriv.h"
#include <iostream>

namespace YAML
{
Expand All @@ -17,7 +19,7 @@ namespace YAML
return *pNode1 < *pNode2;
}

Node::Node(): m_pContent(0), m_alias(false)
Node::Node(): m_pContent(0), m_alias(false), m_pIdentity(this), m_referenced(true)
{
}

Expand All @@ -31,6 +33,9 @@ namespace YAML
delete m_pContent;
m_pContent = 0;
m_alias = false;
m_referenced = false;
m_anchor.clear();
m_tag.clear();
}

void Node::Parse(Scanner *pScanner, const ParserState& state)
Expand All @@ -47,30 +52,50 @@ namespace YAML

ParseHeader(pScanner, state);

// is this an alias? if so, it can have no content
if(m_alias)
// is this an alias? if so, its contents are an alias to
// a previously defined anchor
if(m_alias) {
// the scanner throws an exception if it doesn't know this anchor name
const Node *pReferencedNode = pScanner->Retrieve(m_anchor);
m_pIdentity = pReferencedNode;

// mark the referenced node for the sake of the client code
pReferencedNode->m_referenced = true;

// use of an Alias object keeps the referenced content from
// being deleted twice
Content *pAliasedContent = pReferencedNode->m_pContent;
if(pAliasedContent)
m_pContent = new Alias(pAliasedContent);

return;
}

// now split based on what kind of node we should be
switch(pScanner->peek().type) {
case TT_SCALAR:
m_pContent = new Scalar;
m_pContent->Parse(pScanner, state);
break;
case TT_FLOW_SEQ_START:
case TT_BLOCK_SEQ_START:
case TT_BLOCK_ENTRY:
m_pContent = new Sequence;
m_pContent->Parse(pScanner, state);
break;
case TT_FLOW_MAP_START:
case TT_BLOCK_MAP_START:
m_pContent = new Map;
m_pContent->Parse(pScanner, state);
break;
default:
break;
}

// Have to save anchor before parsing to allow for aliases as
// contained node (recursive structure)
if(!m_anchor.empty())
pScanner->Save(m_anchor, this);

if(m_pContent)
m_pContent->Parse(pScanner, state);
}

// ParseHeader
Expand Down Expand Up @@ -129,33 +154,46 @@ namespace YAML

void Node::Write(std::ostream& out, int indent, bool startedLine, bool onlyOneCharOnLine) const
{
// If using an anchor or tag for the whole document, document start
// must be explicit
bool indicateDocStart = (indent == 0);

// write anchor/alias
if(m_anchor != "") {
if (indicateDocStart) {
out << "--- ";
indicateDocStart = false;
}

if(m_alias)
out << std::string("*");
out << "*";
else
out << std::string("&");
out << m_anchor << std::string(" ");
out << "&";
out << m_anchor << " ";
startedLine = true;
onlyOneCharOnLine = false;
}

// write tag
if(m_tag != "") {
if (indicateDocStart) {
out << "--- ";
indicateDocStart = false;
}

// put the tag in the "proper" brackets
if(m_tag.substr(0, 2) == "!<" && m_tag.substr(m_tag.size() - 1) == ">")
out << m_tag;
if(m_tag.substr(0, 2) == std::string("!<") && m_tag.substr(m_tag.size() - 1) == std::string(">"))
out << m_tag << " ";
else
out << std::string("!<") << m_tag << std::string("> ");
out << "!<" << m_tag << "> ";
startedLine = true;
onlyOneCharOnLine = false;
}

if(!m_pContent) {
out << std::string("\n");
} else {
if(!m_pContent)
out << "\n";
else
m_pContent->Write(out, indent, startedLine, onlyOneCharOnLine);
}
}

CONTENT_TYPE Node::GetType() const
Expand Down
3 changes: 3 additions & 0 deletions src/parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,9 @@ namespace YAML
// and finally eat any doc ends we see
while(!m_pScanner->empty() && m_pScanner->peek().type == TT_DOC_END)
m_pScanner->pop();

// clear anchors from the scanner, which are no longer relevant
m_pScanner->ClearAnchors();
}

// ParseDirectives
Expand Down
Loading

0 comments on commit b3a5a51

Please sign in to comment.