mirror of
https://github.com/jbeder/yaml-cpp.git
synced 2025-09-09 04:41:16 +00:00
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:
@@ -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;
|
||||
|
@@ -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
89
src/aliascontent.cpp
Normal 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);
|
||||
}
|
||||
}
|
@@ -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;
|
@@ -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; }
|
||||
|
28
src/map.cpp
28
src/map.cpp
@@ -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)
|
||||
|
@@ -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; }
|
||||
|
||||
|
67
src/node.cpp
67
src/node.cpp
@@ -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;
|
||||
}
|
||||
|
||||
|
@@ -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)
|
||||
|
@@ -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; }
|
||||
|
||||
|
@@ -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)
|
||||
|
@@ -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; }
|
||||
|
||||
|
@@ -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";
|
||||
|
Reference in New Issue
Block a user