Added emitting for a YAML::Node (instead of the ad-hoc std::ostream overload) so it'll actually emit valid YAML always

This commit is contained in:
Jesse Beder
2009-07-10 23:39:14 +00:00
parent 6c8600ab52
commit 3e0179fd6e
13 changed files with 136 additions and 202 deletions

View File

@@ -1,7 +1,6 @@
#pragma once
#include <string>
#include <ios>
#include <vector>
#include <map>
#include "parserstate.h"
@@ -13,6 +12,7 @@ namespace YAML
{
class Content;
class Scanner;
class Emitter;
enum CONTENT_TYPE { CT_NONE, CT_SCALAR, CT_SEQUENCE, CT_MAP };
@@ -24,7 +24,6 @@ namespace YAML
void Clear();
void Parse(Scanner *pScanner, const ParserState& state);
void Write(std::ostream& out, int indent, bool startedLine, bool onlyOneCharOnLine) const;
CONTENT_TYPE GetType() const;
@@ -65,8 +64,8 @@ namespace YAML
bool IsAlias() const { return m_alias; }
bool IsReferenced() const { return m_referenced; }
// insertion
friend std::ostream& operator << (std::ostream& out, const Node& node);
// emitting
friend Emitter& operator << (Emitter& out, const Node& node);
// ordering
int Compare(const Node& rhs) const;

View File

@@ -1,90 +0,0 @@
#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::GetScalar(std::string& scalar) const
{
return m_pRef->GetScalar(scalar);
}
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);
}
}

89
src/aliascontent.cpp Normal file
View File

@@ -0,0 +1,89 @@
#include "crt.h"
#include "aliascontent.h"
namespace YAML
{
AliasContent::AliasContent(Content* pNodeContent)
: m_pRef(pNodeContent)
{
}
void AliasContent::Parse(Scanner */*pScanner*/, const ParserState& /*state*/)
{
}
void AliasContent::Write(Emitter&) const
{
// no content (just an alias)
}
bool AliasContent::GetBegin(std::vector <Node *>::const_iterator& i) const
{
return m_pRef->GetBegin(i);
}
bool AliasContent::GetBegin(std::map <Node *, Node *, ltnode>::const_iterator& i) const
{
return m_pRef->GetBegin(i);
}
bool AliasContent::GetEnd(std::vector <Node *>::const_iterator& i) const
{
return m_pRef->GetEnd(i);
}
bool AliasContent::GetEnd(std::map <Node *, Node *, ltnode>::const_iterator& i) const
{
return m_pRef->GetEnd(i);
}
Node* AliasContent::GetNode(unsigned n) const
{
return m_pRef->GetNode(n);
}
unsigned AliasContent::GetSize() const
{
return m_pRef->GetSize();
}
bool AliasContent::IsScalar() const
{
return m_pRef->IsScalar();
}
bool AliasContent::IsMap() const
{
return m_pRef->IsMap();
}
bool AliasContent::IsSequence() const
{
return m_pRef->IsSequence();
}
bool AliasContent::GetScalar(std::string& scalar) const
{
return m_pRef->GetScalar(scalar);
}
int AliasContent::Compare(Content *pContent)
{
return m_pRef->Compare(pContent);
}
int AliasContent::Compare(Scalar *pScalar)
{
return m_pRef->Compare(pScalar);
}
int AliasContent::Compare(Sequence *pSequence)
{
return m_pRef->Compare(pSequence);
}
int AliasContent::Compare(Map *pMap)
{
return m_pRef->Compare(pMap);
}
}

View File

