diff --git a/include/util/json_renderer.hpp b/include/util/json_renderer.hpp index 8d221e428..8081eec53 100644 --- a/include/util/json_renderer.hpp +++ b/include/util/json_renderer.hpp @@ -34,7 +34,17 @@ template struct Renderer void operator()(const String &string) { write('"'); - write(escape_JSON(string.value)); + auto size = SizeOfEscapedJSONString(string.value); + if (size == string.value.size()) { + // we don't need to escape anything + write(string.value); + } else { + std::string escaped; + escaped.reserve(size); + EscapeJSONString(string.value, escaped); + + write(escaped); + } write('"'); } diff --git a/include/util/string_util.hpp b/include/util/string_util.hpp index 3235d4915..d07753b9c 100644 --- a/include/util/string_util.hpp +++ b/include/util/string_util.hpp @@ -58,11 +58,32 @@ template char *printInt(char *buffer, int value) return buffer; } -inline std::string escape_JSON(const std::string &input) +inline size_t SizeOfEscapedJSONString(const std::string &string) +{ + size_t size = 0; + for (const char letter : string) + { + switch (letter) + { + case '\\': + case '"': + case '/': + case '\b': + case '\f': + case '\n': + case '\r': + case '\t': + size += 2; + break; + default: + size += 1; + } + } + return size; +} + +inline void EscapeJSONString(const std::string &input, std::string& output) { - // escape and skip reallocations if possible - std::string output; - output.reserve(input.size() + 4); // +4 assumes two backslashes on avg for (const char letter : input) { switch (letter) @@ -96,7 +117,6 @@ inline std::string escape_JSON(const std::string &input) break; } } - return output; } inline std::size_t URIDecode(const std::string &input, std::string &output)