diff --git a/include/yaml-cpp/emitter.h b/include/yaml-cpp/emitter.h index 6ae8b52..0e51e67 100644 --- a/include/yaml-cpp/emitter.h +++ b/include/yaml-cpp/emitter.h @@ -43,10 +43,13 @@ namespace YAML bool SetIndent(unsigned n); bool SetPreCommentIndent(unsigned n); bool SetPostCommentIndent(unsigned n); + bool SetFloatPrecision(unsigned n); + bool SetDoublePrecision(unsigned n); // local setters Emitter& SetLocalValue(EMITTER_MANIP value); Emitter& SetLocalIndent(const _Indent& indent); + Emitter& SetLocalPrecision(const _Precision& precision); // overloads of write Emitter& Write(const std::string& str); @@ -70,6 +73,10 @@ namespace YAML void PreWriteStreamable(std::stringstream& str); void PostWriteIntegralType(const std::stringstream& str); void PostWriteStreamable(const std::stringstream& str); + + template void SetStreamablePrecision(std::stringstream&) {} + unsigned GetFloatPrecision() const; + unsigned GetDoublePrecision() const; private: void PreAtomicWrite(); @@ -118,11 +125,24 @@ namespace YAML std::stringstream str; PreWriteStreamable(str); + SetStreamablePrecision(str); str << value; PostWriteStreamable(str); return *this; } + template<> + inline void Emitter::SetStreamablePrecision(std::stringstream& str) + { + str.precision(GetFloatPrecision()); + } + + template<> + inline void Emitter::SetStreamablePrecision(std::stringstream& str) + { + str.precision(GetDoublePrecision()); + } + // 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); } @@ -156,6 +176,10 @@ namespace YAML inline Emitter& operator << (Emitter& emitter, _Indent indent) { return emitter.SetLocalIndent(indent); } + + inline Emitter& operator << (Emitter& emitter, _Precision precision) { + return emitter.SetLocalPrecision(precision); + } } #endif // EMITTER_H_62B23520_7C8E_11DE_8A39_0800200C9A66 diff --git a/include/yaml-cpp/emittermanip.h b/include/yaml-cpp/emittermanip.h index 5c63419..e80a573 100644 --- a/include/yaml-cpp/emittermanip.h +++ b/include/yaml-cpp/emittermanip.h @@ -135,6 +135,25 @@ namespace YAML inline _Binary Binary(const unsigned char *data, std::size_t size) { return _Binary(data, size); } + + struct _Precision { + _Precision(int floatPrecision_, int doublePrecision_): floatPrecision(floatPrecision_), doublePrecision(doublePrecision_) {} + + int floatPrecision; + int doublePrecision; + }; + + inline _Precision FloatPrecision(unsigned n) { + return _Precision(n, -1); + } + + inline _Precision DoublePrecision(unsigned n) { + return _Precision(-1, n); + } + + inline _Precision Precision(unsigned n) { + return _Precision(n, n); + } } #endif // EMITTERMANIP_H_62B23520_7C8E_11DE_8A39_0800200C9A66 diff --git a/src/emitter.cpp b/src/emitter.cpp index 1583df0..0757882 100644 --- a/src/emitter.cpp +++ b/src/emitter.cpp @@ -93,6 +93,16 @@ namespace YAML { return m_pState->SetPostCommentIndent(n, GLOBAL); } + + bool Emitter::SetFloatPrecision(unsigned n) + { + return m_pState->SetFloatPrecision(n, GLOBAL); + } + + bool Emitter::SetDoublePrecision(unsigned n) + { + return m_pState->SetDoublePrecision(n, GLOBAL); + } // SetLocalValue // . Either start/end a group, or set a modifier locally @@ -145,6 +155,15 @@ namespace YAML return *this; } + Emitter& Emitter::SetLocalPrecision(const _Precision& precision) + { + if(precision.floatPrecision >= 0) + m_pState->SetFloatPrecision(precision.floatPrecision, LOCAL); + if(precision.doublePrecision >= 0) + m_pState->SetDoublePrecision(precision.doublePrecision, LOCAL); + return *this; + } + // GotoNextPreAtomicState // . Runs the state machine, emitting if necessary, and returns 'true' if done (i.e., ready to emit an atom) bool Emitter::GotoNextPreAtomicState() @@ -661,13 +680,22 @@ namespace YAML } } - void Emitter::PreWriteStreamable(std::stringstream& str) + void Emitter::PreWriteStreamable(std::stringstream&) { PreAtomicWrite(); EmitSeparationIfNecessary(); - str.precision(15); } + unsigned Emitter::GetFloatPrecision() const + { + return m_pState->GetFloatPrecision(); + } + + unsigned Emitter::GetDoublePrecision() const + { + return m_pState->GetDoublePrecision(); + } + void Emitter::PostWriteIntegralType(const std::stringstream& str) { m_stream << str.str(); diff --git a/src/emitterstate.cpp b/src/emitterstate.cpp index dfe2b2b..7aea1b8 100644 --- a/src/emitterstate.cpp +++ b/src/emitterstate.cpp @@ -1,5 +1,6 @@ #include "emitterstate.h" #include "yaml-cpp/exceptions.h" +#include namespace YAML { @@ -21,6 +22,8 @@ namespace YAML m_seqFmt.set(Block); m_mapFmt.set(Block); m_mapKeyFmt.set(Auto); + m_floatPrecision.set(6); + m_doublePrecision.set(15); } EmitterState::~EmitterState() @@ -261,5 +264,21 @@ namespace YAML return false; } } + + bool EmitterState::SetFloatPrecision(unsigned value, FMT_SCOPE scope) + { + if(value > std::numeric_limits::digits10) + return false; + _Set(m_floatPrecision, value, scope); + return true; + } + + bool EmitterState::SetDoublePrecision(unsigned value, FMT_SCOPE scope) + { + if(value > std::numeric_limits::digits10) + return false; + _Set(m_doublePrecision, value, scope); + return true; + } } diff --git a/src/emitterstate.h b/src/emitterstate.h index 90be656..661e083 100644 --- a/src/emitterstate.h +++ b/src/emitterstate.h @@ -145,6 +145,11 @@ namespace YAML bool SetMapKeyFormat(EMITTER_MANIP value, FMT_SCOPE scope); EMITTER_MANIP GetMapKeyFormat() const { return m_mapKeyFmt.get(); } + + bool SetFloatPrecision(unsigned value, FMT_SCOPE scope); + unsigned GetFloatPrecision() const { return m_floatPrecision.get(); } + bool SetDoublePrecision(unsigned value, FMT_SCOPE scope); + unsigned GetDoublePrecision() const { return m_doublePrecision.get(); } private: template @@ -169,6 +174,8 @@ namespace YAML Setting m_seqFmt; Setting m_mapFmt; Setting m_mapKeyFmt; + Setting m_floatPrecision; + Setting m_doublePrecision; SettingChanges m_modifiedSettings; SettingChanges m_globalModifiedSettings; diff --git a/test/emittertests.cpp b/test/emittertests.cpp index 2c09ffd..9cba974 100644 --- a/test/emittertests.cpp +++ b/test/emittertests.cpp @@ -874,7 +874,24 @@ namespace Test out << YAML::EndSeq; desiredOutput = "- a\n- \":\"\n- \"\\x10\"\n- \"\\n\"\n- \" \"\n- \"\\t\""; } + + void DefaultPrecision(YAML::Emitter& out, std::string& desiredOutput) + { + out << YAML::BeginSeq; + out << 1.234f; + out << 3.14159265358979; + out << YAML::EndSeq; + desiredOutput = "- 1.234\n- 3.14159265358979"; + } + void SetPrecision(YAML::Emitter& out, std::string& desiredOutput) + { + out << YAML::BeginSeq; + out << YAML::FloatPrecision(3) << 1.234f; + out << YAML::DoublePrecision(6) << 3.14159265358979; + out << YAML::EndSeq; + desiredOutput = "- 1.23\n- 3.14159"; + } //////////////////////////////////////////////////////////////////////////////////////////////////////// // incorrect emitting @@ -1094,6 +1111,8 @@ namespace Test RunEmitterTest(&Emitter::ImplicitDocStart, "implicit doc start", passed, total); RunEmitterTest(&Emitter::EmptyString, "empty string", passed, total); RunEmitterTest(&Emitter::SingleChar, "single char", passed, total); + RunEmitterTest(&Emitter::DefaultPrecision, "default precision", passed, total); + RunEmitterTest(&Emitter::SetPrecision, "set precision", passed, total); RunEmitterErrorTest(&Emitter::ExtraEndSeq, "extra EndSeq", passed, total); RunEmitterErrorTest(&Emitter::ExtraEndMap, "extra EndMap", passed, total);