From d54f4653ed772cf049680afc2eb866c25a265705 Mon Sep 17 00:00:00 2001 From: Evan Driscoll Date: Sat, 2 Jun 2018 02:09:04 -0500 Subject: [PATCH] It's now possible to limit the size of strings --- .../detail/output/fancy_serializer.hpp | 58 +++++++++++++++- single_include/nlohmann/json.hpp | 58 +++++++++++++++- test/src/unit-fancy-serialization.cpp | 68 +++++++++++++++++++ 3 files changed, 182 insertions(+), 2 deletions(-) diff --git a/include/nlohmann/detail/output/fancy_serializer.hpp b/include/nlohmann/detail/output/fancy_serializer.hpp index c3fba10fd..361a76ae9 100644 --- a/include/nlohmann/detail/output/fancy_serializer.hpp +++ b/include/nlohmann/detail/output/fancy_serializer.hpp @@ -28,6 +28,8 @@ struct fancy_serializer_style { unsigned int indent_step = 0; char indent_char = ' '; + + unsigned int strings_maximum_length = 0; }; namespace detail @@ -219,7 +221,61 @@ class fancy_serializer case value_t::string: { o->write_character('\"'); - prim_serializer.dump_escaped(*o, *val.m_value.string, ensure_ascii); + if (style.strings_maximum_length == 0) + { + prim_serializer.dump_escaped(*o, *val.m_value.string, ensure_ascii); + } + else + { + std::stringstream ss; + nlohmann::detail::output_adapter o_string(ss); + nlohmann::detail::output_adapter_t oo_string = o_string; + prim_serializer.dump_escaped(*oo_string, *val.m_value.string, ensure_ascii); + + std::string str = ss.str(); + if (str.size() <= style.strings_maximum_length) + { + o->write_characters(str.c_str(), str.size()); + } + else + { + const unsigned start_len = [](unsigned int maxl) + { + if (maxl <= 3) + { + // There is only room for the ellipsis, + // no characters from the string + return 0u; + } + else if (maxl <= 5) + { + // With four allowed characters, we add in the + // first from the string. With five, we add in + // the *last* instead, so still just one at + // the start. + return 1u; + } + else + { + // We subtract three for the ellipsis + // and one for the last character. + return maxl - 4; + } + }(style.strings_maximum_length); + + const unsigned end_len = + style.strings_maximum_length >= 5 ? 1 : 0; + + const unsigned ellipsis_length = + style.strings_maximum_length >= 3 + ? 3 + : style.strings_maximum_length; + + o->write_characters(str.c_str(), start_len); + o->write_characters("...", ellipsis_length); + o->write_characters(str.c_str() + str.size() - end_len, end_len); + } + } o->write_character('\"'); return; } diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp index c6fc6a283..979e55671 100644 --- a/single_include/nlohmann/json.hpp +++ b/single_include/nlohmann/json.hpp @@ -10098,6 +10098,8 @@ struct fancy_serializer_style { unsigned int indent_step = 0; char indent_char = ' '; + + unsigned int strings_maximum_length = 0; }; namespace detail @@ -10289,7 +10291,61 @@ class fancy_serializer case value_t::string: { o->write_character('\"'); - prim_serializer.dump_escaped(*o, *val.m_value.string, ensure_ascii); + if (style.strings_maximum_length == 0) + { + prim_serializer.dump_escaped(*o, *val.m_value.string, ensure_ascii); + } + else + { + std::stringstream ss; + nlohmann::detail::output_adapter o_string(ss); + nlohmann::detail::output_adapter_t oo_string = o_string; + prim_serializer.dump_escaped(*oo_string, *val.m_value.string, ensure_ascii); + + std::string str = ss.str(); + if (str.size() <= style.strings_maximum_length) + { + o->write_characters(str.c_str(), str.size()); + } + else + { + const unsigned start_len = [](unsigned int maxl) + { + if (maxl <= 3) + { + // There is only room for the ellipsis, + // no characters from the string + return 0u; + } + else if (maxl <= 5) + { + // With four allowed characters, we add in the + // first from the string. With five, we add in + // the *last* instead, so still just one at + // the start. + return 1u; + } + else + { + // We subtract three for the ellipsis + // and one for the last character. + return maxl - 4; + } + }(style.strings_maximum_length); + + const unsigned end_len = + style.strings_maximum_length >= 5 ? 1 : 0; + + const unsigned ellipsis_length = + style.strings_maximum_length >= 3 + ? 3 + : style.strings_maximum_length; + + o->write_characters(str.c_str(), start_len); + o->write_characters("...", ellipsis_length); + o->write_characters(str.c_str() + str.size() - end_len, end_len); + } + } o->write_character('\"'); return; } diff --git a/test/src/unit-fancy-serialization.cpp b/test/src/unit-fancy-serialization.cpp index 17eb6ba3d..3a8e79202 100644 --- a/test/src/unit-fancy-serialization.cpp +++ b/test/src/unit-fancy-serialization.cpp @@ -77,6 +77,74 @@ TEST_CASE("serialization") } } + SECTION("strings") + { + SECTION("long strings usually print") + { + auto str = fancy_to_string( + "The quick brown fox jumps over the lazy brown dog"); + CHECK(str == + "\"The quick brown fox jumps over the lazy brown dog\""); + } + + SECTION("long strings can be shortened") + { + fancy_serializer_style style; + style.strings_maximum_length = 10; + + auto str = fancy_to_string( + "The quick brown fox jumps over the lazy brown dog", + style); + CHECK(str == "\"The qu...g\""); + } + + SECTION("requesting extremely short strings limits what is included") + { + const char* const quick = "The quick brown fox jumps over the lazy brown dog"; + + std::pair tests[] = + { + {5, "\"T...g\""}, + {4, "\"T...\""}, + {3, "\"...\""}, + {2, "\"..\""}, + {1, "\".\""}, + }; + + for (auto test : tests) + { + fancy_serializer_style style; + style.strings_maximum_length = test.first; + auto str = fancy_to_string(quick, style); + CHECK(str == test.second); + } + } + + SECTION("But you cannot ask for a length of zero; that means unlimited") + { + fancy_serializer_style style; + style.strings_maximum_length = 0; + + auto str = fancy_to_string( + "The quick brown fox jumps over the lazy brown dog", + style); + CHECK(str == + "\"The quick brown fox jumps over the lazy brown dog\""); + } + + SECTION("\"Limiting\" to something long doesn't do anything") + { + fancy_serializer_style style; + style.strings_maximum_length = 100; + + auto str = fancy_to_string( + "The quick brown fox jumps over the lazy brown dog", + style); + CHECK(str == + "\"The quick brown fox jumps over the lazy brown dog\""); + } + } + SECTION("given width") { fancy_serializer_style style;