CResource: Make BuildDependencyTree() return a unique_ptr

Makes the functions more memory safe in terms of freeing memory in
exceptional paths .
This commit is contained in:
Lioncash 2020-06-11 18:25:35 -04:00
parent eb8ca98a8a
commit ce315280c3
24 changed files with 82 additions and 93 deletions

View File

@ -92,7 +92,6 @@ CResourceEntry* CResourceEntry::BuildFromDirectory(CResourceStore *pStore, CResT
CResourceEntry::~CResourceEntry() CResourceEntry::~CResourceEntry()
{ {
if (mpResource) delete mpResource; if (mpResource) delete mpResource;
if (mpDependencies) delete mpDependencies;
} }
bool CResourceEntry::LoadMetadata() bool CResourceEntry::LoadMetadata()
@ -171,15 +170,11 @@ void CResourceEntry::SerializeEntryInfo(IArchive& rArc, bool MetadataOnly)
void CResourceEntry::UpdateDependencies() void CResourceEntry::UpdateDependencies()
{ {
if (mpDependencies) mpDependencies.reset();
{
delete mpDependencies;
mpDependencies = nullptr;
}
if (!mpTypeInfo->CanHaveDependencies()) if (!mpTypeInfo->CanHaveDependencies())
{ {
mpDependencies = new CDependencyTree(); mpDependencies = std::make_unique<CDependencyTree>();
return; return;
} }
@ -191,7 +186,7 @@ void CResourceEntry::UpdateDependencies()
if (!mpResource) if (!mpResource)
{ {
errorf("Unable to update cached dependencies; failed to load resource"); errorf("Unable to update cached dependencies; failed to load resource");
mpDependencies = new CDependencyTree(); mpDependencies = std::make_unique<CDependencyTree>();
return; return;
} }

View File

@ -30,7 +30,7 @@ class CResourceEntry
CResource *mpResource; CResource *mpResource;
CResTypeInfo *mpTypeInfo; CResTypeInfo *mpTypeInfo;
CResourceStore *mpStore; CResourceStore *mpStore;
CDependencyTree *mpDependencies; std::unique_ptr<CDependencyTree> mpDependencies;
CAssetID mID; CAssetID mID;
CVirtualDirectory *mpDirectory; CVirtualDirectory *mpDirectory;
TString mName; TString mName;
@ -100,7 +100,7 @@ public:
CResource* Resource() const { return mpResource; } CResource* Resource() const { return mpResource; }
CResTypeInfo* TypeInfo() const { return mpTypeInfo; } CResTypeInfo* TypeInfo() const { return mpTypeInfo; }
CResourceStore* ResourceStore() const { return mpStore; } CResourceStore* ResourceStore() const { return mpStore; }
CDependencyTree* Dependencies() const { return mpDependencies; } CDependencyTree* Dependencies() const { return mpDependencies.get(); }
CAssetID ID() const { return mID; } CAssetID ID() const { return mID; }
CVirtualDirectory* Directory() const { return mpDirectory; } CVirtualDirectory* Directory() const { return mpDirectory; }
TString DirectoryPath() const { return mpDirectory->FullPath(); } TString DirectoryPath() const { return mpDirectory->FullPath(); }

View File

@ -21,10 +21,10 @@ public:
{ {
} }
CDependencyTree* BuildDependencyTree() const override std::unique_ptr<CDependencyTree> BuildDependencyTree() const override
{ {
auto *pTree = new CDependencyTree(); auto pTree = std::make_unique<CDependencyTree>();
AddDependenciesToTree(pTree); AddDependenciesToTree(pTree.get());
return pTree; return pTree;
} }

View File

@ -128,14 +128,14 @@ public:
} }
} }
CDependencyTree* BuildDependencyTree() const std::unique_ptr<CDependencyTree> BuildDependencyTree() const
{ {
CDependencyTree *pTree = new CDependencyTree(); auto pTree = std::make_unique<CDependencyTree>();
// Character dependencies // Character dependencies
for (uint32 iChar = 0; iChar < mCharacters.size(); iChar++) for (const auto& character : mCharacters)
{ {
CSetCharacterDependency *pCharTree = CSetCharacterDependency::BuildTree( mCharacters[iChar] ); CSetCharacterDependency *pCharTree = CSetCharacterDependency::BuildTree(character);
ASSERT(pCharTree); ASSERT(pCharTree);
pTree->AddChild(pCharTree); pTree->AddChild(pCharTree);
} }
@ -150,42 +150,38 @@ public:
pTree->AddChild(pAnimTree); pTree->AddChild(pAnimTree);
} }
} }
else if (Game() <= EGame::Corruption) else if (Game() <= EGame::Corruption)
{ {
const SSetCharacter& rkChar = mCharacters[0]; const SSetCharacter& rkChar = mCharacters[0];
std::set<CAnimPrimitive> PrimitiveSet; std::set<CAnimPrimitive> PrimitiveSet;
// Animations // Animations
for (uint32 iAnim = 0; iAnim < mAnimations.size(); iAnim++) for (auto& anim : mAnimations)
{ {
const SAnimation& rkAnim = mAnimations[iAnim]; anim.pMetaAnim->GetUniquePrimitives(PrimitiveSet);
rkAnim.pMetaAnim->GetUniquePrimitives(PrimitiveSet);
} }
CSourceAnimData *pAnimData = gpResourceStore->LoadResource<CSourceAnimData>(rkChar.AnimDataID); CSourceAnimData *pAnimData = gpResourceStore->LoadResource<CSourceAnimData>(rkChar.AnimDataID);
if (pAnimData) if (pAnimData)
pAnimData->AddTransitionDependencies(pTree); pAnimData->AddTransitionDependencies(pTree.get());
for (auto Iter = PrimitiveSet.begin(); Iter != PrimitiveSet.end(); Iter++) for (auto& prim : PrimitiveSet)
{ {
const CAnimPrimitive& rkPrim = *Iter; pTree->AddDependency(prim.Animation());
pTree->AddDependency(rkPrim.Animation());
} }
// Event sounds // Event sounds
for (uint32 iSound = 0; iSound < rkChar.SoundEffects.size(); iSound++) for (const auto& effect : rkChar.SoundEffects)
{ {
pTree->AddDependency(rkChar.SoundEffects[iSound]); pTree->AddDependency(effect);
} }
} }
else else
{ {
const SSetCharacter& rkChar = mCharacters[0]; const SSetCharacter& rkChar = mCharacters[0];
for (uint32 iDep = 0; iDep < rkChar.DKDependencies.size(); iDep++) for (const auto& dep : rkChar.DKDependencies)
pTree->AddDependency(rkChar.DKDependencies[iDep]); pTree->AddDependency(dep);
} }
return pTree; return pTree;

