From 039a6e3b61c82176f036974947835ea1fdcc6370 Mon Sep 17 00:00:00 2001 From: Benjamin Knecht Date: Thu, 15 Oct 2015 17:28:56 +0200 Subject: [PATCH 1/3] Create format string with sprintf. For now use hardcoded precision '17' for now --- src/lib_json/json_writer.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/lib_json/json_writer.cpp b/src/lib_json/json_writer.cpp index 38dd784..0366db0 100644 --- a/src/lib_json/json_writer.cpp +++ b/src/lib_json/json_writer.cpp @@ -133,17 +133,20 @@ std::string valueToString(UInt value) { #endif // # if defined(JSON_HAS_INT64) -std::string valueToString(double value, bool useSpecialFloats) { +std::string valueToString(double value, bool useSpecialFloats, int precision) { // Allocate a buffer that is more than large enough to store the 16 digits of // precision requested below. char buffer[32]; int len = -1; + char formatString[6]; + sprintf(formatString, "%%.%dg", precision); + // Print into the buffer. We need not request the alternative representation // that always has a decimal point because JSON doesn't distingish the // concepts of reals and integers. if (isfinite(value)) { - len = snprintf(buffer, sizeof(buffer), "%.17g", value); + len = snprintf(buffer, sizeof(buffer), formatString, value); } else { // IEEE standard states that NaN values will not compare to themselves if (value != value) { @@ -160,7 +163,7 @@ std::string valueToString(double value, bool useSpecialFloats) { return buffer; } -std::string valueToString(double value) { return valueToString(value, false); } +std::string valueToString(double value) { return valueToString(value, false, 17); } std::string valueToString(bool value) { return value ? "true" : "false"; } @@ -906,7 +909,7 @@ void BuiltStyledStreamWriter::writeValue(Value const& value) { pushValue(valueToString(value.asLargestUInt())); break; case realValue: - pushValue(valueToString(value.asDouble(), useSpecialFloats_)); + pushValue(valueToString(value.asDouble(), useSpecialFloats_, 17)); break; case stringValue: { From 38022157b234f8a426f50026f4ebf668aa6a1815 Mon Sep 17 00:00:00 2001 From: Benjamin Knecht Date: Thu, 15 Oct 2015 18:00:42 +0200 Subject: [PATCH 2/3] making precision unsigned int adding precision as settings value for StreamBuilder --- src/lib_json/json_writer.cpp | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/src/lib_json/json_writer.cpp b/src/lib_json/json_writer.cpp index 0366db0..0b2d7d5 100644 --- a/src/lib_json/json_writer.cpp +++ b/src/lib_json/json_writer.cpp @@ -133,7 +133,7 @@ std::string valueToString(UInt value) { #endif // # if defined(JSON_HAS_INT64) -std::string valueToString(double value, bool useSpecialFloats, int precision) { +std::string valueToString(double value, bool useSpecialFloats, unsigned int precision) { // Allocate a buffer that is more than large enough to store the 16 digits of // precision requested below. char buffer[32]; @@ -835,7 +835,8 @@ struct BuiltStyledStreamWriter : public StreamWriter std::string const& colonSymbol, std::string const& nullSymbol, std::string const& endingLineFeedSymbol, - bool useSpecialFloats); + bool useSpecialFloats, + unsigned int precision); int write(Value const& root, std::ostream* sout) override; private: void writeValue(Value const& value); @@ -863,6 +864,7 @@ private: bool addChildValues_ : 1; bool indented_ : 1; bool useSpecialFloats_ : 1; + unsigned int precision_; }; BuiltStyledStreamWriter::BuiltStyledStreamWriter( std::string const& indentation, @@ -870,7 +872,8 @@ BuiltStyledStreamWriter::BuiltStyledStreamWriter( std::string const& colonSymbol, std::string const& nullSymbol, std::string const& endingLineFeedSymbol, - bool useSpecialFloats) + bool useSpecialFloats, + unsigned int precision) : rightMargin_(74) , indentation_(indentation) , cs_(cs) @@ -880,6 +883,7 @@ BuiltStyledStreamWriter::BuiltStyledStreamWriter( , addChildValues_(false) , indented_(false) , useSpecialFloats_(useSpecialFloats) + , precision_(precision) { } int BuiltStyledStreamWriter::write(Value const& root, std::ostream* sout) @@ -909,7 +913,7 @@ void BuiltStyledStreamWriter::writeValue(Value const& value) { pushValue(valueToString(value.asLargestUInt())); break; case realValue: - pushValue(valueToString(value.asDouble(), useSpecialFloats_, 17)); + pushValue(valueToString(value.asDouble(), useSpecialFloats_, precision_)); break; case stringValue: { @@ -1124,6 +1128,7 @@ StreamWriter* StreamWriterBuilder::newStreamWriter() const bool eyc = settings_["enableYAMLCompatibility"].asBool(); bool dnp = settings_["dropNullPlaceholders"].asBool(); bool usf = settings_["useSpecialFloats"].asBool(); + unsigned int pre = settings_["precision"].asUInt(); CommentStyle::Enum cs = CommentStyle::All; if (cs_str == "All") { cs = CommentStyle::All; @@ -1142,10 +1147,11 @@ StreamWriter* StreamWriterBuilder::newStreamWriter() const if (dnp) { nullSymbol = ""; } + if (pre > 17) pre = 17; std::string endingLineFeedSymbol = ""; return new BuiltStyledStreamWriter( indentation, cs, - colonSymbol, nullSymbol, endingLineFeedSymbol, usf); + colonSymbol, nullSymbol, endingLineFeedSymbol, usf, pre); } static void getValidWriterKeys(std::set* valid_keys) { @@ -1155,6 +1161,7 @@ static void getValidWriterKeys(std::set* valid_keys) valid_keys->insert("enableYAMLCompatibility"); valid_keys->insert("dropNullPlaceholders"); valid_keys->insert("useSpecialFloats"); + valid_keys->insert("precision"); } bool StreamWriterBuilder::validate(Json::Value* invalid) const { @@ -1186,6 +1193,7 @@ void StreamWriterBuilder::setDefaults(Json::Value* settings) (*settings)["enableYAMLCompatibility"] = false; (*settings)["dropNullPlaceholders"] = false; (*settings)["useSpecialFloats"] = false; + (*settings)["precision"] = 17; //! [StreamWriterBuilderDefaults] } From 9fd1ca8d68ceee52fc1c06d3cb4f5b33daeafce5 Mon Sep 17 00:00:00 2001 From: Benjamin Knecht Date: Thu, 15 Oct 2015 18:32:24 +0200 Subject: [PATCH 3/3] Add test code for precision --- src/test_lib_json/main.cpp | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/src/test_lib_json/main.cpp b/src/test_lib_json/main.cpp index c1061f4..ad0ad5f 100644 --- a/src/test_lib_json/main.cpp +++ b/src/test_lib_json/main.cpp @@ -1675,6 +1675,43 @@ JSONTEST_FIXTURE(ValueTest, specialFloats) { JSONTEST_ASSERT_STRING_EQUAL(expected, result); } +JSONTEST_FIXTURE(ValueTest, precision) { + Json::StreamWriterBuilder b; + b.settings_["precision"] = 5; + + Json::Value v = 100.0/3; + std::string expected = "33.333"; + std::string result = Json::writeString(b, v); + JSONTEST_ASSERT_STRING_EQUAL(expected, result); + + v = 0.25000000; + expected = "0.25"; + result = Json::writeString(b, v); + JSONTEST_ASSERT_STRING_EQUAL(expected, result); + + v = 0.2563456; + expected = "0.25635"; + result = Json::writeString(b, v); + JSONTEST_ASSERT_STRING_EQUAL(expected, result); + + b.settings_["precision"] = 1; + expected = "0.3"; + result = Json::writeString(b, v); + JSONTEST_ASSERT_STRING_EQUAL(expected, result); + + b.settings_["precision"] = 17; + v = 1234857476305.256345694873740545068; + expected = "1234857476305.2563"; + result = Json::writeString(b, v); + JSONTEST_ASSERT_STRING_EQUAL(expected, result); + + b.settings_["precision"] = 24; + v = 0.256345694873740545068; + expected = "0.25634569487374054"; + result = Json::writeString(b, v); + JSONTEST_ASSERT_STRING_EQUAL(expected, result); +} + struct WriterTest : JsonTest::TestCase {}; JSONTEST_FIXTURE(WriterTest, dropNullPlaceholders) { @@ -2489,6 +2526,7 @@ int main(int argc, const char* argv[]) { JSONTEST_REGISTER_FIXTURE(runner, ValueTest, zeroes); JSONTEST_REGISTER_FIXTURE(runner, ValueTest, zeroesInKeys); JSONTEST_REGISTER_FIXTURE(runner, ValueTest, specialFloats); + JSONTEST_REGISTER_FIXTURE(runner, ValueTest, precision); JSONTEST_REGISTER_FIXTURE(runner, WriterTest, dropNullPlaceholders); JSONTEST_REGISTER_FIXTURE(runner, StreamWriterTest, dropNullPlaceholders);