Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 27 additions & 2 deletions inkcpp_compiler/json_compiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,25 @@ void json_compiler::compile(
const nlohmann::json& input, emitter* output, compilation_results* results
)
{
/* Look the top-level keys up rather than reaching for them with operator[].
On a const json, operator[] with a missing key is an assert(), which
aborts the process instead of reporting an error, and any JSON at all can
be handed to a compiler that accepts "a .json file". Every other failure
here is an ink_exception the caller can catch. */
if (! input.is_object()) {
throw ink_exception("this JSON is not an Ink story: its top level is not an object");
}
const auto version_itr = input.find("inkVersion");
if (version_itr == input.end()) {
throw ink_exception("this JSON is not an Ink story: it has no \"inkVersion\"");
}
const auto root_itr = input.find("root");
if (root_itr == input.end()) {
throw ink_exception("this JSON is not an Ink story: it has no \"root\"");
}

// Get the runtime version
_ink_version = input["inkVersion"];
_ink_version = *version_itr;

// Start the output
set_results(results);
Expand All @@ -45,7 +62,7 @@ void json_compiler::compile(
_emitter->set_list_meta(_list_meta);
}
// Compile the root container
compile_container(input["root"], 0, 0);
compile_container(*root_itr, 0, 0);

// finalize
_emitter->finish(_next_container_index);
Expand Down Expand Up @@ -133,6 +150,14 @@ void json_compiler::compile_container(
const std::string& name_override
)
{
/* Every container is an array whose last element is its metadata object, so
rbegin() and the end() - 1 below are only meaningful for a non-empty
array. Reaching them with anything else dereferences an end iterator.
This guard covers the root and every nested container in one place. */
if (! container.is_array() || container.empty()) {
throw ink_exception("malformed Ink story: a container must be a non-empty array");
}

// Grab metadata from the last object in this container
container_meta meta;
bool is_knot = name_override != "" && index_in_parent == -1;
Expand Down
Loading