Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions include/nlohmann/detail/output/serializer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ class serializer

// variable to hold indentation for recursive calls
const auto new_indent = current_indent + indent_step;
if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent))
while (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent))

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe instead go in a single step instead of growing over multiple calls.

indent_string.resize((std::max)(indent_string.size() * 2, new_indent));

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good call, that's cleaner. Switched to the single resize with (std::max)(size*2, new_indent) so it still doubles for amortized growth but jumps straight to the needed width when one doubling wouldn't cover it. Had to cast new_indent to string_t::size_type so max deduces one type. Pushed and re-amalgamated.

{
indent_string.resize(indent_string.size() * 2, ' ');
}
Expand Down Expand Up @@ -199,7 +199,7 @@ class serializer

// variable to hold indentation for recursive calls
const auto new_indent = current_indent + indent_step;
if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent))
while (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent))
{
indent_string.resize(indent_string.size() * 2, ' ');
}
Expand Down Expand Up @@ -260,7 +260,7 @@ class serializer

// variable to hold indentation for recursive calls
const auto new_indent = current_indent + indent_step;
if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent))
while (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent))
{
indent_string.resize(indent_string.size() * 2, ' ');
}
Expand Down
6 changes: 3 additions & 3 deletions single_include/nlohmann/json.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -19833,7 +19833,7 @@ class serializer

// variable to hold indentation for recursive calls
const auto new_indent = current_indent + indent_step;
if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent))
while (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent))
{
indent_string.resize(indent_string.size() * 2, ' ');
}
Expand Down Expand Up @@ -19906,7 +19906,7 @@ class serializer

// variable to hold indentation for recursive calls
const auto new_indent = current_indent + indent_step;
if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent))
while (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent))
{
indent_string.resize(indent_string.size() * 2, ' ');
}
Expand Down Expand Up @@ -19967,7 +19967,7 @@ class serializer

// variable to hold indentation for recursive calls
const auto new_indent = current_indent + indent_step;
if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent))
while (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent))
{
indent_string.resize(indent_string.size() * 2, ' ');
}
Expand Down
30 changes: 30 additions & 0 deletions tests/src/unit-serialization.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,36 @@ TEST_CASE("serialization")
}
}

SECTION("dump with large indentation")
{
// the indentation buffer starts at 512 characters and grows on demand;
// a width that needs more room than a single doubling provides must keep
// growing the buffer rather than emit past its end
const unsigned int width = 1100;

SECTION("object")
{
const json j = {{"outer", {{"inner", 1}}}};
const std::string s = j.dump(static_cast<int>(width));
CHECK(s.find('\n' + std::string(width, ' ') + "\"outer\"") != std::string::npos);
CHECK(s.find('\n' + std::string(2 * width, ' ') + "\"inner\"") != std::string::npos);
}

SECTION("array")
{
const json j = json::array({json::array({1})});
const std::string s = j.dump(static_cast<int>(width));
CHECK(s.find('\n' + std::string(2 * width, ' ') + '1') != std::string::npos);
}

SECTION("binary")
{
const json j = json::binary({1, 2, 3});
const std::string s = j.dump(static_cast<int>(width));
CHECK(s.find('\n' + std::string(width, ' ') + "\"bytes\"") != std::string::npos);
}
}

SECTION("to_string")
{
auto test = [&](std::string const & input, std::string const & expected)
Expand Down