Skip to content

Commit

Permalink
JsonDumper - fix escape, improve coverage
Browse files Browse the repository at this point in the history
  • Loading branch information
vvromanov committed Jan 5, 2025
1 parent 2005195 commit 43b5997
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 17 deletions.
39 changes: 22 additions & 17 deletions src/JsonDumper.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ class JsonDumper {

JsonDumper& StartObject(bool is_array = false)
{
NextItem();
NextItem(true);
Push(is_array);
s << (is_array ? '[' : '{');
if (state.wrap) {
Expand Down Expand Up @@ -106,19 +106,28 @@ class JsonDumper {
return *this << std::string_view(str);
}

JsonDumper& operator<<(char* str)
{
return *this << std::string_view(str);
}

JsonDumper& operator<<(const std::string& str)
{
return *this << std::string_view(str);
}

JsonDumper& operator<<(char ch)
{
// char tmp[2] = { ch, '\0' };
return *this << std::string_view(&ch, 1);
}

JsonDumper& operator<<(double v)
{
if (std::isnan(v)) {
return *this << "nan";
}
if (state.in_array) {
NextItem();
}
NextItem();
s << v;
member_started = false;
return *this;
Expand All @@ -134,19 +143,15 @@ class JsonDumper {

JsonDumper& operator<<(int64_t v)
{
if (state.in_array) {
NextItem();
}
NextItem();
s << v;
member_started = false;
return *this;
}

JsonDumper& operator<<(uint64_t v)
{
if (state.in_array) {
NextItem();
}
NextItem();
s << v;
member_started = false;
return *this;
Expand All @@ -161,19 +166,15 @@ class JsonDumper {
template <class T>
JsonDumper& operator<<(T v)
{
if (state.in_array) {
NextItem();
}
NextItem();
s << '"' << v << '"';
member_started = false;
return *this;
}

JsonDumper& operator<<(std::string_view sv)
{
if (state.in_array) {
NextItem();
}
NextItem();
s << '"';
for (auto c : sv) {
if ((c == '"') || (c == '\\') || (('\0' < c) && (c < ' '))) {
Expand Down Expand Up @@ -226,8 +227,12 @@ class JsonDumper {
state = state_storage.top();
state_storage.pop();
}
void NextItem()

void NextItem(bool force = false)
{
if (!force && !state.in_array) {
return;
}
if (!state.first_element && state.in_array) {
if (state_storage.size() > 1) {
s << ',';
Expand Down
34 changes: 34 additions & 0 deletions tests/JsonDumperTest.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,36 @@
#include "JsonDumper.h"
#include "gtest/gtest.h"

static void TestEscape(char ch, const char* escaped) {
char expected[100];
snprintf(expected, sizeof(expected), "\"%s\"", escaped);
{ //As char
std::ostringstream ss;
JsonDumper j(ss);
j << ch;
EXPECT_EQ(expected, ss.str());
}
{ // As string
std::ostringstream ss;
JsonDumper j(ss);
char str[2] = { ch, '\0' };
j << str;
EXPECT_EQ(expected, ss.str());
}
}

TEST(JsonDumper, Escape) {
TestEscape('A', "A"); //No escape
TestEscape('"', "\\\"");
TestEscape('\\', "\\\\");
TestEscape('\n', "\\n");
TestEscape('\r', "\\r");
TestEscape('\b', "\\b");
TestEscape('\f', "\\f");
TestEscape('\t', "\\t");
TestEscape('\x01', "\\u0001");
}

TEST(JsonDumper, EmptyObject)
{
std::ostringstream ss;
Expand Down Expand Up @@ -31,6 +61,8 @@ static void DumpTest(JsonDumper& j)
j.StartMember("UInt16") << (uint16_t)10;
j.StartMember("UInt32") << (uint32_t)10;
j.StartMember("UInt64") << (uint64_t)10;
j.StartMember("double") << 12.345;
j.StartMember("float") << 12.345f;
j.StartMember("Char") << (char)'c';
j.StartMember("c_str") << "c_string";
j.StartMember("std_str") << std::string("std::string");
Expand Down Expand Up @@ -61,6 +93,8 @@ TEST(JsonDumper, Object)
" \"UInt16\": 10,\n"
" \"UInt32\": 10,\n"
" \"UInt64\": 10,\n"
" \"double\": 12.345,\n"
" \"float\": 12.345,\n"
" \"Char\": \"c\",\n"
" \"c_str\": \"c_string\",\n"
" \"std_str\": \"std::string\",\n"
Expand Down

0 comments on commit 43b5997

Please sign in to comment.