View File

@ -9,9 +9,9 @@ CAnimation::CAnimation(CResourceEntry *pEntry /*= 0*/)
{ {
} }
CDependencyTree* CAnimation::BuildDependencyTree() const std::unique_ptr<CDependencyTree> CAnimation::BuildDependencyTree() const
{ {
CDependencyTree *pTree = new CDependencyTree(); auto pTree = std::make_unique<CDependencyTree>();
pTree->AddDependency(mpEventData); pTree->AddDependency(mpEventData);
return pTree; return pTree;
} }

View File

@ -37,8 +37,8 @@ class CAnimation : public CResource
TResPtr<CAnimEventData> mpEventData; TResPtr<CAnimEventData> mpEventData;
public: public:
CAnimation(CResourceEntry *pEntry = 0); explicit CAnimation(CResourceEntry *pEntry = nullptr);
CDependencyTree* BuildDependencyTree() const override; std::unique_ptr<CDependencyTree> BuildDependencyTree() const override;
void EvaluateTransform(float Time, uint32 BoneID, CVector3f *pOutTranslation, CQuaternion *pOutRotation, CVector3f *pOutScale) const; void EvaluateTransform(float Time, uint32 BoneID, CVector3f *pOutTranslation, CQuaternion *pOutRotation, CVector3f *pOutScale) const;
bool HasTranslation(uint32 BoneID) const; bool HasTranslation(uint32 BoneID) const;

