Commit 0ccc51fb authored by Philipp A. Hartmann's avatar Philipp A. Hartmann

Writer: add SetDoublePrecision to control number of significant digits

Writing a double to an OutputStream current prints at most 6 significant
digits (according to the C standard).

The function SetDoublePrecision(), added to the Writer classes
can be used to fluently set the precision, i.e. the number of
significant digits to use for writing the double:

  Writer<...> writer(...);
  d.Accept(writer.SetDoublePrecision(12));
parent 60b8c119
...@@ -26,6 +26,9 @@ public: ...@@ -26,6 +26,9 @@ public:
PrettyWriter(OutputStream& os, Allocator* allocator = 0, size_t levelDepth = Base::kDefaultLevelDepth) : PrettyWriter(OutputStream& os, Allocator* allocator = 0, size_t levelDepth = Base::kDefaultLevelDepth) :
Base(os, allocator, levelDepth), indentChar_(' '), indentCharCount_(4) {} Base(os, allocator, levelDepth), indentChar_(' '), indentCharCount_(4) {}
//! Overridden for fluent API, see \ref Writer::SetDoublePrecision()
PrettyWriter& SetDoublePrecision(int p) { Base::SetDoublePrecision(p); return *this; }
//! Set custom indentation. //! Set custom indentation.
/*! \param indentChar Character for indentation. Must be whitespace character (' ', '\\t', '\\n', '\\r'). /*! \param indentChar Character for indentation. Must be whitespace character (' ', '\\t', '\\n', '\\r').
\param indentCharCount Number of indent characters for each indentation level. \param indentCharCount Number of indent characters for each indentation level.
......
...@@ -35,7 +35,23 @@ public: ...@@ -35,7 +35,23 @@ public:
typedef typename SourceEncoding::Ch Ch; typedef typename SourceEncoding::Ch Ch;
Writer(OutputStream& os, Allocator* allocator = 0, size_t levelDepth = kDefaultLevelDepth) : Writer(OutputStream& os, Allocator* allocator = 0, size_t levelDepth = kDefaultLevelDepth) :
os_(os), level_stack_(allocator, levelDepth * sizeof(Level)) {} os_(os), level_stack_(allocator, levelDepth * sizeof(Level)),
doublePrecision_(kDefaultDoublePrecision) {}
//! Set the number of significant digits for \c double values
/*! When writing a \c double value to the \c OutputStream, the number
of significant digits is limited to 6 by default.
\param p maximum number of significant digits (default: 6)
\return The Writer itself for fluent API.
*/
Writer& SetDoublePrecision(int p = kDefaultDoublePrecision) {
if (p < 0) p = kDefaultDoublePrecision; // negative precision is ignored
doublePrecision_ = p;
return *this;
}
//! \see SetDoublePrecision()
int GetDoublePrecision() const { return doublePrecision_; }
//@name Implementation of Handler //@name Implementation of Handler
//@{ //@{
...@@ -45,6 +61,18 @@ public: ...@@ -45,6 +61,18 @@ public:
Writer& Uint(unsigned u) { Prefix(kNumberType); WriteUint(u); return *this; } Writer& Uint(unsigned u) { Prefix(kNumberType); WriteUint(u); return *this; }
Writer& Int64(int64_t i64) { Prefix(kNumberType); WriteInt64(i64); return *this; } Writer& Int64(int64_t i64) { Prefix(kNumberType); WriteInt64(i64); return *this; }
Writer& Uint64(uint64_t u64) { Prefix(kNumberType); WriteUint64(u64); return *this; } Writer& Uint64(uint64_t u64) { Prefix(kNumberType); WriteUint64(u64); return *this; }
//! Writes the given \c double value to the stream
/*!
The number of significant digits (the precision) to be written
can be set by \ref SetDoublePrecision() for the Writer:
\code
Writer<...> writer(...);
writer.SetDoublePrecision(12).Double(M_PI);
\endcode
\param d The value to be written.
\return The Writer itself for fluent API.
*/
Writer& Double(double d) { Prefix(kNumberType); WriteDouble(d); return *this; } Writer& Double(double d) { Prefix(kNumberType); WriteDouble(d); return *this; }
Writer& String(const Ch* str, SizeType length, bool copy = false) { Writer& String(const Ch* str, SizeType length, bool copy = false) {
...@@ -161,18 +189,21 @@ protected: ...@@ -161,18 +189,21 @@ protected:
} while (p != buffer); } while (p != buffer);
} }
//! \todo Optimization with custom double-to-string converter.
void WriteDouble(double d) {
char buffer[100];
#ifdef _MSC_VER #ifdef _MSC_VER
int ret = sprintf_s(buffer, sizeof(buffer), "%g", d); #define RAPIDJSON_SNPRINTF sprintf_s
#else #else
int ret = snprintf(buffer, sizeof(buffer), "%g", d); #define RAPIDJSON_SNPRINTF snprintf
#endif #endif
//! \todo Optimization with custom double-to-string converter.
void WriteDouble(double d) {
char buffer[100];
int ret = RAPIDJSON_SNPRINTF(buffer, sizeof(buffer), "%.*g", doublePrecision_, d);
RAPIDJSON_ASSERT(ret >= 1); RAPIDJSON_ASSERT(ret >= 1);
for (int i = 0; i < ret; i++) for (int i = 0; i < ret; i++)
os_.Put(buffer[i]); os_.Put(buffer[i]);
} }
#undef RAPIDJSON_SNPRINTF
void WriteString(const Ch* str, SizeType length) { void WriteString(const Ch* str, SizeType length) {
static const char hexDigits[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; static const char hexDigits[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
...@@ -234,6 +265,9 @@ protected: ...@@ -234,6 +265,9 @@ protected:
OutputStream& os_; OutputStream& os_;
internal::Stack<Allocator> level_stack_; internal::Stack<Allocator> level_stack_;
int doublePrecision_;
static const int kDefaultDoublePrecision = 6;
private: private:
// Prohibit assignment for VC C4512 warning // Prohibit assignment for VC C4512 warning
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment