diff --git a/src/Dependencies.cpp b/src/Dependencies.cpp index f4e4e26dd..5eb050d51 100644 --- a/src/Dependencies.cpp +++ b/src/Dependencies.cpp @@ -42,12 +42,6 @@ #include "WaveTrack.h" #include "WaveClip.h" -// Note, this #include must occur here, not up with the others! -// It must be between the WX_DECLARE_OBJARRAY and WX_DEFINE_OBJARRAY. -#include - -WX_DEFINE_OBJARRAY( AliasedFileArray ); - WX_DECLARE_HASH_MAP(wxString, AliasedFile *, wxStringHash, wxStringEqual, AliasedFileHash); @@ -111,7 +105,7 @@ static void ReplaceBlockFiles(AudacityProject *project, } void FindDependencies(AudacityProject *project, - AliasedFileArray *outAliasedFiles) + AliasedFileArray &outAliasedFiles) { sampleFormat format = project->GetDefaultFormat(); @@ -121,15 +115,14 @@ void FindDependencies(AudacityProject *project, AliasedFileHash aliasedFileHash; BoolBlockFileHash blockFileHash; - int i; - for (i = 0; i < (int)blocks.size(); i++) { - BlockFile *f = blocks[i]->f; + for (const auto &blockFile : blocks) { + BlockFile *f = blockFile->f; if (f->IsAlias() && (blockFileHash.count(f) == 0)) { // f is an alias block we have not yet counted. blockFileHash[f] = true; // Don't count the same blockfile twice. - AliasBlockFile *aliasBlockFile = (AliasBlockFile *)f; - wxFileName fileName = aliasBlockFile->GetAliasedFileName(); + AliasBlockFile *aliasBlockFile = static_cast(f); + const wxFileName &fileName = aliasBlockFile->GetAliasedFileName(); // In DirManager::ProjectFSCK(), if the user has chosen to // "Replace missing audio with silence", the code there puts in an empty wxFileName. @@ -137,7 +130,7 @@ void FindDependencies(AudacityProject *project, if (!fileName.IsOk()) continue; - wxString fileNameStr = fileName.GetFullPath(); + const wxString &fileNameStr = fileName.GetFullPath(); int blockBytes = (SAMPLE_SIZE(format) * aliasBlockFile->GetLength()); if (aliasedFileHash.count(fileNameStr) > 0) @@ -148,11 +141,16 @@ void FindDependencies(AudacityProject *project, { // Haven't counted this AliasBlockFile yet. // Add to return array and internal hash. - outAliasedFiles->Add(AliasedFile(fileName, - blockBytes, - fileName.FileExists())); - aliasedFileHash[fileNameStr] = - &((*outAliasedFiles)[outAliasedFiles->GetCount()-1]); + + // PRL: do this in two steps so that we move instead of copying. + // We don't have a moving push_back in all compilers. + outAliasedFiles.push_back(AliasedFile{}); + outAliasedFiles.back() = + AliasedFile { + wxFileNameWrapper { fileName }, + blockBytes, fileName.FileExists() + }; + aliasedFileHash[fileNameStr] = &outAliasedFiles.back(); } } } @@ -162,7 +160,7 @@ void FindDependencies(AudacityProject *project, // longer be external dependencies (selected by the user), replace // all of those alias block files with disk block files. static void RemoveDependencies(AudacityProject *project, - AliasedFileArray *aliasedFiles) + AliasedFileArray &aliasedFiles) { DirManager *dirManager = project->GetDirManager(); @@ -175,11 +173,10 @@ static void RemoveDependencies(AudacityProject *project, // count total number of bytes to process. AliasedFileHash aliasedFileHash; wxLongLong totalBytesToProcess = 0; - unsigned int i; - for (i = 0; i < aliasedFiles->GetCount(); i++) { - totalBytesToProcess += aliasedFiles->Item(i).mByteCount; - wxString fileNameStr = aliasedFiles->Item(i).mFileName.GetFullPath(); - aliasedFileHash[fileNameStr] = &aliasedFiles->Item(i); + for (auto &aliasedFile : aliasedFiles) { + totalBytesToProcess += aliasedFile.mByteCount; + const wxString &fileNameStr = aliasedFile.mFileName.GetFullPath(); + aliasedFileHash[fileNameStr] = &aliasedFile; } BlockPtrArray blocks; @@ -188,14 +185,14 @@ static void RemoveDependencies(AudacityProject *project, const sampleFormat format = project->GetDefaultFormat(); ReplacedBlockFileHash blockFileHash; wxLongLong completedBytes = 0; - for (i = 0; i < blocks.size(); i++) { - BlockFile *f = blocks[i]->f; + for (const auto blockFile : blocks) { + BlockFile *f = blockFile->f; if (f->IsAlias() && (blockFileHash.count(f) == 0)) { // f is an alias block we have not yet processed. - AliasBlockFile *aliasBlockFile = (AliasBlockFile *)f; - wxFileName fileName = aliasBlockFile->GetAliasedFileName(); - wxString fileNameStr = fileName.GetFullPath(); + AliasBlockFile *aliasBlockFile = static_cast(f); + const wxFileName &fileName = aliasBlockFile->GetAliasedFileName(); + const wxString &fileNameStr = fileName.GetFullPath(); if (aliasedFileHash.count(fileNameStr) == 0) // This aliased file was not selected to be replaced. Skip it. @@ -230,12 +227,8 @@ static void RemoveDependencies(AudacityProject *project, // Subtract one from reference count of NEW block files; they're // now all referenced the proper number of times by the Sequences - ReplacedBlockFileHash::iterator it; - for( it = blockFileHash.begin(); it != blockFileHash.end(); ++it ) - { - BlockFile *f = it->second; - dirManager->Deref(f); - } + for (const auto &pair : blockFileHash) + dirManager->Deref(pair.second); } // @@ -248,7 +241,7 @@ public: DependencyDialog(wxWindow *parent, wxWindowID id, AudacityProject *project, - AliasedFileArray *aliasedFiles, + AliasedFileArray &aliasedFiles, bool isSaving); private: @@ -267,7 +260,7 @@ private: AudacityProject *mProject; - AliasedFileArray *mAliasedFiles; + AliasedFileArray &mAliasedFiles; bool mIsSaving; bool mHasMissingFiles; bool mHasNonMissingFiles; @@ -301,7 +294,7 @@ END_EVENT_TABLE() DependencyDialog::DependencyDialog(wxWindow *parent, wxWindowID id, AudacityProject *project, - AliasedFileArray *aliasedFiles, + AliasedFileArray &aliasedFiles, bool isSaving) : wxDialog(parent, id, _("Project Depends on Other Audio Files"), wxDefaultPosition, wxDefaultSize, @@ -413,10 +406,10 @@ void DependencyDialog::PopulateList() mHasMissingFiles = false; mHasNonMissingFiles = false; unsigned int i; - for (i = 0; i < mAliasedFiles->GetCount(); i++) { - wxFileName fileName = mAliasedFiles->Item(i).mFileName; - wxLongLong byteCount = (mAliasedFiles->Item(i).mByteCount * 124) / 100; - bool bOriginalExists = mAliasedFiles->Item(i).mbOriginalExists; + for (const auto &aliasedFile : mAliasedFiles) { + const wxFileName &fileName = aliasedFile.mFileName; + wxLongLong byteCount = (aliasedFile.mByteCount * 124) / 100; + bool bOriginalExists = aliasedFile.mbOriginalExists; if (bOriginalExists) { @@ -490,19 +483,23 @@ void DependencyDialog::OnCopySelectedFiles(wxCommandEvent & WXUNUSED(event)) { AliasedFileArray aliasedFilesToDelete; - int i; - // Count backwards so we can remove as we go - for(i=(int)mAliasedFiles->GetCount()-1; i>=0; i--) { + long i = 0; + for(auto iter = mAliasedFiles.begin(); iter != mAliasedFiles.end();) { if (mFileListCtrl->GetItemState(i, wxLIST_STATE_SELECTED)) { - aliasedFilesToDelete.Add(mAliasedFiles->Item(i)); - mAliasedFiles->RemoveAt(i); + // Two-step move could be simplified when all compilers have C++11 vector + aliasedFilesToDelete.push_back(AliasedFile{}); + aliasedFilesToDelete.back() = std::move(*iter); + iter = mAliasedFiles.erase(iter); } + else + ++iter; + ++i; } - RemoveDependencies(mProject, &aliasedFilesToDelete); + RemoveDependencies(mProject, aliasedFilesToDelete); PopulateList(); - if ((mAliasedFiles->GetCount() == 0) || !mHasNonMissingFiles) + if (mAliasedFiles.empty() || !mHasNonMissingFiles) { SaveFutureActionChoice(); EndModal(wxID_NO); // Don't need to remove dependencies @@ -548,9 +545,9 @@ bool ShowDependencyDialogIfNeeded(AudacityProject *project, bool isSaving) { AliasedFileArray aliasedFiles; - FindDependencies(project, &aliasedFiles); + FindDependencies(project, aliasedFiles); - if (aliasedFiles.GetCount() == 0) { + if (aliasedFiles.empty()) { if (!isSaving) { wxString msg = @@ -575,7 +572,7 @@ you may lose data."); if (action == wxT("copy")) { // User always wants to remove dependencies - RemoveDependencies(project, &aliasedFiles); + RemoveDependencies(project, aliasedFiles); return true; } if (action == wxT("never")) @@ -583,12 +580,12 @@ you may lose data."); return true; } - DependencyDialog dlog(project, -1, project, &aliasedFiles, isSaving); + DependencyDialog dlog(project, -1, project, aliasedFiles, isSaving); int returnCode = dlog.ShowModal(); if (returnCode == wxID_CANCEL) return false; else if (returnCode == wxID_YES) - RemoveDependencies(project, &aliasedFiles); + RemoveDependencies(project, aliasedFiles); return true; } diff --git a/src/Dependencies.h b/src/Dependencies.h index 70044b235..d4897d8d6 100644 --- a/src/Dependencies.h +++ b/src/Dependencies.h @@ -14,26 +14,43 @@ #ifndef __AUDACITY_DEPENDENCIES__ #define __AUDACITY_DEPENDENCIES__ -#include +#include #include +#include "MemoryX.h" +#include "wxFileNameWrapper.h" class AudacityProject; class AliasedFile { public: - AliasedFile(wxFileName fileName, wxLongLong byteCount, bool bOriginalExists) + AliasedFile() {} + AliasedFile(wxFileNameWrapper &&fileName, + wxLongLong byteCount, bool bOriginalExists) + : mFileName(std::move(fileName)) + , mByteCount(byteCount) + , mbOriginalExists(bOriginalExists) { - mFileName = fileName; - mByteCount = byteCount; - mbOriginalExists = bOriginalExists; - }; - wxFileName mFileName; - wxLongLong mByteCount; // if stored as current default sample format - bool mbOriginalExists; + } + AliasedFile(const AliasedFile &that) = default; + AliasedFile &operator= (AliasedFile&& that) + { + if(this != &that) { + mFileName = std::move(that.mFileName); + mByteCount = that.mByteCount; + mbOriginalExists = that.mbOriginalExists; + } + return *this; + } + + wxFileNameWrapper mFileName; + wxLongLong mByteCount{}; // if stored as current default sample format + bool mbOriginalExists{}; }; -WX_DECLARE_OBJARRAY(AliasedFile, AliasedFileArray); +// use list, not vector, because we need to take addresses of items in the container +// before it has grown to full size. +using AliasedFileArray = std::list; // Checks for alias block files, modifies the project if the @@ -45,6 +62,6 @@ bool ShowDependencyDialogIfNeeded(AudacityProject *project, // Returns a list of aliased files associated with a project. void FindDependencies(AudacityProject *project, - AliasedFileArray *outAliasedFiles); + AliasedFileArray &outAliasedFiles); #endif diff --git a/src/export/Export.cpp b/src/export/Export.cpp index e525f580a..dbc0ecdfd 100644 --- a/src/export/Export.cpp +++ b/src/export/Export.cpp @@ -630,10 +630,9 @@ bool Exporter::GetFilename() overwritingMissingAlias = false; for (size_t i = 0; i < gAudacityProjects.GetCount(); i++) { AliasedFileArray aliasedFiles; - FindDependencies(gAudacityProjects[i], &aliasedFiles); - size_t j; - for (j = 0; j< aliasedFiles.GetCount(); j++) { - if (mFilename.GetFullPath() == aliasedFiles[j].mFileName.GetFullPath() && + FindDependencies(gAudacityProjects[i], aliasedFiles); + for (const auto &aliasedFile : aliasedFiles) { + if (mFilename.GetFullPath() == aliasedFile.mFileName.GetFullPath() && !mFilename.FileExists()) { // Warn and return to the dialog wxMessageBox(_("You are attempting to overwrite an aliased file that is missing.\n\