View File

@ -43,13 +43,13 @@ public:
delete mpDefaultTransition; delete mpDefaultTransition;
} }
CDependencyTree* BuildDependencyTree() const override std::unique_ptr<CDependencyTree> BuildDependencyTree() const override
{ {
// SAND normally has dependencies from meta-transitions and events // SAND normally has dependencies from meta-transitions and events
// However, all of these can be character-specific. To simplify things, all SAND // However, all of these can be character-specific. To simplify things, all SAND
// dependencies are being added to the CHAR dependency tree instead. Therefore the // dependencies are being added to the CHAR dependency tree instead. Therefore the
// SAND dependency tree is left empty. // SAND dependency tree is left empty.
return new CDependencyTree(); return std::make_unique<CDependencyTree>();
} }
void GetUniquePrimitives(std::set<CAnimPrimitive>& rPrimSet) const void GetUniquePrimitives(std::set<CAnimPrimitive>& rPrimSet) const

View File

@ -23,16 +23,16 @@ CGameArea::~CGameArea()
delete mScriptLayers[iSCLY]; delete mScriptLayers[iSCLY];
} }
CDependencyTree* CGameArea::BuildDependencyTree() const std::unique_ptr<CDependencyTree> CGameArea::BuildDependencyTree() const
{ {
// Base dependencies // Base dependencies
CAreaDependencyTree *pTree = new CAreaDependencyTree(); auto pTree = std::make_unique<CAreaDependencyTree>();
std::set<CAssetID> MatTextures; std::set<CAssetID> MatTextures;
mpMaterialSet->GetUsedTextureIDs(MatTextures); mpMaterialSet->GetUsedTextureIDs(MatTextures);
for (auto Iter = MatTextures.begin(); Iter != MatTextures.end(); Iter++) for (const auto& id : MatTextures)
pTree->AddDependency(*Iter); pTree->AddDependency(id);
pTree->AddDependency(mPathID); pTree->AddDependency(mPathID);
@ -43,8 +43,8 @@ CDependencyTree* CGameArea::BuildDependencyTree() const
} }
// Extra deps // Extra deps
for (uint32 iDep = 0; iDep < mExtraAreaDeps.size(); iDep++) for (const auto& dep : mExtraAreaDeps)
pTree->AddDependency(mExtraAreaDeps[iDep]); pTree->AddDependency(dep);
// Layer dependencies // Layer dependencies
std::vector<CAssetID> DummyDeps; std::vector<CAssetID> DummyDeps;

View File

@ -65,9 +65,9 @@ class CGameArea : public CResource
std::vector< std::vector<CAssetID> > mExtraLayerDeps; std::vector< std::vector<CAssetID> > mExtraLayerDeps;
public: public:
CGameArea(CResourceEntry *pEntry = nullptr); explicit CGameArea(CResourceEntry *pEntry = nullptr);
~CGameArea(); ~CGameArea();
CDependencyTree* BuildDependencyTree() const override; std::unique_ptr<CDependencyTree> BuildDependencyTree() const override;
void AddWorldModel(CModel *pModel); void AddWorldModel(CModel *pModel);
void MergeTerrain(); void MergeTerrain();

View File

