Revision: 4021
http://svn.sourceforge.net/winmerge/?rev=4021&view=rev
Author: kimmov
Date: 2007-01-08 12:48:23 -0800 (Mon, 08 Jan 2007)
Log Message:
-----------
PATCH: [ 1593810 ] Line-filtering post compare
Modified Paths:
--------------
trunk/Src/Changes.txt
trunk/Src/DiffWrapper.cpp
trunk/Src/DiffWrapper.h
trunk/Src/MainFrm.cpp
trunk/Src/MainFrm.h
trunk/Src/Merge.dsp
trunk/Src/MergeDoc.cpp
Added Paths:
-----------
trunk/Src/FilterList.cpp
trunk/Src/FilterList.h
Modified: trunk/Src/Changes.txt
===================================================================
--- trunk/Src/Changes.txt 2007-01-08 20:24:54 UTC (rev 4020)
+++ trunk/Src/Changes.txt 2007-01-08 20:48:23 UTC (rev 4021)
@@ -2,6 +2,11 @@
Add new items to top.
(This summarizes all changes to all files under Src, including Src\Languages.)
+2007-01-08 Kimmo
+ PATCH: [ 1593810 ] Line-filtering post compare
+ Src: DiffWrapper.cpp DiffWrapper.h MainFrm.cpp MainFrm.h Merge.dsp MergeDoc.cpp
+ Src new files: FilterList.cpp FilterList.h
+
2007-01-08 Gal
BUG: [ 1597939 ] Rename Edits Wrong Field in Folder Compare List
Src: DirView.cpp
Modified: trunk/Src/DiffWrapper.cpp
===================================================================
--- trunk/Src/DiffWrapper.cpp 2007-01-08 20:24:54 UTC (rev 4020)
+++ trunk/Src/DiffWrapper.cpp 2007-01-08 20:48:23 UTC (rev 4021)
@@ -28,10 +28,12 @@
#include <string>
#include <map>
#include <shlwapi.h>
+#include "Ucs2Utf8.h"
#include "coretools.h"
#include "diffcontext.h"
#include "DiffList.h"
#include "MovedLines.h"
+#include "FilterList.h"
#include "diffwrapper.h"
#include "diff.h"
#include "FileTransform.h"
@@ -86,6 +88,7 @@
, m_pDiffList(NULL)
, m_bPathsAreTemp(FALSE)
, m_pMovedLines(NULL)
+, m_pFilterList(NULL)
{
ZeroMemory(&m_settings, sizeof(DIFFSETTINGS));
ZeroMemory(&m_globalSettings, sizeof(DIFFSETTINGS));
@@ -103,6 +106,7 @@
*/
CDiffWrapper::~CDiffWrapper()
{
+ delete m_pFilterList;
delete m_infoPrediffer;
delete m_FilterCommentsManager;
delete m_pMovedLines;
@@ -1121,6 +1125,48 @@
}
/**
+ * @brief Match regular expression list against given difference.
+ * This function matches the regular expression list against the difference
+ * (given as start line and end line). Matching the diff requires that all
+ * lines in difference match.
+ * @param [in] StartPos First line of the difference.
+ * @param [in] endPos Last line of the difference.
+ * @param [in] FileNo File to match.
+ * return true if any of the expressions matches.
+ */
+bool CDiffWrapper::RegExpFilter(int StartPos, int EndPos, int FileNo)
+{
+ if (m_pFilterList == NULL)
+ {
+ _RPTF0(_CRT_ERROR, "CDiffWrapper::RegExpFilter() called when "
+ "filterlist doesn't exist (=NULL)");
+ return false;
+ }
+
+ const char EolIndicators[] = "\r\n"; //List of characters used as EOL
+ bool linesMatch = true; // set to false when non-matching line is found.
+ int line = StartPos;
+
+ while (line <= EndPos && linesMatch == true)
+ // for (int i = StartPos; i <= EndPos; i++)
+ {
+ std::string LineData(files[FileNo].linbuf[line]);
+ size_t EolPos = LineData.find_first_of(EolIndicators);
+ if (EolPos != std::string::npos)
+ {
+ LineData.erase(EolPos);
+ }
+
+ if (!m_pFilterList->Match(LineData.c_str()))
+ {
+ linesMatch = false;
+ }
+ ++line;
+ }
+ return linesMatch;
+}
+
+/**
* @brief Walk the diff utils change script, building the WinMerge list of diff blocks
*/
void
@@ -1214,6 +1260,23 @@
PostFilter(thisob->line0, QtyLinesLeft, thisob->line1, QtyLinesRight, op, *m_FilterCommentsManager, asLwrCaseExt);
}
+ if (m_pFilterList && m_pFilterList->HasRegExps())
+ {
+ //Determine quantity of lines in this block for both sides
+ int QtyLinesLeft = (trans_b0 - trans_a0);
+ int QtyLinesRight = (trans_b1 - trans_a1);
+
+ // Match lines against regular expression filters
+ // Our strategy is that every line in both sides must
+ // match regexp before we mark difference as ignored.
+ bool match2 = false;
+ bool match1 = RegExpFilter(thisob->line0, thisob->line0 + QtyLinesLeft, 0);
+ if (match1)
+ match2 = RegExpFilter(thisob->line1, thisob->line1 + QtyLinesRight, 1);
+ if (match1 && match2)
+ op = OP_TRIVIAL;
+ }
+
AddDiffRange(trans_a0-1, trans_b0-1, trans_a1-1, trans_b1-1, (BYTE)op);
TRACE(_T("left=%d,%d right=%d,%d op=%d\n"),
trans_a0-1, trans_b0-1, trans_a1-1, trans_b1-1, op);
@@ -1310,6 +1373,54 @@
}
/**
+ * @brief Set line filters, given as one string.
+ * @param [in] filterStr Filters.
+ */
+void CDiffWrapper::SetFilterList(const CString &filterStr)
+{
+ // Remove filterlist if new filter is empty
+ if (filterStr.IsEmpty())
+ {
+ delete m_pFilterList;
+ m_pFilterList = NULL;
+ return;
+ }
+
+ // Adding new filter without previous filter
+ if (!filterStr.IsEmpty() && m_pFilterList == NULL)
+ {
+ m_pFilterList = new FilterList;
+ }
+
+ m_pFilterList->RemoveAllFilters();
+ if (!filterStr.IsEmpty())
+ {
+#ifdef UNICODE
+ // Get the size of UTF-8 string
+ int reg_len = TransformUcs2ToUtf8(filterStr, _tcslen(filterStr), NULL, 0);
+ ++reg_len; // Space for zero at end
+
+ char * regexp_utf = new char[reg_len];
+ ZeroMemory(regexp_utf, reg_len);
+ reg_len = TransformUcs2ToUtf8(filterStr, _tcslen(filterStr), regexp_utf, reg_len);
+#else
+ char *regexp_utf = strdup(filterStr);
+#endif
+
+ // Add every "line" of regexps to regexp list
+ char * token;
+ const char sep[] = "\r\n";
+ token = strtok(regexp_utf, sep);
+ while (token)
+ {
+ m_pFilterList->AddRegExp(token);
+ token = strtok(NULL, sep);
+ }
+ delete [] regexp_utf;
+ }
+}
+
+/**
* @brief Copy text stat results from diffutils back into the FileTextStats structure
*/
void CopyTextStats(const file_data * inf, FileTextStats * myTextStats)
Modified: trunk/Src/DiffWrapper.h
===================================================================
--- trunk/Src/DiffWrapper.h 2007-01-08 20:24:54 UTC (rev 4020)
+++ trunk/Src/DiffWrapper.h 2007-01-08 20:48:23 UTC (rev 4021)
@@ -42,6 +42,7 @@
class FilterCommentsManager;
struct FilterCommentsSet;
class MovedLines;
+class FilterList;
/** @enum COMPARE_TYPE
* @brief Different foldercompare methods.
@@ -228,6 +229,7 @@
void EndDirectoryDiff();
MovedLines * GetMovedLines() { return m_pMovedLines; }
void SetCompareFiles(const CString &OriginalFile1, const CString &OriginalFile2);
+ void SetFilterList(const CString &filterStr);
protected:
void InternalGetOptions(DIFFOPTIONS *options) const;
@@ -239,11 +241,13 @@
int * bin_status, int * bin_file);
void LoadWinMergeDiffsFromDiffUtilsScript(struct change * script, const file_data * inf);
void WritePatchFile(struct change * script, file_data * inf);
+ bool RegExpFilter(int StartPos, int EndPos, int FileNo);
private:
DIFFSETTINGS m_settings; /**< Compare settings for current compare */
DIFFSETTINGS m_globalSettings; /**< Global compare settings */
DIFFSTATUS m_status; /**< Status of last compare */
+ FilterList * m_pFilterList; /**< List of linefilters. */
CString m_s1File; /**< Full path to first diff'ed file. */
CString m_s2File; /**< Full path to second diff'ed file. */
CString m_s1AlternativePath; /**< First file's alternative path (may be relative). */
Added: trunk/Src/FilterList.cpp
===================================================================
--- trunk/Src/FilterList.cpp (rev 0)
+++ trunk/Src/FilterList.cpp 2007-01-08 20:48:23 UTC (rev 4021)
@@ -0,0 +1,130 @@
+/**
+ * @file FilterList.h
+ *
+ * @brief Implementation file for FilterList.
+ */
+
+#include "stdafx.h"
+#include <vector>
+#include "FilterList.h"
+#include "pcre.h"
+
+using namespace std;
+
+/**
+ * @brief Constructor.
+ */
+ FilterList::FilterList()
+: m_lastMatchExpression(NULL)
+{
+}
+
+/**
+ * @brief Destructor.
+ */
+FilterList::~FilterList()
+{
+ RemoveAllFilters();
+ free(m_lastMatchExpression);
+}
+
+/**
+ * @brief Add new regular expression to the list.
+ * This function adds new regular expression to the list of expressions.
+ * The regular expression is compiled and studied for better performance.
+ * @param [in] regularExpression Regular expression as UTF-8 string.
+ */
+void FilterList::AddRegExp(const char * regularExpression)
+{
+ filter_item item;
+ item.filterAsString = strdup(regularExpression);
+
+ const char * errormsg = NULL;
+ int erroroffset = 0;
+ pcre *regexp = pcre_compile(regularExpression, PCRE_UTF8, &errormsg,
+ &erroroffset, NULL);
+ if (regexp)
+ {
+ errormsg = NULL;
+ pcre_extra *pe = pcre_study(regexp, 0, &errormsg);
+
+ item.pRegExp = regexp;
+ if (pe != NULL && errormsg != NULL)
+ item.pRegExpExtra = pe;
+ else
+ item.pRegExpExtra = NULL;
+
+ m_list.push_back(item);
+ }
+}
+
+/**
+ * @brief Removes all expressions from the list.
+ */
+void FilterList::RemoveAllFilters()
+{
+ while (!m_list.empty())
+ {
+ filter_item & item = m_list.back();
+ free(item.filterAsString);
+ pcre_free(item.pRegExp);
+ pcre_free(item.pRegExpExtra);
+ m_list.pop_back();
+ }
+}
+
+/**
+ * @brief Returns if list has any expressions.
+ * @return true if list contains one or more expressions.
+ */
+bool FilterList::HasRegExps()
+{
+ return !m_list.empty();
+}
+
+/**
+ * @brief Match string against list of expressions.
+ * This function matches given @p string against the list of regular
+ * expressions. The matching ends when first match is found, so all
+ * expressions may not be matched against.
+ * @param [in] string UTF-8 string to match.
+ * @return true if any of the expressions did match the string.
+ */
+bool FilterList::Match(const char *string)
+{
+ bool retval = false;
+ unsigned int count = m_list.size();
+
+ unsigned int i = 0;
+ while (i < count && retval == false)
+ {
+ filter_item item = m_list[i];
+ int ovector[30];
+ pcre * regexp = item.pRegExp;
+ pcre_extra * extra = item.pRegExpExtra;
+ int result = pcre_exec(regexp, extra, string, strlen(string),
+ 0, 0, ovector, 30);
+
+ if (result >= 0)
+ {
+ if (m_lastMatchExpression != NULL)
+ free(m_lastMatchExpression);
+ m_lastMatchExpression = strdup(item.filterAsString);
+ retval = true;
+ }
+ else
+ ++i;
+ }
+
+ return retval;
+}
+
+/**
+ * @brief Returns the last matched expression (if any).
+ * This function returns the regular expression string that matched last.
+ * @return Last matched expression, or NULL in case no matches yet.
+ */
+const char * FilterList::GetLastMatchExpression()
+{
+ return m_lastMatchExpression;
+}
Added: trunk/Src/FilterList.h
===================================================================
--- trunk/Src/FilterList.h (rev 0)
+++ trunk/Src/FilterList.h 2007-01-08 20:48:23 UTC (rev 4021)
@@ -0,0 +1,53 @@
+/**
+ * @file FilterList.h
+ *
+ * @brief Declaration file for FilterList.
+ */
+
+#ifndef _FILTERLIST_H_
+#define _FILTERLIST_H_
+
+#include <vector>
+#include "pcre.h"
+
+using namespace std;
+
+/**
+ * @brief Container for one filtering rule / compiled expression.
+ * This structure holds compiled regular expression and a original expression
+ * as a string. We need the original expression string in case we want to
+ * know which regular expression did match.
+ */
+struct filter_item
+{
+ char * filterAsString; /** Original regular expression string */
+ pcre *pRegExp; /**< Compiled regular expression */
+ pcre_extra *pRegExpExtra; /**< Additional information got from regex study */
+};
+
+/**
+ * @brief Regular expression list.
+ * This class holds a list of regular expressions for matching strings.
+ * The class also provides simple function for matching and remembers the
+ * last matched expression.
+ */
+class FilterList
+{
+public:
+ FilterList();
+ ~FilterList();
+
+ void AddRegExp(const char *regularExpression);
+ void RemoveAllFilters();
+ bool HasRegExps();
+ bool Match(const char *string);
+ const char * GetLastMatchExpression();
+
+private:
+ vector <filter_item> m_list;
+ char * m_lastMatchExpression;
+
+};
+
+
+#endif // _FILTERLIST_H_
Modified: trunk/Src/MainFrm.cpp
===================================================================
--- trunk/Src/MainFrm.cpp 2007-01-08 20:24:54 UTC (rev 4020)
+++ trunk/Src/MainFrm.cpp 2007-01-08 20:48:23 UTC (rev 4021)
@@ -254,8 +254,6 @@
{
gLog.EnableLogging(FALSE);
- // destroy the reg expression list
- FreeRegExpList();
// Delete all temporary folders belonging to this process
GetClearTempPath(NULL, NULL);
@@ -288,8 +286,6 @@
if (CMDIFrameWnd::OnCreate(lpCreateStruct) == -1)
return -1;
- // build the initial reg expression list
- RebuildRegExpList(FALSE);
GetFontProperties();
if (!CreateToobar())
@@ -1650,108 +1646,7 @@
CMDIFrameWnd::OnClose();
}
-/// Empty regexp list used internally
-void CMainFrame::FreeRegExpList()
-{
- struct regexp_list *r;
- r = ignore_regexp_list;
- // iterate through the list, free the reg expression
- // list item
- while (ignore_regexp_list)
- {
- r = r->next;
- free((ignore_regexp_list->buf).fastmap);
- free((ignore_regexp_list->buf).buffer);
- free(ignore_regexp_list);
- ignore_regexp_list = r;
- }
-}
-
/**
- * @brief Add regexps from options to internal list
- * @param [in] bShowError When TRUE error messages are shown to user,
- * otherwise just written to log.
- */
-void CMainFrame::RebuildRegExpList(BOOL bShowError)
-{
- USES_CONVERSION;
-
- TCHAR tmp[_MAX_PATH] = {0};
- TCHAR* token;
- TCHAR sep[] = _T("\r\n");
- BOOL valid = TRUE;
-
- // destroy the old list if the it is not NULL
- FreeRegExpList();
-
- // build the new list if the user choose to
- // ignore lines matching the reg expression patterns
- if (GetOptionsMgr()->GetBool(OPT_LINEFILTER_ENABLED))
- {
- // find each regular expression and add to list
- _tcsncpy(tmp, GetOptionsMgr()->GetString(OPT_LINEFILTER_REGEXP), _MAX_PATH);
-
- token = _tcstok(tmp, sep);
- while (token && valid)
- {
- valid = add_regexp(&ignore_regexp_list, T2A(token), bShowError);
- token = _tcstok(NULL, sep);
- }
- }
-
- if (ignore_regexp_list)
- {
- ignore_some_changes = 1;
- }
-}
-
-/// Add the compiled form of regexp pattern to reglist
-static BOOL add_regexp(struct regexp_list **reglist, char const* pattern, BOOL bShowError)
-{
- struct regexp_list *r;
- int m;
- BOOL ret = FALSE;
-
- r = (struct regexp_list *) malloc (sizeof (*r));
- if (r)
- {
- bzero (r, sizeof (*r));
- r->buf.fastmap = (char*) malloc (256);
- if (r->buf.fastmap)
- {
- m = re_compile_pattern (pattern, strlen (pattern), &r->buf);
-
- if (m > 0)
- {
- CString msg;
- CString errMsg;
- VERIFY(errMsg.LoadString(IDS_REGEXP_ERROR));
- errMsg += _T(":\n\n");
- errMsg += pattern;
- errMsg += _T("\n\n");
- int errID = IDS_REGEXP_ERROR + m;
- VERIFY(msg.LoadString(errID));
- errMsg += msg;
- LogErrorString(errMsg);
- if (bShowError)
- AfxMessageBox(errMsg, MB_ICONWARNING);
- }
-
- /* Add to the start of the list, since it's easier than the end. */
- r->next = *reglist;
- *reglist = r;
- ret = TRUE;
- }
- else
- {
- free(r->buf.fastmap);
- r->buf.fastmap = NULL;
- }
- }
- return ret;
-}
-
-/**
* @brief Utility function to update CSuperComboBox format MRU
*/
void CMainFrame::addToMru(LPCTSTR szItem, LPCTSTR szRegSubKey, UINT nMaxItems)
@@ -2530,8 +2425,6 @@
}
GetOptionsMgr()->SaveOption(OPT_LINEFILTER_ENABLED, filter.m_bIgnoreRegExp == TRUE);
GetOptionsMgr()->SaveOption(OPT_LINEFILTER_REGEXP, filter.m_sPattern);
-
- RebuildRegExpList(TRUE);
}
}
Modified: trunk/Src/MainFrm.h
===================================================================
--- trunk/Src/MainFrm.h 2007-01-08 20:24:54 UTC (rev 4020)
+++ trunk/Src/MainFrm.h 2007-01-08 20:48:23 UTC (rev 4021)
@@ -279,12 +279,6 @@
private:
void addToMru(LPCTSTR szItem, LPCTSTR szRegSubKey, UINT nMaxItems = 20);
- // builds the regular expression list if the
- // user choose to ignore Ignore changes affecting only lines
- // that match the specified regexp.
- void RebuildRegExpList(BOOL bShowError);
- // destroy the regular expression list and free up the memory
- void FreeRegExpList();
void GetAllViews(MergeEditViewList * pEditViews, MergeDetailViewList * pDetailViews, DirViewList * pDirViews);
void GetAllMergeDocs(MergeDocList * pMergeDocs);
void GetAllDirDocs(DirDocList * pDirDocs);
Modified: trunk/Src/Merge.dsp
===================================================================
--- trunk/Src/Merge.dsp 2007-01-08 20:24:54 UTC (rev 4020)
+++ trunk/Src/Merge.dsp 2007-01-08 20:48:23 UTC (rev 4021)
@@ -445,6 +445,10 @@
# End Source File
# Begin Source File
+SOURCE=.\FilterList.cpp
+# End Source File
+# Begin Source File
+
SOURCE=.\GhostTextBuffer.cpp
# End Source File
# Begin Source File
@@ -1193,6 +1197,10 @@
# End Source File
# Begin Source File
+SOURCE=.\FilterList.h
+# End Source File
+# Begin Source File
+
SOURCE=.\GhostTextBuffer.h
# End Source File
# Begin Source File
Modified: trunk/Src/MergeDoc.cpp
===================================================================
--- trunk/Src/MergeDoc.cpp 2007-01-08 20:24:54 UTC (rev 4020)
+++ trunk/Src/MergeDoc.cpp 2007-01-08 20:48:23 UTC (rev 4021)
@@ -34,6 +34,7 @@
#include "direct.h"
#include "MainFrm.h"
+#include "Ucs2Utf8.h"
#include "diff.h"
#include "diffcontext.h" // FILE_SAME
#include "MovedLines.h"
@@ -396,6 +397,16 @@
return RESCAN_SUPPRESSED;
}
+ if (GetOptionsMgr()->GetBool(OPT_LINEFILTER_ENABLED))
+ {
+ CString regexp = GetOptionsMgr()->GetString(OPT_LINEFILTER_REGEXP);
+ m_diffWrapper.SetFilterList(regexp);
+ }
+ else
+ {
+ m_diffWrapper.SetFilterList(_T(""));
+ }
+
bLeftFileChanged = IsFileChangedOnDisk(m_filePaths.GetLeft(), fileInfo,
FALSE, 0);
bRightFileChanged = IsFileChangedOnDisk(m_filePaths.GetRight(), fileInfo,
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|