mirror of
https://github.com/OpenRCT2/OpenRCT2
synced 2026-01-24 23:34:37 +01:00
Close #13000: Refactor ObjectFactory to use unique_ptr
Employs the smart pointer unique_ptr for safer memory management. Classes involved: - ObjectRepository - ObjectManager
This commit is contained in:
@@ -164,7 +164,7 @@ 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(
|
||||
static std::unique_ptr<Object> CreateObjectFromJson(
|
||||
IObjectRepository& objectRepository, json_t& jRoot, const IFileDataRetriever* fileRetriever);
|
||||
|
||||
static uint8_t ParseSourceGame(const std::string& s)
|
||||
@@ -183,11 +183,11 @@ namespace ObjectFactory
|
||||
return (result != LookupTable.end()) ? result->second : OBJECT_SOURCE_CUSTOM;
|
||||
}
|
||||
|
||||
static void ReadObjectLegacy(Object* object, IReadObjectContext* context, OpenRCT2::IStream* stream)
|
||||
static void ReadObjectLegacy(Object& object, IReadObjectContext* context, OpenRCT2::IStream* stream)
|
||||
{
|
||||
try
|
||||
{
|
||||
object->ReadLegacy(context, stream);
|
||||
object.ReadLegacy(context, stream);
|
||||
}
|
||||
catch (const IOException&)
|
||||
{
|
||||
@@ -200,11 +200,11 @@ namespace ObjectFactory
|
||||
}
|
||||
}
|
||||
|
||||
Object* CreateObjectFromLegacyFile(IObjectRepository& objectRepository, const utf8* path)
|
||||
std::unique_ptr<Object> CreateObjectFromLegacyFile(IObjectRepository& objectRepository, const utf8* path)
|
||||
{
|
||||
log_verbose("CreateObjectFromLegacyFile(..., \"%s\")", path);
|
||||
|
||||
Object* result = nullptr;
|
||||
std::unique_ptr<Object> result;
|
||||
try
|
||||
{
|
||||
auto fs = OpenRCT2::FileStream(path, OpenRCT2::FILE_MODE_OPEN);
|
||||
@@ -225,7 +225,7 @@ namespace ObjectFactory
|
||||
|
||||
auto chunkStream = OpenRCT2::MemoryStream(chunk->GetData(), chunk->GetLength());
|
||||
auto readContext = ReadObjectContext(objectRepository, objectName, !gOpenRCT2NoGraphics, nullptr);
|
||||
ReadObjectLegacy(result, &readContext, &chunkStream);
|
||||
ReadObjectLegacy(*result, &readContext, &chunkStream);
|
||||
if (readContext.WasError())
|
||||
{
|
||||
throw std::runtime_error("Object has errors");
|
||||
@@ -236,19 +236,17 @@ namespace ObjectFactory
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
log_error("Error: %s when processing object %s", e.what(), path);
|
||||
delete result;
|
||||
result = nullptr;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
Object* CreateObjectFromLegacyData(
|
||||
std::unique_ptr<Object> CreateObjectFromLegacyData(
|
||||
IObjectRepository& objectRepository, const rct_object_entry* entry, const void* data, size_t dataSize)
|
||||
{
|
||||
Guard::ArgumentNotNull(entry, GUARD_LINE);
|
||||
Guard::ArgumentNotNull(data, GUARD_LINE);
|
||||
|
||||
Object* result = CreateObject(*entry);
|
||||
auto result = CreateObject(*entry);
|
||||
if (result != nullptr)
|
||||
{
|
||||
utf8 objectName[DAT_NAME_LENGTH + 1];
|
||||
@@ -256,12 +254,11 @@ namespace ObjectFactory
|
||||
|
||||
auto readContext = ReadObjectContext(objectRepository, objectName, !gOpenRCT2NoGraphics, nullptr);
|
||||
auto chunkStream = OpenRCT2::MemoryStream(data, dataSize);
|
||||
ReadObjectLegacy(result, &readContext, &chunkStream);
|
||||
ReadObjectLegacy(*result, &readContext, &chunkStream);
|
||||
|
||||
if (readContext.WasError())
|
||||
{
|
||||
delete result;
|
||||
result = nullptr;
|
||||
log_error("Error when processing object.");
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -271,52 +268,51 @@ namespace ObjectFactory
|
||||
return result;
|
||||
}
|
||||
|
||||
Object* CreateObject(const rct_object_entry& entry)
|
||||
std::unique_ptr<Object> CreateObject(const rct_object_entry& entry)
|
||||
{
|
||||
Object* result;
|
||||
std::unique_ptr<Object> result;
|
||||
switch (entry.GetType())
|
||||
{
|
||||
case OBJECT_TYPE_RIDE:
|
||||
result = new RideObject(entry);
|
||||
result = std::make_unique<RideObject>(entry);
|
||||
break;
|
||||
case OBJECT_TYPE_SMALL_SCENERY:
|
||||
result = new SmallSceneryObject(entry);
|
||||
result = std::make_unique<SmallSceneryObject>(entry);
|
||||
break;
|
||||
case OBJECT_TYPE_LARGE_SCENERY:
|
||||
result = new LargeSceneryObject(entry);
|
||||
result = std::make_unique<LargeSceneryObject>(entry);
|
||||
break;
|
||||
case OBJECT_TYPE_WALLS:
|
||||
result = new WallObject(entry);
|
||||
result = std::make_unique<WallObject>(entry);
|
||||
break;
|
||||
case OBJECT_TYPE_BANNERS:
|
||||
result = new BannerObject(entry);
|
||||
result = std::make_unique<BannerObject>(entry);
|
||||
break;
|
||||
case OBJECT_TYPE_PATHS:
|
||||
result = new FootpathObject(entry);
|
||||
result = std::make_unique<FootpathObject>(entry);
|
||||
break;
|
||||
case OBJECT_TYPE_PATH_BITS:
|
||||
result = new FootpathItemObject(entry);
|
||||
result = std::make_unique<FootpathItemObject>(entry);
|
||||
break;
|
||||
case OBJECT_TYPE_SCENERY_GROUP:
|
||||
result = new SceneryGroupObject(entry);
|
||||
result = std::make_unique<SceneryGroupObject>(entry);
|
||||
break;
|
||||
case OBJECT_TYPE_PARK_ENTRANCE:
|
||||
result = new EntranceObject(entry);
|
||||
result = std::make_unique<EntranceObject>(entry);
|
||||
break;
|
||||
case OBJECT_TYPE_WATER:
|
||||
result = new WaterObject(entry);
|
||||
result = std::make_unique<WaterObject>(entry);
|
||||
break;
|
||||
case OBJECT_TYPE_SCENARIO_TEXT:
|
||||
result = nullptr;
|
||||
break;
|
||||
case OBJECT_TYPE_TERRAIN_SURFACE:
|
||||
result = new TerrainSurfaceObject(entry);
|
||||
result = std::make_unique<TerrainSurfaceObject>(entry);
|
||||
break;
|
||||
case OBJECT_TYPE_TERRAIN_EDGE:
|
||||
result = new TerrainEdgeObject(entry);
|
||||
result = std::make_unique<TerrainEdgeObject>(entry);
|
||||
break;
|
||||
case OBJECT_TYPE_STATION:
|
||||
result = new StationObject(entry);
|
||||
result = std::make_unique<StationObject>(entry);
|
||||
break;
|
||||
default:
|
||||
throw std::runtime_error("Invalid object type");
|
||||
@@ -355,9 +351,8 @@ namespace ObjectFactory
|
||||
return 0xFF;
|
||||
}
|
||||
|
||||
Object* CreateObjectFromZipFile(IObjectRepository& objectRepository, const std::string_view& path)
|
||||
std::unique_ptr<Object> CreateObjectFromZipFile(IObjectRepository& objectRepository, const std::string_view& path)
|
||||
{
|
||||
Object* result = nullptr;
|
||||
try
|
||||
{
|
||||
auto archive = Zip::Open(path, ZIP_ACCESS::READ);
|
||||
@@ -369,46 +364,38 @@ namespace ObjectFactory
|
||||
|
||||
json_t jRoot = Json::FromVector(jsonBytes);
|
||||
|
||||
Object* obj = nullptr;
|
||||
|
||||
if (jRoot.is_object())
|
||||
{
|
||||
auto fileDataRetriever = ZipDataRetriever(*archive);
|
||||
obj = CreateObjectFromJson(objectRepository, jRoot, &fileDataRetriever);
|
||||
return CreateObjectFromJson(objectRepository, jRoot, &fileDataRetriever);
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
Console::Error::WriteLine("Unable to open or read '%s': %s", path.data(), e.what());
|
||||
|
||||
delete result;
|
||||
result = nullptr;
|
||||
}
|
||||
return result;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Object* CreateObjectFromJsonFile(IObjectRepository& objectRepository, const std::string& path)
|
||||
std::unique_ptr<Object> CreateObjectFromJsonFile(IObjectRepository& objectRepository, const std::string& path)
|
||||
{
|
||||
log_verbose("CreateObjectFromJsonFile(\"%s\")", path.c_str());
|
||||
|
||||
Object* result = nullptr;
|
||||
try
|
||||
{
|
||||
json_t jRoot = Json::ReadFromFile(path.c_str());
|
||||
auto fileDataRetriever = FileSystemDataRetriever(Path::GetDirectory(path));
|
||||
result = CreateObjectFromJson(objectRepository, jRoot, &fileDataRetriever);
|
||||
return CreateObjectFromJson(objectRepository, jRoot, &fileDataRetriever);
|
||||
}
|
||||
catch (const std::runtime_error& err)
|
||||
{
|
||||
Console::Error::WriteLine("Unable to open or read '%s': %s", path.c_str(), err.what());
|
||||
}
|
||||
|
||||
return result;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static void ExtractSourceGames(const std::string& id, json_t& jRoot, Object* result)
|
||||
static void ExtractSourceGames(const std::string& id, json_t& jRoot, Object& result)
|
||||
{
|
||||
auto sourceGames = jRoot["sourceGame"];
|
||||
if (sourceGames.is_array() || sourceGames.is_string())
|
||||
@@ -420,33 +407,34 @@ namespace ObjectFactory
|
||||
}
|
||||
if (!sourceGameVector.empty())
|
||||
{
|
||||
result->SetSourceGames(sourceGameVector);
|
||||
result.SetSourceGames(sourceGameVector);
|
||||
}
|
||||
else
|
||||
{
|
||||
log_error("Object %s has an incorrect sourceGame parameter.", id.c_str());
|
||||
result->SetSourceGames({ OBJECT_SOURCE_CUSTOM });
|
||||
result.SetSourceGames({ OBJECT_SOURCE_CUSTOM });
|
||||
}
|
||||
}
|
||||
// >90% of objects are custom, so allow omitting the parameter without displaying an error.
|
||||
else if (sourceGames.is_null())
|
||||
{
|
||||
result->SetSourceGames({ OBJECT_SOURCE_CUSTOM });
|
||||
result.SetSourceGames({ OBJECT_SOURCE_CUSTOM });
|
||||
}
|
||||
else
|
||||
{
|
||||
log_error("Object %s has an incorrect sourceGame parameter.", id.c_str());
|
||||
result->SetSourceGames({ OBJECT_SOURCE_CUSTOM });
|
||||
result.SetSourceGames({ OBJECT_SOURCE_CUSTOM });
|
||||
}
|
||||
}
|
||||
|
||||
Object* CreateObjectFromJson(IObjectRepository& objectRepository, json_t& jRoot, const IFileDataRetriever* fileRetriever)
|
||||
std::unique_ptr<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;
|
||||
std::unique_ptr<Object> result;
|
||||
|
||||
auto objectType = ParseObjectType(Json::GetString(jRoot["objectType"]));
|
||||
if (objectType != 0xFF)
|
||||
@@ -472,7 +460,6 @@ namespace ObjectFactory
|
||||
result->ReadJson(&readContext, jRoot);
|
||||
if (readContext.WasError())
|
||||
{
|
||||
delete result;
|
||||
throw std::runtime_error("Object has errors");
|
||||
}
|
||||
|
||||
@@ -487,7 +474,7 @@ namespace ObjectFactory
|
||||
}
|
||||
result->SetAuthors(std::move(authorVector));
|
||||
|
||||
ExtractSourceGames(id, jRoot, result);
|
||||
ExtractSourceGames(id, jRoot, *result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user