@@ -4,13 +4,13 @@
namespace YAML
{
class Alias : public Content
class AliasContent : public Content
{
public:
Alias(Content *pNodeContent);
AliasContent(Content *pNodeContent);
virtual void Parse(Scanner* pScanner, const ParserState& state);
virtual void Write(std::ostream& out, int indent, bool startedLine, bool onlyOneCharOnLine);
virtual void Write(Emitter&) const;
virtual bool GetBegin(std::vector <Node *>::const_iterator&) const;
virtual bool GetBegin(std::map <Node *, Node *, ltnode>::const_iterator&) const;

View File

@@ -1,6 +1,5 @@
#pragma once
#include <ios>
#include <vector>
#include <map>
#include "parserstate.h"
@@ -15,6 +14,7 @@ namespace YAML
class Scalar;
class Sequence;
class Map;
class Emitter;
class Content
{
@@ -23,7 +23,7 @@ namespace YAML
virtual ~Content();
virtual void Parse(Scanner *pScanner, const ParserState& state) = 0;
virtual void Write(std::ostream& out, int indent, bool startedLine, bool onlyOneCharOnLine) = 0;
virtual void Write(Emitter& out) const = 0;
virtual bool GetBegin(std::vector <Node *>::const_iterator&) const { return false; }
virtual bool GetBegin(std::map <Node *, Node *, ltnode>::const_iterator&) const { return false; }

View File

@@ -4,7 +4,7 @@
#include "scanner.h"
#include "token.h"
#include "exceptions.h"
#include <iostream>
#include "emitter.h"
#include <memory>
namespace YAML
@@ -129,28 +129,12 @@ namespace YAML
}
}
void Map::Write(std::ostream& out, int indent, bool startedLine, bool onlyOneCharOnLine)
void Map::Write(Emitter& out) const
{
if(startedLine && !onlyOneCharOnLine)
out << "\n";
for(node_map::const_iterator it=m_data.begin();it!=m_data.end();++it) {
if((startedLine && !onlyOneCharOnLine) || it != m_data.begin()) {
for(int i=0;i<indent;i++)
out << " ";
}
out << "? ";
it->first->Write(out, indent + 1, true, it!= m_data.begin() || !startedLine || onlyOneCharOnLine);
for(int i=0;i<indent;i++)
out << " ";
out << ": ";
it->second->Write(out, indent + 1, true, true);
}
if(m_data.empty())
out << "\n";
out << BeginMap;
for(node_map::const_iterator it=m_data.begin();it!=m_data.end();++it)
out << Key << *it->first << Value << *it->second;
out << EndMap;
}
int Map::Compare(Content *pContent)

View File

@@ -17,7 +17,7 @@ namespace YAML
virtual bool GetBegin(std::map <Node *, Node *, ltnode>::const_iterator& it) const;
virtual bool GetEnd(std::map <Node *, Node *, ltnode>::const_iterator& it) const;
virtual void Parse(Scanner *pScanner, const ParserState& state);
virtual void Write(std::ostream& out, int indent, bool startedLine, bool onlyOneCharOnLine);
virtual void Write(Emitter& out) const;
virtual bool IsMap() const { return true; }

View File

@@ -7,9 +7,9 @@
#include "scalar.h"
#include "sequence.h"
#include "map.h"
#include "alias.h"
#include "aliascontent.h"
#include "iterpriv.h"
#include <iostream>
#include "emitter.h"
namespace YAML
{
@@ -66,7 +66,7 @@ namespace YAML
// being deleted twice
Content *pAliasedContent = pReferencedNode->m_pContent;
if(pAliasedContent)
m_pContent = new Alias(pAliasedContent);
m_pContent = new AliasContent(pAliasedContent);
return;
}
@@ -152,50 +152,6 @@ namespace YAML
pScanner->pop();
}
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 << "*";
else
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) == std::string("!<") && m_tag.substr(m_tag.size() - 1) == std::string(">"))
out << m_tag << " ";
else
out << "!<" << m_tag << "> ";
startedLine = true;
onlyOneCharOnLine = false;
}
if(!m_pContent)
out << "\n";
else
m_pContent->Write(out, indent, startedLine, onlyOneCharOnLine);
}
CONTENT_TYPE Node::GetType() const
{
if(!m_pContent)
@@ -289,9 +245,22 @@ namespace YAML
return m_pContent->GetScalar(s);
}
std::ostream& operator << (std::ostream& out, const Node& node)
Emitter& operator << (Emitter& out, const Node& node)
{
node.Write(out, 0, false, false);
// write anchor/alias
if(node.m_anchor != "") {
if(node.m_alias)
out << Alias(node.m_anchor);
else
out << Anchor(node.m_anchor);
}
// TODO: write tag
// write content
if(node.m_pContent)
node.m_pContent->Write(out);
return out;
}

View File

@@ -4,6 +4,7 @@
#include "token.h"
#include "exceptions.h"
#include "node.h"
#include "emitter.h"
namespace YAML
{
@@ -22,19 +23,9 @@ namespace YAML
pScanner->pop();
}
void Scalar::Write(std::ostream& out, int /*indent*/, bool /*startedLine*/, bool /*onlyOneCharOnLine*/)
void Scalar::Write(Emitter& out) const
{
out << "\"";
for(unsigned i=0;i<m_data.size();i++) {
switch(m_data[i]) {
case '\\': out << "\\\\"; break;
case '\t': out << "\\t"; break;
case '\n': out << "\\n"; break;
case '\r': out << "\\r"; break;
default: out << m_data[i]; break;
}
}
out << "\"\n";
out << m_data;
}
int Scalar::Compare(Content *pContent)

View File

@@ -12,7 +12,7 @@ namespace YAML
virtual ~Scalar();
virtual void Parse(Scanner *pScanner, const ParserState& state);
virtual void Write(std::ostream& out, int indent, bool startedLine, bool onlyOneCharOnLine);
virtual void Write(Emitter& out) const;
virtual bool IsScalar() const { return true; }

View File

@@ -3,7 +3,7 @@
#include "node.h"
#include "scanner.h"
#include "token.h"
#include <iostream>
#include "emitter.h"
namespace YAML
{
@@ -133,23 +133,12 @@ namespace YAML
}
}
void Sequence::Write(std::ostream& out, int indent, bool startedLine, bool onlyOneCharOnLine)
void Sequence::Write(Emitter& out) const
{
if(startedLine && !onlyOneCharOnLine)
out << "\n";
for(unsigned i=0;i<m_data.size();i++) {
if((startedLine && !onlyOneCharOnLine) || i > 0) {
for(int j=0;j<indent;j++)
out << " ";
}
out << "- ";
m_data[i]->Write(out, indent + 1, true, i > 0 || !startedLine || onlyOneCharOnLine);
}
if(m_data.empty())
out << "\n";
out << BeginSeq;
for(unsigned i=0;i<m_data.size();i++)
out << *m_data[i];
out << EndSeq;
}
int Sequence::Compare(Content *pContent)

View File

@@ -20,7 +20,7 @@ namespace YAML
virtual unsigned GetSize() const;
virtual void Parse(Scanner *pScanner, const ParserState& state);
virtual void Write(std::ostream& out, int indent, bool startedLine, bool onlyOneCharOnLine);
virtual void Write(Emitter& out) const;
virtual bool IsSequence() const { return true; }

View File

@@ -14,6 +14,9 @@ int main(int argc, char **argv)
while(parser) {
YAML::Node doc;
parser.GetNextDocument(doc);
YAML::Emitter emitter;
emitter << doc;
std::cout << emitter.c_str() << "\n";
}
} catch(const YAML::Exception& e) {
std::cerr << e.what() << "\n";