From 03d58100cb633df818544071b447551947495c06 Mon Sep 17 00:00:00 2001 From: Leonardo Zide Date: Tue, 20 Oct 2026 20:56:19 -0700 Subject: [PATCH] Own library primitives with unique pointers Store primitive entries as unique_ptr values so source destruction and replacement release their owned data automatically. This removes the manual deletion loop and prevents leaking an overwritten entry during discovery while preserving borrowed pointers used by loaders. Remove the duplicate IsPrimitive lookup and use FindPrimitive for directory precedence checks and primitive detection during model import. Validated with a warning-free Qt 6.10 Debug build, all 58 offscreen lifecycle groups, and clean diff whitespace checks. --- common/lc_library.cpp | 21 ++++++--------------- common/lc_library.h | 9 +-------- common/lc_model.cpp | 2 +- 3 files changed, 8 insertions(+), 24 deletions(-) diff --git a/common/lc_library.cpp b/common/lc_library.cpp index f21861f0..bcb6e9c3 100644 --- a/common/lc_library.cpp +++ b/common/lc_library.cpp @@ -732,13 +732,13 @@ bool lcPiecesLibrary::OpenArchive(std::unique_ptr File, lcZipFileType Zi PieceData->SetZipFile(ZipFileType, FileIdx); } else - Source->Primitives[Name] = new lcLibraryPrimitive(QString(), FileInfo.file_name + (Name - NormalizedName.c_str()), ZipFileType, FileIdx, false, false, true); + Source->Primitives[Name] = std::make_unique(QString(), FileInfo.file_name + (Name - NormalizedName.c_str()), ZipFileType, FileIdx, false, false, true); } else if (!strncmp(Name, "P/", 2)) { Name += 2; - Source->Primitives[Name] = new lcLibraryPrimitive(QString(), FileInfo.file_name + (Name - NormalizedName.c_str()), ZipFileType, FileIdx, IsStudPrimitive(Name), IsStudStylePrimitive(Name), false); + Source->Primitives[Name] = std::make_unique(QString(), FileInfo.file_name + (Name - NormalizedName.c_str()), ZipFileType, FileIdx, IsStudPrimitive(Name), IsStudStylePrimitive(Name), false); } } @@ -850,14 +850,14 @@ bool lcPiecesLibrary::OpenDirectory(const QDir& LibraryDir, bool ShowProgress) if (Name.size() <= 4 || Name.compare(Name.size() - 4, 4, ".DAT")) continue; - if (BaseFolderIdx > 0 && IsPrimitive(Name.c_str())) + if (BaseFolderIdx > 0 && FindPrimitive(Name.c_str())) continue; if (BaseFolderIdx == static_cast(lcLibraryFolderType::Unofficial)) mHasUnofficial = true; const bool SubFile = SubFileDirectories[DirectoryIdx]; - Source->Primitives[Name] = new lcLibraryPrimitive(std::move(FileName), RelativeName, lcZipFileType::Count, 0, !SubFile && IsStudPrimitive(Name.c_str()), IsStudStylePrimitive(Name.c_str()), SubFile); + Source->Primitives[Name] = std::make_unique(std::move(FileName), RelativeName, lcZipFileType::Count, 0, !SubFile && IsStudPrimitive(Name.c_str()), IsStudStylePrimitive(Name.c_str()), SubFile); } } @@ -2186,7 +2186,7 @@ void lcPiecesLibrary::UpdateStudStyleAndColors(lcStudStyle StudStyle, bool StudC { for (const auto& PrimitiveIt : Source->Primitives) { - lcLibraryPrimitive* Primitive = PrimitiveIt.second; + lcLibraryPrimitive* Primitive = PrimitiveIt.second.get(); if (Primitive->mStudStyle || Primitive->mMeshData.mHasStyleStud) Primitive->Unload(); @@ -2229,15 +2229,6 @@ void lcPiecesLibrary::UpdateStudStyleAndColors(lcStudStyle StudStyle, bool StudC mAssetLoader->ResumeQueuedWork(); } -bool lcPiecesLibrary::IsPrimitive(const char* Name) const -{ - for (const std::unique_ptr& Source : mSources) - if (Source->Primitives.find(Name) != Source->Primitives.end()) - return true; - - return false; -} - lcLibraryPrimitive* lcPiecesLibrary::FindPrimitive(const char* Name) const { for (const std::unique_ptr& Source : mSources) @@ -2245,7 +2236,7 @@ lcLibraryPrimitive* lcPiecesLibrary::FindPrimitive(const char* Name) const const auto PrimitiveIt = Source->Primitives.find(Name); if (PrimitiveIt != Source->Primitives.end()) - return PrimitiveIt->second; + return PrimitiveIt->second.get(); } return nullptr; diff --git a/common/lc_library.h b/common/lc_library.h index 68a492b8..ad6c8e24 100644 --- a/common/lc_library.h +++ b/common/lc_library.h @@ -107,19 +107,13 @@ struct lcLibrarySource { lcLibrarySource() = default; - ~lcLibrarySource() - { - for (const auto& PrimitiveIt : Primitives) - delete PrimitiveIt.second; - } - lcLibrarySource(const lcLibrarySource&) = delete; lcLibrarySource(lcLibrarySource&&) = delete; lcLibrarySource& operator=(const lcLibrarySource&) = delete; lcLibrarySource& operator=(lcLibrarySource&&) = delete; lcLibrarySourceType Type; - std::map Primitives; + std::map> Primitives; }; // Coordinates asset sources, loading, settings and shared render buffers. @@ -265,7 +259,6 @@ public: std::string GetPartId(const lcPieceData* PieceData) const; // Queries primitive sources; FindPrimitive() returns a borrowed entry. - bool IsPrimitive(const char* Name) const; lcLibraryPrimitive* FindPrimitive(const char* Name) const; // Loads shared primitive data, waiting for another worker when necessary. diff --git a/common/lc_model.cpp b/common/lc_model.cpp index 6bf9902b..dccd95ab 100644 --- a/common/lc_model.cpp +++ b/common/lc_model.cpp @@ -999,7 +999,7 @@ void lcModel::LoadLDraw(QIODevice& Device, Project* Project) QByteArray CleanId = PartId.toLatin1().toUpper().replace('\\', '/'); - if (Library->IsPrimitive(CleanId.constData())) + if (Library->FindPrimitive(CleanId.constData())) { mFileLines.append(OriginalLine); mHasDirectGeometry = true;