diff --git a/include/yaml-cpp/emitter.h b/include/yaml-cpp/emitter.h index eebdd4c..96478d5 100644 --- a/include/yaml-cpp/emitter.h +++ b/include/yaml-cpp/emitter.h @@ -51,6 +51,7 @@ namespace YAML // overloads of write Emitter& Write(const std::string& str); Emitter& Write(bool b); + Emitter& Write(char ch); Emitter& Write(const _Alias& alias); Emitter& Write(const _Anchor& anchor); Emitter& Write(const _Tag& tag); @@ -125,6 +126,7 @@ namespace YAML // overloads of insertion inline Emitter& operator << (Emitter& emitter, const std::string& v) { return emitter.Write(v); } inline Emitter& operator << (Emitter& emitter, bool v) { return emitter.Write(v); } + inline Emitter& operator << (Emitter& emitter, char v) { return emitter.Write(v); } inline Emitter& operator << (Emitter& emitter, const _Alias& v) { return emitter.Write(v); } inline Emitter& operator << (Emitter& emitter, const _Anchor& v) { return emitter.Write(v); } inline Emitter& operator << (Emitter& emitter, const _Tag& v) { return emitter.Write(v); } diff --git a/src/emitter.cpp b/src/emitter.cpp index c49fcc9..1583df0 100644 --- a/src/emitter.cpp +++ b/src/emitter.cpp @@ -733,6 +733,20 @@ namespace YAML return *this; } + Emitter& Emitter::Write(char ch) + { + if(!good()) + return *this; + + PreAtomicWrite(); + EmitSeparationIfNecessary(); + + Utils::WriteChar(m_stream, ch); + + PostAtomicWrite(); + return *this; + } + Emitter& Emitter::Write(const _Alias& alias) { if(!good()) diff --git a/src/emitterutils.cpp b/src/emitterutils.cpp index 95a01fa..361cce5 100644 --- a/src/emitterutils.cpp +++ b/src/emitterutils.cpp @@ -268,6 +268,26 @@ namespace YAML return true; } + bool WriteChar(ostream& out, char ch) + { + if(('a' <= ch && ch <= 'z') || ('A' <= ch && ch <= 'Z')) + out << ch; + else if((0x20 <= ch && ch <= 0x7e) || ch == ' ') + out << "\"" << ch << "\""; + else if(ch == '\t') + out << "\"\\t\""; + else if(ch == '\n') + out << "\"\\n\""; + else if(ch == '\b') + out << "\"\\b\""; + else { + out << "\""; + WriteDoubleQuoteEscapeSequence(out, ch); + out << "\""; + } + return true; + } + bool WriteComment(ostream& out, const std::string& str, int postCommentIndent) { const unsigned curIndent = out.col(); diff --git a/src/emitterutils.h b/src/emitterutils.h index 27ca115..4e3eed9 100644 --- a/src/emitterutils.h +++ b/src/emitterutils.h @@ -17,6 +17,7 @@ namespace YAML bool WriteSingleQuotedString(ostream& out, const std::string& str); bool WriteDoubleQuotedString(ostream& out, const std::string& str, bool escapeNonAscii); bool WriteLiteralString(ostream& out, const std::string& str, int indent); + bool WriteChar(ostream& out, char ch); bool WriteComment(ostream& out, const std::string& str, int postCommentIndent); bool WriteAlias(ostream& out, const std::string& str); bool WriteAnchor(ostream& out, const std::string& str); diff --git a/test/emittertests.cpp b/test/emittertests.cpp index 165e05b..2c09ffd 100644 --- a/test/emittertests.cpp +++ b/test/emittertests.cpp @@ -861,8 +861,21 @@ namespace Test out << YAML::EndMap; desiredOutput = "key: \"\""; } + + void SingleChar(YAML::Emitter& out, std::string& desiredOutput) + { + out << YAML::BeginSeq; + out << 'a'; + out << ':'; + out << (char)0x10; + out << '\n'; + out << ' '; + out << '\t'; + out << YAML::EndSeq; + desiredOutput = "- a\n- \":\"\n- \"\\x10\"\n- \"\\n\"\n- \" \"\n- \"\\t\""; + } - //////////////////////////////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////////////////////////////// // incorrect emitting void ExtraEndSeq(YAML::Emitter& out, std::string& desiredError) @@ -1080,6 +1093,7 @@ namespace Test RunEmitterTest(&Emitter::DocStartAndEnd, "doc start and end", passed, total); RunEmitterTest(&Emitter::ImplicitDocStart, "implicit doc start", passed, total); RunEmitterTest(&Emitter::EmptyString, "empty string", passed, total); + RunEmitterTest(&Emitter::SingleChar, "single char", passed, total); RunEmitterErrorTest(&Emitter::ExtraEndSeq, "extra EndSeq", passed, total); RunEmitterErrorTest(&Emitter::ExtraEndMap, "extra EndMap", passed, total);