@ -16,9 +16,9 @@ public:
: CResource(pEntry) : CResource(pEntry)
{} {}
CDependencyTree* BuildDependencyTree() const override std::unique_ptr<CDependencyTree> BuildDependencyTree() const override
{ {
auto *pTree = new CDependencyTree(); auto pTree = std::make_unique<CDependencyTree>();
for (const auto& sample : mSamples) for (const auto& sample : mSamples)
pTree->AddDependency(sample); pTree->AddDependency(sample);

View File

@ -9,19 +9,19 @@ class CDependencyGroup : public CResource
std::vector<CAssetID> mDependencies; std::vector<CAssetID> mDependencies;
public: public:
CDependencyGroup(CResourceEntry *pEntry = 0) : CResource(pEntry) {} explicit CDependencyGroup(CResourceEntry *pEntry = nullptr) : CResource(pEntry) {}
inline void Clear() { mDependencies.clear(); } void Clear() { mDependencies.clear(); }
inline uint32 NumDependencies() const { return mDependencies.size(); } uint32 NumDependencies() const { return mDependencies.size(); }
inline CAssetID DependencyByIndex(uint32 Index) const { return mDependencies[Index]; } CAssetID DependencyByIndex(uint32 Index) const { return mDependencies[Index]; }
inline void AddDependency(const CAssetID& rkID) void AddDependency(const CAssetID& rkID)
{ {
if (!HasDependency(rkID)) if (!HasDependency(rkID))
mDependencies.push_back(rkID); mDependencies.push_back(rkID);
} }
inline void AddDependency(CResource *pRes) void AddDependency(CResource *pRes)
{ {
if ( pRes && !HasDependency(pRes->ID()) ) if ( pRes && !HasDependency(pRes->ID()) )
mDependencies.push_back(pRes->ID()); mDependencies.push_back(pRes->ID());
@ -50,12 +50,12 @@ public:
return false; return false;
} }
CDependencyTree* BuildDependencyTree() const std::unique_ptr<CDependencyTree> BuildDependencyTree() const
{ {
CDependencyTree *pTree = new CDependencyTree(); auto pTree = std::make_unique<CDependencyTree>();
for (auto DepIt = mDependencies.begin(); DepIt != mDependencies.end(); DepIt++) for (const auto& dep : mDependencies)
pTree->AddDependency(*DepIt); pTree->AddDependency(dep);
return pTree; return pTree;
} }

View File

@ -22,9 +22,9 @@ inline float PtsToFloat(int32 Pt)
return 0.00208333f * Pt; return 0.00208333f * Pt;
} }
CDependencyTree* CFont::BuildDependencyTree() const std::unique_ptr<CDependencyTree> CFont::BuildDependencyTree() const
{ {
CDependencyTree *pOut = new CDependencyTree(); auto pOut = std::make_unique<CDependencyTree>();
pOut->AddDependency(mpFontTexture); pOut->AddDependency(mpFontTexture);
return pOut; return pOut;
} }

View File

@ -59,9 +59,9 @@ class CFont : public CResource
public: public:
CFont(CResourceEntry *pEntry = nullptr); explicit CFont(CResourceEntry *pEntry = nullptr);
~CFont(); ~CFont();
CDependencyTree* BuildDependencyTree() const override; std::unique_ptr<CDependencyTree> BuildDependencyTree() const override;
CVector2f RenderString(const TString& rkString, CRenderer *pRenderer, float AspectRatio, CVector2f RenderString(const TString& rkString, CRenderer *pRenderer, float AspectRatio,
CVector2f Position = CVector2f(0,0), CVector2f Position = CVector2f(0,0),
CColor FillColor = CColor::skWhite, CColor StrokeColor = CColor::skBlack, CColor FillColor = CColor::skWhite, CColor StrokeColor = CColor::skBlack,

View File

@ -10,13 +10,13 @@ class CMapArea : public CResource
CAssetID mNameString; CAssetID mNameString;
public: public:
CMapArea(CResourceEntry *pEntry = nullptr) explicit CMapArea(CResourceEntry *pEntry = nullptr)
: CResource(pEntry) : CResource(pEntry)
{} {}
CDependencyTree* BuildDependencyTree() const override std::unique_ptr<CDependencyTree> BuildDependencyTree() const override
{ {
auto *pTree = new CDependencyTree(); auto pTree = std::make_unique<CDependencyTree>();
pTree->AddDependency(mNameString); pTree->AddDependency(mNameString);
return pTree; return pTree;
} }

View File

@ -10,6 +10,7 @@
#include <Common/CFourCC.h> #include <Common/CFourCC.h>
#include <Common/TString.h> #include <Common/TString.h>
#include <Common/Serialization/IArchive.h> #include <Common/Serialization/IArchive.h>
#include <memory>
// This macro creates functions that allow us to easily identify this resource type. // This macro creates functions that allow us to easily identify this resource type.
// Must be included on every CResource subclass. // Must be included on every CResource subclass.
@ -41,9 +42,9 @@ public:
} }
virtual ~CResource() {} virtual ~CResource() {}
virtual CDependencyTree* BuildDependencyTree() const { return new CDependencyTree(); } virtual std::unique_ptr<CDependencyTree> BuildDependencyTree() const { return std::make_unique<CDependencyTree>(); }
virtual void Serialize(IArchive& /*rArc*/) {} virtual void Serialize(IArchive& /*rArc*/) {}
virtual void InitializeNewResource() {} virtual void InitializeNewResource() {}
CResourceEntry* Entry() const { return mpEntry; } CResourceEntry* Entry() const { return mpEntry; }
CResTypeInfo* TypeInfo() const { return mpEntry->TypeInfo(); } CResTypeInfo* TypeInfo() const { return mpEntry->TypeInfo(); }

