Skip to content

Commit b230e92

Browse files
simplify use of RapidYAML for std.parseYaml, improve YAML stream handling
There is really no need to parse the YAML, and then re-serialize it, and then perform a string-splitting operation into a std::vector, and then re-parse each chunk individually, in order to convert a YAML stream into a JSON array.
1 parent 67977f3 commit b230e92

2 files changed

Lines changed: 16 additions & 32 deletions

File tree

core/vm.cpp

Lines changed: 14 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1686,41 +1686,29 @@ class Interpreter {
16861686

16871687
std::string value = encode_utf8(static_cast<HeapString *>(args[0].v.h)->value);
16881688

1689-
ryml::Tree tree = treeFromString(value);
1689+
ryml::Tree tree = ryml::parse_in_arena(ryml::to_csubstr(value));
16901690

16911691
json j;
1692-
if (tree.is_stream(tree.root_id())) {
1693-
// Split into individual yaml documents
1694-
std::stringstream ss;
1695-
ss << tree;
1696-
std::vector<std::string> v = split(ss.str(), "---\n");
1697-
1698-
// Convert yaml to json and push onto json array
1699-
ryml::Tree doc;
1700-
for (std::size_t i = 0; i < v.size(); ++i) {
1701-
if (!v[i].empty()) {
1702-
doc = treeFromString(v[i]);
1703-
j.push_back(yamlTreeToJson(doc));
1704-
}
1705-
}
1706-
} else if (tree.type(tree.root_id()).is_notype()) {
1692+
if (tree.type(tree.root_id()).is_notype()) {
17071693
scratch = makeNull();
17081694
return nullptr;
1695+
} else if (tree.is_stream(tree.root_id())) {
1696+
ryml::ConstNodeRef root = tree.crootref();
1697+
for (ryml::ConstNodeRef node : root.children()) {
1698+
std::ostringstream jsonText;
1699+
jsonText << ryml::as_json(node);
1700+
j.push_back(json::parse(jsonText.str()));
1701+
}
17091702
} else {
1710-
j = yamlTreeToJson(tree);
1703+
std::ostringstream jsonText;
1704+
jsonText << ryml::as_json(tree);
1705+
j = json::parse(jsonText.str());
17111706
}
1712-
1713-
bool filled;
1714-
1715-
otherJsonToHeap(j, filled, scratch);
1716-
1707+
bool filled_unused;
1708+
otherJsonToHeap(j, filled_unused, scratch);
17171709
return nullptr;
17181710
}
17191711

1720-
const ryml::Tree treeFromString(const std::string& s) {
1721-
return ryml::parse_in_arena(ryml::to_csubstr(s));
1722-
}
1723-
17241712
const std::vector<std::string> split(const std::string& s, const std::string& delimiter) {
17251713
size_t pos_start = 0, pos_end, delim_len = delimiter.length();
17261714
std::string token;
@@ -1736,12 +1724,6 @@ class Interpreter {
17361724
return res;
17371725
}
17381726

1739-
const json yamlTreeToJson(const ryml::Tree& tree) {
1740-
std::ostringstream jsonStream;
1741-
jsonStream << ryml::as_json(tree);
1742-
return json::parse(jsonStream.str());
1743-
}
1744-
17451727
void otherJsonToHeap(const json &v, bool &filled, Value &attach) {
17461728
// In order to not anger the garbage collector, assign to attach immediately after
17471729
// making the heap object.

test_suite/stdlib.jsonnet

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1481,6 +1481,8 @@ std.assertEqual(std.parseJson('{"a": {"b": ["c", 42]}}'), { a: { b: ['c', 42] }
14811481
// Empty input evaluates to `null`.
14821482
// Regression test for https://github.com/google/jsonnet/issues/1270
14831483
std.assertEqual(std.parseYaml(' \n'), null) &&
1484+
// Stream input, regression test for https://github.com/google/jsonnet/issues/1148
1485+
std.assertEqual(std.parseYaml('1\n---'), [1, null]) &&
14841486
std.assertEqual(std.parseYaml('{}'), {}) &&
14851487
std.assertEqual(std.parseYaml('[]'), []) &&
14861488
std.assertEqual(

0 commit comments

Comments
 (0)