Skip to content

Commit

Permalink
Merge pull request #298 from biojppm/fix/emitjson
Browse files Browse the repository at this point in the history
[fix] json emitter should escape control characters
  • Loading branch information
biojppm authored Aug 29, 2022
2 parents 4ee4e84 + 2eb72db commit f020b03
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 15 deletions.
1 change: 1 addition & 0 deletions changelog/0.5.0.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@
Tree tree2 = parse_in_arena(to_csubstr(s));
EXPECT_EQ(tree2["s"].val(), tree["s"].val());
```
- Fix [#297](https://github.com/biojppm/rapidyaml/issues/297) ([PR#298](https://github.com/biojppm/rapidyaml/pull/298)): JSON emitter should escape control characters.
- Fix [#274](https://github.com/biojppm/rapidyaml/issues/274) ([PR#296](https://github.com/biojppm/rapidyaml/pull/296)): Lists with unindented items and trailing empty values parse incorrectly:
```yaml
foo:
Expand Down
52 changes: 37 additions & 15 deletions src/c4/yml/emit.def.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -878,14 +878,8 @@ void Emitter<Writer>::_write_scalar(csubstr s, bool was_quoted)
template<class Writer>
void Emitter<Writer>::_write_scalar_json(csubstr s, bool as_key, bool was_quoted)
{
if(was_quoted)
{
this->Writer::_do_write('"');
this->Writer::_do_write(s);
this->Writer::_do_write('"');
}
// json only allows strings as keys
else if(!as_key && (s.is_number() || s == "true" || s == "null" || s == "false"))
if(!as_key && !was_quoted && (s.is_number() || s == "true" || s == "null" || s == "false"))
{
this->Writer::_do_write(s);
}
Expand All @@ -895,15 +889,43 @@ void Emitter<Writer>::_write_scalar_json(csubstr s, bool as_key, bool was_quoted
this->Writer::_do_write('"');
for(size_t i = 0; i < s.len; ++i)
{
if(s[i] == '"')
switch(s.str[i])
{
if(i > 0)
{
csubstr sub = s.range(pos, i);
this->Writer::_do_write(sub);
}
pos = i + 1;
this->Writer::_do_write("\\\"");
case '"':
this->Writer ::_do_write(s.range(pos, i));
this->Writer ::_do_write("\\\"");
pos = i + 1;
break;
case '\n':
this->Writer ::_do_write(s.range(pos, i));
this->Writer ::_do_write("\\n");
pos = i + 1;
break;
case '\t':
this->Writer ::_do_write(s.range(pos, i));
this->Writer ::_do_write("\\t");
pos = i + 1;
break;
case '\\':
this->Writer ::_do_write(s.range(pos, i));
this->Writer ::_do_write("\\\\");
pos = i + 1;
break;
case '\r':
this->Writer ::_do_write(s.range(pos, i));
this->Writer ::_do_write("\\r");
pos = i + 1;
break;
case '\b':
this->Writer ::_do_write(s.range(pos, i));
this->Writer ::_do_write("\\b");
pos = i + 1;
break;
case '\f':
this->Writer ::_do_write(s.range(pos, i));
this->Writer ::_do_write("\\f");
pos = i + 1;
break;
}
}
if(pos < s.len)
Expand Down
27 changes: 27 additions & 0 deletions test/test_json.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,33 @@ broken_value: '0.30.2'
)");
}

TEST(emit_json, issue297)
{
char yml_buf[] = R"(
comment: |
abc
def
)";
Tree t = parse_in_place(yml_buf);
auto s = emitrs_json<std::string>(t);
EXPECT_EQ(s, "{\"comment\": \"abc\\ndef\\n\"}");
}

TEST(emit_json, issue297_escaped_chars)
{
Tree t = parse_in_arena("{}");
t["quote"] = "abc\"def";
t["newline"] = "abc\ndef";
t["tab"] = "abc\tdef";
t["carriage"] = "abc\rdef";
t["backslash"] = "abc\\def";
t["backspace"] = "abc\bdef";
t["formfeed"] = "abc\fdef";
std::string expected = R"({"quote": "abc\"def","newline": "abc\ndef","tab": "abc\tdef","carriage": "abc\rdef","backslash": "abc\\def","backspace": "abc\bdef","formfeed": "abc\fdef"})";
auto actual = emitrs_json<std::string>(t);
EXPECT_EQ(actual, expected);
}


#define _test(actual_src, expected_src) \
{ \
Expand Down

0 comments on commit f020b03

Please sign in to comment.