View File

@ -17,14 +17,14 @@ CWorld::~CWorld()
{ {
} }
CDependencyTree* CWorld::BuildDependencyTree() const std::unique_ptr<CDependencyTree> CWorld::BuildDependencyTree() const
{ {
CDependencyTree *pTree = new CDependencyTree(); auto pTree = std::make_unique<CDependencyTree>();
for (uint32 iArea = 0; iArea < mAreas.size(); iArea++) for (const auto& area : mAreas)
{ {
pTree->AddDependency(mAreas[iArea].AreaResID); pTree->AddDependency(area.AreaResID);
pTree->AddDependency(mAreas[iArea].pAreaName); pTree->AddDependency(area.pAreaName);
} }
pTree->AddDependency(mpWorldName); pTree->AddDependency(mpWorldName);

View File

@ -90,7 +90,7 @@ public:
explicit CWorld(CResourceEntry *pEntry = nullptr); explicit CWorld(CResourceEntry *pEntry = nullptr);
~CWorld(); ~CWorld();
CDependencyTree* BuildDependencyTree() const override; std::unique_ptr<CDependencyTree> BuildDependencyTree() const override;
void SetAreaLayerInfo(CGameArea *pArea); void SetAreaLayerInfo(CGameArea *pArea);
TString InGameName() const; TString InGameName() const;
TString AreaInGameName(uint32 AreaIndex) const; TString AreaInGameName(uint32 AreaIndex) const;

View File

@ -164,7 +164,7 @@ void CScriptLoader::ReadProperty(IProperty *pProp, uint32 Size, IInputStream& rS
{ {
warnf("%s [0x%X]: Asset property \"%s\" (%s) has a reference to an illegal asset type: %s", warnf("%s [0x%X]: Asset property \"%s\" (%s) has a reference to an illegal asset type: %s",
*rSCLY.GetSourceString(), *rSCLY.GetSourceString(),
rSCLY.Tell() - ID.Length(), rSCLY.Tell() - static_cast<uint32>(ID.Length()),
*pAsset->Name(), *pAsset->Name(),
*pAsset->IDString(true), *pAsset->IDString(true),
*pEntry->CookedExtension().ToString()); *pEntry->CookedExtension().ToString());

View File

@ -30,19 +30,18 @@ CModel::~CModel()
} }
CDependencyTree* CModel::BuildDependencyTree() const std::unique_ptr<CDependencyTree> CModel::BuildDependencyTree() const
{ {
CDependencyTree *pTree = new CDependencyTree(); auto pTree = std::make_unique<CDependencyTree>();
std::set<CAssetID> TextureIDs; std::set<CAssetID> TextureIDs;
for (uint32 iSet = 0; iSet < mMaterialSets.size(); iSet++) for (CMaterialSet* set : mMaterialSets)
{ {
CMaterialSet *pSet = mMaterialSets[iSet]; set->GetUsedTextureIDs(TextureIDs);
pSet->GetUsedTextureIDs(TextureIDs);
} }
for (auto Iter = TextureIDs.begin(); Iter != TextureIDs.end(); Iter++) for (const auto& id : TextureIDs)
pTree->AddDependency(*Iter); pTree->AddDependency(id);
return pTree; return pTree;
} }

View File

@ -25,7 +25,7 @@ public:
CModel(CMaterialSet *pSet, bool OwnsMatSet); CModel(CMaterialSet *pSet, bool OwnsMatSet);
~CModel(); ~CModel();
CDependencyTree* BuildDependencyTree() const override; std::unique_ptr<CDependencyTree> BuildDependencyTree() const override;
void BufferGL(); void BufferGL();
void GenerateMaterialShaders(); void GenerateMaterialShaders();
void ClearGLBuffer() override; void ClearGLBuffer() override;

View File

@ -43,9 +43,9 @@ CBoolRef CScan::IsCriticalPropertyRef() const
} }
/** CResource interface */ /** CResource interface */
CDependencyTree* CScan::BuildDependencyTree() const std::unique_ptr<CDependencyTree> CScan::BuildDependencyTree() const
{ {
CDependencyTree* pTree = new CDependencyTree(); auto pTree = std::make_unique<CDependencyTree>();
pTree->ParseProperties(Entry(), ScanData().Property(), ScanData().DataPointer()); pTree->ParseProperties(Entry(), ScanData().Property(), ScanData().DataPointer());
return pTree; return pTree;
} }

View File

@ -28,7 +28,7 @@ public:
CBoolRef IsCriticalPropertyRef() const; CBoolRef IsCriticalPropertyRef() const;
/** CResource interface */ /** CResource interface */
CDependencyTree* BuildDependencyTree() const override; std::unique_ptr<CDependencyTree> BuildDependencyTree() const override;
}; };
#endif // CSCAN_H #endif // CSCAN_H

