From 3e0179fd6e1c6d78dd39c246d5c28628b4296c6f Mon Sep 17 00:00:00 2001 From: Jesse Beder Date: Fri, 10 Jul 2009 23:39:14 +0000 Subject: [PATCH] Added emitting for a YAML::Node (instead of the ad-hoc std::ostream overload) so it'll actually emit valid YAML always --- include/node.h | 7 ++- src/alias.cpp | 90 --------------------------------- src/aliascontent.cpp | 89 ++++++++++++++++++++++++++++++++ src/{alias.h => aliascontent.h} | 6 +-- src/content.h | 4 +- src/map.cpp | 28 +++------- src/map.h | 2 +- src/node.cpp | 67 +++++++----------------- src/scalar.cpp | 15 ++---- src/scalar.h | 2 +- src/sequence.cpp | 23 +++------ src/sequence.h | 2 +- util/parse.cpp | 3 ++ 13 files changed, 136 insertions(+), 202 deletions(-) delete mode 100644 src/alias.cpp create mode 100644 src/aliascontent.cpp rename src/{alias.h => aliascontent.h} (84%) diff --git a/include/node.h b/include/node.h index 1b1530f..cb4870c 100644 --- a/include/node.h +++ b/include/node.h @@ -1,7 +1,6 @@ #pragma once #include -#include #include #include #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; diff --git a/src/alias.cpp b/src/alias.cpp deleted file mode 100644 index f6c43af..0000000 --- a/src/alias.cpp +++ /dev/null @@ -1,90 +0,0 @@ -#include "crt.h" -#include "alias.h" -#include - -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 ::const_iterator& i) const - { - return m_pRef->GetBegin(i); - } - - bool Alias::GetBegin(std::map ::const_iterator& i) const - { - return m_pRef->GetBegin(i); - } - - bool Alias::GetEnd(std::vector ::const_iterator& i) const - { - return m_pRef->GetEnd(i); - } - - bool Alias::GetEnd(std::map ::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); - } -} diff --git a/src/aliascontent.cpp b/src/aliascontent.cpp new file mode 100644 index 0000000..ca64a89 --- /dev/null +++ b/src/aliascontent.cpp @@ -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 ::const_iterator& i) const + { + return m_pRef->GetBegin(i); + } + + bool AliasContent::GetBegin(std::map ::const_iterator& i) const + { + return m_pRef->GetBegin(i); + } + + bool AliasContent::GetEnd(std::vector ::const_iterator& i) const + { + return m_pRef->GetEnd(i); + } + + bool AliasContent::GetEnd(std::map ::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); + } +} diff --git a/src/alias.h b/src/aliascontent.h similarity index 84% rename from src/alias.h rename to src/aliascontent.h index 9513665..55460d7 100644 --- a/src/alias.h +++ b/src/aliascontent.h @@ -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 ::const_iterator&) const; virtual bool GetBegin(std::map ::const_iterator&) const; diff --git a/src/content.h b/src/content.h index 6399682..5bb7ffa 100644 --- a/src/content.h +++ b/src/content.h @@ -1,6 +1,5 @@ #pragma once -#include #include #include #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 ::const_iterator&) const { return false; } virtual bool GetBegin(std::map ::const_iterator&) const { return false; } diff --git a/src/map.cpp b/src/map.cpp index b7a7ec8..3565b70 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -4,7 +4,7 @@ #include "scanner.h" #include "token.h" #include "exceptions.h" -#include +#include "emitter.h" #include 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;ifirst->Write(out, indent + 1, true, it!= m_data.begin() || !startedLine || onlyOneCharOnLine); - - for(int i=0;isecond->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) diff --git a/src/map.h b/src/map.h index be722f4..71da430 100644 --- a/src/map.h +++ b/src/map.h @@ -17,7 +17,7 @@ namespace YAML virtual bool GetBegin(std::map ::const_iterator& it) const; virtual bool GetEnd(std::map ::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; } diff --git a/src/node.cpp b/src/node.cpp index 34b303c..89341cc 100644 --- a/src/node.cpp +++ b/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 +#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; } diff --git a/src/scalar.cpp b/src/scalar.cpp index 5576f23..e8146fa 100644 --- a/src/scalar.cpp +++ b/src/scalar.cpp @@ -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 +#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 0) { - for(int j=0;jWrite(out, indent + 1, true, i > 0 || !startedLine || onlyOneCharOnLine); - } - - if(m_data.empty()) - out << "\n"; + out << BeginSeq; + for(unsigned i=0;i