Replace diff_match_patch with dtl library for performing text diffs

Replacement is done for license reasons: diff_match_patch is
distributed under Apache-2.0 license which is not GPLv2-compatible.
This commit is contained in:
Dmitri Ovodok 2018-11-06 14:04:11 +02:00
parent 3fdfab33f4
commit e1986bd86b
21 changed files with 1618 additions and 4132 deletions

View File

@ -716,7 +716,7 @@ endif (NOT MSVC)
##
subdirs(
mscore awl bww2mxml share midi audiofile fluid libmscore synthesizer
effects thirdparty/rtf2html thirdparty/diff thirdparty/beatroot
effects thirdparty/rtf2html thirdparty/beatroot
thirdparty/qzip thirdparty/kQOAuth
)

View File

@ -39,7 +39,7 @@ else (NOT MSVC)
endif (NOT MSVC)
include_directories(
${PROJECT_SOURCE_DIR}/thirdparty/diff
${PROJECT_SOURCE_DIR}/thirdparty/dtl
)
add_library (
@ -106,10 +106,6 @@ add_library (
scorediff.cpp
)
target_link_libraries(libmscore
diff_match_patch
)
##
## Code coverage. Only affects DEBUG builds.
##

View File

@ -18,7 +18,7 @@
#include "staff.h"
#include "xml.h"
#include "diff_match_patch.h"
#include "dtl/dtl.hpp"
#include <algorithm>
#include <utility>
@ -29,7 +29,7 @@ namespace Ms {
// MscxModeDiff
//---------------------------------------------------------
class MscxModeDiff : private ::diff_match_patch {
class MscxModeDiff {
static constexpr const char* tagRegExpStr = "</?(?<name>[A-z_][A-z_0-9\\-.:]*)( [A-z_0-9\\-.:\\s=\"]*)?/?>";
const QRegularExpression tagRegExp;
@ -42,6 +42,8 @@ class MscxModeDiff : private ::diff_match_patch {
Tag(int l, TagType t, const QString& n) : line(l), type(t), name(n) {}
};
static DiffType fromDtlDiffType(dtl::edit_t dtlType);
void adjustSemanticsMscx(std::vector<TextDiff>&);
int adjustSemanticsMscxOneDiff(std::vector<TextDiff>& diffs, int index);
int nextDiffOnShiftIndex(const std::vector<TextDiff>& diffs, int index, bool down);
@ -91,84 +93,86 @@ MscxModeDiff::MscxModeDiff()
: tagRegExp(tagRegExpStr)
{}
//---------------------------------------------------------
// MscxModeDiff::fromDtlDiffType
//---------------------------------------------------------
DiffType MscxModeDiff::fromDtlDiffType(dtl::edit_t dtlType)
{
switch(dtlType) {
case dtl::SES_DELETE:
return DiffType::DELETE;
case dtl::SES_COMMON:
return DiffType::EQUAL;
case dtl::SES_ADD:
return DiffType::INSERT;
}
Q_ASSERT(false); // dtlType must have one of the values handled above.
return DiffType::EQUAL;
}
//---------------------------------------------------------
// MscxModeDiff::lineModeDiff
//---------------------------------------------------------
std::vector<TextDiff> MscxModeDiff::lineModeDiff(const QString& s1, const QString& s2)
{
QList<QVariant> l = diff_linesToChars(s1, s2);
QList<::Diff> diffLines = diff_main(l[0].toString(), l[1].toString(), false);
// type declarations for dtl library
typedef QStringRef elem;
typedef std::pair<elem, dtl::elemInfo> sesElem;
typedef std::vector<sesElem> sesElemVec;
std::vector<TextDiff> diffs(diffLines.size());
// QVector does not contain range constructor used inside dtl
// so we have to convert to std::vector.
std::vector<QStringRef> lines1 = s1.splitRef('\n').toStdVector();
std::vector<QStringRef> lines2 = s2.splitRef('\n').toStdVector();
dtl::Diff<QStringRef, std::vector<QStringRef>> diff(lines1, lines2);
diff.compose();
const sesElemVec changes = diff.getSes().getSequence();
std::vector<TextDiff> diffs;
int line[2][2] {{1, 1}, {1, 1}}; // for correct assigning line numbers to
// DELETE and INSERT diffs we need to
// count lines separately for these diff
// types (EQUAL can use both counters).
for (int i = 0; i < diffLines.size(); ++i) {
TextDiff& d = diffs[i];
::Diff& ld = diffLines[i];
const int iThis = (ld.operation == DELETE) ? 0 : 1; // for EQUAL doesn't matter
const int iOther = (iThis == 1) ? 0 : 1;
if (ld.operation == EQUAL)
line[iThis][iOther] = line[iOther][iOther];
for (const sesElem& ch : changes) {
DiffType type = fromDtlDiffType(ch.second.type);
const int iThis = (type == DiffType::DELETE) ? 0 : 1; // for EQUAL doesn't matter
d.start[0] = line[iThis][0];
d.start[1] = line[iThis][1];
// After diff_linesToChars call each line is represented by one
// Unicode character, so counting them we can count differing lines
const int lines = ld.text.size();
switch (ld.operation) {
case DELETE:
line[iThis][iThis] += lines;
d.type = DiffType::DELETE;
break;
case INSERT:
line[iThis][iThis] += lines;
d.type = DiffType::INSERT;
break;
case EQUAL:
line[iThis][0] += lines;
line[iThis][1] += lines;
d.type = DiffType::EQUAL;
break;
if (diffs.empty() || diffs.back().type != type) {
if (!diffs.empty()) {
// sync line numbers
DiffType prevType = diffs.back().type;
const int prevThis = (prevType == DiffType::DELETE) ? 0 : 1;
const int prevOther = (prevThis == 1) ? 0 : 1;
if (prevType == DiffType::EQUAL)
std::copy_n(line[prevThis], 2, line[prevOther]);
else
line[prevThis][prevOther] = line[prevOther][prevOther];
if (type == DiffType::EQUAL) {
const int iOther = (iThis == 1) ? 0 : 1;
line[iThis][iOther] = line[iOther][iOther];
}
}
diffs.emplace_back();
TextDiff& d = diffs.back();
d.type = type;
std::copy_n(line[iThis], 2, d.start);
d.end[0] = line[iThis][0] - 1; // equal line numbers would mean an actual change in that line.
d.end[1] = line[iThis][1] - 1;
}
d.end[0] = line[iThis][0] - 1;
d.end[1] = line[iThis][1] - 1;
// sync line numbers
switch(ld.operation) {
case DELETE:
case INSERT:
line[iThis][iOther] = line[iOther][iOther];
// Do not update line[iOther], if the next diff has
// other type (but not EQUAL), old values are correct.
break;
case EQUAL:
std::copy(line[iThis], line[iThis] + 2, line[iOther]);
break;
}
}
// Update text in diffs to match actual content of MSCX code
diff_charsToLines(diffLines, l[2].toStringList());
for (int i = 0; i < diffLines.size(); ++i) {
TextDiff& diff = diffs[i];
QString& text = diffLines[i].text;
switch(diff.type) {
case DiffType::DELETE:
diff.text[0] = text;
break;
case DiffType::INSERT:
diff.text[1] = text;
break;
case DiffType::EQUAL:
diff.text[0] = text;
diff.text[1] = text;
break;
default:
break;
TextDiff& d = diffs.back();
d.end[iThis] = (line[iThis][iThis]++);
d.text[iThis].append(ch.first).append('\n');
if (type == DiffType::EQUAL) {
const int iOther = (iThis == 1) ? 0 : 1;
d.end[iOther] = (line[iThis][iOther]++);
d.text[iOther].append(ch.first).append('\n');
}
}

View File

@ -446,7 +446,6 @@ endif (MSVC)
target_link_libraries(mscore
awl
diff_match_patch
bww
rtf2html
${QTSINGLEAPPLICATION_LIBRARIES}

View File

@ -83,7 +83,6 @@
#include "omr/importpdf.h"
#endif
#include "diff/diff_match_patch.h"
#include "libmscore/chordlist.h"
#include "libmscore/mscore.h"
#include "thirdparty/qzip/qzipreader_p.h"

View File

@ -1,65 +0,0 @@
#=============================================================================
# MusE
# Linux Music Editor
# $Id:$
#
# Copyright (C) 2010 by Werner Schweer and others
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#=============================================================================
include (${PROJECT_SOURCE_DIR}/build/gch.cmake)
if (APPLE)
file(GLOB_RECURSE INCS "*.h")
else (APPLE)
set(INCS "")
endif (APPLE)
if (NOT MSVC)
set(_all_h_file "${PROJECT_BINARY_DIR}/all.h")
else (NOT MSVC)
set(_all_h_file "${PROJECT_SOURCE_DIR}/all.h")
endif (NOT MSVC)
add_library(diff_match_patch STATIC
diff_match_patch.cpp
${_all_h_file}
${PCH}
${INCS}
)
if (NOT MSVC)
set_target_properties (
diff_match_patch
PROPERTIES
COMPILE_FLAGS "${PCH_INCLUDE} -g -Wall -Wextra -Winvalid-pch"
)
else (NOT MSVC)
set_target_properties (
diff_match_patch
PROPERTIES
COMPILE_FLAGS "${PCH_INCLUDE}"
)
endif (NOT MSVC)
xcode_pch(diff_match_patch all)
# Use MSVC pre-compiled headers
vstudio_pch( diff_match_patch )
# MSVC does not depend on mops1 & mops2 for PCH
if (NOT MSVC)
ADD_DEPENDENCIES(diff_match_patch mops1)
ADD_DEPENDENCIES(diff_match_patch mops2)
endif (NOT MSVC)

View File

@ -1,11 +0,0 @@
Diff, Match and Patch Library
http://code.google.com/p/google-diff-match-patch/
Neil Fraser
C++: (ported by Mike Slemmer)
* diff_match_patch.pro
* diff_match_patch.h
* diff_match_patch.cpp
* diff_match_patch_test.h
* diff_match_patch_test.cpp

File diff suppressed because it is too large Load Diff

View File

@ -1,628 +0,0 @@
/*
* Copyright 2008 Google Inc. All Rights Reserved.
* Author: fraser@google.com (Neil Fraser)
* Author: mikeslemmer@gmail.com (Mike Slemmer)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Diff Match and Patch
* http://code.google.com/p/google-diff-match-patch/
*/
#ifndef DIFF_MATCH_PATCH_H
#define DIFF_MATCH_PATCH_H
#include <ctime>
/*
* Functions for diff, match and patch.
* Computes the difference between two texts to create a patch.
* Applies the patch onto another text, allowing for errors.
*
* @author fraser@google.com (Neil Fraser)
*
* Qt/C++ port by mikeslemmer@gmail.com (Mike Slemmer):
*
* Code known to compile and run with Qt 4.3 through Qt 4.7.
*
* Here is a trivial sample program which works properly when linked with this
* library:
*
#include <QtCore>
#include <QString>
#include <QList>
#include <QMap>
#include <QVariant>
#include "diff_match_patch.h"
int main(int argc, char **argv) {
diff_match_patch dmp;
QString str1 = QString("First string in diff");
QString str2 = QString("Second string in diff");
QString strPatch = dmp.patch_toText(dmp.patch_make(str1, str2));
QPair<QString, QVector<bool> > out
= dmp.patch_apply(dmp.patch_fromText(strPatch), str1);
QString strResult = out.first;
// here, strResult will equal str2 above.
return 0;
}
*/
/**-
* The data structure representing a diff is a Linked list of Diff objects:
* {Diff(Operation.DELETE, "Hello"), Diff(Operation.INSERT, "Goodbye"),
* Diff(Operation.EQUAL, " world.")}
* which means: delete "Hello", add "Goodbye" and keep " world."
*/
#undef DELETE
#undef INSERT
#undef EQUAL
enum Operation {
DELETE, INSERT, EQUAL
};
/**
* Class representing one diff operation.
*/
class Diff {
public:
Operation operation;
// One of: INSERT, DELETE or EQUAL.
QString text;
// The text associated with this diff operation.
/**
* Constructor. Initializes the diff with the provided values.
* @param operation One of INSERT, DELETE or EQUAL.
* @param text The text being applied.
*/
Diff(Operation _operation, const QString &_text);
Diff();
inline bool isNull() const;
QString toString() const;
bool operator==(const Diff &d) const;
bool operator!=(const Diff &d) const;
static QString strOperation(Operation op);
};
/**
* Class representing one patch operation.
*/
class Patch {
public:
QList<Diff> diffs;
int start1;
int start2;
int length1;
int length2;
/**
* Constructor. Initializes with an empty list of diffs.
*/
Patch();
bool isNull() const;
QString toString();
};
/**
* Class containing the diff, match and patch methods.
* Also contains the behaviour settings.
*/
class diff_match_patch {
friend class diff_match_patch_test;
public:
// Defaults.
// Set these on your diff_match_patch instance to override the defaults.
// Number of seconds to map a diff before giving up (0 for infinity).
float Diff_Timeout;
// Cost of an empty edit operation in terms of edit characters.
short Diff_EditCost;
// At what point is no match declared (0.0 = perfection, 1.0 = very loose).
float Match_Threshold;
// How far to search for a match (0 = exact location, 1000+ = broad match).
// A match this many characters away from the expected location will add
// 1.0 to the score (0.0 is a perfect match).
int Match_Distance;
// When deleting a large block of text (over ~64 characters), how close does
// the contents have to match the expected contents. (0.0 = perfection,
// 1.0 = very loose). Note that Match_Threshold controls how closely the
// end points of a delete need to match.
float Patch_DeleteThreshold;
// Chunk size for context length.
short Patch_Margin;
// The number of bits in an int.
short Match_MaxBits;
public:
diff_match_patch();
// DIFF FUNCTIONS
/**
* Find the differences between two texts.
* Run a faster slightly less optimal diff.
* This method allows the 'checklines' of diff_main() to be optional.
* Most of the time checklines is wanted, so default to true.
* @param text1 Old string to be diffed.
* @param text2 New string to be diffed.
* @return Linked List of Diff objects.
*/
QList<Diff> diff_main(const QString &text1, const QString &text2);
/**
* Find the differences between two texts.
* @param text1 Old string to be diffed.
* @param text2 New string to be diffed.
* @param checklines Speedup flag. If false, then don't run a
* line-level diff first to identify the changed areas.
* If true, then run a faster slightly less optimal diff.
* @return Linked List of Diff objects.
*/
QList<Diff> diff_main(const QString &text1, const QString &text2, bool checklines);
/**
* Find the differences between two texts. Simplifies the problem by
* stripping any common prefix or suffix off the texts before diffing.
* @param text1 Old string to be diffed.
* @param text2 New string to be diffed.
* @param checklines Speedup flag. If false, then don't run a
* line-level diff first to identify the changed areas.
* If true, then run a faster slightly less optimal diff.
* @param deadline Time when the diff should be complete by. Used
* internally for recursive calls. Users should set DiffTimeout instead.
* @return Linked List of Diff objects.
*/
private:
QList<Diff> diff_main(const QString &text1, const QString &text2, bool checklines, clock_t deadline);
/**
* Find the differences between two texts. Assumes that the texts do not
* have any common prefix or suffix.
* @param text1 Old string to be diffed.
* @param text2 New string to be diffed.
* @param checklines Speedup flag. If false, then don't run a
* line-level diff first to identify the changed areas.
* If true, then run a faster slightly less optimal diff.
* @param deadline Time when the diff should be complete by.
* @return Linked List of Diff objects.
*/
private:
QList<Diff> diff_compute(QString text1, QString text2, bool checklines, clock_t deadline);
/**
* Do a quick line-level diff on both strings, then rediff the parts for
* greater accuracy.
* This speedup can produce non-minimal diffs.
* @param text1 Old string to be diffed.
* @param text2 New string to be diffed.
* @param deadline Time when the diff should be complete by.
* @return Linked List of Diff objects.
*/
private:
QList<Diff> diff_lineMode(QString text1, QString text2, clock_t deadline);
/**
* Find the 'middle snake' of a diff, split the problem in two
* and return the recursively constructed diff.
* See Myers 1986 paper: An O(ND) Difference Algorithm and Its Variations.
* @param text1 Old string to be diffed.
* @param text2 New string to be diffed.
* @return Linked List of Diff objects.
*/
protected:
QList<Diff> diff_bisect(const QString &text1, const QString &text2, clock_t deadline);
/**
* Given the location of the 'middle snake', split the diff in two parts
* and recurse.
* @param text1 Old string to be diffed.
* @param text2 New string to be diffed.
* @param x Index of split point in text1.
* @param y Index of split point in text2.
* @param deadline Time at which to bail if not yet complete.
* @return LinkedList of Diff objects.
*/
private:
QList<Diff> diff_bisectSplit(const QString &text1, const QString &text2, int x, int y, clock_t deadline);
/**
* Split two texts into a list of strings. Reduce the texts to a string of
* hashes where each Unicode character represents one line.
* @param text1 First string.
* @param text2 Second string.
* @return Three element Object array, containing the encoded text1, the
* encoded text2 and the List of unique strings. The zeroth element
* of the List of unique strings is intentionally blank.
*/
protected:
QList<QVariant> diff_linesToChars(const QString &text1, const QString &text2); // return elems 0 and 1 are QString, elem 2 is QStringList
/**
* Split a text into a list of strings. Reduce the texts to a string of
* hashes where each Unicode character represents one line.
* @param text String to encode.
* @param lineArray List of unique strings.
* @param lineHash Map of strings to indices.
* @return Encoded string.
*/
private:
QString diff_linesToCharsMunge(const QString &text, QStringList &lineArray,
QMap<QString, int> &lineHash);
/**
* Rehydrate the text in a diff from a string of line hashes to real lines of
* text.
* @param diffs LinkedList of Diff objects.
* @param lineArray List of unique strings.
*/
protected: // changed for usage in scorediff
void diff_charsToLines(QList<Diff> &diffs, const QStringList &lineArray);
/**
* Determine the common prefix of two strings.
* @param text1 First string.
* @param text2 Second string.
* @return The number of characters common to the start of each string.
*/
public:
int diff_commonPrefix(const QString &text1, const QString &text2);
/**
* Determine the common suffix of two strings.
* @param text1 First string.
* @param text2 Second string.
* @return The number of characters common to the end of each string.
*/
public:
int diff_commonSuffix(const QString &text1, const QString &text2);
/**
* Determine if the suffix of one string is the prefix of another.
* @param text1 First string.
* @param text2 Second string.
* @return The number of characters common to the end of the first
* string and the start of the second string.
*/
protected:
int diff_commonOverlap(const QString &text1, const QString &text2);
/**
* Do the two texts share a substring which is at least half the length of
* the longer text?
* This speedup can produce non-minimal diffs.
* @param text1 First string.
* @param text2 Second string.
* @return Five element String array, containing the prefix of text1, the
* suffix of text1, the prefix of text2, the suffix of text2 and the
* common middle. Or null if there was no match.
*/
protected:
QStringList diff_halfMatch(const QString &text1, const QString &text2);
/**
* Does a substring of shorttext exist within longtext such that the
* substring is at least half the length of longtext?
* @param longtext Longer string.
* @param shorttext Shorter string.
* @param i Start index of quarter length substring within longtext.
* @return Five element String array, containing the prefix of longtext, the
* suffix of longtext, the prefix of shorttext, the suffix of shorttext
* and the common middle. Or null if there was no match.
*/
private:
QStringList diff_halfMatchI(const QString &longtext, const QString &shorttext, int i);
/**
* Reduce the number of edits by eliminating semantically trivial equalities.
* @param diffs LinkedList of Diff objects.
*/
public:
void diff_cleanupSemantic(QList<Diff> &diffs);
/**
* Look for single edits surrounded on both sides by equalities
* which can be shifted sideways to align the edit to a word boundary.
* e.g: The c<ins>at c</ins>ame. -> The <ins>cat </ins>came.
* @param diffs LinkedList of Diff objects.
*/
public:
void diff_cleanupSemanticLossless(QList<Diff> &diffs);
/**
* Given two strings, compute a score representing whether the internal
* boundary falls on logical boundaries.
* Scores range from 5 (best) to 0 (worst).
* @param one First string.
* @param two Second string.
* @return The score.
*/
private:
int diff_cleanupSemanticScore(const QString &one, const QString &two);
/**
* Reduce the number of edits by eliminating operationally trivial equalities.
* @param diffs LinkedList of Diff objects.
*/
public:
void diff_cleanupEfficiency(QList<Diff> &diffs);
/**
* Reorder and merge like edit sections. Merge equalities.
* Any edit section can move as long as it doesn't cross an equality.
* @param diffs LinkedList of Diff objects.
*/
public:
void diff_cleanupMerge(QList<Diff> &diffs);
/**
* loc is a location in text1, compute and return the equivalent location in
* text2.
* e.g. "The cat" vs "The big cat", 1->1, 5->8
* @param diffs LinkedList of Diff objects.
* @param loc Location within text1.
* @return Location within text2.
*/
public:
int diff_xIndex(const QList<Diff> &diffs, int loc);
/**
* Convert a Diff list into a pretty HTML report.
* @param diffs LinkedList of Diff objects.
* @return HTML representation.
*/
public:
QString diff_prettyHtml(const QList<Diff> &diffs);
/**
* Compute and return the source text (all equalities and deletions).
* @param diffs LinkedList of Diff objects.
* @return Source text.
*/
public:
QString diff_text1(const QList<Diff> &diffs);
/**
* Compute and return the destination text (all equalities and insertions).
* @param diffs LinkedList of Diff objects.
* @return Destination text.
*/
public:
QString diff_text2(const QList<Diff> &diffs);
/**
* Compute the Levenshtein distance; the number of inserted, deleted or
* substituted characters.
* @param diffs LinkedList of Diff objects.
* @return Number of changes.
*/
public:
int diff_levenshtein(const QList<Diff> &diffs);
/**
* Crush the diff into an encoded string which describes the operations
* required to transform text1 into text2.
* E.g. =3\t-2\t+ing -> Keep 3 chars, delete 2 chars, insert 'ing'.
* Operations are tab-separated. Inserted text is escaped using %xx notation.
* @param diffs Array of diff tuples.
* @return Delta text.
*/
public:
QString diff_toDelta(const QList<Diff> &diffs);
/**
* Given the original text1, and an encoded string which describes the
* operations required to transform text1 into text2, compute the full diff.
* @param text1 Source string for the diff.
* @param delta Delta text.
* @return Array of diff tuples or null if invalid.
* @throws QString If invalid input.
*/
public:
QList<Diff> diff_fromDelta(const QString &text1, const QString &delta);
// MATCH FUNCTIONS
/**
* Locate the best instance of 'pattern' in 'text' near 'loc'.
* Returns -1 if no match found.
* @param text The text to search.
* @param pattern The pattern to search for.
* @param loc The location to search around.
* @return Best match index or -1.
*/
public:
int match_main(const QString &text, const QString &pattern, int loc);
/**
* Locate the best instance of 'pattern' in 'text' near 'loc' using the
* Bitap algorithm. Returns -1 if no match found.
* @param text The text to search.
* @param pattern The pattern to search for.
* @param loc The location to search around.
* @return Best match index or -1.
*/
protected:
int match_bitap(const QString &text, const QString &pattern, int loc);
/**
* Compute and return the score for a match with e errors and x location.
* @param e Number of errors in match.
* @param x Location of match.
* @param loc Expected location of match.
* @param pattern Pattern being sought.
* @return Overall score for match (0.0 = good, 1.0 = bad).
*/
private:
double match_bitapScore(int e, int x, int loc, const QString &pattern);
/**
* Initialise the alphabet for the Bitap algorithm.
* @param pattern The text to encode.
* @return Hash of character locations.
*/
protected:
QMap<QChar, int> match_alphabet(const QString &pattern);
// PATCH FUNCTIONS
/**
* Increase the context until it is unique,
* but don't let the pattern expand beyond Match_MaxBits.
* @param patch The patch to grow.
* @param text Source text.
*/
protected:
void patch_addContext(Patch &patch, const QString &text);
/**
* Compute a list of patches to turn text1 into text2.
* A set of diffs will be computed.
* @param text1 Old text.
* @param text2 New text.
* @return LinkedList of Patch objects.
*/
public:
QList<Patch> patch_make(const QString &text1, const QString &text2);
/**
* Compute a list of patches to turn text1 into text2.
* text1 will be derived from the provided diffs.
* @param diffs Array of diff tuples for text1 to text2.
* @return LinkedList of Patch objects.
*/
public:
QList<Patch> patch_make(const QList<Diff> &diffs);
/**
* Compute a list of patches to turn text1 into text2.
* text2 is ignored, diffs are the delta between text1 and text2.
* @param text1 Old text.
* @param text2 Ignored.
* @param diffs Array of diff tuples for text1 to text2.
* @return LinkedList of Patch objects.
* @deprecated Prefer patch_make(const QString &text1, const QList<Diff> &diffs).
*/
public:
QList<Patch> patch_make(const QString &text1, const QString &text2, const QList<Diff> &diffs);
/**
* Compute a list of patches to turn text1 into text2.
* text2 is not provided, diffs are the delta between text1 and text2.
* @param text1 Old text.
* @param diffs Array of diff tuples for text1 to text2.
* @return LinkedList of Patch objects.
*/
public:
QList<Patch> patch_make(const QString &text1, const QList<Diff> &diffs);
/**
* Given an array of patches, return another array that is identical.
* @param patches Array of patch objects.
* @return Array of patch objects.
*/
public:
QList<Patch> patch_deepCopy(QList<Patch> &patches);
/**
* Merge a set of patches onto the text. Return a patched text, as well
* as an array of true/false values indicating which patches were applied.
* @param patches Array of patch objects.
* @param text Old text.
* @return Two element Object array, containing the new text and an array of
* boolean values.
*/
public:
QPair<QString,QVector<bool> > patch_apply(QList<Patch> &patches, const QString &text);
/**
* Add some padding on text start and end so that edges can match something.
* Intended to be called only from within patch_apply.
* @param patches Array of patch objects.
* @return The padding string added to each side.
*/
public:
QString patch_addPadding(QList<Patch> &patches);
/**
* Look through the patches and break up any which are longer than the
* maximum limit of the match algorithm.
* Intended to be called only from within patch_apply.
* @param patches LinkedList of Patch objects.
*/
public:
void patch_splitMax(QList<Patch> &patches);
/**
* Take a list of patches and return a textual representation.
* @param patches List of Patch objects.
* @return Text representation of patches.
*/
public:
QString patch_toText(const QList<Patch> &patches);
/**
* Parse a textual representation of patches and return a List of Patch
* objects.
* @param textline Text representation of patches.
* @return List of Patch objects.
* @throws QString If invalid input.
*/
public:
QList<Patch> patch_fromText(const QString &textline);
/**
* A safer version of QString.mid(pos). This one returns "" instead of
* null when the postion equals the string length.
* @param str String to take a substring from.
* @param pos Position to start the substring from.
* @return Substring.
*/
private:
static inline QString safeMid(const QString &str, int pos) {
return (pos == str.length()) ? QString("") : str.mid(pos);
}
/**
* A safer version of QString.mid(pos, len). This one returns "" instead of
* null when the postion equals the string length.
* @param str String to take a substring from.
* @param pos Position to start the substring from.
* @param len Length of substring.
* @return Substring.
*/
private:
static inline QString safeMid(const QString &str, int pos, int len) {
return (pos == str.length()) ? QString("") : str.mid(pos, len);
}
};
#endif // DIFF_MATCH_PATCH_H

File diff suppressed because it is too large Load Diff

View File

@ -1,92 +0,0 @@
/*
* Copyright 2008 Google Inc. All Rights Reserved.
* Author: fraser@google.com (Neil Fraser)
* Author: mikeslemmer@gmail.com (Mike Slemmer)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Diff Match and Patch -- Test Harness
* http://code.google.com/p/google-diff-match-patch/
*/
#ifndef DIFF_MATCH_PATCH_TEST_H
#define DIFF_MATCH_PATCH_TEST_H
class diff_match_patch_test {
public:
diff_match_patch_test();
void run_all_tests();
// DIFF TEST FUNCTIONS
void testDiffCommonPrefix();
void testDiffCommonSuffix();
void testDiffCommonOverlap();
void testDiffHalfmatch();
void testDiffLinesToChars();
void testDiffCharsToLines();
void testDiffCleanupMerge();
void testDiffCleanupSemanticLossless();
void testDiffCleanupSemantic();
void testDiffCleanupEfficiency();
void testDiffPrettyHtml();
void testDiffText();
void testDiffDelta();
void testDiffXIndex();
void testDiffLevenshtein();
void testDiffBisect();
void testDiffMain();
// MATCH TEST FUNCTIONS
void testMatchAlphabet();
void testMatchBitap();
void testMatchMain();
// PATCH TEST FUNCTIONS
void testPatchObj();
void testPatchFromText();
void testPatchToText();
void testPatchAddContext();
void testPatchMake();
void testPatchSplitMax();
void testPatchAddPadding();
void testPatchApply();
private:
diff_match_patch dmp;
// Define equality.
void assertEquals(const QString &strCase, int n1, int n2);
void assertEquals(const QString &strCase, const QString &s1, const QString &s2);
void assertEquals(const QString &strCase, const Diff &d1, const Diff &d2);
void assertEquals(const QString &strCase, const QList<Diff> &list1, const QList<Diff> &list2);
void assertEquals(const QString &strCase, const QList<QVariant> &list1, const QList<QVariant> &list2);
void assertEquals(const QString &strCase, const QVariant &var1, const QVariant &var2);
void assertEquals(const QString &strCase, const QMap<QChar, int> &m1, const QMap<QChar, int> &m2);
void assertEquals(const QString &strCase, const QStringList &list1, const QStringList &list2);
void assertTrue(const QString &strCase, bool value);
void assertFalse(const QString &strCase, bool value);
void assertEmpty(const QString &strCase, const QStringList &list);
// Construct the two texts which made up the diff originally.
QStringList diff_rebuildtexts(QList<Diff> diffs);
// Private function for quickly building lists of diffs.
QList<Diff> diffList(
// Diff(INSERT, NULL) is invalid and thus is used as the default argument.
Diff d1 = Diff(INSERT, NULL), Diff d2 = Diff(INSERT, NULL),
Diff d3 = Diff(INSERT, NULL), Diff d4 = Diff(INSERT, NULL),
Diff d5 = Diff(INSERT, NULL), Diff d6 = Diff(INSERT, NULL),
Diff d7 = Diff(INSERT, NULL), Diff d8 = Diff(INSERT, NULL),
Diff d9 = Diff(INSERT, NULL), Diff d10 = Diff(INSERT, NULL));
};
#endif // DIFF_MATCH_PATCH_TEST_H

2
thirdparty/dtl/CONTRIBUTORS vendored Normal file
View File

@ -0,0 +1,2 @@
Tatsuhiko Kubo <cubicdaiya@gmail.com>
Jan Weiß <jan@geheimwerk.de>

30
thirdparty/dtl/COPYING vendored Normal file
View File

@ -0,0 +1,30 @@
In short, Diff Template Library is distributed under so called "BSD license",
Copyright (c) 2015 Tatsuhiko Kubo <cubicdaiya@gmail.com>
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the authors nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

692
thirdparty/dtl/dtl/Diff.hpp vendored Normal file
View File

@ -0,0 +1,692 @@
/**
dtl -- Diff Template Library
In short, Diff Template Library is distributed under so called "BSD license",
Copyright (c) 2015 Tatsuhiko Kubo <cubicdaiya@gmail.com>
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the authors nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/* If you use this library, you must include dtl.hpp only. */
#ifndef DTL_DIFF_H
#define DTL_DIFF_H
namespace dtl {
/**
* diff class template
* sequence must support random_access_iterator.
*/
template <typename elem, typename sequence = vector< elem >, typename comparator = Compare< elem > >
class Diff
{
private :
dtl_typedefs(elem, sequence)
sequence A;
sequence B;
size_t M;
size_t N;
size_t delta;
size_t offset;
long long *fp;
long long editDistance;
Lcs< elem > lcs;
Ses< elem > ses;
editPath path;
editPathCordinates pathCordinates;
bool swapped;
bool huge;
bool trivial;
bool editDistanceOnly;
uniHunkVec uniHunks;
comparator cmp;
public :
Diff () {}
Diff (const sequence& a,
const sequence& b) : A(a), B(b), ses(false) {
init();
}
Diff (const sequence& a,
const sequence& b,
bool deletesFirst) : A(a), B(b), ses(deletesFirst) {
init();
}
Diff (const sequence& a,
const sequence& b,
const comparator& comp) : A(a), B(b), ses(false), cmp(comp) {
init();
}
Diff (const sequence& a,
const sequence& b,
bool deleteFirst,
const comparator& comp) : A(a), B(b), ses(deleteFirst), cmp(comp) {
init();
}
~Diff() {}
long long getEditDistance () const {
return editDistance;
}
Lcs< elem > getLcs () const {
return lcs;
}
elemVec getLcsVec () const {
return lcs.getSequence();
}
Ses< elem > getSes () const {
return ses;
}
uniHunkVec getUniHunks () const {
return uniHunks;
}
/* These should be deprecated */
bool isHuge () const {
return huge;
}
void onHuge () {
this->huge = true;
}
void offHuge () {
this->huge = false;
}
bool isUnserious () const {
return trivial;
}
void onUnserious () {
this->trivial = true;
}
void offUnserious () {
this->trivial = false;
}
void onOnlyEditDistance () {
this->editDistanceOnly = true;
}
/* These are the replacements for the above */
bool hugeEnabled () const {
return huge;
}
void enableHuge () {
this->huge = true;
}
void disableHuge () {
this->huge = false;
}
bool trivialEnabled () const {
return trivial;
}
void enableTrivial () const {
this->trivial = true;
}
void disableTrivial () {
this->trivial = false;
}
void editDistanceOnlyEnabled () {
this->editDistanceOnly = true;
}
/**
* patching with Unified Format Hunks
*/
sequence uniPatch (const sequence& seq) {
elemList seqLst(seq.begin(), seq.end());
sesElemVec shunk;
sesElemVec_iter vsesIt;
elemList_iter lstIt = seqLst.begin();
long long inc_dec_total = 0;
long long gap = 1;
for (uniHunkVec_iter it=uniHunks.begin();it!=uniHunks.end();++it) {
joinSesVec(shunk, it->common[0]);
joinSesVec(shunk, it->change);
joinSesVec(shunk, it->common[1]);
it->a += inc_dec_total;
inc_dec_total += it->inc_dec_count;
for (long long i=0;i<it->a - gap;++i) {
++lstIt;
}
gap = it->a + it->b + it->inc_dec_count;
vsesIt = shunk.begin();
while (vsesIt!=shunk.end()) {
switch (vsesIt->second.type) {
case SES_ADD :
seqLst.insert(lstIt, vsesIt->first);
break;
case SES_DELETE :
if (lstIt != seqLst.end()) {
lstIt = seqLst.erase(lstIt);
}
break;
case SES_COMMON :
if (lstIt != seqLst.end()) {
++lstIt;
}
break;
default :
// no fall-through
break;
}
++vsesIt;
}
shunk.clear();
}
sequence patchedSeq(seqLst.begin(), seqLst.end());
return patchedSeq;
}
/**
* patching with Shortest Edit Script (SES)
*/
sequence patch (const sequence& seq) const {
sesElemVec sesSeq = ses.getSequence();
elemList seqLst(seq.begin(), seq.end());
elemList_iter lstIt = seqLst.begin();
for (sesElemVec_iter sesIt=sesSeq.begin();sesIt!=sesSeq.end();++sesIt) {
switch (sesIt->second.type) {
case SES_ADD :
seqLst.insert(lstIt, sesIt->first);
break;
case SES_DELETE :
lstIt = seqLst.erase(lstIt);
break;
case SES_COMMON :
++lstIt;
break;
default :
// no through
break;
}
}
sequence patchedSeq(seqLst.begin(), seqLst.end());
return patchedSeq;
}
/**
* compose Longest Common Subsequence and Shortest Edit Script.
* The algorithm implemented here is based on "An O(NP) Sequence Comparison Algorithm"
* described by Sun Wu, Udi Manber and Gene Myers
*/
void compose() {
if (isHuge()) {
pathCordinates.reserve(MAX_CORDINATES_SIZE);
}
long long p = -1;
fp = new long long[M + N + 3];
fill(&fp[0], &fp[M + N + 3], -1);
path = editPath(M + N + 3);
fill(path.begin(), path.end(), -1);
ONP:
do {
++p;
for (long long k=-p;k<=static_cast<long long>(delta)-1;++k) {
fp[k+offset] = snake(k, fp[k-1+offset]+1, fp[k+1+offset]);
}
for (long long k=static_cast<long long>(delta)+p;k>=static_cast<long long>(delta)+1;--k) {
fp[k+offset] = snake(k, fp[k-1+offset]+1, fp[k+1+offset]);
}
fp[delta+offset] = snake(static_cast<long long>(delta), fp[delta-1+offset]+1, fp[delta+1+offset]);
} while (fp[delta+offset] != static_cast<long long>(N) && pathCordinates.size() < MAX_CORDINATES_SIZE);
editDistance += static_cast<long long>(delta) + 2 * p;
long long r = path[delta+offset];
P cordinate;
editPathCordinates epc(0);
// recording edit distance only
if (editDistanceOnly) {
delete[] this->fp;
return;
}
while(r != -1) {
cordinate.x = pathCordinates[(size_t)r].x;
cordinate.y = pathCordinates[(size_t)r].y;
epc.push_back(cordinate);
r = pathCordinates[(size_t)r].k;
}
// record Longest Common Subsequence & Shortest Edit Script
if (!recordSequence(epc)) {
pathCordinates.resize(0);
epc.resize(0);
p = -1;
goto ONP;
}
delete[] this->fp;
}
/**
* print difference between A and B as an SES
*/
template < typename stream >
void printSES (stream& out) const {
sesElemVec ses_v = ses.getSequence();
for_each(ses_v.begin(), ses_v.end(), ChangePrinter< sesElem, stream >(out));
}
void printSES (ostream& out = cout) const {
printSES< ostream >(out);
}
/**
* print differences given an SES
*/
template < typename stream >
static void printSES (const Ses< elem >& s, stream& out) {
sesElemVec ses_v = s.getSequence();
for_each(ses_v.begin(), ses_v.end(), ChangePrinter< sesElem, stream >(out));
}
static void printSES (const Ses< elem >& s, ostream& out = cout) {
printSES< ostream >(s, out);
}
/**
* print difference between A and B as an SES with custom printer
*/
template < typename stream, template < typename SEET, typename STRT > class PT >
void printSES (stream& out) const {
sesElemVec ses_v = ses.getSequence ();
for_each (ses_v.begin (), ses_v.end(), PT < sesElem, stream > (out));
}
/**
* print difference between A and B in the Unified Format
*/
template < typename stream >
void printUnifiedFormat (stream& out) const {
for_each(uniHunks.begin(), uniHunks.end(), UniHunkPrinter< sesElem, stream >(out));
}
void printUnifiedFormat (ostream& out = cout) const {
printUnifiedFormat< ostream >(out);
}
/**
* print unified format difference with given unified format hunks
*/
template < typename stream >
static void printUnifiedFormat (const uniHunkVec& hunks, stream& out) {
for_each(hunks.begin(), hunks.end(), UniHunkPrinter< sesElem >(out));
}
static void printUnifiedFormat (const uniHunkVec& hunks, ostream& out = cout) {
printUnifiedFormat< ostream >(hunks, out);
}
/**
* compose Unified Format Hunks from Shortest Edit Script
*/
void composeUnifiedHunks () {
sesElemVec common[2];
sesElemVec change;
sesElemVec ses_v = ses.getSequence();
long long l_cnt = 1;
long long length = distance(ses_v.begin(), ses_v.end());
long long middle = 0;
bool isMiddle, isAfter;
elemInfo einfo;
long long a, b, c, d; // @@ -a,b +c,d @@
long long inc_dec_count = 0;
uniHunk< sesElem > hunk;
sesElemVec adds;
sesElemVec deletes;
isMiddle = isAfter = false;
a = b = c = d = 0;
for (sesElemVec_iter it=ses_v.begin();it!=ses_v.end();++it, ++l_cnt) {
einfo = it->second;
switch (einfo.type) {
case SES_ADD :
middle = 0;
++inc_dec_count;
adds.push_back(*it);
if (!isMiddle) isMiddle = true;
if (isMiddle) ++d;
if (l_cnt >= length) {
joinSesVec(change, deletes);
joinSesVec(change, adds);
isAfter = true;
}
break;
case SES_DELETE :
middle = 0;
--inc_dec_count;
deletes.push_back(*it);
if (!isMiddle) isMiddle = true;
if (isMiddle) ++b;
if (l_cnt >= length) {
joinSesVec(change, deletes);
joinSesVec(change, adds);
isAfter = true;
}
break;
case SES_COMMON :
++b;++d;
if (common[1].empty() && adds.empty() && deletes.empty() && change.empty()) {
if (static_cast<long long>(common[0].size()) < DTL_CONTEXT_SIZE) {
if (a == 0 && c == 0) {
if (!wasSwapped()) {
a = einfo.beforeIdx;
c = einfo.afterIdx;
} else {
a = einfo.afterIdx;
c = einfo.beforeIdx;
}
}
common[0].push_back(*it);
} else {
rotate(common[0].begin(), common[0].begin() + 1, common[0].end());
common[0].pop_back();
common[0].push_back(*it);
++a;++c;
--b;--d;
}
}
if (isMiddle && !isAfter) {
++middle;
joinSesVec(change, deletes);
joinSesVec(change, adds);
change.push_back(*it);
if (middle >= DTL_SEPARATE_SIZE || l_cnt >= length) {
isAfter = true;
}
adds.clear();
deletes.clear();
}
break;
default :
// no through
break;
}
// compose unified format hunk
if (isAfter && !change.empty()) {
sesElemVec_iter cit = it;
long long cnt = 0;
for (long long i=0;i<DTL_SEPARATE_SIZE && (cit != ses_v.end());++i, ++cit) {
if (cit->second.type == SES_COMMON) {
++cnt;
}
}
if (cnt < DTL_SEPARATE_SIZE && l_cnt < length) {
middle = 0;
isAfter = false;
continue;
}
if (static_cast<long long>(common[0].size()) >= DTL_SEPARATE_SIZE) {
long long c0size = static_cast<long long>(common[0].size());
rotate(common[0].begin(),
common[0].begin() + (size_t)c0size - DTL_SEPARATE_SIZE,
common[0].end());
for (long long i=0;i<c0size - DTL_SEPARATE_SIZE;++i) {
common[0].pop_back();
}
a += c0size - DTL_SEPARATE_SIZE;
c += c0size - DTL_SEPARATE_SIZE;
}
if (a == 0) ++a;
if (c == 0) ++c;
if (wasSwapped()) swap(a, c);
hunk.a = a;
hunk.b = b;
hunk.c = c;
hunk.d = d;
hunk.common[0] = common[0];
hunk.change = change;
hunk.common[1] = common[1];
hunk.inc_dec_count = inc_dec_count;
uniHunks.push_back(hunk);
isMiddle = false;
isAfter = false;
common[0].clear();
common[1].clear();
adds.clear();
deletes.clear();
change.clear();
a = b = c = d = middle = inc_dec_count = 0;
}
}
}
/**
* compose ses from stream
*/
template <typename stream>
static Ses< elem > composeSesFromStream (stream& st)
{
elem line;
Ses< elem > ret;
long long x_idx, y_idx;
x_idx = y_idx = 1;
while (getline(st, line)) {
elem mark(line.begin(), line.begin() + 1);
elem e(line.begin() + 1, line.end());
if (mark == SES_MARK_DELETE) {
ret.addSequence(e, x_idx, 0, SES_DELETE);
++x_idx;
} else if (mark == SES_MARK_ADD) {
ret.addSequence(e, y_idx, 0, SES_ADD);
++y_idx;
} else if (mark == SES_MARK_COMMON) {
ret.addSequence(e, x_idx, y_idx, SES_COMMON);
++x_idx;
++y_idx;
}
}
return ret;
}
private :
/**
* initialize
*/
void init () {
M = distance(A.begin(), A.end());
N = distance(B.begin(), B.end());
if (M < N) {
swapped = false;
} else {
swap(A, B);
swap(M, N);
swapped = true;
}
editDistance = 0;
delta = N - M;
offset = M + 1;
huge = false;
trivial = false;
editDistanceOnly = false;
fp = NULL;
}
/**
* search shortest path and record the path
*/
long long snake(const long long& k, const long long& above, const long long& below) {
long long r = above > below ? path[(size_t)k-1+offset] : path[(size_t)k+1+offset];
long long y = max(above, below);
long long x = y - k;
while ((size_t)x < M && (size_t)y < N && (swapped ? cmp.impl(B[(size_t)y], A[(size_t)x]) : cmp.impl(A[(size_t)x], B[(size_t)y]))) {
++x;++y;
}
path[(size_t)k+offset] = static_cast<long long>(pathCordinates.size());
if (!editDistanceOnly) {
P p;
p.x = x;p.y = y;p.k = r;
pathCordinates.push_back(p);
}
return y;
}
/**
* record SES and LCS
*/
bool recordSequence (const editPathCordinates& v) {
sequence_const_iter x(A.begin());
sequence_const_iter y(B.begin());
long long x_idx, y_idx; // line number for Unified Format
long long px_idx, py_idx; // cordinates
bool complete = false;
x_idx = y_idx = 1;
px_idx = py_idx = 0;
for (size_t i=v.size()-1;!complete;--i) {
while(px_idx < v[i].x || py_idx < v[i].y) {
if (v[i].y - v[i].x > py_idx - px_idx) {
if (!wasSwapped()) {
ses.addSequence(*y, 0, y_idx, SES_ADD);
} else {
ses.addSequence(*y, y_idx, 0, SES_DELETE);
}
++y;
++y_idx;
++py_idx;
} else if (v[i].y - v[i].x < py_idx - px_idx) {
if (!wasSwapped()) {
ses.addSequence(*x, x_idx, 0, SES_DELETE);
} else {
ses.addSequence(*x, 0, x_idx, SES_ADD);
}
++x;
++x_idx;
++px_idx;
} else {
if (!wasSwapped()) {
lcs.addSequence(*x);
ses.addSequence(*x, x_idx, y_idx, SES_COMMON);
} else {
lcs.addSequence(*y);
ses.addSequence(*y, y_idx, x_idx, SES_COMMON);
}
++x;
++y;
++x_idx;
++y_idx;
++px_idx;
++py_idx;
}
}
if (i == 0) complete = true;
}
if (x_idx > static_cast<long long>(M) && y_idx > static_cast<long long>(N)) {
// all recording succeeded
} else {
// trivial difference
if (trivialEnabled()) {
if (!wasSwapped()) {
recordOddSequence(x_idx, M, x, SES_DELETE);
recordOddSequence(y_idx, N, y, SES_ADD);
} else {
recordOddSequence(x_idx, M, x, SES_ADD);
recordOddSequence(y_idx, N, y, SES_DELETE);
}
return true;
}
// nontrivial difference
sequence A_(A.begin() + (size_t)x_idx - 1, A.end());
sequence B_(B.begin() + (size_t)y_idx - 1, B.end());
A = A_;
B = B_;
M = distance(A.begin(), A.end());
N = distance(B.begin(), B.end());
delta = N - M;
offset = M + 1;
delete[] fp;
fp = new long long[M + N + 3];
fill(&fp[0], &fp[M + N + 3], -1);
fill(path.begin(), path.end(), -1);
return false;
}
return true;
}
/**
* record odd sequence in SES
*/
void inline recordOddSequence (long long idx, long long length, sequence_const_iter it, const edit_t et) {
while(idx < length){
ses.addSequence(*it, idx, 0, et);
++it;
++idx;
++editDistance;
}
ses.addSequence(*it, idx, 0, et);
++editDistance;
}
/**
* join SES vectors
*/
void inline joinSesVec (sesElemVec& s1, sesElemVec& s2) const {
if (!s2.empty()) {
for (sesElemVec_iter vit=s2.begin();vit!=s2.end();++vit) {
s1.push_back(*vit);
}
}
}
/**
* check if the sequences have been swapped
*/
bool inline wasSwapped () const {
return swapped;
}
};
}
#endif // DTL_DIFF_H

245
thirdparty/dtl/dtl/Diff3.hpp vendored Normal file
View File

@ -0,0 +1,245 @@
/**
dtl -- Diff Template Library
In short, Diff Template Library is distributed under so called "BSD license",
Copyright (c) 2015 Tatsuhiko Kubo <cubicdaiya@gmail.com>
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the authors nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/* If you use this library, you must include dtl.hpp only. */
#ifndef DTL_DIFF3_H
#define DTL_DIFF3_H
namespace dtl {
/**
* diff3 class template
* sequence must support random_access_iterator.
*/
template <typename elem, typename sequence = vector< elem >, typename comparator = Compare< elem > >
class Diff3
{
private:
dtl_typedefs(elem, sequence)
sequence A;
sequence B;
sequence C;
sequence S;
Diff< elem, sequence, comparator > diff_ba;
Diff< elem, sequence, comparator > diff_bc;
bool conflict;
elem csepabegin;
elem csepa;
elem csepaend;
public :
Diff3 () {}
Diff3 (const sequence& a,
const sequence& b,
const sequence& c) : A(a), B(b), C(c),
diff_ba(b, a), diff_bc(b, c),
conflict(false) {}
~Diff3 () {}
bool isConflict () const {
return conflict;
}
sequence getMergedSequence () const {
return S;
}
/**
* merge changes B and C into A
*/
bool merge () {
if (diff_ba.getEditDistance() == 0) { // A == B
if (diff_bc.getEditDistance() == 0) { // A == B == C
S = B;
return true;
}
S = C;
return true;
} else { // A != B
if (diff_bc.getEditDistance() == 0) { // A != B == C
S = A;
return true;
} else { // A != B != C
S = merge_();
if (isConflict()) { // conflict occured
return false;
}
}
}
return true;
}
/**
* compose differences
*/
void compose () {
diff_ba.compose();
diff_bc.compose();
}
private :
/**
* merge implementation
*/
sequence merge_ () {
elemVec seq;
Ses< elem > ses_ba = diff_ba.getSes();
Ses< elem > ses_bc = diff_bc.getSes();
sesElemVec ses_ba_v = ses_ba.getSequence();
sesElemVec ses_bc_v = ses_bc.getSequence();
sesElemVec_iter ba_it = ses_ba_v.begin();
sesElemVec_iter bc_it = ses_bc_v.begin();
sesElemVec_iter ba_end = ses_ba_v.end();
sesElemVec_iter bc_end = ses_bc_v.end();
while (!isEnd(ba_end, ba_it) || !isEnd(bc_end, bc_it)) {
while (true) {
if (!isEnd(ba_end, ba_it) &&
!isEnd(bc_end, bc_it) &&
ba_it->first == bc_it->first &&
ba_it->second.type == SES_COMMON &&
bc_it->second.type == SES_COMMON) {
// do nothing
} else {
break;
}
if (!isEnd(ba_end, ba_it)) seq.push_back(ba_it->first);
else if (!isEnd(bc_end, bc_it)) seq.push_back(bc_it->first);
forwardUntilEnd(ba_end, ba_it);
forwardUntilEnd(bc_end, bc_it);
}
if (isEnd(ba_end, ba_it) || isEnd(bc_end, bc_it)) break;
if ( ba_it->second.type == SES_COMMON
&& bc_it->second.type == SES_DELETE) {
forwardUntilEnd(ba_end, ba_it);
forwardUntilEnd(bc_end, bc_it);
} else if (ba_it->second.type == SES_COMMON &&
bc_it->second.type == SES_ADD) {
seq.push_back(bc_it->first);
forwardUntilEnd(bc_end, bc_it);
} else if (ba_it->second.type == SES_DELETE &&
bc_it->second.type == SES_COMMON) {
forwardUntilEnd(ba_end, ba_it);
forwardUntilEnd(bc_end, bc_it);
} else if (ba_it->second.type == SES_DELETE &&
bc_it->second.type == SES_DELETE) {
if (ba_it->first == bc_it->first) {
forwardUntilEnd(ba_end, ba_it);
forwardUntilEnd(bc_end, bc_it);
} else {
// conflict
conflict = true;
return B;
}
} else if (ba_it->second.type == SES_DELETE &&
bc_it->second.type == SES_ADD) {
// conflict
conflict = true;
return B;
} else if (ba_it->second.type == SES_ADD &&
bc_it->second.type == SES_COMMON) {
seq.push_back(ba_it->first);
forwardUntilEnd(ba_end, ba_it);
} else if (ba_it->second.type == SES_ADD &&
bc_it->second.type == SES_DELETE) {
// conflict
conflict = true;
return B;
} else if (ba_it->second.type == SES_ADD &&
bc_it->second.type == SES_ADD) {
if (ba_it->first == bc_it->first) {
seq.push_back(ba_it->first);
forwardUntilEnd(ba_end, ba_it);
forwardUntilEnd(bc_end, bc_it);
} else {
// conflict
conflict = true;
return B;
}
}
}
if (isEnd(ba_end, ba_it)) {
addDecentSequence(bc_end, bc_it, seq);
} else if (isEnd(bc_end, bc_it)) {
addDecentSequence(ba_end, ba_it, seq);
}
sequence mergedSeq(seq.begin(), seq.end());
return mergedSeq;
}
/**
* join elem vectors
*/
void inline joinElemVec (elemVec& s1, elemVec& s2) const {
if (!s2.empty()) {
for (elemVec_iter vit=s2.begin();vit!=s2.end();++vit) {
s1.push_back(*vit);
}
}
}
/**
* check if sequence is at end
*/
template <typename T_iter>
bool inline isEnd (const T_iter& end, const T_iter& it) const {
return it == end ? true : false;
}
/**
* increment iterator until iterator is at end
*/
template <typename T_iter>
void inline forwardUntilEnd (const T_iter& end, T_iter& it) const {
if (!isEnd(end, it)) ++it;
}
/**
* add elements whose SES's type is ADD
*/
void inline addDecentSequence (const sesElemVec_iter& end, sesElemVec_iter& it, elemVec& seq) const {
while (!isEnd(end, it)) {
if (it->second.type == SES_ADD) seq.push_back(it->first);
++it;
}
}
};
}
#endif // DTL_DIFF3_H

55
thirdparty/dtl/dtl/Lcs.hpp vendored Normal file
View File

@ -0,0 +1,55 @@
/**
dtl -- Diff Template Library
In short, Diff Template Library is distributed under so called "BSD license",
Copyright (c) 2015 Tatsuhiko Kubo <cubicdaiya@gmail.com>
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the authors nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/* If you use this library, you must include dtl.hpp only. */
#ifndef DTL_LCS_H
#define DTL_LCS_H
namespace dtl {
/**
* Longest Common Subsequence template class
*/
template <typename elem>
class Lcs : public Sequence< elem >
{
public :
Lcs () {}
~Lcs () {}
};
}
#endif // DTL_LCS_H

65
thirdparty/dtl/dtl/Sequence.hpp vendored Normal file
View File

@ -0,0 +1,65 @@
/**
dtl -- Diff Template Library
In short, Diff Template Library is distributed under so called "BSD license",
Copyright (c) 2015 Tatsuhiko Kubo <cubicdaiya@gmail.com>
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the authors nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/* If you use this library, you must include dtl.hpp only. */
#ifndef DTL_SEQUENCE_H
#define DTL_SEQUENCE_H
namespace dtl {
/**
* sequence class template
*/
template <typename elem>
class Sequence
{
public :
typedef vector< elem > elemVec;
Sequence () {}
virtual ~Sequence () {}
elemVec getSequence () const {
return sequence;
}
void addSequence (elem e) {
sequence.push_back(e);
}
protected :
elemVec sequence;
};
}
#endif // DTL_SEQUENCE_H

132
thirdparty/dtl/dtl/Ses.hpp vendored Normal file
View File

@ -0,0 +1,132 @@
/**
dtl -- Diff Template Library
In short, Diff Template Library is distributed under so called "BSD license",
Copyright (c) 2015 Tatsuhiko Kubo <cubicdaiya@gmail.com>
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the authors nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/* If you use this library, you must include dtl.hpp only. */
#ifndef DTL_SES_H
#define DTL_SES_H
namespace dtl {
/**
* Shortest Edit Script template class
*/
template <typename elem>
class Ses : public Sequence< elem >
{
private :
typedef pair< elem, elemInfo > sesElem;
typedef vector< sesElem > sesElemVec;
public :
Ses () : onlyAdd(true), onlyDelete(true), onlyCopy(true), deletesFirst(false) {
nextDeleteIdx = 0;
}
Ses (bool moveDel) : onlyAdd(true), onlyDelete(true), onlyCopy(true), deletesFirst(moveDel) {
nextDeleteIdx = 0;
}
~Ses () {}
bool isOnlyAdd () const {
return onlyAdd;
}
bool isOnlyDelete () const {
return onlyDelete;
}
bool isOnlyCopy () const {
return onlyCopy;
}
bool isOnlyOneOperation () const {
return isOnlyAdd() || isOnlyDelete() || isOnlyCopy();
}
bool isChange () const {
return !onlyCopy;
}
using Sequence< elem >::addSequence;
void addSequence (elem e, long long beforeIdx, long long afterIdx, const edit_t type) {
elemInfo info;
info.beforeIdx = beforeIdx;
info.afterIdx = afterIdx;
info.type = type;
sesElem pe(e, info);
if (!deletesFirst) {
sequence.push_back(pe);
}
switch (type) {
case SES_DELETE:
onlyCopy = false;
onlyAdd = false;
if (deletesFirst) {
sequence.insert(sequence.begin() + nextDeleteIdx, pe);
nextDeleteIdx++;
}
break;
case SES_COMMON:
onlyAdd = false;
onlyDelete = false;
if (deletesFirst) {
sequence.push_back(pe);
nextDeleteIdx = sequence.size();
}
break;
case SES_ADD:
onlyDelete = false;
onlyCopy = false;
if (deletesFirst) {
sequence.push_back(pe);
}
break;
}
}
sesElemVec getSequence () const {
return sequence;
}
private :
sesElemVec sequence;
bool onlyAdd;
bool onlyDelete;
bool onlyCopy;
bool deletesFirst;
size_t nextDeleteIdx;
};
}
#endif // DTL_SES_H

47
thirdparty/dtl/dtl/dtl.hpp vendored Normal file
View File

@ -0,0 +1,47 @@
/**
dtl -- Diff Template Library
In short, Diff Template Library is distributed under so called "BSD license",
Copyright (c) 2015 Tatsuhiko Kubo <cubicdaiya@gmail.com>
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the authors nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef DTL_H
#define DTL_H
#include "variables.hpp"
#include "functors.hpp"
#include "Sequence.hpp"
#include "Lcs.hpp"
#include "Ses.hpp"
#include "Diff.hpp"
#include "Diff3.hpp"
#endif // DTL_H

137
thirdparty/dtl/dtl/functors.hpp vendored Normal file
View File

@ -0,0 +1,137 @@
/**
dtl -- Diff Template Library
In short, Diff Template Library is distributed under so called "BSD license",
Copyright (c) 2015 Tatsuhiko Kubo <cubicdaiya@gmail.com>
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the authors nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/* If you use this library, you must include dtl.hpp only. */
#ifndef DTL_FUNCTORS_H
#define DTL_FUNCTORS_H
namespace dtl {
/**
* printer class template
*/
template <typename sesElem, typename stream = ostream >
class Printer
{
public :
Printer () : out_(cout) {}
Printer (stream& out) : out_(out) {}
virtual ~Printer () {}
virtual void operator() (const sesElem& se) const = 0;
protected :
stream& out_;
};
/**
* common element printer class template
*/
template <typename sesElem, typename stream = ostream >
class CommonPrinter : public Printer < sesElem, stream >
{
public :
CommonPrinter () : Printer < sesElem, stream > () {}
CommonPrinter (stream& out) : Printer < sesElem, stream > (out) {}
~CommonPrinter () {}
void operator() (const sesElem& se) const {
this->out_ << SES_MARK_COMMON << se.first << endl;
}
};
/**
* ses element printer class template
*/
template <typename sesElem, typename stream = ostream >
class ChangePrinter : public Printer < sesElem, stream >
{
public :
ChangePrinter () : Printer < sesElem, stream > () {}
ChangePrinter (stream& out) : Printer < sesElem, stream > (out) {}
~ChangePrinter () {}
void operator() (const sesElem& se) const {
switch (se.second.type) {
case SES_ADD:
this->out_ << SES_MARK_ADD << se.first << endl;
break;
case SES_DELETE:
this->out_ << SES_MARK_DELETE << se.first << endl;
break;
case SES_COMMON:
this->out_ << SES_MARK_COMMON << se.first << endl;
break;
}
}
};
/**
* unified format element printer class template
*/
template <typename sesElem, typename stream = ostream >
class UniHunkPrinter
{
public :
UniHunkPrinter () : out_(cout) {}
UniHunkPrinter (stream& out) : out_(out) {}
~UniHunkPrinter () {}
void operator() (const uniHunk< sesElem >& hunk) const {
out_ << "@@"
<< " -" << hunk.a << "," << hunk.b
<< " +" << hunk.c << "," << hunk.d
<< " @@" << endl;
for_each(hunk.common[0].begin(), hunk.common[0].end(), CommonPrinter< sesElem, stream >(out_));
for_each(hunk.change.begin(), hunk.change.end(), ChangePrinter< sesElem, stream >(out_));
for_each(hunk.common[1].begin(), hunk.common[1].end(), CommonPrinter< sesElem, stream >(out_));
}
private :
stream& out_;
};
/**
* compare class template
*/
template <typename elem>
class Compare
{
public :
Compare () {}
virtual ~Compare () {}
virtual inline bool impl (const elem& e1, const elem& e2) const {
return e1 == e2;
}
};
}
#endif // DTL_FUNCTORS_H

142
thirdparty/dtl/dtl/variables.hpp vendored Normal file
View File

@ -0,0 +1,142 @@
/**
dtl -- Diff Template Library
In short, Diff Template Library is distributed under so called "BSD license",
Copyright (c) 2015 Tatsuhiko Kubo <cubicdaiya@gmail.com>
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the authors nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/* If you use this library, you must include dtl.hpp only. */
#ifndef DTL_VARIABLES_H
#define DTL_VARIABLES_H
#include <vector>
#include <list>
#include <string>
#include <algorithm>
#include <iostream>
namespace dtl {
using std::vector;
using std::string;
using std::pair;
using std::ostream;
using std::list;
using std::for_each;
using std::distance;
using std::fill;
using std::cout;
using std::endl;
using std::rotate;
using std::swap;
using std::max;
/**
* version string
*/
const string version = "1.19";
/**
* type of edit for SES
*/
typedef int edit_t;
const edit_t SES_DELETE = -1;
const edit_t SES_COMMON = 0;
const edit_t SES_ADD = 1;
/**
* mark of SES
*/
#define SES_MARK_DELETE "-"
#define SES_MARK_COMMON " "
#define SES_MARK_ADD "+"
/**
* info for Unified Format
*/
typedef struct eleminfo {
long long beforeIdx; // index of prev sequence
long long afterIdx; // index of after sequence
edit_t type; // type of edit(Add, Delete, Common)
bool operator==(const eleminfo& other) const{
return (this->beforeIdx == other.beforeIdx && this->afterIdx == other.afterIdx && this->type == other.type);
}
} elemInfo;
const long long DTL_SEPARATE_SIZE = 3;
const long long DTL_CONTEXT_SIZE = 3;
/**
* cordinate for registering route
*/
typedef struct Point {
long long x; // x cordinate
long long y; // y cordinate
long long k; // vertex
} P;
/**
* limit of cordinate size
*/
const unsigned long long MAX_CORDINATES_SIZE = 2000000;
typedef vector< long long > editPath;
typedef vector< P > editPathCordinates;
/**
* Structure of Unified Format Hunk
*/
template <typename sesElem>
struct uniHunk {
long long a, b, c, d; // @@ -a,b +c,d @@
vector< sesElem > common[2]; // anteroposterior commons on changes
vector< sesElem > change; // changes
long long inc_dec_count; // count of increace and decrease
};
#define dtl_typedefs(elem, sequence) \
typedef pair< elem, elemInfo > sesElem; \
typedef vector< sesElem > sesElemVec; \
typedef vector< uniHunk< sesElem > > uniHunkVec; \
typedef list< elem > elemList; \
typedef vector< elem > elemVec; \
typedef typename uniHunkVec::iterator uniHunkVec_iter; \
typedef typename sesElemVec::iterator sesElemVec_iter; \
typedef typename elemList::iterator elemList_iter; \
typedef typename sequence::iterator sequence_iter; \
typedef typename sequence::const_iterator sequence_const_iter; \
typedef typename elemVec::iterator elemVec_iter;
}
#endif // DTL_VARIABLES_H