OSDN Git Service

PATCH: [ 1205724 ] Two-phase directory compare
authorKimmo Varis <kimmov@gmail.com>
Wed, 8 Jun 2005 20:55:12 +0000 (20:55 +0000)
committerKimmo Varis <kimmov@gmail.com>
Wed, 8 Jun 2005 20:55:12 +0000 (20:55 +0000)
Src/7zCommon.cpp
Src/7zCommon.h
Src/DiffContext.cpp
Src/DiffContext.h
Src/DiffItem.cpp [new file with mode: 0644]
Src/DiffItem.h [new file with mode: 0644]

index e819063..74cbeff 100644 (file)
@@ -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
index a201d39..8abfa06 100644 (file)
@@ -61,7 +61,7 @@ private:
        CMapStringToPtr m_rgImpliedFoldersLeft;
        CMapStringToPtr m_rgImpliedFoldersRight;
 //     helper methods
-       const DIFFITEM &Next();
+       DIFFITEM Next();
 public:
        enum
        {
index a75173f..7fe8771 100644 (file)
@@ -34,7 +34,7 @@
 #include "paths.h"
 #include "coretools.h"
 #include "codepage_detect.h"
-#include "DiffFileInfo.h"
+#include "DiffItemList.h"
 #include <shlwapi.h>
 
 #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)
 {
index 311b3d1..7b6b71a 100644 (file)
 #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<DIFFITEM,DIFFITEM> m_dirlist, *m_pList; // master list of differences
+       CList<DIFFITEM,DIFFITEM&> *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 (file)
index 0000000..3b4e841
--- /dev/null
@@ -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 (file)
index 0000000..93a1054
--- /dev/null
@@ -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