diff --git a/Src/Common/UnicodeString.cpp b/Src/Common/UnicodeString.cpp index 7b6c8fd27ef..04f609a3a05 100644 --- a/Src/Common/UnicodeString.cpp +++ b/Src/Common/UnicodeString.cpp @@ -103,7 +103,7 @@ String to_charstr(TCHAR ch) * This function searches for a string inside another string an if found, * replaces it with another string. Function can replace several instances * of the string inside one string. - * @param [in] target A string containing another string to replace. + * @param [in,out] target A string containing another string to replace. * @param [in] find A string to search and replace with another (@p replace). * @param [in] replace A string used to replace original (@p find). */ @@ -119,6 +119,27 @@ void replace(String &target, const String &find, const String &replace) } } +/** + * @brief Replace the characters that matche characters specified in its arguments + * @param [in,out] str - A string containing another string to replace. + * @param [in] chars - characters to search for + * @param [in] rep - String to replace + */ +void replace_chars(String& str, const TCHAR* chars, const TCHAR *rep) +{ + String::size_type pos = 0; + size_t replen = _tcslen(rep); + while ((pos = str.find_first_of(chars, pos)) != std::string::npos) + { + std::string::size_type posend = str.find_first_not_of(chars, pos); + if (posend != String::npos) + str.replace(pos, posend - pos, rep); + else + str.replace(pos, str.length() - pos, rep); + pos += replen; + } +} + /** * @brief Compare two strings ignoring the character casing. * @param [in] str1 First string to compare. diff --git a/Src/Common/UnicodeString.h b/Src/Common/UnicodeString.h index a4426a90a2d..b9f72070130 100644 --- a/Src/Common/UnicodeString.h +++ b/Src/Common/UnicodeString.h @@ -34,6 +34,7 @@ TCHAR from_charstr(const String& str); String to_charstr(TCHAR ch); void replace(String &target, const String &find, const String &replace); +void replace_chars(String& str, const TCHAR* chars, const TCHAR* rep); // Comparing int compare_nocase(const String &str1, const String &str2); diff --git a/Src/DiffWrapper.cpp b/Src/DiffWrapper.cpp index 0debf5af60f..6ba0f8e692c 100644 --- a/Src/DiffWrapper.cpp +++ b/Src/DiffWrapper.cpp @@ -305,7 +305,7 @@ static void ReplaceSpaces(std::string & str, const char *rep) if (posend != String::npos) str.replace(pos, posend - pos, rep); else - str.replace(pos, 1, rep); + str.replace(pos, str.length() - pos, rep); pos += replen; } } @@ -325,7 +325,7 @@ static void ReplaceNumbers(std::string& str, const char* rep) if (posend != String::npos) str.replace(pos, posend - pos, rep); else - str.replace(pos, 1, rep); + str.replace(pos, str.length() - pos, rep); pos += replen; } } diff --git a/Src/MergeDoc.cpp b/Src/MergeDoc.cpp index 74a70099222..dcf542e8680 100644 --- a/Src/MergeDoc.cpp +++ b/Src/MergeDoc.cpp @@ -538,8 +538,13 @@ int CMergeDoc::Rescan(bool &bBinary, IDENTLEVEL &identical, m_ptBuf[nBuffer]->prepareForRescan(); // Divide diff blocks to match lines. - if (GetOptionsMgr()->GetBool(OPT_CMP_MATCH_SIMILAR_LINES) && m_nBuffers < 3) - AdjustDiffBlocks(); + if (GetOptionsMgr()->GetBool(OPT_CMP_MATCH_SIMILAR_LINES)) + { + if (m_nBuffers < 3) + AdjustDiffBlocks(); + else + AdjustDiffBlocks3way(); + } // Analyse diff-list (updating real line-numbers) // this operation does not change the modified flag diff --git a/Src/MergeDoc.h b/Src/MergeDoc.h index 507cf9c4071..afa81345a45 100644 --- a/Src/MergeDoc.h +++ b/Src/MergeDoc.h @@ -269,7 +269,7 @@ class CMergeDoc : public CDocument, public IMergeDoc void AddToSubstitutionFilters(CMergeEditView* pView, bool bReversed = false); std::vector GetWordDiffArrayInDiffBlock(int nDiff); std::vector GetWordDiffArray(int nLineIndex); - std::vector GetWordDiffArrayInRange(const int begin[3], const int end[3]); + std::vector GetWordDiffArrayInRange(const int begin[3], const int end[3], int pane1 = -1, int pane2 = -1); void ClearWordDiffCache(int nDiff = -1); private: void Computelinediff(CMergeEditView *pView, CRect rc[], bool bReversed); @@ -431,8 +431,13 @@ class CMergeDoc : public CDocument, public IMergeDoc void PrimeTextBuffers(); void HideLines(); void AdjustDiffBlocks(); - void AdjustDiffBlock(DiffMap & diffmap, const DIFFRANGE & diffrange, const std::vector& worddiffs, int lo0, int hi0, int lo1, int hi1); - int GetMatchCost(int line0, int line1, const std::vector& worddiffs); + void AdjustDiffBlocks3way(); + void AdjustDiffBlock(DiffMap & diffmap, const DIFFRANGE & diffrange, + const std::vector& worddiffs, + int i0, int i1, int lo0, int hi0, int lo1, int hi1); + int GetMatchCost(const DIFFRANGE& dr, int i0, int i1, int line0, int line1, const std::vector& worddiffs); + OP_TYPE ComputeOpType3way(const std::vector>& vlines, size_t index, + const DIFFRANGE& diffrange, const DIFFOPTIONS& diffOptions); void FlagTrivialLines(); void FlagMovedLines(); String GetFileExt(LPCTSTR sFileName, LPCTSTR sDescription) const; diff --git a/Src/MergeDocDiffSync.cpp b/Src/MergeDocDiffSync.cpp index 445cc747b5b..939bbdd0e63 100644 --- a/Src/MergeDocDiffSync.cpp +++ b/Src/MergeDocDiffSync.cpp @@ -19,6 +19,287 @@ using std::vector; +static void +ValidateDiffMap(const DiffMap& diffmap) +{ + for (const auto& line : diffmap.m_map) + assert(line != DiffMap::BAD_MAP_ENTRY); +} + +template +static void +ValidateVirtualLineToRealLineMap( + const std::vector>& vlines, + const std::array& nlines) +{ + int line[npanes]{}; + for (const auto& v : vlines) + { + for (int pane = 0; pane < npanes; ++pane) + { + if (v[pane] != DiffMap::GHOST_MAP_ENTRY) + { + assert(line[pane] == v[pane]); + ++line[pane]; + } + } + } + for (int pane = 0; pane < npanes; ++pane) + assert(line[pane] == nlines[pane]); +} + +template +static void +PrintVirtualLineToRealLineMap( + const String& name, + const std::vector>& vlines) +{ + OutputDebugString((_T("[") + name + _T("]\n")).c_str()); + for (size_t i = 0; i < vlines.size(); ++i) + { + String str = strutils::format(_T("vline%d: "), static_cast(i)); + std::vector ary; + for (int j = 0; j < npanes; ++j) + ary.push_back(vlines[i][j] == DiffMap::GHOST_MAP_ENTRY ? _T("-----") : strutils::format(_T("%5d"), vlines[i][j])); + str += strutils::join(ary.begin(), ary.end(), _T(",")) + _T("\n"); + OutputDebugString(str.c_str()); + } +} + +/** + * @brief Create map from virtual line to real line. + */ +static std::vector> +CreateVirtualLineToRealLineMap( + const DiffMap& diffmap, int nlines0, int nlines1) +{ + std::vector> vlines; + int line0 = 0, line1 = 0; + while (line0 < nlines0) + { + const int map_line0 = diffmap.m_map[line0]; + if (map_line0 == DiffMap::GHOST_MAP_ENTRY || map_line0 == DiffMap::BAD_MAP_ENTRY) + { + vlines.push_back({ line0++, DiffMap::GHOST_MAP_ENTRY }); + } + else + { + while (line1 < map_line0) + vlines.push_back({ DiffMap::GHOST_MAP_ENTRY, line1++ }); + vlines.push_back({ line0++, line1++ }); + } + } + while (line1 < nlines1) + vlines.push_back({ DiffMap::GHOST_MAP_ENTRY, line1++ }); + ValidateVirtualLineToRealLineMap(vlines, std::array{ nlines0, nlines1 }); + return vlines; +} + +/** + * @brief Create map from virtual line to real line. (3-way) + */ +static std::vector> +CreateVirtualLineToRealLineMap3way( + const DiffMap& diffmap01, const DiffMap& diffmap12, const DiffMap& diffmap20, + int nlines0, int nlines1, int nlines2) +{ + std::vector> vlines01 = CreateVirtualLineToRealLineMap(diffmap01, nlines0, nlines1); + std::vector> vlines12 = CreateVirtualLineToRealLineMap(diffmap12, nlines1, nlines2); + std::vector> vlines20 = CreateVirtualLineToRealLineMap(diffmap20, nlines2, nlines0); + std::vector> vlines; + size_t i01 = 0, i12 = 0, i20 = 0; + int line0 = 0, line1 = 0, line2 = 0; + bool is_vlines20_usable = true; + // 1. + for (line1 = 0; line1 < nlines1; ++line1) + { + size_t i01b = i01; + size_t i12b = i12; + size_t i20b = i20; + // 1.1 + for (; i01 < vlines01.size(); ++i01) + if (vlines01[i01][1] == line1) + break; + for (; i12 < vlines12.size(); ++i12) + if (vlines12[i12][0] == line1) + break; + assert(i01 < vlines01.size() && i12 < vlines12.size()); + // 1.2 + bool used_vlines20 = false; + if (is_vlines20_usable) + { + if (vlines12[i12][1] != DiffMap::GHOST_MAP_ENTRY && vlines01[i01][0] != DiffMap::GHOST_MAP_ENTRY) + { + // 1.2.1 + line2 = vlines12[i12][1]; + line0 = vlines01[i01][0]; + size_t i20tmp; + for (i20tmp = i20b; i20tmp < vlines20.size(); ++i20tmp) + if (vlines20[i20tmp][0] == line2 && vlines20[i20tmp][1] == line0) + break; + if (i20tmp < vlines20.size()) + { + // 1.2.1.1 + for (; i20 < i20tmp; ++i20) + vlines.push_back({ vlines20[i20][1], DiffMap::GHOST_MAP_ENTRY, vlines20[i20][0] }); + ++i20; + used_vlines20 = true; + } + else + { + // 1.2.1.2 + is_vlines20_usable = false; + } + } + else + { + // 1.2.2 + is_vlines20_usable = false; + } + } + // 1.3 + if (!used_vlines20) + { + size_t i01tmp, i12tmp; + for (i01tmp = i01b, i12tmp = i12b; i01tmp < i01 && i12tmp < i12; ++i01tmp, ++i12tmp) + vlines.push_back({ vlines01[i01tmp][0], DiffMap::GHOST_MAP_ENTRY, vlines12[i12tmp][1] }); + if (i01 - i01b < i12 - i12b) + { + // 1.3.1 + for (; i12tmp < i12; ++i12tmp) + vlines.push_back({ DiffMap::GHOST_MAP_ENTRY, DiffMap::GHOST_MAP_ENTRY, vlines12[i12tmp][1] }); + } + else if (i01 - i01b > i12 - i12b) + { + // 1.3.2 + for (; i01tmp < i01; ++i01tmp) + vlines.push_back({ vlines01[i01tmp][0], DiffMap::GHOST_MAP_ENTRY, DiffMap::GHOST_MAP_ENTRY }); + } + } + vlines.push_back({ vlines01[i01++][0], line1, vlines12[i12++][1]}); + } + // 2. + if (i01 < vlines01.size() || i12 < vlines12.size()) + { + if (is_vlines20_usable) + { + // 2.1 + for (; i20 < vlines20.size(); ++i20) + vlines.push_back({ vlines20[i20][1], DiffMap::GHOST_MAP_ENTRY, vlines20[i20][0] }); + } + else + { + // 2.2 + for (; i01 < vlines01.size() && i12 < vlines12.size(); ++i01, ++i12) + vlines.push_back({ vlines01[i01][0], DiffMap::GHOST_MAP_ENTRY, vlines12[i12][1] }); + if (vlines01.size() - i01 < vlines12.size() - i12) + { + // 2.2.1 + for (; i12 < vlines12.size(); ++i12) + vlines.push_back({ DiffMap::GHOST_MAP_ENTRY, DiffMap::GHOST_MAP_ENTRY, vlines12[i12][1] }); + } + else if (vlines01.size() - i01 > vlines12.size() - i12) + { + // 2.2.2 + for (; i01 < vlines01.size(); ++i01) + vlines.push_back({ vlines01[i01][0], DiffMap::GHOST_MAP_ENTRY, DiffMap::GHOST_MAP_ENTRY }); + } + } + } + ValidateVirtualLineToRealLineMap(vlines, std::array{ nlines0, nlines1, nlines2 }); +#ifdef _DEBUG + PrintVirtualLineToRealLineMap(_T("vline01"), vlines01); + PrintVirtualLineToRealLineMap(_T("vline12"), vlines12); + PrintVirtualLineToRealLineMap(_T("vline20"), vlines20); + PrintVirtualLineToRealLineMap(_T("vline3way"), vlines); +#endif + return vlines; +} + +OP_TYPE CMergeDoc::ComputeOpType3way( + const std::vector>& vlines, size_t index, + const DIFFRANGE& diffrange, const DIFFOPTIONS& diffOptions) +{ + if (vlines[index][0] != DiffMap::GHOST_MAP_ENTRY && + vlines[index][1] == DiffMap::GHOST_MAP_ENTRY && + vlines[index][2] == DiffMap::GHOST_MAP_ENTRY) + { + return OP_1STONLY; + } + else if (vlines[index][0] == DiffMap::GHOST_MAP_ENTRY && + vlines[index][1] != DiffMap::GHOST_MAP_ENTRY && + vlines[index][2] == DiffMap::GHOST_MAP_ENTRY) + { + return OP_2NDONLY; + } + else if (vlines[index][0] == DiffMap::GHOST_MAP_ENTRY && + vlines[index][1] == DiffMap::GHOST_MAP_ENTRY && + vlines[index][2] != DiffMap::GHOST_MAP_ENTRY) + { + return OP_3RDONLY; + } + + int line0 = diffrange.begin[0] + vlines[index][0]; + int line1 = diffrange.begin[1] + vlines[index][1]; + int line2 = diffrange.begin[2] + vlines[index][2]; + + if (vlines[index][0] != DiffMap::GHOST_MAP_ENTRY && + vlines[index][1] != DiffMap::GHOST_MAP_ENTRY && + vlines[index][2] == DiffMap::GHOST_MAP_ENTRY) + { + String strLine0(m_ptBuf[0]->GetLineChars(line0), m_ptBuf[0]->GetFullLineLength(line0)); + String strLine1(m_ptBuf[1]->GetLineChars(line1), m_ptBuf[1]->GetFullLineLength(line1)); + if (strdiff::Compare(strLine0, strLine1, + !diffOptions.bIgnoreCase, !diffOptions.bIgnoreEol, + diffOptions.nIgnoreWhitespace, diffOptions.bIgnoreNumbers) == 0) + return OP_3RDONLY; + return OP_DIFF; + } + else if (vlines[index][0] != DiffMap::GHOST_MAP_ENTRY && + vlines[index][1] == DiffMap::GHOST_MAP_ENTRY && + vlines[index][2] != DiffMap::GHOST_MAP_ENTRY) + { + String strLine0(m_ptBuf[0]->GetLineChars(line0), m_ptBuf[0]->GetFullLineLength(line0)); + String strLine2(m_ptBuf[2]->GetLineChars(line2), m_ptBuf[2]->GetFullLineLength(line2)); + if (strdiff::Compare(strLine0, strLine2, + !diffOptions.bIgnoreCase, !diffOptions.bIgnoreEol, + diffOptions.nIgnoreWhitespace, diffOptions.bIgnoreNumbers) == 0) + return OP_2NDONLY; + return OP_DIFF; + } + else if (vlines[index][0] == DiffMap::GHOST_MAP_ENTRY && + vlines[index][1] != DiffMap::GHOST_MAP_ENTRY && + vlines[index][2] != DiffMap::GHOST_MAP_ENTRY) + { + String strLine1(m_ptBuf[1]->GetLineChars(line1), m_ptBuf[1]->GetFullLineLength(line1)); + String strLine2(m_ptBuf[2]->GetLineChars(line2), m_ptBuf[2]->GetFullLineLength(line2)); + if (strdiff::Compare(strLine1, strLine2, + !diffOptions.bIgnoreCase, !diffOptions.bIgnoreEol, + diffOptions.nIgnoreWhitespace, diffOptions.bIgnoreNumbers) == 0) + return OP_1STONLY; + return OP_DIFF; + } + else + { + String strLine0(m_ptBuf[0]->GetLineChars(line0), m_ptBuf[0]->GetFullLineLength(line0)); + String strLine1(m_ptBuf[1]->GetLineChars(line1), m_ptBuf[1]->GetFullLineLength(line1)); + String strLine2(m_ptBuf[2]->GetLineChars(line2), m_ptBuf[2]->GetFullLineLength(line2)); + if (strdiff::Compare(strLine0, strLine1, + !diffOptions.bIgnoreCase, !diffOptions.bIgnoreEol, + diffOptions.nIgnoreWhitespace, diffOptions.bIgnoreNumbers) == 0) + return OP_3RDONLY; + if (strdiff::Compare(strLine0, strLine2, + !diffOptions.bIgnoreCase, !diffOptions.bIgnoreEol, + diffOptions.nIgnoreWhitespace, diffOptions.bIgnoreNumbers) == 0) + return OP_2NDONLY; + if (strdiff::Compare(strLine1, strLine2, + !diffOptions.bIgnoreCase, !diffOptions.bIgnoreEol, + diffOptions.nIgnoreWhitespace, diffOptions.bIgnoreNumbers) == 0) + return OP_1STONLY; + return OP_DIFF; + } +} + /** * @brief Divide diff blocks to match lines in diff blocks. */ @@ -45,72 +326,314 @@ void CMergeDoc::AdjustDiffBlocks() const std::vector worddiffs = GetWordDiffArrayInRange(diffrange.begin, diffrange.end); DiffMap diffmap; diffmap.InitDiffMap(nlines0); - AdjustDiffBlock(diffmap, diffrange, worddiffs, lo0, hi0, lo1, hi1); + AdjustDiffBlock(diffmap, diffrange, worddiffs, 0, 1, lo0, hi0, lo1, hi1); + ValidateDiffMap(diffmap); + std::vector> vlines = CreateVirtualLineToRealLineMap(diffmap, nlines0, nlines1); // divide diff blocks - DIFFRANGE dr; - int line0, line1, lineend0; - for (line0 = 0, line1 = 0; line0 < nlines0;) + int line0 = 0, line1 = 0; + for (size_t i = 0; i < vlines.size();) { - const int map_line0 = diffmap.m_map[line0]; - if (map_line0 == DiffMap::GHOST_MAP_ENTRY || - map_line0 == DiffMap::BAD_MAP_ENTRY) + DIFFRANGE dr; + size_t ib = i; + if ((vlines[i][0] != DiffMap::GHOST_MAP_ENTRY) && + (vlines[i][1] != DiffMap::GHOST_MAP_ENTRY)) + { + while (i < vlines.size() && + (vlines[i][0] != DiffMap::GHOST_MAP_ENTRY) && + (vlines[i][1] != DiffMap::GHOST_MAP_ENTRY)) + { + line0++; + line1++; + i++; + } + dr.begin[0] = diffrange.begin[0] + vlines[ib][0]; + dr.begin[1] = diffrange.begin[1] + vlines[ib][1]; + dr.end[0] = diffrange.begin[0] + vlines[i - 1][0]; + dr.end[1] = diffrange.begin[1] + vlines[i - 1][1]; + dr.blank[0] = dr.blank[1] = -1; + dr.op = diffrange.op; + newDiffList.AddDiff(dr); + } + else if ((vlines[i][0] == DiffMap::GHOST_MAP_ENTRY) && + (vlines[i][1] != DiffMap::GHOST_MAP_ENTRY)) { - for (lineend0 = line0; lineend0 < nlines0; lineend0++) + while (i < vlines.size() && + (vlines[i][0] == DiffMap::GHOST_MAP_ENTRY) && + (vlines[i][1] != DiffMap::GHOST_MAP_ENTRY)) { - const int map_lineend0 = diffmap.m_map[lineend0]; - if (map_lineend0 != DiffMap::GHOST_MAP_ENTRY && - map_lineend0 != DiffMap::BAD_MAP_ENTRY) - break; + line1++; + i++; } dr.begin[0] = diffrange.begin[0] + line0; + dr.begin[1] = diffrange.begin[1] + vlines[ib][1]; + dr.end[0] = diffrange.begin[0] + line0 - 1; + dr.end[1] = diffrange.begin[1] + vlines[i - 1][1]; + dr.blank[0] = dr.blank[1] = -1; + dr.op = diffrange.op; + newDiffList.AddDiff(dr); + } + else if ((vlines[i][0] != DiffMap::GHOST_MAP_ENTRY) && + (vlines[i][1] == DiffMap::GHOST_MAP_ENTRY)) + { + while (i < vlines.size() && + (vlines[i][0] != DiffMap::GHOST_MAP_ENTRY) && + (vlines[i][1] == DiffMap::GHOST_MAP_ENTRY)) + { + line0++; + i++; + } + dr.begin[0] = diffrange.begin[0] + vlines[ib][0]; dr.begin[1] = diffrange.begin[1] + line1; - dr.end[0] = diffrange.begin[0] + lineend0 - 1; - dr.end[1] = dr.begin[1] - 1; + dr.end[0] = diffrange.begin[0] + vlines[i - 1][0]; + dr.end[1] = diffrange.begin[1] + line1 - 1; dr.blank[0] = dr.blank[1] = -1; - dr.op = OP_DIFF; + dr.op = diffrange.op; newDiffList.AddDiff(dr); - line0 = lineend0; } else { - if (map_line0 > line1) - { - dr.begin[0] = diffrange.begin[0] + line0; - dr.begin[1] = diffrange.begin[1] + line1; - dr.end[0] = dr.begin[0] - 1; - dr.end[1] = diffrange.begin[1] + map_line0 - 1; - dr.blank[0] = dr.blank[1] = -1; - dr.op = OP_DIFF; - newDiffList.AddDiff(dr); - line1 = map_line0; - } + assert(0); + } + } + } + else + { + newDiffList.AddDiff(diffrange); + } + } - for (lineend0 = line0 + 1; lineend0 < nlines0; lineend0++) + // recreate m_diffList + m_diffList.Clear(); + nDiffCount = newDiffList.GetSize(); + for (nDiff = 0; nDiff < nDiffCount; nDiff++) + m_diffList.AddDiff(*newDiffList.DiffRangeAt(nDiff)); +} + +/** + * @brief Divide diff blocks to match lines in diff blocks. (3-way) + */ +void CMergeDoc::AdjustDiffBlocks3way() +{ + int nDiff; + int nDiffCount = m_diffList.GetSize(); + + // Go through and do our best to line up lines within each diff block + // between left side and right side + DiffList newDiffList; + newDiffList.Clear(); + for (nDiff = 0; nDiff < nDiffCount; nDiff++) + { + const DIFFRANGE & diffrange = *m_diffList.DiffRangeAt(nDiff); + // size map correctly (it will hold one entry for each left-side line + int nlines0 = diffrange.end[0] - diffrange.begin[0] + 1; + int nlines1 = diffrange.end[1] - diffrange.begin[1] + 1; + int nlines2 = diffrange.end[2] - diffrange.begin[2] + 1; + if ((nlines0 > 0) + (nlines1 > 0) + (nlines2 > 0) > 1) + { + // Call worker to do all lines in block + int lo0 = 0, hi0 = nlines0 - 1; + int lo1 = 0, hi1 = nlines1 - 1; + int lo2 = 0, hi2 = nlines2 - 1; + const std::vector worddiffs01 = GetWordDiffArrayInRange(diffrange.begin, diffrange.end, 0, 1); + const std::vector worddiffs12 = GetWordDiffArrayInRange(diffrange.begin, diffrange.end, 1, 2); + const std::vector worddiffs20 = GetWordDiffArrayInRange(diffrange.begin, diffrange.end, 2, 0); + DiffMap diffmap01, diffmap12, diffmap20; + diffmap01.InitDiffMap(nlines0); + diffmap12.InitDiffMap(nlines1); + diffmap20.InitDiffMap(nlines2); + AdjustDiffBlock(diffmap01, diffrange, worddiffs01, 0, 1, lo0, hi0, lo1, hi1); + AdjustDiffBlock(diffmap12, diffrange, worddiffs12, 1, 2, lo1, hi1, lo2, hi2); + AdjustDiffBlock(diffmap20, diffrange, worddiffs20, 2, 0, lo2, hi2, lo0, hi0); + ValidateDiffMap(diffmap01); + ValidateDiffMap(diffmap12); + ValidateDiffMap(diffmap20); + std::vector> vlines = CreateVirtualLineToRealLineMap3way(diffmap01, diffmap12, diffmap20, nlines0, nlines1, nlines2); + + DIFFOPTIONS diffOptions = {0}; + m_diffWrapper.GetOptions(&diffOptions); + std::vector opary(vlines.size()); + for (size_t i = 0; i < vlines.size(); ++i) + opary[i] = (diffrange.op == OP_TRIVIAL) ? + OP_TRIVIAL : + ComputeOpType3way(vlines, i, diffrange, diffOptions); + // divide diff blocks + int line0 = 0, line1 = 0, line2 = 0; + for (size_t i = 0; i < vlines.size();) + { + DIFFRANGE dr; + size_t ib = i; + OP_TYPE op = opary[i]; + if ((vlines[i][0] != DiffMap::GHOST_MAP_ENTRY) && + (vlines[i][1] != DiffMap::GHOST_MAP_ENTRY) && + (vlines[i][2] != DiffMap::GHOST_MAP_ENTRY)) + { + while (i < vlines.size() && + (vlines[i][0] != DiffMap::GHOST_MAP_ENTRY) && + (vlines[i][1] != DiffMap::GHOST_MAP_ENTRY) && + (vlines[i][2] != DiffMap::GHOST_MAP_ENTRY) && + op == opary[i]) { - if (map_line0 != diffmap.m_map[lineend0 - 1] + 1) - break; + line0++; + line1++; + line2++; + i++; + } + dr.begin[0] = diffrange.begin[0] + vlines[ib][0]; + dr.begin[1] = diffrange.begin[1] + vlines[ib][1]; + dr.begin[2] = diffrange.begin[2] + vlines[ib][2]; + dr.end[0] = diffrange.begin[0] + vlines[i - 1][0]; + dr.end[1] = diffrange.begin[1] + vlines[i - 1][1]; + dr.end[2] = diffrange.begin[2] + vlines[i - 1][2]; + dr.blank[0] = dr.blank[1] = dr.blank[2] = -1; + dr.op = op; + newDiffList.AddDiff(dr); + } + else if ((vlines[i][0] == DiffMap::GHOST_MAP_ENTRY) && + (vlines[i][1] != DiffMap::GHOST_MAP_ENTRY) && + (vlines[i][2] != DiffMap::GHOST_MAP_ENTRY)) + { + while (i < vlines.size() && + (vlines[i][0] == DiffMap::GHOST_MAP_ENTRY) && + (vlines[i][1] != DiffMap::GHOST_MAP_ENTRY) && + (vlines[i][2] != DiffMap::GHOST_MAP_ENTRY) && + op == opary[i]) + { + line1++; + line2++; + i++; } dr.begin[0] = diffrange.begin[0] + line0; + dr.begin[1] = diffrange.begin[1] + vlines[ib][1]; + dr.begin[2] = diffrange.begin[2] + vlines[ib][2]; + dr.end[0] = diffrange.begin[0] + line0 - 1; + dr.end[1] = diffrange.begin[1] + vlines[i - 1][1]; + dr.end[2] = diffrange.begin[2] + vlines[i - 1][2]; + dr.blank[0] = dr.blank[1] = dr.blank[2] = -1; + dr.op = op; + newDiffList.AddDiff(dr); + } + else if ((vlines[i][0] != DiffMap::GHOST_MAP_ENTRY) && + (vlines[i][1] == DiffMap::GHOST_MAP_ENTRY) && + (vlines[i][2] != DiffMap::GHOST_MAP_ENTRY)) + { + while (i < vlines.size() && + (vlines[i][0] != DiffMap::GHOST_MAP_ENTRY) && + (vlines[i][1] == DiffMap::GHOST_MAP_ENTRY) && + (vlines[i][2] != DiffMap::GHOST_MAP_ENTRY) && + op == opary[i]) + { + line0++; + line2++; + i++; + } + dr.begin[0] = diffrange.begin[0] + vlines[ib][0]; dr.begin[1] = diffrange.begin[1] + line1; - dr.end[0] = diffrange.begin[0] + lineend0 - 1; - dr.end[1] = diffrange.begin[1] + diffmap.m_map[lineend0 - 1]; - dr.blank[0] = dr.blank[1] = -1; - dr.op = diffrange.op == OP_TRIVIAL ? OP_TRIVIAL : OP_DIFF; + dr.begin[2] = diffrange.begin[2] + vlines[ib][2]; + dr.end[0] = diffrange.begin[0] + vlines[i - 1][0]; + dr.end[1] = diffrange.begin[1] + line1 - 1; + dr.end[2] = diffrange.begin[2] + vlines[i - 1][2]; + dr.blank[0] = dr.blank[1] = dr.blank[2] = -1; + dr.op = op; newDiffList.AddDiff(dr); - line0 = lineend0; - line1 = diffmap.m_map[lineend0 - 1] + 1; } - } - if (line1 <= hi1) - { - dr.begin[0] = diffrange.begin[0] + line0; - dr.begin[1] = diffrange.begin[1] + line1; - dr.end[0] = dr.begin[0] - 1; - dr.end[1] = diffrange.begin[1] + hi1; - dr.blank[0] = dr.blank[1] = -1; - dr.op = diffrange.op == OP_TRIVIAL ? OP_TRIVIAL : OP_DIFF; - newDiffList.AddDiff(dr); + else if ((vlines[i][0] != DiffMap::GHOST_MAP_ENTRY) && + (vlines[i][1] != DiffMap::GHOST_MAP_ENTRY) && + (vlines[i][2] == DiffMap::GHOST_MAP_ENTRY)) + { + while (i < vlines.size() && + (vlines[i][0] != DiffMap::GHOST_MAP_ENTRY) && + (vlines[i][1] != DiffMap::GHOST_MAP_ENTRY) && + (vlines[i][2] == DiffMap::GHOST_MAP_ENTRY) && + op == opary[i]) + { + line0++; + line1++; + i++; + } + dr.begin[0] = diffrange.begin[0] + vlines[ib][0]; + dr.begin[1] = diffrange.begin[1] + vlines[ib][1]; + dr.begin[2] = diffrange.begin[2] + line2; + dr.end[0] = diffrange.begin[0] + vlines[i - 1][0]; + dr.end[1] = diffrange.begin[1] + vlines[i - 1][1]; + dr.end[2] = diffrange.begin[2] + line2 - 1; + dr.blank[0] = dr.blank[1] = dr.blank[2] = -1; + dr.op = op; + newDiffList.AddDiff(dr); + } + else if ((vlines[i][0] != DiffMap::GHOST_MAP_ENTRY) && + (vlines[i][1] == DiffMap::GHOST_MAP_ENTRY) && + (vlines[i][2] == DiffMap::GHOST_MAP_ENTRY)) + { + while (i < vlines.size() && + (vlines[i][0] != DiffMap::GHOST_MAP_ENTRY) && + (vlines[i][1] == DiffMap::GHOST_MAP_ENTRY) && + (vlines[i][2] == DiffMap::GHOST_MAP_ENTRY) && + op == opary[i]) + { + line0++; + i++; + } + dr.begin[0] = diffrange.begin[0] + vlines[ib][0]; + dr.begin[1] = diffrange.begin[1] + line1; + dr.begin[2] = diffrange.begin[2] + line2; + dr.end[0] = diffrange.begin[0] + vlines[i - 1][0]; + dr.end[1] = diffrange.begin[1] + line1 - 1; + dr.end[2] = diffrange.begin[2] + line2 - 1; + dr.blank[0] = dr.blank[1] = dr.blank[2] = -1; + dr.op = op; + newDiffList.AddDiff(dr); + } + else if ((vlines[i][0] == DiffMap::GHOST_MAP_ENTRY) && + (vlines[i][1] != DiffMap::GHOST_MAP_ENTRY) && + (vlines[i][2] == DiffMap::GHOST_MAP_ENTRY)) + { + while (i < vlines.size() && + (vlines[i][0] == DiffMap::GHOST_MAP_ENTRY) && + (vlines[i][1] != DiffMap::GHOST_MAP_ENTRY) && + (vlines[i][2] == DiffMap::GHOST_MAP_ENTRY) && + op == opary[i]) + { + line1++; + i++; + } + dr.begin[0] = diffrange.begin[0] + line0; + dr.begin[1] = diffrange.begin[1] + vlines[ib][1]; + dr.begin[2] = diffrange.begin[2] + line2; + dr.end[0] = diffrange.begin[0] + line0 - 1; + dr.end[1] = diffrange.begin[1] + vlines[i - 1][1]; + dr.end[2] = diffrange.begin[2] + line2 - 1; + dr.blank[0] = dr.blank[1] = dr.blank[2] = -1; + dr.op = op; + newDiffList.AddDiff(dr); + } + else if ((vlines[i][0] == DiffMap::GHOST_MAP_ENTRY) && + (vlines[i][1] == DiffMap::GHOST_MAP_ENTRY) && + (vlines[i][2] != DiffMap::GHOST_MAP_ENTRY)) + { + while (i < vlines.size() && + (vlines[i][0] == DiffMap::GHOST_MAP_ENTRY) && + (vlines[i][1] == DiffMap::GHOST_MAP_ENTRY) && + (vlines[i][2] != DiffMap::GHOST_MAP_ENTRY) && + op == opary[i]) + { + line2++; + i++; + } + dr.begin[0] = diffrange.begin[0] + line0; + dr.begin[1] = diffrange.begin[1] + line1; + dr.begin[2] = diffrange.begin[2] + vlines[ib][2]; + dr.end[0] = diffrange.begin[0] + line0 - 1; + dr.end[1] = diffrange.begin[1] + line1 - 1; + dr.end[2] = diffrange.begin[2] + vlines[i - 1][2]; + dr.blank[0] = dr.blank[1] = dr.blank[2] = -1; + dr.op = op; + newDiffList.AddDiff(dr); + } + else + { + assert(0); + } } } else @@ -132,19 +655,30 @@ void CMergeDoc::AdjustDiffBlocks() * The cost of making them equal is the measure of their dissimilarity * which is their Levenshtein distance. */ -int CMergeDoc::GetMatchCost(int line0, int line1, const std::vector& worddiffs) +int CMergeDoc::GetMatchCost(const DIFFRANGE& dr, int i0, int i1, int line0, int line1, const std::vector& worddiffs) { int matchlen = 0; for (size_t i = 0; i < worddiffs.size(); ++i) { if (i == 0) { - if (line0 == worddiffs[i].beginline[0] && line1 == worddiffs[i].beginline[1]) - matchlen += worddiffs[i].begin[0]; + if (line0 < worddiffs[0].beginline[0] && line1 < worddiffs[0].beginline[1]) + { + if (line0 - dr.begin[i0] == line1 - dr.begin[i1]) + matchlen += m_ptBuf[i0]->GetFullLineLength(line0); + } + else if (line0 == worddiffs[0].beginline[0] && line1 == worddiffs[0].beginline[1]) + matchlen += worddiffs[0].begin[0]; } else { - if (worddiffs[i - 1].endline[0] <= line0 && worddiffs[i - 1].endline[1] <= line1 && + if (worddiffs[i - 1].endline[0] < line0 && worddiffs[i - 1].endline[1] < line1 && + line0 < worddiffs[i].beginline[0] && line1 < worddiffs[i].beginline[1]) + { + if (line0 - worddiffs[i - 1].endline[0] == line1 - worddiffs[i - 1].endline[1]) + matchlen += m_ptBuf[i0]->GetFullLineLength(line0); + } + else if (worddiffs[i - 1].endline[0] <= line0 && worddiffs[i - 1].endline[1] <= line1 && line0 <= worddiffs[i].beginline[0] && line1 <= worddiffs[i].beginline[1]) { if (worddiffs[i - 1].endline[0] == worddiffs[i].beginline[0]) @@ -157,9 +691,29 @@ int CMergeDoc::GetMatchCost(int line0, int line1, const std::vector& w worddiffs[i + 1].beginline[0] != worddiffs[i].endline[0] && worddiffs[i + 1].beginline[1] != worddiffs[i].endline[1]) { if (worddiffs[i].endline[0] == line0 && worddiffs[i].endline[1] == line1) - matchlen += m_ptBuf[0]->GetFullLineLength(line0) - worddiffs[i].end[0] - 1; + matchlen += m_ptBuf[i0]->GetFullLineLength(line0) - worddiffs[i].end[0] - 1; + } + } + if (worddiffs.empty()) + { + if (line0 - dr.begin[i0] == line1 - dr.begin[i1]) + matchlen += m_ptBuf[i0]->GetFullLineLength(line0); + } + else + { + auto lastWordDiff = worddiffs.back(); + if (lastWordDiff.endline[0] < line0 && lastWordDiff.endline[1] < line1) + { + if (line0 - lastWordDiff.endline[0] == line1 - lastWordDiff.endline[1]) + matchlen += m_ptBuf[i0]->GetFullLineLength(line0); } } +/* +#ifdef _DEBUG + String str = strutils::format(_T("pane%d,%d line%5d,%5d match len: %d\n"), i0, i1, line0, line1, matchlen); + OutputDebugString(str.c_str()); +#endif +*/ return -matchlen; } @@ -172,21 +726,28 @@ int CMergeDoc::GetMatchCost(int line0, int line1, const std::vector& w * Find best match, and use that to split problem into two parts (above & below match) * and call ourselves recursively to solve each smaller problem */ -void CMergeDoc::AdjustDiffBlock(DiffMap & diffMap, const DIFFRANGE & diffrange, const std::vector& worddiffs, int lo0, int hi0, int lo1, int hi1) +void CMergeDoc::AdjustDiffBlock(DiffMap & diffMap, const DIFFRANGE & diffrange, const std::vector& worddiffs, int i0, int i1, int lo0, int hi0, int lo1, int hi1) { // Map & lo & hi numbers are all relative to this block // We need to know offsets to find actual line strings from buffer - int offset0 = diffrange.begin[0]; - int offset1 = diffrange.begin[1]; + int offset0 = diffrange.begin[i0]; + int offset1 = diffrange.begin[i1]; // # of lines on left and right int lines0 = hi0 - lo0 + 1; int lines1 = hi1 - lo1 + 1; - - ASSERT(lines0 > 0 && lines1 > 0); - // shortcut special case + if (lines0 == 0) + { + return; + } + if (lines1 == 0) + { + for (int w=0; w CMergeDoc::GetWordDiffArrayInDiffBlock(int nDiff) return worddiffs; } -std::vector CMergeDoc::GetWordDiffArrayInRange(const int begin[3], const int end[3]) +std::vector +CMergeDoc::GetWordDiffArrayInRange(const int begin[3], const int end[3], int pane1/*=-1*/, int pane2/*=-1*/) { DIFFOPTIONS diffOptions = {0}; m_diffWrapper.GetOptions(&diffOptions); String str[3]; std::unique_ptr nOffsets[3]; std::vector worddiffs; - for (int file = 0; file < m_nBuffers; file++) + std::vector panes; + if (pane1 == -1 && pane2 == -1) + panes = (m_nBuffers == 2) ? std::vector{0, 1} : std::vector{ 0, 1, 2 }; + else + panes = std::vector{ pane1, pane2 }; + for (size_t i = 0; i < panes.size(); ++i) { + int file = panes[i]; int nLineBegin = begin[file]; int nLineEnd = end[file]; if (nLineEnd >= m_ptBuf[file]->GetLineCount()) return worddiffs; nOffsets[file].reset(new int[nLineEnd - nLineBegin + 1]); CString strText; - if (nLineBegin != nLineEnd || m_ptBuf[file]->GetLineLength(nLineEnd) > 0) - m_ptBuf[file]->GetTextWithoutEmptys(nLineBegin, 0, nLineEnd, m_ptBuf[file]->GetLineLength(nLineEnd), strText); - strText += m_ptBuf[file]->GetLineEol(nLineEnd); - str[file].assign(strText, strText.GetLength()); - - nOffsets[file][0] = 0; + if (nLineBegin <= nLineEnd) + { + if (nLineBegin != nLineEnd || m_ptBuf[file]->GetLineLength(nLineEnd) > 0) + m_ptBuf[file]->GetTextWithoutEmptys(nLineBegin, 0, nLineEnd, m_ptBuf[file]->GetLineLength(nLineEnd), strText); + strText += m_ptBuf[file]->GetLineEol(nLineEnd); + nOffsets[file][0] = 0; + } + str[i].assign(strText, strText.GetLength()); for (int nLine = nLineBegin; nLine < nLineEnd; nLine++) nOffsets[file][nLine-nLineBegin+1] = nOffsets[file][nLine-nLineBegin] + m_ptBuf[file]->GetFullLineLength(nLine); } @@ -364,55 +373,56 @@ std::vector CMergeDoc::GetWordDiffArrayInRange(const int begin[3], con bool byteColoring = GetByteColoringOption(); // Make the call to stringdiffs, which does all the hard & tedious computations - std::vector wdiffs = strdiff::ComputeWordDiffs(m_nBuffers, str, casitive, eolSensitive, xwhite, diffOptions.bIgnoreNumbers ,breakType, byteColoring); + std::vector wdiffs = + strdiff::ComputeWordDiffs(static_cast(panes.size()), str, casitive, eolSensitive, xwhite, diffOptions.bIgnoreNumbers, breakType, byteColoring); - int i; std::vector::iterator it; - for (i = 0, it = wdiffs.begin(); it != wdiffs.end(); ++i, ++it) + for (it = wdiffs.begin(); it != wdiffs.end(); ++it) { WordDiff wd; - for (int file = 0; file < m_nBuffers; file++) + for (size_t i = 0; i < panes.size(); ++i) { + int file = panes[i]; int nLineBegin = begin[file]; int nLineEnd = end[file]; int nLine; for (nLine = nLineBegin; nLine < nLineEnd; nLine++) { - if (it->begin[file] == nOffsets[file][nLine-nLineBegin] || it->begin[file] < nOffsets[file][nLine-nLineBegin+1]) + if (it->begin[i] == nOffsets[file][nLine-nLineBegin] || it->begin[i] < nOffsets[file][nLine-nLineBegin+1]) break; } - wd.beginline[file] = nLine; - wd.begin[file] = it->begin[file] - nOffsets[file][nLine-nLineBegin]; - if (m_ptBuf[file]->GetLineLength(nLine) < wd.begin[file]) + wd.beginline[i] = nLine; + wd.begin[i] = it->begin[i] - nOffsets[file][nLine-nLineBegin]; + if (m_ptBuf[file]->GetLineLength(nLine) < wd.begin[i]) { - if (wd.beginline[file] < m_ptBuf[file]->GetLineCount() - 1) + if (wd.beginline[i] < m_ptBuf[file]->GetLineCount() - 1) { - wd.begin[file] = 0; - wd.beginline[file]++; + wd.begin[i] = 0; + wd.beginline[i]++; } else { - wd.begin[file] = m_ptBuf[file]->GetLineLength(nLine); + wd.begin[i] = m_ptBuf[file]->GetLineLength(nLine); } } for (; nLine < nLineEnd; nLine++) { - if (it->end[file] + 1 == nOffsets[file][nLine-nLineBegin] || it->end[file] + 1 < nOffsets[file][nLine-nLineBegin+1]) + if (it->end[i] + 1 == nOffsets[file][nLine-nLineBegin] || it->end[i] + 1 < nOffsets[file][nLine-nLineBegin+1]) break; } - wd.endline[file] = nLine; - wd.end[file] = it->end[file] + 1 - nOffsets[file][nLine-nLineBegin]; - if (m_ptBuf[file]->GetLineLength(nLine) < wd.end[file]) + wd.endline[i] = nLine; + wd.end[i] = it->end[i] + 1 - nOffsets[file][nLine-nLineBegin]; + if (m_ptBuf[file]->GetLineLength(nLine) < wd.end[i]) { - if (wd.endline[file] < m_ptBuf[file]->GetLineCount() - 1) + if (wd.endline[i] < m_ptBuf[file]->GetLineCount() - 1) { - wd.end[file] = 0; - wd.endline[file]++; + wd.end[i] = 0; + wd.endline[i]++; } else { - wd.end[file] = m_ptBuf[file]->GetLineLength(nLine); + wd.end[i] = m_ptBuf[file]->GetLineLength(nLine); } } } diff --git a/Src/stringdiffs.cpp b/Src/stringdiffs.cpp index 745dc350731..e54cd4d1a9f 100644 --- a/Src/stringdiffs.cpp +++ b/Src/stringdiffs.cpp @@ -195,6 +195,40 @@ ComputeWordDiffs(int nFiles, const String *str, return diffs; } +int Compare(const String& str1, const String& str2, + bool case_sensitive, bool eol_sensitive, int whitespace, bool ignore_numbers) +{ + if (case_sensitive && eol_sensitive && whitespace == WHITESPACE_COMPARE_ALL && !ignore_numbers) + return str2.compare(str1); + String s1 = str1, s2 = str2; + if (!case_sensitive) + { + s1 = strutils::makelower(s1); + s2 = strutils::makelower(s2); + } + if (whitespace == WHITESPACE_IGNORE_CHANGE) + { + strutils::replace_chars(s1, _T(" \t"), _T(" ")); + strutils::replace_chars(s2, _T(" \t"), _T(" ")); + } + else if (whitespace == WHITESPACE_IGNORE_ALL) + { + strutils::replace_chars(s1, _T(" \t"), _T("")); + strutils::replace_chars(s2, _T(" \t"), _T("")); + } + if (!eol_sensitive) + { + strutils::replace_chars(s1, _T("\r\n"), _T("\n")); + strutils::replace_chars(s2, _T("\r\n"), _T("\n")); + } + if (ignore_numbers) + { + strutils::replace_chars(s1, _T("0123456789"), _T("")); + strutils::replace_chars(s2, _T("0123456789"), _T("")); + } + return s2.compare(s1); +} + /** * @brief stringdiffs constructor simply loads all members from arguments */ diff --git a/Src/stringdiffs.h b/Src/stringdiffs.h index 5882045a19a..6c32ca82c04 100644 --- a/Src/stringdiffs.h +++ b/Src/stringdiffs.h @@ -45,5 +45,7 @@ std::vector ComputeWordDiffs(const String& str1, const String& str2, bool case_sensitive, bool eol_sensitive, int whitespace, bool ignore_numbers, int breakType, bool byte_level); std::vector ComputeWordDiffs(int nStrings, const String *str, bool case_sensitive, bool eol_sensitive, int whitespace, bool ignore_numbers, int breakType, bool byte_level); +int Compare(const String& str1, const String& str2, + bool case_sensitive, bool eol_sensitive, int whitespace, bool ignore_numbers); } diff --git a/Testing/Data/Compare/Dir1/file3way1_!!!.txt b/Testing/Data/Compare/Dir1/file3way1_!!!.txt new file mode 100644 index 00000000000..e0696a4766b --- /dev/null +++ b/Testing/Data/Compare/Dir1/file3way1_!!!.txt @@ -0,0 +1,3 @@ +01234 +A +56789 diff --git a/Testing/Data/Compare/Dir1/file3way1_!!G.txt b/Testing/Data/Compare/Dir1/file3way1_!!G.txt new file mode 100644 index 00000000000..e0696a4766b --- /dev/null +++ b/Testing/Data/Compare/Dir1/file3way1_!!G.txt @@ -0,0 +1,3 @@ +01234 +A +56789 diff --git a/Testing/Data/Compare/Dir1/file3way1_!==.txt b/Testing/Data/Compare/Dir1/file3way1_!==.txt new file mode 100644 index 00000000000..e0696a4766b --- /dev/null +++ b/Testing/Data/Compare/Dir1/file3way1_!==.txt @@ -0,0 +1,3 @@ +01234 +A +56789 diff --git a/Testing/Data/Compare/Dir1/file3way1_!G!.txt b/Testing/Data/Compare/Dir1/file3way1_!G!.txt new file mode 100644 index 00000000000..e0696a4766b --- /dev/null +++ b/Testing/Data/Compare/Dir1/file3way1_!G!.txt @@ -0,0 +1,3 @@ +01234 +A +56789 diff --git a/Testing/Data/Compare/Dir1/file3way1_!GG.txt b/Testing/Data/Compare/Dir1/file3way1_!GG.txt new file mode 100644 index 00000000000..e0696a4766b --- /dev/null +++ b/Testing/Data/Compare/Dir1/file3way1_!GG.txt @@ -0,0 +1,3 @@ +01234 +A +56789 diff --git a/Testing/Data/Compare/Dir1/file3way1_=!=.txt b/Testing/Data/Compare/Dir1/file3way1_=!=.txt new file mode 100644 index 00000000000..f7ee25ffaca --- /dev/null +++ b/Testing/Data/Compare/Dir1/file3way1_=!=.txt @@ -0,0 +1,3 @@ +01234 +AC +56789 diff --git a/Testing/Data/Compare/Dir1/file3way1_==!.txt b/Testing/Data/Compare/Dir1/file3way1_==!.txt new file mode 100644 index 00000000000..b5df55af10d --- /dev/null +++ b/Testing/Data/Compare/Dir1/file3way1_==!.txt @@ -0,0 +1,3 @@ +01234 +AB +56789 diff --git a/Testing/Data/Compare/Dir1/file3way1_==G.txt b/Testing/Data/Compare/Dir1/file3way1_==G.txt new file mode 100644 index 00000000000..b5df55af10d --- /dev/null +++ b/Testing/Data/Compare/Dir1/file3way1_==G.txt @@ -0,0 +1,3 @@ +01234 +AB +56789 diff --git a/Testing/Data/Compare/Dir1/file3way1_=G=.txt b/Testing/Data/Compare/Dir1/file3way1_=G=.txt new file mode 100644 index 00000000000..f7ee25ffaca --- /dev/null +++ b/Testing/Data/Compare/Dir1/file3way1_=G=.txt @@ -0,0 +1,3 @@ +01234 +AC +56789 diff --git a/Testing/Data/Compare/Dir1/file3way1_G!!.txt b/Testing/Data/Compare/Dir1/file3way1_G!!.txt new file mode 100644 index 00000000000..eb3debb2bc4 --- /dev/null +++ b/Testing/Data/Compare/Dir1/file3way1_G!!.txt @@ -0,0 +1,2 @@ +01234 +56789 diff --git a/Testing/Data/Compare/Dir1/file3way1_G!G.txt b/Testing/Data/Compare/Dir1/file3way1_G!G.txt new file mode 100644 index 00000000000..eb3debb2bc4 --- /dev/null +++ b/Testing/Data/Compare/Dir1/file3way1_G!G.txt @@ -0,0 +1,2 @@ +01234 +56789 diff --git a/Testing/Data/Compare/Dir1/file3way1_G==.txt b/Testing/Data/Compare/Dir1/file3way1_G==.txt new file mode 100644 index 00000000000..eb3debb2bc4 --- /dev/null +++ b/Testing/Data/Compare/Dir1/file3way1_G==.txt @@ -0,0 +1,2 @@ +01234 +56789 diff --git a/Testing/Data/Compare/Dir1/file3way1_GG!.txt b/Testing/Data/Compare/Dir1/file3way1_GG!.txt new file mode 100644 index 00000000000..eb3debb2bc4 --- /dev/null +++ b/Testing/Data/Compare/Dir1/file3way1_GG!.txt @@ -0,0 +1,2 @@ +01234 +56789 diff --git a/Testing/Data/Compare/Dir1/file3way2_!!!.txt b/Testing/Data/Compare/Dir1/file3way2_!!!.txt new file mode 100644 index 00000000000..1a044a708d4 --- /dev/null +++ b/Testing/Data/Compare/Dir1/file3way2_!!!.txt @@ -0,0 +1,4 @@ +01234 +abcde +A +56789 diff --git a/Testing/Data/Compare/Dir1/file3way2_!!G.txt b/Testing/Data/Compare/Dir1/file3way2_!!G.txt new file mode 100644 index 00000000000..f5cd9f8bbee --- /dev/null +++ b/Testing/Data/Compare/Dir1/file3way2_!!G.txt @@ -0,0 +1,4 @@ +01234 +abced +A +56789 diff --git a/Testing/Data/Compare/Dir1/file3way2_!==.txt b/Testing/Data/Compare/Dir1/file3way2_!==.txt new file mode 100644 index 00000000000..f5cd9f8bbee --- /dev/null +++ b/Testing/Data/Compare/Dir1/file3way2_!==.txt @@ -0,0 +1,4 @@ +01234 +abced +A +56789 diff --git a/Testing/Data/Compare/Dir1/file3way2_!G!.txt b/Testing/Data/Compare/Dir1/file3way2_!G!.txt new file mode 100644 index 00000000000..f5cd9f8bbee --- /dev/null +++ b/Testing/Data/Compare/Dir1/file3way2_!G!.txt @@ -0,0 +1,4 @@ +01234 +abced +A +56789 diff --git a/Testing/Data/Compare/Dir1/file3way2_!GG.txt b/Testing/Data/Compare/Dir1/file3way2_!GG.txt new file mode 100644 index 00000000000..f5cd9f8bbee --- /dev/null +++ b/Testing/Data/Compare/Dir1/file3way2_!GG.txt @@ -0,0 +1,4 @@ +01234 +abced +A +56789 diff --git a/Testing/Data/Compare/Dir1/file3way2_=!=.txt b/Testing/Data/Compare/Dir1/file3way2_=!=.txt new file mode 100644 index 00000000000..d147f4f298a --- /dev/null +++ b/Testing/Data/Compare/Dir1/file3way2_=!=.txt @@ -0,0 +1,4 @@ +01234 +abced +AC +56789 diff --git a/Testing/Data/Compare/Dir1/file3way2_==!.txt b/Testing/Data/Compare/Dir1/file3way2_==!.txt new file mode 100644 index 00000000000..ed0d18e348f --- /dev/null +++ b/Testing/Data/Compare/Dir1/file3way2_==!.txt @@ -0,0 +1,4 @@ +01234 +abced +AB +56789 diff --git a/Testing/Data/Compare/Dir1/file3way2_==G.txt b/Testing/Data/Compare/Dir1/file3way2_==G.txt new file mode 100644 index 00000000000..ed0d18e348f --- /dev/null +++ b/Testing/Data/Compare/Dir1/file3way2_==G.txt @@ -0,0 +1,4 @@ +01234 +abced +AB +56789 diff --git a/Testing/Data/Compare/Dir1/file3way2_=G=.txt b/Testing/Data/Compare/Dir1/file3way2_=G=.txt new file mode 100644 index 00000000000..d147f4f298a --- /dev/null +++ b/Testing/Data/Compare/Dir1/file3way2_=G=.txt @@ -0,0 +1,4 @@ +01234 +abced +AC +56789 diff --git a/Testing/Data/Compare/Dir1/file3way2_G!!.txt b/Testing/Data/Compare/Dir1/file3way2_G!!.txt new file mode 100644 index 00000000000..26adf930acb --- /dev/null +++ b/Testing/Data/Compare/Dir1/file3way2_G!!.txt @@ -0,0 +1,3 @@ +01234 +abced +56789 diff --git a/Testing/Data/Compare/Dir1/file3way2_G!G.txt b/Testing/Data/Compare/Dir1/file3way2_G!G.txt new file mode 100644 index 00000000000..26adf930acb --- /dev/null +++ b/Testing/Data/Compare/Dir1/file3way2_G!G.txt @@ -0,0 +1,3 @@ +01234 +abced +56789 diff --git a/Testing/Data/Compare/Dir1/file3way2_G==.txt b/Testing/Data/Compare/Dir1/file3way2_G==.txt new file mode 100644 index 00000000000..26adf930acb --- /dev/null +++ b/Testing/Data/Compare/Dir1/file3way2_G==.txt @@ -0,0 +1,3 @@ +01234 +abced +56789 diff --git a/Testing/Data/Compare/Dir1/file3way2_GG!.txt b/Testing/Data/Compare/Dir1/file3way2_GG!.txt new file mode 100644 index 00000000000..26adf930acb --- /dev/null +++ b/Testing/Data/Compare/Dir1/file3way2_GG!.txt @@ -0,0 +1,3 @@ +01234 +abced +56789 diff --git a/Testing/Data/Compare/Dir1/file3way3_1.2.1-2.1.txt b/Testing/Data/Compare/Dir1/file3way3_1.2.1-2.1.txt new file mode 100644 index 00000000000..46f740df91d --- /dev/null +++ b/Testing/Data/Compare/Dir1/file3way3_1.2.1-2.1.txt @@ -0,0 +1,4 @@ +01234 +A 1111 +A 2222 +56789 diff --git a/Testing/Data/Compare/Dir1/file3way3_1.2.1.1.txt b/Testing/Data/Compare/Dir1/file3way3_1.2.1.1.txt new file mode 100644 index 00000000000..46f740df91d --- /dev/null +++ b/Testing/Data/Compare/Dir1/file3way3_1.2.1.1.txt @@ -0,0 +1,4 @@ +01234 +A 1111 +A 2222 +56789 diff --git a/Testing/Data/Compare/Dir1/file3way3_1.2.2-1.3.1.txt b/Testing/Data/Compare/Dir1/file3way3_1.2.2-1.3.1.txt new file mode 100644 index 00000000000..33fa7254d1a --- /dev/null +++ b/Testing/Data/Compare/Dir1/file3way3_1.2.2-1.3.1.txt @@ -0,0 +1,6 @@ +01234 +A 1111 +A 2222 +A 3333 +A 5555 +56789 diff --git a/Testing/Data/Compare/Dir1/file3way3_1.2.2-1.3.2.txt b/Testing/Data/Compare/Dir1/file3way3_1.2.2-1.3.2.txt new file mode 100644 index 00000000000..a60bc7acc92 --- /dev/null +++ b/Testing/Data/Compare/Dir1/file3way3_1.2.2-1.3.2.txt @@ -0,0 +1,7 @@ +01234 +A 1111 +A 2222 +A 3333 +A 4444 +A 5555 +56789 diff --git a/Testing/Data/Compare/Dir1/file3way3_1.2.2-2.2.1.txt b/Testing/Data/Compare/Dir1/file3way3_1.2.2-2.2.1.txt new file mode 100644 index 00000000000..716fd5682c4 --- /dev/null +++ b/Testing/Data/Compare/Dir1/file3way3_1.2.2-2.2.1.txt @@ -0,0 +1,5 @@ +01234 +A 1111 +A 2222 +A 3333 +56789 diff --git a/Testing/Data/Compare/Dir1/file3way3_1.2.2-2.2.2.txt b/Testing/Data/Compare/Dir1/file3way3_1.2.2-2.2.2.txt new file mode 100644 index 00000000000..a69daed3ff6 --- /dev/null +++ b/Testing/Data/Compare/Dir1/file3way3_1.2.2-2.2.2.txt @@ -0,0 +1,6 @@ +01234 +A 1111 +A 2222 +A 3333 +A 4444 +56789 diff --git a/Testing/Data/Compare/Dir2/file3way1_!!!.txt b/Testing/Data/Compare/Dir2/file3way1_!!!.txt new file mode 100644 index 00000000000..98b9867df32 --- /dev/null +++ b/Testing/Data/Compare/Dir2/file3way1_!!!.txt @@ -0,0 +1,3 @@ +01234 +B +56789 diff --git a/Testing/Data/Compare/Dir2/file3way1_!!G.txt b/Testing/Data/Compare/Dir2/file3way1_!!G.txt new file mode 100644 index 00000000000..98b9867df32 --- /dev/null +++ b/Testing/Data/Compare/Dir2/file3way1_!!G.txt @@ -0,0 +1,3 @@ +01234 +B +56789 diff --git a/Testing/Data/Compare/Dir2/file3way1_!==.txt b/Testing/Data/Compare/Dir2/file3way1_!==.txt new file mode 100644 index 00000000000..d066941aa51 --- /dev/null +++ b/Testing/Data/Compare/Dir2/file3way1_!==.txt @@ -0,0 +1,3 @@ +01234 +BC +56789 diff --git a/Testing/Data/Compare/Dir2/file3way1_!G!.txt b/Testing/Data/Compare/Dir2/file3way1_!G!.txt new file mode 100644 index 00000000000..eb3debb2bc4 --- /dev/null +++ b/Testing/Data/Compare/Dir2/file3way1_!G!.txt @@ -0,0 +1,2 @@ +01234 +56789 diff --git a/Testing/Data/Compare/Dir2/file3way1_!GG.txt b/Testing/Data/Compare/Dir2/file3way1_!GG.txt new file mode 100644 index 00000000000..eb3debb2bc4 --- /dev/null +++ b/Testing/Data/Compare/Dir2/file3way1_!GG.txt @@ -0,0 +1,2 @@ +01234 +56789 diff --git a/Testing/Data/Compare/Dir2/file3way1_=!=.txt b/Testing/Data/Compare/Dir2/file3way1_=!=.txt new file mode 100644 index 00000000000..98b9867df32 --- /dev/null +++ b/Testing/Data/Compare/Dir2/file3way1_=!=.txt @@ -0,0 +1,3 @@ +01234 +B +56789 diff --git a/Testing/Data/Compare/Dir2/file3way1_==!.txt b/Testing/Data/Compare/Dir2/file3way1_==!.txt new file mode 100644 index 00000000000..b5df55af10d --- /dev/null +++ b/Testing/Data/Compare/Dir2/file3way1_==!.txt @@ -0,0 +1,3 @@ +01234 +AB +56789 diff --git a/Testing/Data/Compare/Dir2/file3way1_==G.txt b/Testing/Data/Compare/Dir2/file3way1_==G.txt new file mode 100644 index 00000000000..b5df55af10d --- /dev/null +++ b/Testing/Data/Compare/Dir2/file3way1_==G.txt @@ -0,0 +1,3 @@ +01234 +AB +56789 diff --git a/Testing/Data/Compare/Dir2/file3way1_=G=.txt b/Testing/Data/Compare/Dir2/file3way1_=G=.txt new file mode 100644 index 00000000000..eb3debb2bc4 --- /dev/null +++ b/Testing/Data/Compare/Dir2/file3way1_=G=.txt @@ -0,0 +1,2 @@ +01234 +56789 diff --git a/Testing/Data/Compare/Dir2/file3way1_G!!.txt b/Testing/Data/Compare/Dir2/file3way1_G!!.txt new file mode 100644 index 00000000000..98b9867df32 --- /dev/null +++ b/Testing/Data/Compare/Dir2/file3way1_G!!.txt @@ -0,0 +1,3 @@ +01234 +B +56789 diff --git a/Testing/Data/Compare/Dir2/file3way1_G!G.txt b/Testing/Data/Compare/Dir2/file3way1_G!G.txt new file mode 100644 index 00000000000..98b9867df32 --- /dev/null +++ b/Testing/Data/Compare/Dir2/file3way1_G!G.txt @@ -0,0 +1,3 @@ +01234 +B +56789 diff --git a/Testing/Data/Compare/Dir2/file3way1_G==.txt b/Testing/Data/Compare/Dir2/file3way1_G==.txt new file mode 100644 index 00000000000..d066941aa51 --- /dev/null +++ b/Testing/Data/Compare/Dir2/file3way1_G==.txt @@ -0,0 +1,3 @@ +01234 +BC +56789 diff --git a/Testing/Data/Compare/Dir2/file3way1_GG!.txt b/Testing/Data/Compare/Dir2/file3way1_GG!.txt new file mode 100644 index 00000000000..eb3debb2bc4 --- /dev/null +++ b/Testing/Data/Compare/Dir2/file3way1_GG!.txt @@ -0,0 +1,2 @@ +01234 +56789 diff --git a/Testing/Data/Compare/Dir2/file3way2_!!!.txt b/Testing/Data/Compare/Dir2/file3way2_!!!.txt new file mode 100644 index 00000000000..a35d115266b --- /dev/null +++ b/Testing/Data/Compare/Dir2/file3way2_!!!.txt @@ -0,0 +1,4 @@ +01234 +efghi +B +56789 diff --git a/Testing/Data/Compare/Dir2/file3way2_!!G.txt b/Testing/Data/Compare/Dir2/file3way2_!!G.txt new file mode 100644 index 00000000000..a35d115266b --- /dev/null +++ b/Testing/Data/Compare/Dir2/file3way2_!!G.txt @@ -0,0 +1,4 @@ +01234 +efghi +B +56789 diff --git a/Testing/Data/Compare/Dir2/file3way2_!==.txt b/Testing/Data/Compare/Dir2/file3way2_!==.txt new file mode 100644 index 00000000000..70f8b7a1a14 --- /dev/null +++ b/Testing/Data/Compare/Dir2/file3way2_!==.txt @@ -0,0 +1,4 @@ +01234 +efghi +BC +56789 diff --git a/Testing/Data/Compare/Dir2/file3way2_!G!.txt b/Testing/Data/Compare/Dir2/file3way2_!G!.txt new file mode 100644 index 00000000000..5048ffc4d3d --- /dev/null +++ b/Testing/Data/Compare/Dir2/file3way2_!G!.txt @@ -0,0 +1,3 @@ +01234 +efghi +56789 diff --git a/Testing/Data/Compare/Dir2/file3way2_!GG.txt b/Testing/Data/Compare/Dir2/file3way2_!GG.txt new file mode 100644 index 00000000000..5048ffc4d3d --- /dev/null +++ b/Testing/Data/Compare/Dir2/file3way2_!GG.txt @@ -0,0 +1,3 @@ +01234 +efghi +56789 diff --git a/Testing/Data/Compare/Dir2/file3way2_=!=.txt b/Testing/Data/Compare/Dir2/file3way2_=!=.txt new file mode 100644 index 00000000000..a35d115266b --- /dev/null +++ b/Testing/Data/Compare/Dir2/file3way2_=!=.txt @@ -0,0 +1,4 @@ +01234 +efghi +B +56789 diff --git a/Testing/Data/Compare/Dir2/file3way2_==!.txt b/Testing/Data/Compare/Dir2/file3way2_==!.txt new file mode 100644 index 00000000000..1ec49eb0a04 --- /dev/null +++ b/Testing/Data/Compare/Dir2/file3way2_==!.txt @@ -0,0 +1,4 @@ +01234 +efghi +AB +56789 diff --git a/Testing/Data/Compare/Dir2/file3way2_==G.txt b/Testing/Data/Compare/Dir2/file3way2_==G.txt new file mode 100644 index 00000000000..1ec49eb0a04 --- /dev/null +++ b/Testing/Data/Compare/Dir2/file3way2_==G.txt @@ -0,0 +1,4 @@ +01234 +efghi +AB +56789 diff --git a/Testing/Data/Compare/Dir2/file3way2_=G=.txt b/Testing/Data/Compare/Dir2/file3way2_=G=.txt new file mode 100644 index 00000000000..5048ffc4d3d --- /dev/null +++ b/Testing/Data/Compare/Dir2/file3way2_=G=.txt @@ -0,0 +1,3 @@ +01234 +efghi +56789 diff --git a/Testing/Data/Compare/Dir2/file3way2_G!!.txt b/Testing/Data/Compare/Dir2/file3way2_G!!.txt new file mode 100644 index 00000000000..a35d115266b --- /dev/null +++ b/Testing/Data/Compare/Dir2/file3way2_G!!.txt @@ -0,0 +1,4 @@ +01234 +efghi +B +56789 diff --git a/Testing/Data/Compare/Dir2/file3way2_G!G.txt b/Testing/Data/Compare/Dir2/file3way2_G!G.txt new file mode 100644 index 00000000000..a35d115266b --- /dev/null +++ b/Testing/Data/Compare/Dir2/file3way2_G!G.txt @@ -0,0 +1,4 @@ +01234 +efghi +B +56789 diff --git a/Testing/Data/Compare/Dir2/file3way2_G==.txt b/Testing/Data/Compare/Dir2/file3way2_G==.txt new file mode 100644 index 00000000000..70f8b7a1a14 --- /dev/null +++ b/Testing/Data/Compare/Dir2/file3way2_G==.txt @@ -0,0 +1,4 @@ +01234 +efghi +BC +56789 diff --git a/Testing/Data/Compare/Dir2/file3way2_GG!.txt b/Testing/Data/Compare/Dir2/file3way2_GG!.txt new file mode 100644 index 00000000000..5048ffc4d3d --- /dev/null +++ b/Testing/Data/Compare/Dir2/file3way2_GG!.txt @@ -0,0 +1,3 @@ +01234 +efghi +56789 diff --git a/Testing/Data/Compare/Dir2/file3way3_1.2.1-2.1.txt b/Testing/Data/Compare/Dir2/file3way3_1.2.1-2.1.txt new file mode 100644 index 00000000000..add9cb25447 --- /dev/null +++ b/Testing/Data/Compare/Dir2/file3way3_1.2.1-2.1.txt @@ -0,0 +1,3 @@ +01234 +B 1111 +56789 diff --git a/Testing/Data/Compare/Dir2/file3way3_1.2.1.1.txt b/Testing/Data/Compare/Dir2/file3way3_1.2.1.1.txt new file mode 100644 index 00000000000..962490634c1 --- /dev/null +++ b/Testing/Data/Compare/Dir2/file3way3_1.2.1.1.txt @@ -0,0 +1,3 @@ +01234 +B 2222 +56789 diff --git a/Testing/Data/Compare/Dir2/file3way3_1.2.2-1.3.1.txt b/Testing/Data/Compare/Dir2/file3way3_1.2.2-1.3.1.txt new file mode 100644 index 00000000000..29170313ef7 --- /dev/null +++ b/Testing/Data/Compare/Dir2/file3way3_1.2.2-1.3.1.txt @@ -0,0 +1,6 @@ +01234 +B 1111 +B 2222 +B 3333 +B 5555 +56789 diff --git a/Testing/Data/Compare/Dir2/file3way3_1.2.2-1.3.2.txt b/Testing/Data/Compare/Dir2/file3way3_1.2.2-1.3.2.txt new file mode 100644 index 00000000000..29170313ef7 --- /dev/null +++ b/Testing/Data/Compare/Dir2/file3way3_1.2.2-1.3.2.txt @@ -0,0 +1,6 @@ +01234 +B 1111 +B 2222 +B 3333 +B 5555 +56789 diff --git a/Testing/Data/Compare/Dir2/file3way3_1.2.2-2.2.1.txt b/Testing/Data/Compare/Dir2/file3way3_1.2.2-2.2.1.txt new file mode 100644 index 00000000000..5f3c0dc44bb --- /dev/null +++ b/Testing/Data/Compare/Dir2/file3way3_1.2.2-2.2.1.txt @@ -0,0 +1,5 @@ +01234 +B 1111 +B 2222 +B 3333 +56789 diff --git a/Testing/Data/Compare/Dir2/file3way3_1.2.2-2.2.2.txt b/Testing/Data/Compare/Dir2/file3way3_1.2.2-2.2.2.txt new file mode 100644 index 00000000000..5f3c0dc44bb --- /dev/null +++ b/Testing/Data/Compare/Dir2/file3way3_1.2.2-2.2.2.txt @@ -0,0 +1,5 @@ +01234 +B 1111 +B 2222 +B 3333 +56789 diff --git a/Testing/Data/Compare/Dir3/file3way1_!!!.txt b/Testing/Data/Compare/Dir3/file3way1_!!!.txt new file mode 100644 index 00000000000..0f1b581a674 --- /dev/null +++ b/Testing/Data/Compare/Dir3/file3way1_!!!.txt @@ -0,0 +1,3 @@ +01234 +C +56789 diff --git a/Testing/Data/Compare/Dir3/file3way1_!!G.txt b/Testing/Data/Compare/Dir3/file3way1_!!G.txt new file mode 100644 index 00000000000..eb3debb2bc4 --- /dev/null +++ b/Testing/Data/Compare/Dir3/file3way1_!!G.txt @@ -0,0 +1,2 @@ +01234 +56789 diff --git a/Testing/Data/Compare/Dir3/file3way1_!==.txt b/Testing/Data/Compare/Dir3/file3way1_!==.txt new file mode 100644 index 00000000000..d066941aa51 --- /dev/null +++ b/Testing/Data/Compare/Dir3/file3way1_!==.txt @@ -0,0 +1,3 @@ +01234 +BC +56789 diff --git a/Testing/Data/Compare/Dir3/file3way1_!G!.txt b/Testing/Data/Compare/Dir3/file3way1_!G!.txt new file mode 100644 index 00000000000..0f1b581a674 --- /dev/null +++ b/Testing/Data/Compare/Dir3/file3way1_!G!.txt @@ -0,0 +1,3 @@ +01234 +C +56789 diff --git a/Testing/Data/Compare/Dir3/file3way1_!GG.txt b/Testing/Data/Compare/Dir3/file3way1_!GG.txt new file mode 100644 index 00000000000..eb3debb2bc4 --- /dev/null +++ b/Testing/Data/Compare/Dir3/file3way1_!GG.txt @@ -0,0 +1,2 @@ +01234 +56789 diff --git a/Testing/Data/Compare/Dir3/file3way1_=!=.txt b/Testing/Data/Compare/Dir3/file3way1_=!=.txt new file mode 100644 index 00000000000..f7ee25ffaca --- /dev/null +++ b/Testing/Data/Compare/Dir3/file3way1_=!=.txt @@ -0,0 +1,3 @@ +01234 +AC +56789 diff --git a/Testing/Data/Compare/Dir3/file3way1_==!.txt b/Testing/Data/Compare/Dir3/file3way1_==!.txt new file mode 100644 index 00000000000..0f1b581a674 --- /dev/null +++ b/Testing/Data/Compare/Dir3/file3way1_==!.txt @@ -0,0 +1,3 @@ +01234 +C +56789 diff --git a/Testing/Data/Compare/Dir3/file3way1_==G.txt b/Testing/Data/Compare/Dir3/file3way1_==G.txt new file mode 100644 index 00000000000..eb3debb2bc4 --- /dev/null +++ b/Testing/Data/Compare/Dir3/file3way1_==G.txt @@ -0,0 +1,2 @@ +01234 +56789 diff --git a/Testing/Data/Compare/Dir3/file3way1_=G=.txt b/Testing/Data/Compare/Dir3/file3way1_=G=.txt new file mode 100644 index 00000000000..f7ee25ffaca --- /dev/null +++ b/Testing/Data/Compare/Dir3/file3way1_=G=.txt @@ -0,0 +1,3 @@ +01234 +AC +56789 diff --git a/Testing/Data/Compare/Dir3/file3way1_G!!.txt b/Testing/Data/Compare/Dir3/file3way1_G!!.txt new file mode 100644 index 00000000000..0f1b581a674 --- /dev/null +++ b/Testing/Data/Compare/Dir3/file3way1_G!!.txt @@ -0,0 +1,3 @@ +01234 +C +56789 diff --git a/Testing/Data/Compare/Dir3/file3way1_G!G.txt b/Testing/Data/Compare/Dir3/file3way1_G!G.txt new file mode 100644 index 00000000000..eb3debb2bc4 --- /dev/null +++ b/Testing/Data/Compare/Dir3/file3way1_G!G.txt @@ -0,0 +1,2 @@ +01234 +56789 diff --git a/Testing/Data/Compare/Dir3/file3way1_G==.txt b/Testing/Data/Compare/Dir3/file3way1_G==.txt new file mode 100644 index 00000000000..d066941aa51 --- /dev/null +++ b/Testing/Data/Compare/Dir3/file3way1_G==.txt @@ -0,0 +1,3 @@ +01234 +BC +56789 diff --git a/Testing/Data/Compare/Dir3/file3way1_GG!.txt b/Testing/Data/Compare/Dir3/file3way1_GG!.txt new file mode 100644 index 00000000000..0f1b581a674 --- /dev/null +++ b/Testing/Data/Compare/Dir3/file3way1_GG!.txt @@ -0,0 +1,3 @@ +01234 +C +56789 diff --git a/Testing/Data/Compare/Dir3/file3way2_!!!.txt b/Testing/Data/Compare/Dir3/file3way2_!!!.txt new file mode 100644 index 00000000000..96890c86a9c --- /dev/null +++ b/Testing/Data/Compare/Dir3/file3way2_!!!.txt @@ -0,0 +1,4 @@ +01234 +jklmn +C +56789 diff --git a/Testing/Data/Compare/Dir3/file3way2_!!G.txt b/Testing/Data/Compare/Dir3/file3way2_!!G.txt new file mode 100644 index 00000000000..c78576e1b7e --- /dev/null +++ b/Testing/Data/Compare/Dir3/file3way2_!!G.txt @@ -0,0 +1,3 @@ +01234 +jklmn +56789 diff --git a/Testing/Data/Compare/Dir3/file3way2_!==.txt b/Testing/Data/Compare/Dir3/file3way2_!==.txt new file mode 100644 index 00000000000..4a8d60f0296 --- /dev/null +++ b/Testing/Data/Compare/Dir3/file3way2_!==.txt @@ -0,0 +1,4 @@ +01234 +jklmn +BC +56789 diff --git a/Testing/Data/Compare/Dir3/file3way2_!G!.txt b/Testing/Data/Compare/Dir3/file3way2_!G!.txt new file mode 100644 index 00000000000..96890c86a9c --- /dev/null +++ b/Testing/Data/Compare/Dir3/file3way2_!G!.txt @@ -0,0 +1,4 @@ +01234 +jklmn +C +56789 diff --git a/Testing/Data/Compare/Dir3/file3way2_!GG.txt b/Testing/Data/Compare/Dir3/file3way2_!GG.txt new file mode 100644 index 00000000000..c78576e1b7e --- /dev/null +++ b/Testing/Data/Compare/Dir3/file3way2_!GG.txt @@ -0,0 +1,3 @@ +01234 +jklmn +56789 diff --git a/Testing/Data/Compare/Dir3/file3way2_=!=.txt b/Testing/Data/Compare/Dir3/file3way2_=!=.txt new file mode 100644 index 00000000000..1f01362cb6c --- /dev/null +++ b/Testing/Data/Compare/Dir3/file3way2_=!=.txt @@ -0,0 +1,4 @@ +01234 +jklmn +AC +56789 diff --git a/Testing/Data/Compare/Dir3/file3way2_==!.txt b/Testing/Data/Compare/Dir3/file3way2_==!.txt new file mode 100644 index 00000000000..96890c86a9c --- /dev/null +++ b/Testing/Data/Compare/Dir3/file3way2_==!.txt @@ -0,0 +1,4 @@ +01234 +jklmn +C +56789 diff --git a/Testing/Data/Compare/Dir3/file3way2_==G.txt b/Testing/Data/Compare/Dir3/file3way2_==G.txt new file mode 100644 index 00000000000..c78576e1b7e --- /dev/null +++ b/Testing/Data/Compare/Dir3/file3way2_==G.txt @@ -0,0 +1,3 @@ +01234 +jklmn +56789 diff --git a/Testing/Data/Compare/Dir3/file3way2_=G=.txt b/Testing/Data/Compare/Dir3/file3way2_=G=.txt new file mode 100644 index 00000000000..1f01362cb6c --- /dev/null +++ b/Testing/Data/Compare/Dir3/file3way2_=G=.txt @@ -0,0 +1,4 @@ +01234 +jklmn +AC +56789 diff --git a/Testing/Data/Compare/Dir3/file3way2_G!!.txt b/Testing/Data/Compare/Dir3/file3way2_G!!.txt new file mode 100644 index 00000000000..96890c86a9c --- /dev/null +++ b/Testing/Data/Compare/Dir3/file3way2_G!!.txt @@ -0,0 +1,4 @@ +01234 +jklmn +C +56789 diff --git a/Testing/Data/Compare/Dir3/file3way2_G!G.txt b/Testing/Data/Compare/Dir3/file3way2_G!G.txt new file mode 100644 index 00000000000..c78576e1b7e --- /dev/null +++ b/Testing/Data/Compare/Dir3/file3way2_G!G.txt @@ -0,0 +1,3 @@ +01234 +jklmn +56789 diff --git a/Testing/Data/Compare/Dir3/file3way2_G==.txt b/Testing/Data/Compare/Dir3/file3way2_G==.txt new file mode 100644 index 00000000000..4a8d60f0296 --- /dev/null +++ b/Testing/Data/Compare/Dir3/file3way2_G==.txt @@ -0,0 +1,4 @@ +01234 +jklmn +BC +56789 diff --git a/Testing/Data/Compare/Dir3/file3way2_GG!.txt b/Testing/Data/Compare/Dir3/file3way2_GG!.txt new file mode 100644 index 00000000000..96890c86a9c --- /dev/null +++ b/Testing/Data/Compare/Dir3/file3way2_GG!.txt @@ -0,0 +1,4 @@ +01234 +jklmn +C +56789 diff --git a/Testing/Data/Compare/Dir3/file3way3_1.2.1-2.1.txt b/Testing/Data/Compare/Dir3/file3way3_1.2.1-2.1.txt new file mode 100644 index 00000000000..d806d57f5a4 --- /dev/null +++ b/Testing/Data/Compare/Dir3/file3way3_1.2.1-2.1.txt @@ -0,0 +1,5 @@ +01234 +C 1111 +C 2222 +C 3333 +56789 diff --git a/Testing/Data/Compare/Dir3/file3way3_1.2.1.1.txt b/Testing/Data/Compare/Dir3/file3way3_1.2.1.1.txt new file mode 100644 index 00000000000..1da2435b815 --- /dev/null +++ b/Testing/Data/Compare/Dir3/file3way3_1.2.1.1.txt @@ -0,0 +1,4 @@ +01234 +C 1111 +C 2222 +56789 diff --git a/Testing/Data/Compare/Dir3/file3way3_1.2.2-1.3.1.txt b/Testing/Data/Compare/Dir3/file3way3_1.2.2-1.3.1.txt new file mode 100644 index 00000000000..ac933d6ee57 --- /dev/null +++ b/Testing/Data/Compare/Dir3/file3way3_1.2.2-1.3.1.txt @@ -0,0 +1,6 @@ +01234 +C 2222 +C 3333 +C 4444 +C 5555 +56789 diff --git a/Testing/Data/Compare/Dir3/file3way3_1.2.2-1.3.2.txt b/Testing/Data/Compare/Dir3/file3way3_1.2.2-1.3.2.txt new file mode 100644 index 00000000000..0e9af1c2a75 --- /dev/null +++ b/Testing/Data/Compare/Dir3/file3way3_1.2.2-1.3.2.txt @@ -0,0 +1,5 @@ +01234 +C 2222 +C 3333 +C 5555 +56789 diff --git a/Testing/Data/Compare/Dir3/file3way3_1.2.2-2.2.1.txt b/Testing/Data/Compare/Dir3/file3way3_1.2.2-2.2.1.txt new file mode 100644 index 00000000000..75fdd6829a2 --- /dev/null +++ b/Testing/Data/Compare/Dir3/file3way3_1.2.2-2.2.1.txt @@ -0,0 +1,5 @@ +01234 +C 2222 +C 3333 +C 4444 +56789 diff --git a/Testing/Data/Compare/Dir3/file3way3_1.2.2-2.2.2.txt b/Testing/Data/Compare/Dir3/file3way3_1.2.2-2.2.2.txt new file mode 100644 index 00000000000..b6ca0c9fef5 --- /dev/null +++ b/Testing/Data/Compare/Dir3/file3way3_1.2.2-2.2.2.txt @@ -0,0 +1,4 @@ +01234 +C 2222 +C 3333 +56789 diff --git a/Testing/GoogleTest/StringDiffs/stringdiffs_test.cpp b/Testing/GoogleTest/StringDiffs/stringdiffs_test.cpp index b301932c30e..69ad20d6f3b 100644 --- a/Testing/GoogleTest/StringDiffs/stringdiffs_test.cpp +++ b/Testing/GoogleTest/StringDiffs/stringdiffs_test.cpp @@ -723,4 +723,113 @@ namespace } + TEST_F(StringDiffsTest, CompareCase) + { + int result; + result = strdiff::Compare(_T("abc"), _T("abc"), false, true, 0, false); + EXPECT_EQ(0, result); + result = strdiff::Compare(_T("ABC"), _T("abc"), false, true, 0, false); + EXPECT_EQ(0, result); + result = strdiff::Compare(_T("abc"), _T("ABC"), false, true, 0, false); + EXPECT_EQ(0, result); + result = strdiff::Compare(_T("aBC"), _T("Bcd"), false, true, 0, false); + EXPECT_EQ(1, result); + result = strdiff::Compare(_T("Bcd"), _T("aBC"), false, true, 0, false); + EXPECT_EQ(-1, result); + } + + TEST_F(StringDiffsTest, CompareWhiltespaces1) + { + int result; + result = strdiff::Compare(_T("abc def"), _T("abc def"), true, true, 1, false); + EXPECT_EQ(0, result); + result = strdiff::Compare(_T("abc def"), _T("abc def"), true, true, 1, false); + EXPECT_EQ(0, result); + result = strdiff::Compare(_T("abc def"), _T("abc def"), true, true, 1, false); + EXPECT_EQ(0, result); + result = strdiff::Compare(_T("abc \tdef"), _T("abc def"), true, true, 1, false); + EXPECT_EQ(0, result); + result = strdiff::Compare(_T("abc def"), _T("abc \tdef"), true, true, 1, false); + EXPECT_EQ(0, result); + result = strdiff::Compare(_T("abc def"), _T("abcdef"), true, true, 1, false); + EXPECT_EQ(1, result); + result = strdiff::Compare(_T("abcdef"), _T("abc def"), true, true, 1, false); + EXPECT_EQ(-1, result); + } + + TEST_F(StringDiffsTest, CompareWhiltespaces2) + { + int result; + result = strdiff::Compare(_T("abc def"), _T("abc def"), true, true, 2, false); + EXPECT_EQ(0, result); + result = strdiff::Compare(_T("abc def"), _T("abc def"), true, true, 2, false); + EXPECT_EQ(0, result); + result = strdiff::Compare(_T("abc def"), _T("abc def"), true, true, 2, false); + EXPECT_EQ(0, result); + result = strdiff::Compare(_T("abc \tdef"), _T("abc def"), true, true, 2, false); + EXPECT_EQ(0, result); + result = strdiff::Compare(_T("abc def"), _T("abc \tdef"), true, true, 2, false); + EXPECT_EQ(0, result); + result = strdiff::Compare(_T("abc def"), _T("abcdef"), true, true, 2, false); + EXPECT_EQ(0, result); + result = strdiff::Compare(_T("abcdef"), _T("abc def"), true, true, 2, false); + EXPECT_EQ(0, result); + result = strdiff::Compare(_T("abc\tdef"), _T("abcdef"), true, true, 2, false); + EXPECT_EQ(0, result); + result = strdiff::Compare(_T("abcdef"), _T("abc\tdef"), true, true, 2, false); + EXPECT_EQ(0, result); + result = strdiff::Compare(_T("abcde"), _T("abcdef"), true, true, 2, false); + EXPECT_EQ(1, result); + result = strdiff::Compare(_T("abcdef"), _T("abcde"), true, true, 2, false); + EXPECT_EQ(-1, result); + } + + TEST_F(StringDiffsTest, CompareEOL) + { + int result; + result = strdiff::Compare(_T("abc\r\n"), _T("abc\r\n"), true, false, 0, false); + EXPECT_EQ(0, result); + result = strdiff::Compare(_T("abc\r\n"), _T("abc\r"), true, false, 0, false); + EXPECT_EQ(0, result); + result = strdiff::Compare(_T("abc\r"), _T("abc\r\n"), true, false, 0, false); + EXPECT_EQ(0, result); + result = strdiff::Compare(_T("abc\r\n"), _T("abc\n"), true, false, 0, false); + EXPECT_EQ(0, result); + result = strdiff::Compare(_T("abc\n"), _T("abc\r\n"), true, false, 0, false); + EXPECT_EQ(0, result); + result = strdiff::Compare(_T("abc\n"), _T("abc\r"), true, false, 0, false); + EXPECT_EQ(0, result); + result = strdiff::Compare(_T("abc\r"), _T("abc\n"), true, false, 0, false); + EXPECT_EQ(0, result); + result = strdiff::Compare(String(_T("abc\r\0"), 5), _T("abc\r\n"), true, false, 0, false); + EXPECT_EQ(-1, result); + result = strdiff::Compare(_T("abc\r\n"), String(_T("abc\r\0"), 5), true, false, 0, false); + EXPECT_EQ(1, result); + } + + TEST_F(StringDiffsTest, CompareNumbers) + { + int result; + result = strdiff::Compare(_T("1a"), _T("2a"), true, true, 0, true); + EXPECT_EQ(0, result); + result = strdiff::Compare(_T("a123"), _T("a234"), true, true, 0, true); + EXPECT_EQ(0, result); + result = strdiff::Compare(_T("a"), _T("123a"), true, true, 0, true); + EXPECT_EQ(0, result); + result = strdiff::Compare(_T("123a"), _T("a"), true, true, 0, true); + EXPECT_EQ(0, result); + result = strdiff::Compare(_T("123"), _T(""), true, true, 0, true); + EXPECT_EQ(0, result); + result = strdiff::Compare(_T(""), _T("123"), true, true, 0, true); + EXPECT_EQ(0, result); + result = strdiff::Compare(_T("123a"), _T("123b"), true, true, 0, true); + EXPECT_EQ(1, result); + result = strdiff::Compare(_T("123b"), _T("123a"), true, true, 0, true); + EXPECT_EQ(-1, result); + result = strdiff::Compare(_T("a123"), _T("b123"), true, true, 0, true); + EXPECT_EQ(1, result); + result = strdiff::Compare(_T("b123"), _T("a123"), true, true, 0, true); + EXPECT_EQ(-1, result); + } + } // namespace