View File

@ -254,19 +254,17 @@ void CStringTable::Serialize(IArchive& Arc)
} }
/** Build the dependency tree for this resource */ /** Build the dependency tree for this resource */
CDependencyTree* CStringTable::BuildDependencyTree() const std::unique_ptr<CDependencyTree> CStringTable::BuildDependencyTree() const
{ {
// STRGs can reference FONTs with the &font=; formatting tag and TXTRs with the &image=; tag // STRGs can reference FONTs with the &font=; formatting tag and TXTRs with the &image=; tag
CDependencyTree* pTree = new CDependencyTree(); auto pTree = std::make_unique<CDependencyTree>();
EIDLength IDLength = CAssetID::GameIDLength( Game() ); EIDLength IDLength = CAssetID::GameIDLength( Game() );
for (uint LanguageIdx = 0; LanguageIdx < mLanguages.size(); LanguageIdx++) for (const SLanguageData& language : mLanguages)
{ {
const SLanguageData& kLanguage = mLanguages[LanguageIdx]; for (const auto& stringData : language.Strings)
for (uint StringIdx = 0; StringIdx < kLanguage.Strings.size(); StringIdx++)
{ {
const TString& kString = kLanguage.Strings[StringIdx].String; const TString& kString = stringData.String;
for (int TagIdx = kString.IndexOf('&'); TagIdx != -1; TagIdx = kString.IndexOf('&', TagIdx + 1)) for (int TagIdx = kString.IndexOf('&'); TagIdx != -1; TagIdx = kString.IndexOf('&', TagIdx + 1))
{ {
@ -320,7 +318,7 @@ CDependencyTree* CStringTable::BuildDependencyTree() const
else if (ImageType == "B") else if (ImageType == "B")
TexturesStart = 2; TexturesStart = 2;
else if (ImageType.IsHexString(false, IDLength * 2)) else if (ImageType.IsHexString(false, static_cast<int>(IDLength) * 2))
TexturesStart = 0; TexturesStart = 0;
else else

View File

@ -89,7 +89,7 @@ public:
void Serialize(IArchive& Arc) override; void Serialize(IArchive& Arc) override;
/** Build the dependency tree for this resource */ /** Build the dependency tree for this resource */
CDependencyTree* BuildDependencyTree() const override; std::unique_ptr<CDependencyTree> BuildDependencyTree() const override;
/** Static - Strip all formatting tags for a given string */ /** Static - Strip all formatting tags for a given string */
static TString StripFormatting(const TString& kInString); static TString StripFormatting(const TString& kInString);