From 03df73a7b01855a2632c0ea7244a342651b539fe Mon Sep 17 00:00:00 2001 From: Jesse Beder Date: Tue, 17 Nov 2009 20:21:22 +0000 Subject: [PATCH] Refactored emitter operator << overloads to not template them, so it's easier to overload for pointer types --- include/emitter.h | 61 +++++++++++++++++++++++++----------- src/emitter.cpp | 40 ------------------------ test/emittertests.cpp | 72 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 115 insertions(+), 58 deletions(-) diff --git a/include/emitter.h b/include/emitter.h index 259d899..a353e71 100644 --- a/include/emitter.h +++ b/include/emitter.h @@ -9,6 +9,7 @@ #include "null.h" #include #include +#include namespace YAML { @@ -45,29 +46,23 @@ namespace YAML // overloads of write Emitter& Write(const std::string& str); - Emitter& Write(const char *str); - Emitter& Write(int value) { return WriteIntegralType(value); } - Emitter& Write(unsigned int value) { return WriteIntegralType(value); } - Emitter& Write(short value) { return WriteIntegralType(value); } - Emitter& Write(unsigned short value) { return WriteIntegralType(value); } - Emitter& Write(long value) { return WriteIntegralType(value); } - Emitter& Write(unsigned long value) { return WriteIntegralType(value); } Emitter& Write(bool b); - Emitter& Write(float f); - Emitter& Write(double d); Emitter& Write(const _Alias& alias); Emitter& Write(const _Anchor& anchor); Emitter& Write(const _Tag& tag); Emitter& Write(const _Comment& comment); Emitter& Write(const _Null& null); + template + Emitter& WriteIntegralType(T value); + + template + Emitter& WriteStreamable(T value); + private: void PreWriteIntegralType(std::stringstream& str); void PostWriteIntegralType(const std::stringstream& str); - template - Emitter& WriteIntegralType(T value); - private: enum ATOMIC_TYPE { AT_SCALAR, AT_SEQ, AT_BLOCK_SEQ, AT_FLOW_SEQ, AT_MAP, AT_BLOCK_MAP, AT_FLOW_MAP }; @@ -100,19 +95,49 @@ namespace YAML PostWriteIntegralType(str); return *this; } + + template + inline Emitter& Emitter::WriteStreamable(T value) + { + if(!good()) + return *this; + + PreAtomicWrite(); + EmitSeparationIfNecessary(); + + std::stringstream str; + str << value; + m_stream << str.str(); + + PostAtomicWrite(); + return *this; + } // overloads of insertion - template - inline Emitter& operator << (Emitter& emitter, T v) { - return emitter.Write(v); - } + 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, 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); } + inline Emitter& operator << (Emitter& emitter, const _Comment& v) { return emitter.Write(v); } + inline Emitter& operator << (Emitter& emitter, const _Null& v) { return emitter.Write(v); } + + inline Emitter& operator << (Emitter& emitter, const char *v) { return emitter.Write(std::string(v)); } + + inline Emitter& operator << (Emitter& emitter, int v) { return emitter.WriteIntegralType(v); } + inline Emitter& operator << (Emitter& emitter, unsigned int v) { return emitter.WriteIntegralType(v); } + inline Emitter& operator << (Emitter& emitter, short v) { return emitter.WriteIntegralType(v); } + inline Emitter& operator << (Emitter& emitter, unsigned short v) { return emitter.WriteIntegralType(v); } + inline Emitter& operator << (Emitter& emitter, long v) { return emitter.WriteIntegralType(v); } + inline Emitter& operator << (Emitter& emitter, unsigned long v) { return emitter.WriteIntegralType(v); } + + inline Emitter& operator << (Emitter& emitter, float v) { return emitter.WriteStreamable(v); } + inline Emitter& operator << (Emitter& emitter, double v) { return emitter.WriteStreamable(v); } - template <> inline Emitter& operator << (Emitter& emitter, EMITTER_MANIP value) { return emitter.SetLocalValue(value); } - template <> inline Emitter& operator << (Emitter& emitter, _Indent indent) { return emitter.SetLocalIndent(indent); } diff --git a/src/emitter.cpp b/src/emitter.cpp index bb5f80b..675fcf8 100644 --- a/src/emitter.cpp +++ b/src/emitter.cpp @@ -549,14 +549,6 @@ namespace YAML return *this; } - Emitter& Emitter::Write(const char *str) - { - if(!good()) - return *this; - - return Write(std::string(str)); - } - void Emitter::PreWriteIntegralType(std::stringstream& str) { PreAtomicWrite(); @@ -623,38 +615,6 @@ namespace YAML return *this; } - Emitter& Emitter::Write(float f) - { - if(!good()) - return *this; - - PreAtomicWrite(); - EmitSeparationIfNecessary(); - - std::stringstream str; - str << f; - m_stream << str.str(); - - PostAtomicWrite(); - return *this; - } - - Emitter& Emitter::Write(double d) - { - if(!good()) - return *this; - - PreAtomicWrite(); - EmitSeparationIfNecessary(); - - std::stringstream str; - str << d; - m_stream << str.str(); - - PostAtomicWrite(); - return *this; - } - Emitter& Emitter::Write(const _Alias& alias) { if(!good()) diff --git a/test/emittertests.cpp b/test/emittertests.cpp index fa0ef5c..58c3d92 100644 --- a/test/emittertests.cpp +++ b/test/emittertests.cpp @@ -558,6 +558,74 @@ namespace Test desiredOutput = "--- \"\x24 \xC2\xA2 \xE2\x82\xAC \xF0\xA4\xAD\xA2\""; } + struct Foo { + Foo(): x(0) {} + Foo(int x_, const std::string& bar_): x(x_), bar(bar_) {} + + int x; + std::string bar; + }; + + YAML::Emitter& operator << (YAML::Emitter& out, const Foo& foo) { + out << YAML::BeginMap; + out << YAML::Key << "x" << YAML::Value << foo.x; + out << YAML::Key << "bar" << YAML::Value << foo.bar; + out << YAML::EndMap; + return out; + } + + void UserType(YAML::Emitter& out, std::string& desiredOutput) + { + out << YAML::BeginSeq; + out << Foo(5, "hello"); + out << Foo(3, "goodbye"); + out << YAML::EndSeq; + + desiredOutput = "---\n-\n x: 5\n bar: hello\n-\n x: 3\n bar: goodbye"; + } + + void UserTypeInContainer(YAML::Emitter& out, std::string& desiredOutput) + { + std::vector fv; + fv.push_back(Foo(5, "hello")); + fv.push_back(Foo(3, "goodbye")); + out << fv; + + desiredOutput = "---\n-\n x: 5\n bar: hello\n-\n x: 3\n bar: goodbye"; + } + + template + YAML::Emitter& operator << (YAML::Emitter& out, const T *v) { + if(v) + out << *v; + else + out << YAML::Null; + return out; + } + + void PointerToInt(YAML::Emitter& out, std::string& desiredOutput) + { + int foo = 5; + int *bar = &foo; + int *baz = 0; + out << YAML::BeginSeq; + out << bar << baz; + out << YAML::EndSeq; + + desiredOutput = "---\n- 5\n- ~"; + } + + void PointerToUserType(YAML::Emitter& out, std::string& desiredOutput) + { + Foo foo(5, "hello"); + Foo *bar = &foo; + Foo *baz = 0; + out << YAML::BeginSeq; + out << bar << baz; + out << YAML::EndSeq; + + desiredOutput = "---\n-\n x: 5\n bar: hello\n- ~"; + } //////////////////////////////////////////////////////////////////////////////////////////////////////// // incorrect emitting @@ -733,6 +801,10 @@ namespace Test RunEmitterTest(&Emitter::EscapedUnicode, "escaped unicode", passed, total); RunEmitterTest(&Emitter::Unicode, "unicode", passed, total); RunEmitterTest(&Emitter::DoubleQuotedUnicode, "double quoted unicode", passed, total); + RunEmitterTest(&Emitter::UserType, "user type", passed, total); + RunEmitterTest(&Emitter::UserTypeInContainer, "user type in container", passed, total); + RunEmitterTest(&Emitter::PointerToInt, "pointer to int", passed, total); + RunEmitterTest(&Emitter::PointerToUserType, "pointer to user type", passed, total); RunEmitterErrorTest(&Emitter::ExtraEndSeq, "extra EndSeq", passed, total); RunEmitterErrorTest(&Emitter::ExtraEndMap, "extra EndMap", passed, total);