From 1b6c113e2be4631a8eaea33e6ba69ba78ccd317c Mon Sep 17 00:00:00 2001 From: Kimmo Varis Date: Wed, 8 Jun 2005 20:55:12 +0000 Subject: [PATCH] PATCH: [ 1205724 ] Two-phase directory compare --- Src/7zCommon.cpp | 12 +++-- Src/7zCommon.h | 2 +- Src/DiffContext.cpp | 135 ++-------------------------------------------------- Src/DiffContext.h | 117 ++++++--------------------------------------- Src/DiffItem.cpp | 63 ++++++++++++++++++++++++ Src/DiffItem.h | 92 +++++++++++++++++++++++++++++++++++ 6 files changed, 181 insertions(+), 240 deletions(-) create mode 100644 Src/DiffItem.cpp create mode 100644 Src/DiffItem.h diff --git a/Src/7zCommon.cpp b/Src/7zCommon.cpp index e819063cb..74cbeffe7 100644 --- a/Src/7zCommon.cpp +++ b/Src/7zCommon.cpp @@ -64,6 +64,8 @@ DATE: BY: DESCRIPTION: 2005/02/26 Jochen Tucht Use WinAPI to obtain ISO language/region codes 2005/02/27 Jochen Tucht FIX [1152375] 2005/04/24 Kimmo Varis Don't use DiffContext exported from DirView +2005/06/08 Kimmo Varis Use DIFFITEM, not reference to it (hopefully only + temporarily, to sort out new directory compare) */ // RCS ID line follows -- this is updated by CVS @@ -747,7 +749,7 @@ CDirView::DirItemEnumerator::DirItemEnumerator(CDirView *pView, int nFlags) // Collect implied folders for (UINT i = Open() ; i-- ; ) { - const DIFFITEM &di = Next(); + DIFFITEM di = Next(); if ((m_nFlags & DiffsOnly) && !m_pView->IsItemNavigableDiff(di)) { continue; @@ -802,7 +804,7 @@ UINT CDirView::DirItemEnumerator::Open() /** * @brief Return next item. */ -const DIFFITEM &CDirView::DirItemEnumerator::Next() +DIFFITEM CDirView::DirItemEnumerator::Next() { enum {nMask = LVNI_FOCUSED|LVNI_SELECTED|LVNI_CUT|LVNI_DROPHILITED}; while ((m_nIndex = pView(m_pView)->GetNextItem(m_nIndex, m_nFlags & nMask)) == -1) @@ -830,7 +832,7 @@ const DIFFITEM &CDirView::DirItemEnumerator::Next() Merge7z::Envelope *CDirView::DirItemEnumerator::Enum(Item &item) { CDirDoc * pDoc = m_pView->GetDocument(); - const DIFFITEM &di = Next(); + DIFFITEM di = Next(); if ((m_nFlags & DiffsOnly) && !m_pView->IsItemNavigableDiff(di)) { @@ -1008,7 +1010,7 @@ void CDirView::DirItemEnumerator::CollectFiles(CString &strBuffer) int cchBuffer = 0; for (i = Open() ; i-- ; ) { - const DIFFITEM &di = Next(); + DIFFITEM di = Next(); if (m_bRight ? m_pView->IsItemOpenableOnRightWith(di) : m_pView->IsItemOpenableOnLeftWith(di)) { cchBuffer += @@ -1020,7 +1022,7 @@ void CDirView::DirItemEnumerator::CollectFiles(CString &strBuffer) LPTSTR pchBuffer = strBuffer.GetBufferSetLength(cchBuffer); for (i = Open() ; i-- ; ) { - const DIFFITEM &di = Next(); + DIFFITEM di = Next(); if (m_bRight ? m_pView->IsItemOpenableOnRightWith(di) : m_pView->IsItemOpenableOnLeftWith(di)) { pchBuffer += wsprintf diff --git a/Src/7zCommon.h b/Src/7zCommon.h index a201d39ba..8abfa0631 100644 --- a/Src/7zCommon.h +++ b/Src/7zCommon.h @@ -61,7 +61,7 @@ private: CMapStringToPtr m_rgImpliedFoldersLeft; CMapStringToPtr m_rgImpliedFoldersRight; // helper methods - const DIFFITEM &Next(); + DIFFITEM Next(); public: enum { diff --git a/Src/DiffContext.cpp b/Src/DiffContext.cpp index a75173f94..7fe877151 100644 --- a/Src/DiffContext.cpp +++ b/Src/DiffContext.cpp @@ -34,7 +34,7 @@ #include "paths.h" #include "coretools.h" #include "codepage_detect.h" -#include "DiffFileInfo.h" +#include "DiffItemList.h" #include #ifdef _DEBUG @@ -56,8 +56,6 @@ static char THIS_FILE[]=__FILE__; */ CDiffContext::CDiffContext(LPCTSTR pszLeft /*=NULL*/, LPCTSTR pszRight /*=NULL*/) : m_bRecurse(FALSE) -, pNamesLeft(NULL) -, pNamesRight(NULL) , m_piFilterGlobal(NULL) , m_piPluginInfos(NULL) , m_msgUpdateStatus(0) @@ -78,8 +76,6 @@ CDiffContext::CDiffContext(LPCTSTR pszLeft /*=NULL*/, LPCTSTR pszRight /*=NULL*/ * @param [in] src Existing CDiffContext whose data is copied. */ CDiffContext::CDiffContext(LPCTSTR pszLeft, LPCTSTR pszRight, CDiffContext& src) -: pNamesLeft(NULL) -, pNamesRight(NULL) { // This is used somehow in recursive comparisons // I think that it is only used during rescan to copy into temporaries @@ -98,15 +94,6 @@ CDiffContext::CDiffContext(LPCTSTR pszLeft, LPCTSTR pszRight, CDiffContext& src) m_bIgnoreSmallTimeDiff = src.m_bIgnoreSmallTimeDiff; } -CDiffContext::~CDiffContext() -{ - if (pNamesLeft != NULL) - free(pNamesLeft); - if (pNamesRight != NULL) - free(pNamesRight); -} - - /** * @brief Fetch & return the fixed file version as a dotted string */ @@ -119,99 +106,15 @@ static CString GetFixedFileVersion(const CString & path) /** * @brief Add new diffitem to CDiffContext array */ -void CDiffContext::AddDiff(DIFFITEM & di) +void CDiffContext::AddDiff(const DIFFITEM & di) { - m_pList->AddTail(di); + DiffItemList::AddDiff(di); + // ignore return value SendMessage(m_hDirFrame, m_msgUpdateStatus, di.diffcode, NULL); } /** - * @brief Remove diffitem from CDiffContext array - * @param diffpos position of item to remove - */ -void CDiffContext::RemoveDiff(POSITION diffpos) -{ - m_pList->RemoveAt(diffpos); -} - -/** - * @brief Empty CDiffContext array - */ -void CDiffContext::RemoveAll() -{ - m_pList->RemoveAll(); -} - -/** - * @brief Get position of first item in CDiffContext array - */ -POSITION CDiffContext::GetFirstDiffPosition() const -{ - return m_pList->GetHeadPosition(); -} - -/** - * @brief Get position of next item in CDiffContext array - * @param diffpos position of current item, updated to next item position - * @return Diff Item in current position - */ -DIFFITEM CDiffContext::GetNextDiffPosition(POSITION & diffpos) const -{ - return m_pList->GetNext(diffpos); -} - -/** - * @brief Get Diff Item at given position of CDiffContext array - * @param diffpos position of item to return - */ -const DIFFITEM & CDiffContext::GetDiffAt(POSITION diffpos) const -{ - return m_pList->GetAt(diffpos); -} - -/** - * @brief Get number of items in CDiffContext array - */ -int CDiffContext::GetDiffCount() const -{ - return m_pList->GetCount(); -} - -/** - * @brief Alter some bit flags of the diffcode. - * - * Examples: - * SetDiffStatusCode(pos, DIFFCODE::SAME, DIFFCODE::COMPAREFLAGS) - * changes the comparison result to be the same. - * - * SetDiffStatusCode(pos, DIFFCODE::BOTH, DIFFCODE::SIDEFLAG) - * changes the side status to be both (sides). - * - * SetDiffStatusCode(pos, DIFFCODE::SAME+DIFFCODE::BOTH, DIFFCODE::COMPAREFLAGS+DIFFCODE::SIDEFLAG); - * changes the comparison result to be the same and the side status to be both - */ -void CDiffContext::SetDiffStatusCode(POSITION diffpos, UINT diffcode, UINT mask) -{ - ASSERT(diffpos); - DIFFITEM & di = m_pList->GetAt(diffpos); - ASSERT(! ((~mask) & diffcode) ); // make sure they only set flags in their mask - di.diffcode &= (~mask); // remove current data - di.diffcode |= diffcode; // add new data -} - -/** - * @brief Update difference counts. - */ -void CDiffContext::SetDiffCounts(POSITION diffpos, UINT diffs, UINT ignored) -{ - ASSERT(diffpos); - DIFFITEM & di = m_pList->GetAt(diffpos); - di.ndiffs = diffs + ignored; // see StoreDiffResult() in DirScan.cpp - di.nsdiffs = diffs; -} - -/** * @brief Update info in list (specified by position) from disk * @param [in] diffpos Difference to update * @param [in] bLeft Update left-side item @@ -299,36 +202,6 @@ void CDiffContext::UpdateVersion(DIFFITEM & di, DiffFileInfo & dfi) const dfi.version = GetFixedFileVersion(filepath); } -/** @brief Return path to left file, including all but file name */ -CString DIFFITEM::getLeftFilepath(const CString sLeftRoot) const -{ - CString sPath; - if (!isSideRight()) - { - sPath = sLeftRoot; - if (sSubdir.GetLength()) - { - sPath = paths_ConcatPath(sPath, sSubdir); - } - } - return sPath; -} - -/** @brief Return path to right file, including all but file name */ -CString DIFFITEM::getRightFilepath(const CString sRightRoot) const -{ - CString sPath; - if (!isSideLeft()) - { - sPath = sRightRoot; - if (sSubdir.GetLength()) - { - sPath = paths_ConcatPath(sPath, sSubdir); - } - } - return sPath; -} - /** @brief Forward call to retrieve plugin info (winds up in DirDoc) */ void CDiffContext::FetchPluginInfos(const CString& filteredFilenames, PackingInfo ** infoUnpacker, PrediffingInfo ** infoPrediffer) { diff --git a/Src/DiffContext.h b/Src/DiffContext.h index 311b3d1ba..7b6b71afd 100644 --- a/Src/DiffContext.h +++ b/Src/DiffContext.h @@ -10,95 +10,22 @@ #define AFX_DIFFCONTEXT_H__D3CC86BE_F11E_11D2_826C_00A024706EDC__INCLUDED_ #pragma once +#ifndef _PATH_CONTEXT_H_ +#include "PathContext.h" +#endif + #ifndef _DIFF_FILE_INFO_H_INCLUDED #include "DiffFileInfo.h" #endif -#ifndef _PATH_CONTEXT_H_ -#include "PathContext.h" +#ifndef _DIFF_ITEM_LIST_H_ +#include "DiffItemList.h" #endif class PackingInfo; class PrediffingInfo; class IDiffFilter; - -struct dirdata -{ - char const **names; /* Sorted names of files in dir, 0-terminated. */ - char *data; /* Allocated storage for file names. */ -}; - -// values for DIFFITEM.code -struct DIFFCODE -{ - enum - { - // We use extra bits so that no valid values are 0 - // and each set of flags is in a different hex digit - // to make debugging easier - // These can always be packed down in the future - TEXTFLAG=0x3, TEXT=0x1, BIN=0x2, - DIRFLAG=0x30, FILE=0x10, DIR=0x20, - SIDEFLAG=0x300, LEFT=0x100, RIGHT=0x200, BOTH=0x300, - COMPAREFLAGS=0x7000, NOCMP=0x0000, SAME=0x1000, DIFF=0x2000, CMPERR=0x4000, - FILTERFLAGS=0x30000, INCLUDED=0x10000, SKIPPED=0x20000, - }; - - int diffcode; - - DIFFCODE(int diffcode) : diffcode(diffcode) { } - // file/directory - bool isDirectory() const { return ((diffcode & DIFFCODE::DIRFLAG) == DIFFCODE::DIR); } - // left/right - bool isSideLeft() const { return ((diffcode & DIFFCODE::SIDEFLAG) == DIFFCODE::LEFT); } - bool isSideRight() const { return ((diffcode & DIFFCODE::SIDEFLAG) == DIFFCODE::RIGHT); } - // result filters - bool isResultError() const { return ((diffcode & DIFFCODE::COMPAREFLAGS) == DIFFCODE::CMPERR); } - bool isResultSame() const { return ((diffcode & DIFFCODE::COMPAREFLAGS) == DIFFCODE::SAME); } - bool isResultDiff() const { return (!isResultSame() && !isResultFiltered() && !isResultError() && - !isSideLeft() && !isSideRight()); } - bool isResultFiltered() const { return ((diffcode & DIFFCODE::FILTERFLAGS) == DIFFCODE::SKIPPED); } - // type - bool isBin() const { return ((diffcode & DIFFCODE::TEXTFLAG) == DIFFCODE::BIN); } -}; - -class CDiffContext; - -/** - * @brief information about one diff (including files on both sides) - * - * Bitmask can be seen as a 4 dimensional space; that is, there are four - * different attributes, and each entry picks one of each attribute - * independently. - * - * One dimension is how the compare went: same or different or - * skipped or error. - * - * One dimension is file mode: text or binary (text is only if - * both sides were text) - * - * One dimension is existence: both sides, left only, or right only - * - * One dimension is type: directory, or file - * - * @note times in fileinfo's are seconds since January 1, 1970. - * See Dirscan.cpp/fentry and Dirscan.cpp/LoadFiles() - */ - -struct DIFFITEM : DIFFCODE -{ - DiffFileInfo left; - DiffFileInfo right; - CString sfilename; - CString sSubdir; //*< Common subdirectory from root of comparison */ - int nsdiffs; - int ndiffs; - - DIFFITEM() : DIFFCODE(0), ndiffs(-1), nsdiffs(-1) { } - - CString getLeftFilepath(CString sLeftRoot) const; - CString getRightFilepath(CString sRightRoot) const; -}; +struct DIFFITEM; // Interface for reporting current file, as diff traverses file tree class IDiffStatus @@ -122,17 +49,14 @@ public: * @note If you add new member variables, remember to copy values in * CDiffContext::CDiffContext(..,CDiffContext) constructor! */ -class CDiffContext +class CDiffContext : public DiffItemList { public: CDiffContext(LPCTSTR pszLeft, LPCTSTR pszRight); CDiffContext(LPCTSTR pszLeft, LPCTSTR pszRight, CDiffContext& src); - virtual ~CDiffContext(); // add & remove differences - void AddDiff(DIFFITEM & di); - void RemoveDiff(POSITION diffpos); - void RemoveAll(); + virtual void AddDiff(const DIFFITEM & di); void UpdateVersion(DIFFITEM & di, DiffFileInfo & dfi) const; //@{ @@ -144,22 +68,13 @@ public: * Normalized paths are preferred to use - short paths are expanded * and trailing slashes removed (except from root path). */ - const CString & GetLeftPath() const { return m_paths.GetLeft(FALSE); } - const CString & GetRightPath() const { return m_paths.GetRight(FALSE); } - const CString & GetNormalizedLeft() const { return m_paths.GetLeft(); } - const CString & GetNormalizedRight() const { return m_paths.GetRight(); } + CString GetLeftPath() const { return m_paths.GetLeft(FALSE); } + CString GetRightPath() const { return m_paths.GetRight(FALSE); } + CString GetNormalizedLeft() const { return m_paths.GetLeft(); } + CString GetNormalizedRight() const { return m_paths.GetRight(); } //@} - // to iterate over all differences on list - POSITION GetFirstDiffPosition() const; - DIFFITEM GetNextDiffPosition(POSITION & diffpos) const; - const DIFFITEM & GetDiffAt(POSITION diffpos) const; -// int GetDiffStatus(POSITION diffpos); - int GetDiffCount() const; - // change an existing difference - void SetDiffStatusCode(POSITION diffpos, UINT diffcode, UINT mask); - void SetDiffCounts(POSITION diffpos, UINT diffs, UINT ignored); void UpdateInfoFromDiskHalf(DIFFITEM & di, DiffFileInfo & dfi); void UpdateStatusFromDisk(POSITION diffpos, BOOL bLeft, BOOL bRight); @@ -175,12 +90,8 @@ public: int m_nCompMethod; /**< Compare method */ BOOL m_bIgnoreSmallTimeDiff; /**< Ignore small timedifferences when comparing by date */ - struct dirdata ddLeft, ddRight; - char *pNamesLeft; - char *pNamesRight; - private: - CList m_dirlist, *m_pList; // master list of differences + CList *m_pList; /**< Pointer to list, used to access list */ PathContext m_paths; /**< (root) paths for this context */ }; diff --git a/Src/DiffItem.cpp b/Src/DiffItem.cpp new file mode 100644 index 000000000..3b4e84173 --- /dev/null +++ b/Src/DiffItem.cpp @@ -0,0 +1,63 @@ +/** + * @file DiffItem.cpp + * + * @brief Implementation of DIFFITEM + */ +// RCS ID line follows -- this is updated by CVS +// $Id$ + +#include "stdafx.h" +#include "DiffItem.h" +#include "paths.h" + +#ifdef _DEBUG +#undef THIS_FILE +static char THIS_FILE[]=__FILE__; +#define new DEBUG_NEW +#endif + +/** + * @brief Copy constructor. + */ +DIFFITEM::DIFFITEM(const DIFFITEM &di) +{ + left = di.left; + right = di.right; + diffcode = di.diffcode; + if (di.sfilename.GetLength()) + sfilename = di.sfilename; + if (di.sSubdir.GetLength()) + sSubdir = di.sSubdir; + nsdiffs = di.nsdiffs; + ndiffs = di.ndiffs; +} + +/** @brief Return path to left file, including all but file name */ +CString DIFFITEM::getLeftFilepath(CString sLeftRoot) const +{ + CString sPath; + if (!isSideRight()) + { + sPath = sLeftRoot; + if (sSubdir.GetLength()) + { + sPath = paths_ConcatPath(sPath, sSubdir); + } + } + return sPath; +} + +/** @brief Return path to right file, including all but file name */ +CString DIFFITEM::getRightFilepath(CString sRightRoot) const +{ + CString sPath; + if (!isSideLeft()) + { + sPath = sRightRoot; + if (sSubdir.GetLength()) + { + sPath = paths_ConcatPath(sPath, sSubdir); + } + } + return sPath; +} diff --git a/Src/DiffItem.h b/Src/DiffItem.h new file mode 100644 index 000000000..93a105457 --- /dev/null +++ b/Src/DiffItem.h @@ -0,0 +1,92 @@ +/** + * @file DiffItem.h + * + * @brief Declaration of DIFFITEM + */ +// RCS ID line follows -- this is updated by CVS +// $Id$ + +#ifndef _DIFF_ITEM_H_ +#define _DIFF_ITEM_H_ + +#ifndef _DIFF_FILE_INFO_H_INCLUDED +#include "DiffFileInfo.h" +#endif + +/** + * @brief values for DIFFITEM.code + */ +struct DIFFCODE +{ + enum + { + // We use extra bits so that no valid values are 0 + // and each set of flags is in a different hex digit + // to make debugging easier + // These can always be packed down in the future + TEXTFLAG=0x3, TEXT=0x1, BIN=0x2, + DIRFLAG=0x30, FILE=0x10, DIR=0x20, + SIDEFLAG=0x300, LEFT=0x100, RIGHT=0x200, BOTH=0x300, + COMPAREFLAGS=0x7000, NOCMP=0x0000, SAME=0x1000, DIFF=0x2000, CMPERR=0x4000, + FILTERFLAGS=0x30000, INCLUDED=0x10000, SKIPPED=0x20000, + }; + + int diffcode; + + DIFFCODE() : diffcode(0) { } + DIFFCODE(int diffcode) : diffcode(diffcode) { } + DIFFCODE(const DIFFCODE &code) : diffcode(code.diffcode) { } + + // file/directory + bool isDirectory() const { return ((diffcode & DIFFCODE::DIRFLAG) == DIFFCODE::DIR); } + // left/right + bool isSideLeft() const { return ((diffcode & DIFFCODE::SIDEFLAG) == DIFFCODE::LEFT); } + bool isSideRight() const { return ((diffcode & DIFFCODE::SIDEFLAG) == DIFFCODE::RIGHT); } + // result filters + bool isResultError() const { return ((diffcode & DIFFCODE::COMPAREFLAGS) == DIFFCODE::CMPERR); } + bool isResultSame() const { return ((diffcode & DIFFCODE::COMPAREFLAGS) == DIFFCODE::SAME); } + bool isResultDiff() const { return (!isResultSame() && !isResultFiltered() && !isResultError() && + !isSideLeft() && !isSideRight()); } + bool isResultFiltered() const { return ((diffcode & DIFFCODE::FILTERFLAGS) == DIFFCODE::SKIPPED); } + // type + bool isBin() const { return ((diffcode & DIFFCODE::TEXTFLAG) == DIFFCODE::BIN); } +}; + +/** + * @brief information about one diff (including files on both sides) + * + * Bitmask can be seen as a 4 dimensional space; that is, there are four + * different attributes, and each entry picks one of each attribute + * independently. + * + * One dimension is how the compare went: same or different or + * skipped or error. + * + * One dimension is file mode: text or binary (text is only if + * both sides were text) + * + * One dimension is existence: both sides, left only, or right only + * + * One dimension is type: directory, or file + * + * @note times in fileinfo's are seconds since January 1, 1970. + * See Dirscan.cpp/fentry and Dirscan.cpp/LoadFiles() + */ +struct DIFFITEM : DIFFCODE +{ + DiffFileInfo left; /**< Fileinfo for left file */ + DiffFileInfo right; /**< Fileinfo for right file */ + CString sfilename; /**< Filename (without path!) */ + CString sSubdir; //*< Common subdirectory from root of comparison */ + int nsdiffs; /**< Amount of non-ignored differences */ + int ndiffs; /**< Total amount of differences */ + + DIFFITEM() : ndiffs(-1), nsdiffs(-1), + sfilename(_T("")), sSubdir(_T("")) { } + DIFFITEM(const DIFFITEM &di); + + CString getLeftFilepath(CString sLeftRoot) const; + CString getRightFilepath(CString sRightRoot) const; +}; + +#endif // _DIFF_ITEM_H_ \ No newline at end of file -- 2.11.0