Skip to content

Commit

Permalink
BugFix: JSONStateWriter prettyprint output is nolonger minified. (#1232)
Browse files Browse the repository at this point in the history
* BugFix: JSONStateWriter prettyprint output is nolonger minified.

rapidjson's PrettyWriter extends Writer, but methods are non-virtual, leading to former bug.

This fix is best solution of the bad options (heavy templating, dual internal writers).

Closes #1231

* Fixup, implementation did not consider nested quotes

Would have broken if it encounterd an odd number of nested quotes within a string.
  • Loading branch information
Robadob authored Oct 1, 2024
1 parent 42786c5 commit ed7d1d7
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 9 deletions.
6 changes: 5 additions & 1 deletion include/flamegpu/io/JSONStateWriter.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,13 @@ class JSONStateWriter : public StateWriter {
bool environment_written = false;
bool macro_environment_written = false;
bool agents_written = false;
// Dirty workaround for PrettyWriter overloads not being virtual
bool newline_purge_required = false;
std::string outputPath;
rapidjson::StringBuffer buffer;
std::unique_ptr<rapidjson::Writer<rapidjson::StringBuffer, rapidjson::UTF8<>, rapidjson::UTF8<>, rapidjson::CrtAllocator, rapidjson::kWriteNanAndInfFlag>> writer;
// Typedef because the template is too long
typedef rapidjson::PrettyWriter<rapidjson::StringBuffer, rapidjson::UTF8<>, rapidjson::UTF8<>, rapidjson::CrtAllocator, rapidjson::kWriteNanAndInfFlag> PrettyWriter;
std::unique_ptr<PrettyWriter> writer;
};
} // namespace io
} // namespace flamegpu
Expand Down
31 changes: 23 additions & 8 deletions src/flamegpu/io/JSONStateWriter.cu
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include <string>
#include <numeric>
#include <set>
#include <algorithm>

#include "flamegpu/exception/FLAMEGPUException.h"
#include "flamegpu/model/AgentDescription.h"
Expand All @@ -27,13 +28,11 @@ void JSONStateWriter::beginWrite(const std::string &output_file, bool pretty_pri
THROW exception::UnknownInternalError("Writing already active, in JSONStateWriter::beginWrite()");
}
buffer = rapidjson::StringBuffer();
if (pretty_print) {
auto t_writer = std::make_unique<rapidjson::PrettyWriter<rapidjson::StringBuffer, rapidjson::UTF8<>, rapidjson::UTF8<>, rapidjson::CrtAllocator, rapidjson::kWriteNanAndInfFlag>>(buffer);
t_writer->SetIndent('\t', 1);
writer = std::move(t_writer);
} else {
writer = std::make_unique<rapidjson::Writer<rapidjson::StringBuffer, rapidjson::UTF8<>, rapidjson::UTF8<>, rapidjson::CrtAllocator, rapidjson::kWriteNanAndInfFlag>>(buffer);
}
writer = std::make_unique<PrettyWriter>(buffer);
// PrettyWriter overloads Writer, but methods aren't virtual so pointer casting doesn't work as intended
// This is the best of the bad options for this particular implementation
writer->SetIndent('\t', pretty_print ? 1 : 0);
newline_purge_required = !pretty_print;
// Begin Json file
writer->StartObject();

Expand All @@ -53,7 +52,23 @@ void JSONStateWriter::endWrite() {
writer->EndObject();

std::ofstream out(outputPath, std::ofstream::trunc);
out << buffer.GetString();
if (newline_purge_required) {
// Minify the output
std::string t_buffer = buffer.GetString();
// Replace all spaces outside of quotes with \n
bool in_string = false;
auto it = t_buffer.begin();
++it; // First char in generated JSON will never be a quote or space
for (; it != t_buffer.end(); ++it) {
if (*it == '"' && *(it-1) != '\\') in_string = !in_string; // Catch string begin/end, ignore nested quotes
if (*it == ' ' && !in_string) *it = '\n';
}
// Remove newlines
t_buffer.erase(std::remove(t_buffer.begin(), t_buffer.end(), '\n'), t_buffer.end());
out << t_buffer;
} else {
out << buffer.GetString();
}
out.close();

writer.reset();
Expand Down

0 comments on commit ed7d1d7

Please sign in to comment.