Refactor ObjectFactory to use new JSON library

- Removed a few try-catch blocks as this is now handled in Json::Read[...]
This commit is contained in:
Simon Jarrett 2020-08-12 20:03:29 +01:00
parent 5f17554c25
commit 97b44a7181
1 changed files with 61 additions and 75 deletions

View File

@ -160,8 +160,12 @@ public:
namespace ObjectFactory
{
/**
* @param jRoot Must be JSON node of type object
* @note jRoot is deliberately left non-const: json_t behaviour changes when const
*/
static Object* CreateObjectFromJson(
IObjectRepository& objectRepository, const json_t* jRoot, const IFileDataRetriever* fileRetriever);
IObjectRepository& objectRepository, json_t& jRoot, const IFileDataRetriever* fileRetriever);
static uint8_t ParseSourceGame(const std::string& s)
{
@ -363,16 +367,16 @@ namespace ObjectFactory
throw std::runtime_error("Unable to open object.json.");
}
json_error_t jsonLoadError;
auto jRoot = json_loadb(reinterpret_cast<const char*>(jsonBytes.data()), jsonBytes.size(), 0, &jsonLoadError);
if (jRoot == nullptr)
json_t jRoot = Json::FromVector(jsonBytes);
Object* obj = nullptr;
if (jRoot.is_object())
{
throw JsonException(&jsonLoadError);
auto fileDataRetriever = ZipDataRetriever(*archive);
obj = CreateObjectFromJson(objectRepository, jRoot, &fileDataRetriever);
}
auto fileDataRetriever = ZipDataRetriever(*archive);
Object* obj = CreateObjectFromJson(objectRepository, jRoot, &fileDataRetriever);
json_decref(jRoot);
return obj;
}
catch (const std::exception& e)
@ -392,96 +396,78 @@ namespace ObjectFactory
Object* result = nullptr;
try
{
auto jRoot = Json::ReadFromFile(path.c_str());
json_t jRoot = Json::ReadFromFile(path.c_str());
auto fileDataRetriever = FileSystemDataRetriever(Path::GetDirectory(path));
result = CreateObjectFromJson(objectRepository, jRoot, &fileDataRetriever);
json_decref(jRoot);
}
catch (const std::runtime_error& err)
{
Console::Error::WriteLine("Unable to open or read '%s': %s", path.c_str(), err.what());
delete result;
result = nullptr;
}
return result;
}
Object* CreateObjectFromJson(
IObjectRepository& objectRepository, const json_t* jRoot, const IFileDataRetriever* fileRetriever)
Object* CreateObjectFromJson(IObjectRepository& objectRepository, json_t& jRoot, const IFileDataRetriever* fileRetriever)
{
Guard::Assert(jRoot.is_object(), "ObjectFactory::CreateObjectFromJson expects parameter jRoot to be object");
log_verbose("CreateObjectFromJson(...)");
Object* result = nullptr;
auto jObjectType = json_object_get(jRoot, "objectType");
if (json_is_string(jObjectType))
auto objectType = ParseObjectType(Json::GetString(jRoot["objectType"]));
if (objectType != 0xFF)
{
auto objectType = ParseObjectType(json_string_value(jObjectType));
if (objectType != 0xFF)
auto id = Json::GetString(jRoot["id"]);
rct_object_entry entry = {};
auto originalId = Json::GetString(jRoot["originalId"]);
auto originalName = originalId;
if (originalId.length() == 8 + 1 + 8 + 1 + 8)
{
auto id = json_string_value(json_object_get(jRoot, "id"));
entry.flags = std::stoul(originalId.substr(0, 8), nullptr, 16);
originalName = originalId.substr(9, 8);
entry.checksum = std::stoul(originalId.substr(18, 8), nullptr, 16);
}
auto minLength = std::min<size_t>(8, originalName.length());
std::memcpy(entry.name, originalName.c_str(), minLength);
rct_object_entry entry = {};
auto originalId = String::ToStd(json_string_value(json_object_get(jRoot, "originalId")));
auto originalName = originalId;
if (originalId.length() == 8 + 1 + 8 + 1 + 8)
{
entry.flags = std::stoul(originalId.substr(0, 8), nullptr, 16);
originalName = originalId.substr(9, 8);
entry.checksum = std::stoul(originalId.substr(18, 8), nullptr, 16);
}
auto minLength = std::min<size_t>(8, originalName.length());
std::memcpy(entry.name, originalName.c_str(), minLength);
result = CreateObject(entry);
result->SetIdentifier(id);
result->MarkAsJsonObject();
auto readContext = ReadObjectContext(objectRepository, id, !gOpenRCT2NoGraphics, fileRetriever);
result->ReadJson(&readContext, jRoot);
if (readContext.WasError())
{
throw std::runtime_error("Object has errors");
}
result = CreateObject(entry);
result->SetIdentifier(id);
result->MarkAsJsonObject();
auto readContext = ReadObjectContext(objectRepository, id, !gOpenRCT2NoGraphics, fileRetriever);
result->ReadJson(&readContext, jRoot);
if (readContext.WasError())
auto jAuthors = jRoot["authors"];
std::vector<std::string> authorVector;
for (const auto& jAuthor : jAuthors)
{
if (jAuthor.is_string())
{
throw std::runtime_error("Object has errors");
authorVector.emplace_back(Json::GetString(jAuthor));
}
}
result->SetAuthors(std::move(authorVector));
auto authors = json_object_get(jRoot, "authors");
if (json_is_array(authors))
auto sourceGames = jRoot["sourceGame"];
if (sourceGames.is_array() || sourceGames.is_string())
{
std::vector<uint8_t> sourceGameVector;
for (const auto& jSourceGame : sourceGames)
{
std::vector<std::string> authorVector;
for (size_t j = 0; j < json_array_size(authors); j++)
{
json_t* tryString = json_array_get(authors, j);
if (json_is_string(tryString))
{
authorVector.emplace_back(json_string_value(tryString));
}
}
result->SetAuthors(std::move(authorVector));
}
else if (json_is_string(authors))
{
result->SetAuthors({ json_string_value(authors) });
}
auto sourceGames = json_object_get(jRoot, "sourceGame");
if (json_is_array(sourceGames))
{
std::vector<uint8_t> sourceGameVector;
for (size_t j = 0; j < json_array_size(sourceGames); j++)
{
sourceGameVector.push_back(ParseSourceGame(json_string_value(json_array_get(sourceGames, j))));
}
result->SetSourceGames(sourceGameVector);
}
else if (json_is_string(sourceGames))
{
auto sourceGame = json_string_value(sourceGames);
result->SetSourceGames({ ParseSourceGame(sourceGame) });
}
else
{
log_error("Object %s has an incorrect sourceGame parameter.", id);
result->SetSourceGames({ OBJECT_SOURCE_CUSTOM });
sourceGameVector.push_back(ParseSourceGame(Json::GetString(jSourceGame)));
}
result->SetSourceGames(sourceGameVector);
}
else
{
log_error("Object %s has an incorrect sourceGame parameter.", id.c_str());
result->SetSourceGames({ OBJECT_SOURCE_CUSTOM });
}
}
return result;