init
This commit is contained in:
commit
a38d72a9de
31
.gitignore
vendored
Normal file
31
.gitignore
vendored
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
examples/unidiff
|
||||||
|
examples/unistrdiff
|
||||||
|
examples/strdiff
|
||||||
|
examples/strdiff_cp
|
||||||
|
examples/strdiff3
|
||||||
|
examples/intdiff
|
||||||
|
examples/bdiff
|
||||||
|
examples/intdiff3
|
||||||
|
examples/patch
|
||||||
|
examples/fpatch
|
||||||
|
examples/st2ses
|
||||||
|
test/strdiff3_test
|
||||||
|
test/*/*/*_
|
||||||
|
*.o
|
||||||
|
*.orig
|
||||||
|
*~
|
||||||
|
.semantic.cache
|
||||||
|
.DS_Store
|
||||||
|
*.swp
|
||||||
|
GPATH
|
||||||
|
GRTAGS
|
||||||
|
GSYMS
|
||||||
|
GTAGS
|
||||||
|
TAGS
|
||||||
|
dtl_test
|
||||||
|
.sconsign.dblite
|
||||||
|
.sconf_temp
|
||||||
|
config.log
|
||||||
|
^\#
|
||||||
|
\#$
|
||||||
|
\.\#
|
16
.travis.yml
Normal file
16
.travis.yml
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
language: cpp
|
||||||
|
compiler:
|
||||||
|
- gcc
|
||||||
|
- clang
|
||||||
|
before_script:
|
||||||
|
- wget http://googletest.googlecode.com/files/gtest-1.7.0.zip
|
||||||
|
- unzip -q gtest-1.7.0.zip
|
||||||
|
- cd gtest-1.7.0
|
||||||
|
- ./configure
|
||||||
|
- make
|
||||||
|
- cd ..
|
||||||
|
script:
|
||||||
|
- cd examples
|
||||||
|
- scons
|
||||||
|
- cd ../test
|
||||||
|
- GTEST_ROOT=$PWD/../gtest-1.7.0 scons check
|
2
CONTRIBUTORS
Normal file
2
CONTRIBUTORS
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
Tatsuhiko Kubo <cubicdaiya@gmail.com>
|
||||||
|
Jan Weiß <jan@geheimwerk.de>
|
30
COPYING
Normal file
30
COPYING
Normal 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.
|
258
ChangeLog
Normal file
258
ChangeLog
Normal file
@ -0,0 +1,258 @@
|
|||||||
|
2015-05-03 Tatsuhiko Kubo <cubicdaiya@gmail.com>
|
||||||
|
|
||||||
|
* added some minor changes.
|
||||||
|
|
||||||
|
* 1.19 released
|
||||||
|
|
||||||
|
2013-01-10 Tatsuhiko Kubo <cubicdaiya@gmail.com>
|
||||||
|
|
||||||
|
* add printSES function for custom Printer Thanks to Hu Shubin
|
||||||
|
|
||||||
|
* remove files related mercurial
|
||||||
|
|
||||||
|
* 1.18 released
|
||||||
|
|
||||||
|
2012-11-18 Tatsuhiko Kubo <cubicdaiya@gmail.com>
|
||||||
|
|
||||||
|
* add version-string variable
|
||||||
|
|
||||||
|
* replace get_current_dir_name to getcwd(get_current_dir_name is not in Mountain Lion)
|
||||||
|
|
||||||
|
* fix small typo
|
||||||
|
|
||||||
|
* 1.17 released
|
||||||
|
|
||||||
|
2012-10-26 Tatsuhiko Kubo <cubicdaiya@gmail.com>, Jan Weiß <jan@geheimwerk.de>
|
||||||
|
|
||||||
|
* Improving comments
|
||||||
|
|
||||||
|
* rewrite README with markdown-style
|
||||||
|
|
||||||
|
* support gtest1.6
|
||||||
|
|
||||||
|
* allow clients to handle if DTL swaps the arrays it is passed
|
||||||
|
|
||||||
|
* fix incorrect results for SES_COMMON when swapped
|
||||||
|
|
||||||
|
* add explicit initialization of ses
|
||||||
|
|
||||||
|
* implement option to force the order of sesElem objects in the ses
|
||||||
|
|
||||||
|
* fix problem -> issues/4(test succeeds when result-file does not exist)
|
||||||
|
|
||||||
|
* 1.16 released
|
||||||
|
|
||||||
|
2011-11-10 Tatsuhiko Kubo <cubicdaiya@gmail.com>
|
||||||
|
|
||||||
|
* remove unused variable
|
||||||
|
|
||||||
|
* 1.15 released
|
||||||
|
|
||||||
|
2011-06-18 Tatsuhiko Kubo <cubicdaiya@gmail.com>
|
||||||
|
|
||||||
|
* fix Issue #7 (isOnlyOneOperation returns incorrect value)
|
||||||
|
|
||||||
|
* 1.14 released
|
||||||
|
|
||||||
|
2011-04-10 Tatsuhiko Kubo <cubicdaiya@gmail.com>
|
||||||
|
|
||||||
|
* add check for libraries with SCons
|
||||||
|
|
||||||
|
* add installer with SCons
|
||||||
|
|
||||||
|
* add sample of diff(bdiff)
|
||||||
|
|
||||||
|
* 1.13 released
|
||||||
|
|
||||||
|
2011-01-23 Tatsuhiko Kubo <cubicdaiya@gmail.com>
|
||||||
|
|
||||||
|
* forget to add template parameter of stream for print methods of printUnifiedFormat
|
||||||
|
|
||||||
|
* 1.12 released
|
||||||
|
|
||||||
|
2011-01-01 Tatsuhiko Kubo <cubicdaiya@gmail.com>
|
||||||
|
|
||||||
|
* add template parameter of stream for print methods
|
||||||
|
|
||||||
|
* function of importing ses
|
||||||
|
|
||||||
|
* 1.11 released
|
||||||
|
|
||||||
|
2010-11-23 Tatsuhiko Kubo <cubicdaiya@gmail.com>
|
||||||
|
|
||||||
|
* use static_cast instead of C-style cast
|
||||||
|
|
||||||
|
* remove specifyConfliction
|
||||||
|
|
||||||
|
* 1.10 released
|
||||||
|
|
||||||
|
2010-09-20 Tatsuhiko Kubo <cubicdaiya@gmail.com>
|
||||||
|
|
||||||
|
* fix bug of specifyConfliction
|
||||||
|
|
||||||
|
* add parameter for Diff3's comparator
|
||||||
|
|
||||||
|
* fix the bug which uniPatch fails
|
||||||
|
|
||||||
|
* add debug option for examples
|
||||||
|
|
||||||
|
* divide test sources
|
||||||
|
|
||||||
|
* 1.09 released
|
||||||
|
|
||||||
|
2010-08-29 Tatsuhiko Kubo <cubicdaiya@gmail.com>
|
||||||
|
|
||||||
|
* fix the problem that comparator parameter is completely ignored.
|
||||||
|
|
||||||
|
* remove the warning 'comparison of unsigned expression >= 0 is always true' ( use -W )
|
||||||
|
|
||||||
|
* move directory 'src' to 'dtl'
|
||||||
|
|
||||||
|
* remove Makefile for examples and test
|
||||||
|
|
||||||
|
* 1.08 released
|
||||||
|
|
||||||
|
2010-07-11 Tatsuhiko Kubo <cubicdaiya@gmail.com>
|
||||||
|
|
||||||
|
* fix potential risk on 64bit environment(size of 'int' and size of 'size_t')
|
||||||
|
|
||||||
|
* add scons
|
||||||
|
|
||||||
|
* fix bug of specifyConfliction
|
||||||
|
|
||||||
|
* fix memory leak when onlyEditDistance is true
|
||||||
|
|
||||||
|
* change indent size from 2 to 4
|
||||||
|
|
||||||
|
* 1.07 released
|
||||||
|
|
||||||
|
2010-05-01 Tatsuhiko Kubo <cubicdaiya@gmail.com>
|
||||||
|
|
||||||
|
* add specifyConfliction
|
||||||
|
|
||||||
|
* 1.06 released
|
||||||
|
|
||||||
|
2010-04-13 Tatsuhiko Kubo <cubicdaiya@gmail.com>
|
||||||
|
|
||||||
|
* constructors takes referenced parameter
|
||||||
|
|
||||||
|
* fix seg fault bug (http://code.google.com/p/dtl-cpp/issues/detail?id=2)
|
||||||
|
|
||||||
|
* 1.05 released
|
||||||
|
|
||||||
|
2009-12-01 Tatsuhiko Kubo <cubicdaiya@gmail.com>
|
||||||
|
|
||||||
|
* add test programs with googletest
|
||||||
|
|
||||||
|
* add sample of diff(uintdiff)
|
||||||
|
|
||||||
|
* 1.04 released
|
||||||
|
|
||||||
|
2009-10-02 Tatsuhiko Kubo <cubicdaiya@gmail.com>
|
||||||
|
|
||||||
|
* add function getLcsVec
|
||||||
|
|
||||||
|
* divide header files
|
||||||
|
|
||||||
|
* 1.03 released
|
||||||
|
|
||||||
|
2009-09-08 Tatsuhiko Kubo <cubicdaiya@gmail.com>
|
||||||
|
|
||||||
|
* rename editType to edit_t
|
||||||
|
|
||||||
|
* add print functions
|
||||||
|
|
||||||
|
* add functor of compare
|
||||||
|
|
||||||
|
* use 'using' declaration
|
||||||
|
|
||||||
|
* refactoring
|
||||||
|
|
||||||
|
* add ignore patterns for Mercurial
|
||||||
|
|
||||||
|
* 1.02 released.
|
||||||
|
|
||||||
|
2009-08-08 Tatsuhiko Kubo <cubicdaiya@gmail.com>
|
||||||
|
|
||||||
|
* append appropriate const keyword
|
||||||
|
|
||||||
|
* refactoring
|
||||||
|
|
||||||
|
* 1.01 released.
|
||||||
|
|
||||||
|
2009-07-04 Tatsuhiko Kubo <cubicdaiya@gmail.com>
|
||||||
|
|
||||||
|
* resolve problem memory leak occurs when default copy constructor set in motion.
|
||||||
|
|
||||||
|
* 1.00 released.
|
||||||
|
|
||||||
|
2009-06-08 Tatsuhiko Kubo <cubicdaiya@gmail.com>
|
||||||
|
|
||||||
|
* enhance readability
|
||||||
|
|
||||||
|
* change behavior when conflicted
|
||||||
|
|
||||||
|
* decliment parameter for patch function
|
||||||
|
|
||||||
|
* 0.07 released.
|
||||||
|
|
||||||
|
2009-05-08 Tatsuhiko Kubo <cubicdaiya@gmail.com>
|
||||||
|
|
||||||
|
* add flag for recording only editdistance
|
||||||
|
|
||||||
|
* add sample of unidiff for string (unistrdiff)
|
||||||
|
|
||||||
|
* add unserious diff. ver 0.03 has this feture.
|
||||||
|
|
||||||
|
* fix bug for merge
|
||||||
|
|
||||||
|
* add function getUniHunks
|
||||||
|
|
||||||
|
* 0.06 released.
|
||||||
|
|
||||||
|
2008-12-12 Tatsuhiko Kubo <cubicdaiya@gmail.com>
|
||||||
|
|
||||||
|
* add sample of diff3 (strdiff3, intdiff3)
|
||||||
|
|
||||||
|
* add diff3
|
||||||
|
|
||||||
|
* + -> - to - -> + with Unified Diff Format
|
||||||
|
|
||||||
|
* add function uniPatch. this function can patch with Unified Diff Format Data Structure
|
||||||
|
|
||||||
|
* dtl Import Unified Diff Format Data Structure from unidiff.cpp.
|
||||||
|
|
||||||
|
* fix bug. function check whether file exists(common.cpp)
|
||||||
|
|
||||||
|
* 0.05 released.
|
||||||
|
|
||||||
|
2008-11-10 Tatsuhiko Kubo <cubicdaiya@gmail.com>
|
||||||
|
|
||||||
|
* Improves accuracy of diff
|
||||||
|
|
||||||
|
* fix serious memory bug for patch
|
||||||
|
|
||||||
|
* changed type of argument in function fileExists(common.hpp, common.cpp)
|
||||||
|
|
||||||
|
* 0.04 released.
|
||||||
|
|
||||||
|
2008-11-06 Tatsuhiko Kubo <cubicdaiya@gmail.com>
|
||||||
|
|
||||||
|
* add erorr check for sample programs
|
||||||
|
|
||||||
|
* 0.03 released.
|
||||||
|
|
||||||
|
2008-10-31 Tatsuhiko Kubo <cubicdaiya@gmail.com>
|
||||||
|
|
||||||
|
* rename ChangLog to ChangeLog
|
||||||
|
|
||||||
|
* modifiy README
|
||||||
|
|
||||||
|
* output OK message on patch and fpatch
|
||||||
|
|
||||||
|
* 0.02 released.
|
||||||
|
|
||||||
|
2008-10-30 Tatsuhiko Kubo <cubicdaiya@gmail.com>
|
||||||
|
|
||||||
|
* 0.01 released.
|
||||||
|
|
683
README.md
Normal file
683
README.md
Normal file
@ -0,0 +1,683 @@
|
|||||||
|
# dtl
|
||||||
|
|
||||||
|
[](https://travis-ci.org/cubicdaiya/dtl)
|
||||||
|
|
||||||
|
`dtl` is the diff template library written in C++. The name of template is derived C++'s Template.
|
||||||
|
|
||||||
|
# Table of contents
|
||||||
|
|
||||||
|
* [Features](#features)
|
||||||
|
* [Getting started](#getting-started)
|
||||||
|
* [Compare two strings](#compare-two-strings)
|
||||||
|
* [Compare two data has arbitrary type](#compare-two-data-has-arbitrary-type)
|
||||||
|
* [Merge three sequences](#merge-three-sequences)
|
||||||
|
* [Patch function](#patch-function)
|
||||||
|
* [Difference as Unified Format](#difference-as-unified-format)
|
||||||
|
* [Compare large sequences](#compare-large-sequences)
|
||||||
|
* [Unserious difference](#unserious-difference)
|
||||||
|
* [Calculate only Edit Distance](#calculate-only-edit-distance)
|
||||||
|
* [Algorithm](#algorithm)
|
||||||
|
* [Computational complexity](#computational-complexity)
|
||||||
|
* [Comparison when difference between two sequences is very large](#comparison-when-difference-between-two-sequences-is-very-large)
|
||||||
|
* [Implementations with various programming languages](#implementations-with-various-programming-languages)
|
||||||
|
* [Examples](#examples)
|
||||||
|
* [strdiff](#strdiff)
|
||||||
|
* [intdiff](#intdiff)
|
||||||
|
* [unidiff](#unidiff)
|
||||||
|
* [unistrdiff](#unistrdiff)
|
||||||
|
* [strdiff3](#strdiff3)
|
||||||
|
* [intdiff3](#intdiff3)
|
||||||
|
* [patch](#patch)
|
||||||
|
* [fpatch](#fpatch)
|
||||||
|
* [Running tests](#running-tests)
|
||||||
|
* [Building test programs](#building-test-programs)
|
||||||
|
* [Running test programs](#running-test-programs)
|
||||||
|
* [License](#license)
|
||||||
|
|
||||||
|
# Features
|
||||||
|
|
||||||
|
`dtl` provides the functions for comparing two sequences have arbitrary type. But sequences must support random access\_iterator.
|
||||||
|
|
||||||
|
# Getting started
|
||||||
|
|
||||||
|
To start using this library, all you need to do is include `dtl.hpp`.
|
||||||
|
|
||||||
|
```c++
|
||||||
|
#include "dtl/dtl.hpp"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Compare two strings
|
||||||
|
|
||||||
|
First of all, calculate the difference between two strings.
|
||||||
|
|
||||||
|
```c++
|
||||||
|
typedef char elem;
|
||||||
|
typedef std::string sequence;
|
||||||
|
sequence A("abc");
|
||||||
|
sequence B("abd");
|
||||||
|
dtl::Diff< elem, sequence > d(A, B);
|
||||||
|
d.compose();
|
||||||
|
```
|
||||||
|
|
||||||
|
When the above code is run, `dtl` calculates the difference between A and B as Edit Distance and LCS and SES.
|
||||||
|
|
||||||
|
The meaning of these three terms is below.
|
||||||
|
|
||||||
|
| Edit Distance | Edit Distance is numerical value for declaring a difference between two sequences. |
|
||||||
|
|:--------------|:-----------------------------------------------------------------------------------|
|
||||||
|
| LCS | LCS stands for Longest Common Subsequence. |
|
||||||
|
| SES | SES stands for Shortest Edit Script. I mean SES is the shortest course of action for tranlating one sequence into another sequence.|
|
||||||
|
|
||||||
|
If one sequence is "abc" and another sequence is "abd", Edit Distance and LCS and SES is below.
|
||||||
|
|
||||||
|
| Edit Distance | 2 |
|
||||||
|
|:--------------|:----------------|
|
||||||
|
| LCS | ab |
|
||||||
|
| SES | C a C b D c A d |
|
||||||
|
|
||||||
|
* 「C」:Common
|
||||||
|
* 「D」:Delete
|
||||||
|
* 「A」:ADD
|
||||||
|
|
||||||
|
If you want to know in more detail, please see [examples/strdiff.cpp](https://github.com/cubicdaiya/dtl/blob/master/examples/strdiff.cpp).
|
||||||
|
|
||||||
|
This calculates Edit Distance and LCS and SES of two strings received as command line arguments and prints each.
|
||||||
|
|
||||||
|
When one string is "abc" and another string "abd", the output of `strdiff` is below.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ ./strdiff abc abd
|
||||||
|
editDistance:2
|
||||||
|
LCS:ab
|
||||||
|
SES
|
||||||
|
a
|
||||||
|
b
|
||||||
|
-c
|
||||||
|
+d
|
||||||
|
$
|
||||||
|
```
|
||||||
|
|
||||||
|
## Compare two data has arbitrary type
|
||||||
|
|
||||||
|
`dtl` can compare data has aribtrary type because of the C++'s template.
|
||||||
|
|
||||||
|
But the compared data type must support the random access\_iterator.
|
||||||
|
|
||||||
|
In the previous example, the string data compared,
|
||||||
|
|
||||||
|
`dtl` can also compare two int vectors like the example below.
|
||||||
|
|
||||||
|
```c++
|
||||||
|
int a[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
|
||||||
|
int b[10] = {3, 5, 1, 4, 5, 1, 7, 9, 6, 10};
|
||||||
|
std::vector<int> A(&a[0], &a[10]);
|
||||||
|
std::vector<int> B(&b[0], &b[10]);
|
||||||
|
dtl::Diff< int > d(A, B);
|
||||||
|
d.compose();
|
||||||
|
```
|
||||||
|
|
||||||
|
If you want to know in more detail, please see [examples/intdiff.cpp](https://github.com/cubicdaiya/dtl/blob/master/examples/intdiff.cpp).
|
||||||
|
|
||||||
|
## Merge three sequences
|
||||||
|
|
||||||
|
`dtl` has the diff3 function.
|
||||||
|
|
||||||
|
This function is that `dtl` merges three sequences.
|
||||||
|
|
||||||
|
Additionally `dtl` detects the confliction.
|
||||||
|
|
||||||
|
```c++
|
||||||
|
typedef char elem;
|
||||||
|
typedef std::string sequence;
|
||||||
|
sequence A("qqqabc");
|
||||||
|
sequence B("abc");
|
||||||
|
sequence C("abcdef");
|
||||||
|
dtl::Diff3<elem, sequence> diff3(A, B, C);
|
||||||
|
diff3.compose();
|
||||||
|
if (!diff3.merge()) {
|
||||||
|
std::cerr << "conflict." << std::endl;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
std::cout << "result:" << diff3.getMergedSequence() << std::endl;
|
||||||
|
```
|
||||||
|
|
||||||
|
When the above code is run, the output is below.
|
||||||
|
|
||||||
|
```console
|
||||||
|
result:qqqabcdef
|
||||||
|
```
|
||||||
|
|
||||||
|
If you want to know in more detail, please see [examples/strdiff3.cpp](https://github.com/cubicdaiya/dtl/blob/master/examples/strdiff3.cpp).
|
||||||
|
|
||||||
|
## Patch function
|
||||||
|
|
||||||
|
`dtl` can also translates one sequence to another sequence with SES.
|
||||||
|
|
||||||
|
```c++
|
||||||
|
typedef char elem;
|
||||||
|
typedef std::string sequence;
|
||||||
|
sequence A("abc");
|
||||||
|
sequence B("abd");
|
||||||
|
dtl::Diff<elem, sequence> d(A, B);
|
||||||
|
d.compose();
|
||||||
|
string s1(A);
|
||||||
|
string s2 = d.patch(s1);
|
||||||
|
```
|
||||||
|
|
||||||
|
When the above code is run, s2 becomes "abd".
|
||||||
|
The SES of A("abc") and B("abd") is below.
|
||||||
|
|
||||||
|
```console
|
||||||
|
Common a
|
||||||
|
Common b
|
||||||
|
Delete c
|
||||||
|
Add d
|
||||||
|
```
|
||||||
|
|
||||||
|
The patch function translates a sequence as argument with SES.
|
||||||
|
For this example, "abc" is translated to "abd" with above SES.
|
||||||
|
|
||||||
|
Please see dtl's header files about the data structure of SES.
|
||||||
|
|
||||||
|
## Difference as Unified Format
|
||||||
|
|
||||||
|
`dtl` can also treat difference as Unified Format. See the example below.
|
||||||
|
|
||||||
|
```c++
|
||||||
|
typedef char elem;
|
||||||
|
typedef std::string sequence;
|
||||||
|
sequence A("acbdeaqqqqqqqcbed");
|
||||||
|
sequence B("acebdabbqqqqqqqabed");
|
||||||
|
dtl::Diff<elem, sequence > d(A, B);
|
||||||
|
d.compose(); // construct an edit distance and LCS and SES
|
||||||
|
d.composeUnifiedHunks(); // construct a difference as Unified Format with SES.
|
||||||
|
d.printUnifiedFormat(); // print a difference as Unified Format.
|
||||||
|
```
|
||||||
|
|
||||||
|
The difference as Unified Format of "acbdeaqqqqqqqcbed" and "acebdabbqqqqqqqabed" is below.
|
||||||
|
|
||||||
|
```diff
|
||||||
|
@@ -1,9 +1,11 @@
|
||||||
|
a
|
||||||
|
c
|
||||||
|
+e
|
||||||
|
b
|
||||||
|
d
|
||||||
|
-e
|
||||||
|
a
|
||||||
|
+b
|
||||||
|
+b
|
||||||
|
q
|
||||||
|
q
|
||||||
|
q
|
||||||
|
@@ -11,7 +13,7 @@
|
||||||
|
q
|
||||||
|
q
|
||||||
|
q
|
||||||
|
-c
|
||||||
|
+a
|
||||||
|
b
|
||||||
|
e
|
||||||
|
d
|
||||||
|
```
|
||||||
|
|
||||||
|
The data structure Unified Format is below.
|
||||||
|
|
||||||
|
```c++
|
||||||
|
/**
|
||||||
|
* Structure of Unified Format Hunk
|
||||||
|
*/
|
||||||
|
template <typename sesElem>
|
||||||
|
struct uniHunk {
|
||||||
|
int a, b, c, d; // @@ -a,b +c,d @@
|
||||||
|
std::vector<sesElem> common[2]; // anteroposterior commons on changes
|
||||||
|
std::vector<sesElem> change; // changes
|
||||||
|
int inc_dec_count; // count of increace and decrease
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
The actual blocks of Unified Format is this structure's vector.
|
||||||
|
|
||||||
|
If you want to know in more detail, please see [examples/unistrdiff.cpp](https://github.com/cubicdaiya/dtl/blob/master/examples/unistrdiff.cpp)
|
||||||
|
and [examples/unidiff.cpp](https://github.com/cubicdaiya/dtl/blob/master/examples/unidiff.cpp) and dtl's header files.
|
||||||
|
|
||||||
|
In addtion, `dtl` has the function translates one sequence to another sequence with Unified Format.
|
||||||
|
|
||||||
|
```c++
|
||||||
|
typedef char elem;
|
||||||
|
typedef std::string sequence;
|
||||||
|
sequence A("abc");
|
||||||
|
sequence B("abd");
|
||||||
|
dtl::Diff<elem, sequence> d(A, B);
|
||||||
|
d.compose();
|
||||||
|
d.composeUnifiedHunks()
|
||||||
|
string s1(A);
|
||||||
|
string s2 = d.UniPatch(s1);
|
||||||
|
```
|
||||||
|
|
||||||
|
When the above code is run, s2 becomes "abd".
|
||||||
|
The uniPatch function translates a sequence as argument with Unified Format blocks.
|
||||||
|
|
||||||
|
For this example, "abc" is translated to "abd" with the Unified Format block below.
|
||||||
|
|
||||||
|
```diff
|
||||||
|
@@ -1,3 +1,3 @@
|
||||||
|
a
|
||||||
|
b
|
||||||
|
-c
|
||||||
|
+d
|
||||||
|
```
|
||||||
|
|
||||||
|
## Compare large sequences
|
||||||
|
|
||||||
|
When compare two large sequences, `dtl` can optimizes the calculation of difference with the onHuge function.
|
||||||
|
|
||||||
|
But this function is could use when the compared data type is std::vector.
|
||||||
|
|
||||||
|
When you use this function, you may call this function before calling compose function.
|
||||||
|
|
||||||
|
```c++
|
||||||
|
typedef char elem;
|
||||||
|
typedef std::vector<elem> sequence;
|
||||||
|
sequence A;
|
||||||
|
sequence B;
|
||||||
|
/* ・・・ */
|
||||||
|
dtl::Diff< elem, sequence > d(A, B);
|
||||||
|
d.onHuge();
|
||||||
|
d.compose();
|
||||||
|
```
|
||||||
|
|
||||||
|
## Unserious difference
|
||||||
|
|
||||||
|
The calculation of difference is very heavy.
|
||||||
|
`dtl` uses An O(NP) Sequence Comparison Algorithm.
|
||||||
|
|
||||||
|
Though this Algorithm is sufficiently fast,
|
||||||
|
when difference between two sequences is very large,
|
||||||
|
|
||||||
|
the calculation of LCS and SES needs massive amounts of memory.
|
||||||
|
|
||||||
|
`dtl` avoids above-described problem by dividing each sequence into plural subsequences
|
||||||
|
and joining the difference of each subsequence finally.
|
||||||
|
|
||||||
|
As this way repeats allocating massive amounts of memory,
|
||||||
|
`dtl` provides other way. It is the way of calculating unserious difference.
|
||||||
|
|
||||||
|
For example, The normal SES of "abc" and "abd" is below.
|
||||||
|
|
||||||
|
```console
|
||||||
|
Common a
|
||||||
|
Common b
|
||||||
|
Delete c
|
||||||
|
Add d
|
||||||
|
```
|
||||||
|
|
||||||
|
The unserious SES of "abc" and "abd" is below.
|
||||||
|
|
||||||
|
```console
|
||||||
|
Delete a
|
||||||
|
Delete b
|
||||||
|
Delete c
|
||||||
|
Add a
|
||||||
|
Add b
|
||||||
|
Add d
|
||||||
|
```
|
||||||
|
|
||||||
|
Of course, when "abc" and "abd" are compared with `dtl`, above difference is not derived.
|
||||||
|
|
||||||
|
`dtl` calculates the unserious difference when `dtl` judges the calculation of LCS and SES
|
||||||
|
needs massive amounts of memory and unserious difference function is ON.
|
||||||
|
|
||||||
|
`dtl` joins the calculated difference before `dtl` judges it and unserious difference finally.
|
||||||
|
|
||||||
|
As a result, all difference is not unserious difference when unserious difference function is ON.
|
||||||
|
|
||||||
|
When you use this function, you may call this function before calling compose function.
|
||||||
|
|
||||||
|
```c++
|
||||||
|
typedef char elem;
|
||||||
|
typedef std::string sequence;
|
||||||
|
sequence A("abc");
|
||||||
|
sequence B("abd");
|
||||||
|
dtl::Diff< elem, sequence > d(A, B);
|
||||||
|
d.onUnserious();
|
||||||
|
d.compose();
|
||||||
|
```
|
||||||
|
|
||||||
|
## Calculate only Edit Distance
|
||||||
|
|
||||||
|
As using onOnlyEditDistance, `dtl` calculates the only edit distance.
|
||||||
|
|
||||||
|
If you need only edit distance, you may use this function,
|
||||||
|
because the calculation of edit distance is lighter than the calculation of LCS and SES.
|
||||||
|
|
||||||
|
When you use this function, you may call this function before calling compose function.
|
||||||
|
|
||||||
|
```c++
|
||||||
|
typedef char elem;
|
||||||
|
typedef std::string sequence;
|
||||||
|
sequence A("abc");
|
||||||
|
sequence B("abd");
|
||||||
|
dtl::Diff< elem, sequence > d(A, B);
|
||||||
|
d.onOnlyEditDistance();
|
||||||
|
d.compose();
|
||||||
|
```
|
||||||
|
|
||||||
|
# Algorithm
|
||||||
|
|
||||||
|
The algorithm `dtl` uses is based on "An O(NP) Sequence Comparison Algorithm" by described by Sun Wu, Udi Manber and Gene Myers.
|
||||||
|
|
||||||
|
An O(NP) Sequence Comparison Algorithm(following, Wu's O(NP) Algorithm) is the efficient algorithm for comparing two sequences.
|
||||||
|
|
||||||
|
## Computational complexity
|
||||||
|
|
||||||
|
The computational complexity of Wu's O(NP) Algorithm is averagely O(N+PD), in the worst case, is O(NP).
|
||||||
|
|
||||||
|
## Comparison when difference between two sequences is very large
|
||||||
|
|
||||||
|
Calculating LCS and SES efficiently at any time is a little difficult.
|
||||||
|
|
||||||
|
Because that the calculation of LCS and SES needs massive amounts of memory when a difference between two sequences is very large.
|
||||||
|
|
||||||
|
The program uses that algorithm don't consider that will burst in the worst case.
|
||||||
|
|
||||||
|
`dtl` avoids above-described problem by dividing each sequence into plural subsequences and joining the difference of each subsequence finally.(This feature is supported after version 0.04)
|
||||||
|
|
||||||
|
## Implementations with various programming languages
|
||||||
|
|
||||||
|
There are the Wu's O(NP) Algorithm implementations with various programming languages below.
|
||||||
|
|
||||||
|
https://github.com/cubicdaiya/onp
|
||||||
|
|
||||||
|
# Examples
|
||||||
|
|
||||||
|
There are examples in [dtl/examples](https://github.com/cubicdaiya/dtl/tree/master/examples).
|
||||||
|
`dtl` uses SCons for building examples and tests. If you build and run examples and tests, install SCons.
|
||||||
|
|
||||||
|
## strdiff
|
||||||
|
|
||||||
|
`strdiff` calculates a difference between two string sequences, but multi byte is not supported.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ cd dtl/examples
|
||||||
|
$ scons strdiff
|
||||||
|
$ ./strdiff acbdeacbed acebdabbabed
|
||||||
|
editDistance:6
|
||||||
|
LCS:acbdabed
|
||||||
|
SES
|
||||||
|
a
|
||||||
|
c
|
||||||
|
+ e
|
||||||
|
b
|
||||||
|
d
|
||||||
|
- e
|
||||||
|
a
|
||||||
|
- c
|
||||||
|
b
|
||||||
|
+ b
|
||||||
|
+ a
|
||||||
|
+ b
|
||||||
|
e
|
||||||
|
d
|
||||||
|
$
|
||||||
|
```
|
||||||
|
|
||||||
|
## intdiff
|
||||||
|
|
||||||
|
`intdiff` calculates a diffrence between two int arrays sequences.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ cd dtl/examples
|
||||||
|
$ scons intdiff
|
||||||
|
$ ./intdiff # There are data in intdiff.cpp
|
||||||
|
1 2 3 4 5 6 7 8 9 10
|
||||||
|
3 5 1 4 5 1 7 9 6 10
|
||||||
|
editDistance:8
|
||||||
|
LCS: 3 4 5 7 9 10
|
||||||
|
SES
|
||||||
|
- 1
|
||||||
|
- 2
|
||||||
|
3
|
||||||
|
+ 5
|
||||||
|
+ 1
|
||||||
|
4
|
||||||
|
5
|
||||||
|
- 6
|
||||||
|
+ 1
|
||||||
|
7
|
||||||
|
- 8
|
||||||
|
9
|
||||||
|
+ 6
|
||||||
|
10
|
||||||
|
$
|
||||||
|
```
|
||||||
|
|
||||||
|
## unidiff
|
||||||
|
|
||||||
|
`unidiff` calculates a diffrence between two text file sequences,
|
||||||
|
and output the difference between files with unified format.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ cd dtl/examples
|
||||||
|
$ scons unidiff
|
||||||
|
$ cat a.txt
|
||||||
|
a
|
||||||
|
e
|
||||||
|
c
|
||||||
|
z
|
||||||
|
z
|
||||||
|
d
|
||||||
|
e
|
||||||
|
f
|
||||||
|
a
|
||||||
|
b
|
||||||
|
c
|
||||||
|
d
|
||||||
|
e
|
||||||
|
f
|
||||||
|
g
|
||||||
|
h
|
||||||
|
i
|
||||||
|
$ cat b.txt
|
||||||
|
a
|
||||||
|
d
|
||||||
|
e
|
||||||
|
c
|
||||||
|
f
|
||||||
|
e
|
||||||
|
a
|
||||||
|
b
|
||||||
|
c
|
||||||
|
d
|
||||||
|
e
|
||||||
|
f
|
||||||
|
g
|
||||||
|
h
|
||||||
|
i
|
||||||
|
$ ./unidiff a.txt b.txt
|
||||||
|
--- a.txt 2008-08-26 07:03:28 +0900
|
||||||
|
+++ b.txt 2008-08-26 03:02:42 +0900
|
||||||
|
@@ -1,11 +1,9 @@
|
||||||
|
a
|
||||||
|
-e
|
||||||
|
-c
|
||||||
|
-z
|
||||||
|
-z
|
||||||
|
d
|
||||||
|
e
|
||||||
|
+c
|
||||||
|
f
|
||||||
|
+e
|
||||||
|
a
|
||||||
|
b
|
||||||
|
c
|
||||||
|
$
|
||||||
|
```
|
||||||
|
|
||||||
|
## unistrdiff
|
||||||
|
|
||||||
|
`unistrdiff` calculates a diffrence between two string sequences.
|
||||||
|
and output the difference between strings with unified format.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ cd dtl/examples
|
||||||
|
$ scons unistrdiff
|
||||||
|
$ ./unistrdiff acbdeacbed acebdabbabed
|
||||||
|
editDistance:6
|
||||||
|
LCS:acbdabed
|
||||||
|
@@ -1,10 +1,12 @@
|
||||||
|
a
|
||||||
|
c
|
||||||
|
+e
|
||||||
|
b
|
||||||
|
d
|
||||||
|
-e
|
||||||
|
a
|
||||||
|
-c
|
||||||
|
b
|
||||||
|
+b
|
||||||
|
+a
|
||||||
|
+b
|
||||||
|
e
|
||||||
|
d
|
||||||
|
$
|
||||||
|
```
|
||||||
|
|
||||||
|
## strdiff3
|
||||||
|
|
||||||
|
`strdiff3` merges three string sequence and output the merged sequence.
|
||||||
|
When the confliction has occured, output the string "conflict.".
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ cd dtl/examples
|
||||||
|
$ scons strdiff3
|
||||||
|
$ ./strdiff3 qabc abc abcdef
|
||||||
|
result:qabcdef
|
||||||
|
$
|
||||||
|
```
|
||||||
|
|
||||||
|
There is a output below when conflict occured.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ ./strdiff3 adc abc aec
|
||||||
|
conflict.
|
||||||
|
$
|
||||||
|
```
|
||||||
|
|
||||||
|
## intdiff3
|
||||||
|
|
||||||
|
`intdiff3` merges three integer sequence(vector) and output the merged sequence.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ cd dtl/examples
|
||||||
|
$ scons intdiff3
|
||||||
|
$ ./intdiff3
|
||||||
|
a:1 2 3 4 5 6 7 3 9 10
|
||||||
|
b:1 2 3 4 5 6 7 8 9 10
|
||||||
|
c:1 2 3 9 5 6 7 8 9 10
|
||||||
|
s:1 2 3 9 5 6 7 3 9 10
|
||||||
|
intdiff3 OK
|
||||||
|
$
|
||||||
|
```
|
||||||
|
|
||||||
|
## patch
|
||||||
|
|
||||||
|
`patch` is the test program. Supposing that there are two strings is called by A and B,
|
||||||
|
`patch` translates A to B with Shortest Edit Script or unified format difference.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ cd dtl/examples
|
||||||
|
$ scons patch
|
||||||
|
$ ./patch abc abd
|
||||||
|
before:abc
|
||||||
|
after :abd
|
||||||
|
patch successed
|
||||||
|
before:abc
|
||||||
|
after :abd
|
||||||
|
unipatch successed
|
||||||
|
$
|
||||||
|
```
|
||||||
|
|
||||||
|
## fpatch
|
||||||
|
|
||||||
|
`fpatch` is the test program. Supposing that there are two files is called by A and B,
|
||||||
|
`fpatch` translates A to B with Shortest Edit Script or unified format difference.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ cd dtl/examples
|
||||||
|
$ scons fpatch
|
||||||
|
$ cat a.txt
|
||||||
|
a
|
||||||
|
e
|
||||||
|
c
|
||||||
|
z
|
||||||
|
z
|
||||||
|
d
|
||||||
|
e
|
||||||
|
f
|
||||||
|
a
|
||||||
|
b
|
||||||
|
c
|
||||||
|
d
|
||||||
|
e
|
||||||
|
f
|
||||||
|
g
|
||||||
|
h
|
||||||
|
i
|
||||||
|
$ cat b.txt
|
||||||
|
$ cat b.txt
|
||||||
|
a
|
||||||
|
d
|
||||||
|
e
|
||||||
|
c
|
||||||
|
f
|
||||||
|
e
|
||||||
|
a
|
||||||
|
b
|
||||||
|
c
|
||||||
|
d
|
||||||
|
e
|
||||||
|
f
|
||||||
|
g
|
||||||
|
h
|
||||||
|
i
|
||||||
|
$ ./fpatch a.txt b.txt
|
||||||
|
fpatch successed
|
||||||
|
unipatch successed
|
||||||
|
$
|
||||||
|
```
|
||||||
|
|
||||||
|
# Running tests
|
||||||
|
|
||||||
|
`dtl` uses [googletest](http://code.google.com/p/googletest/) and [SCons](http://www.scons.org/) with testing dtl-self.
|
||||||
|
|
||||||
|
# Building test programs
|
||||||
|
|
||||||
|
If you build test programs for `dtl`, run `scons` in test direcotry.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ GTEST_ROOT=${gtest_root_dir} scons
|
||||||
|
```
|
||||||
|
|
||||||
|
# Running test programs
|
||||||
|
|
||||||
|
If you run all tests for `dtl`, run 'scons check' in test direcotry. (it is necessary that gtest is compiled)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ GTEST_ROOT=${gtest_root_dir} scons check
|
||||||
|
```
|
||||||
|
|
||||||
|
If you run sectional tests, you may exeucte `dtl_test` directly after you run `scons`.
|
||||||
|
Following command is the example for testing only Strdifftest.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ ./dtl_test --gtest_filter='Strdifftest.*'
|
||||||
|
```
|
||||||
|
|
||||||
|
`--gtest-filters` is the function of googletest. googletest has many useful functions for testing software flexibly.
|
||||||
|
If you want to know other functions of googletest, run `./dtl_test --help`.
|
||||||
|
|
||||||
|
|
||||||
|
# License
|
||||||
|
|
||||||
|
Please read the file [COPYING](https://github.com/cubicdaiya/dtl/blob/master/COPYING).
|
7
SConstruct
Normal file
7
SConstruct
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
import os
|
||||||
|
|
||||||
|
# install script
|
||||||
|
|
||||||
|
prefix = ARGUMENTS.get('prefix', '/usr/local')
|
||||||
|
headers = Glob('dtl/*.hpp')
|
||||||
|
Alias('install', Install(os.path.join(prefix, 'dtl', 'include'), headers))
|
692
dtl/Diff.hpp
Normal file
692
dtl/Diff.hpp
Normal 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
dtl/Diff3.hpp
Normal file
245
dtl/Diff3.hpp
Normal 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
dtl/Lcs.hpp
Normal file
55
dtl/Lcs.hpp
Normal 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
dtl/Sequence.hpp
Normal file
65
dtl/Sequence.hpp
Normal 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
dtl/Ses.hpp
Normal file
132
dtl/Ses.hpp
Normal 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
dtl/dtl.hpp
Normal file
47
dtl/dtl.hpp
Normal 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
dtl/functors.hpp
Normal file
137
dtl/functors.hpp
Normal 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
dtl/variables.hpp
Normal file
142
dtl/variables.hpp
Normal 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
|
42
examples/SConstruct
Normal file
42
examples/SConstruct
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
import os
|
||||||
|
|
||||||
|
# SConstruct for dtl examples
|
||||||
|
|
||||||
|
env = Environment(CPPPATH='..')
|
||||||
|
debug = ARGUMENTS.get('debug', 'n')
|
||||||
|
if debug == 'y' or debug == 'yes':
|
||||||
|
env.Append(CPPFLAGS = ['-Wall', '-g'])
|
||||||
|
else:
|
||||||
|
env.Append(CPPFLAGS = ['-Wall', '-O2'])
|
||||||
|
|
||||||
|
if os.sys.platform != "win32":
|
||||||
|
env.Append(CPPDEFINES = ['HAVE_UNISTD_H'])
|
||||||
|
|
||||||
|
conf = Configure(env);
|
||||||
|
|
||||||
|
if not conf.CheckCXX():
|
||||||
|
print "The C++ compiler is not installed!"
|
||||||
|
Exit(1)
|
||||||
|
|
||||||
|
libs = ['stdc++']
|
||||||
|
for lib in libs:
|
||||||
|
if not conf.CheckLib(lib):
|
||||||
|
print "library " + lib + " not installed!"
|
||||||
|
Exit(1)
|
||||||
|
|
||||||
|
conf.Finish()
|
||||||
|
|
||||||
|
targets = { 'strdiff' : ['strdiff.cpp', 'common.cpp'], # diff between two string sequences
|
||||||
|
'intdiff' : ['intdiff.cpp'], # diff between two integer sequences
|
||||||
|
'unidiff' : ['unidiff.cpp', 'common.cpp'], # unified diff between two files
|
||||||
|
'unistrdiff' : ['unistrdiff.cpp', 'common.cpp'], # unified diff between two strings
|
||||||
|
'bdiff' : ['bdiff.cpp', 'common.cpp'], # diff between two byte sequences
|
||||||
|
'strdiff3' : ['strdiff3.cpp', 'common.cpp'], # three-way string diff program using dtl
|
||||||
|
'intdiff3' : ['intdiff3.cpp'], # three-way integer diff program using dtl
|
||||||
|
'patch' : ['patch.cpp', 'common.cpp'], # string patch program using dtl
|
||||||
|
'fpatch' : ['fpatch.cpp', 'common.cpp'], # file patch program using dtl
|
||||||
|
'st2ses' : ['st2ses.cpp', 'common.cpp'], # convert SES format file to SES instance
|
||||||
|
'strdiff_cp' : ['strdiff_cp.cpp', 'common.cpp'], # diff between two string sequences with custom printer
|
||||||
|
}
|
||||||
|
|
||||||
|
[ env.Program(target, targets[target]) for target in targets ]
|
73
examples/bdiff.cpp
Normal file
73
examples/bdiff.cpp
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
|
||||||
|
#include <dtl/dtl.hpp>
|
||||||
|
#include "common.hpp"
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <vector>
|
||||||
|
#include <string>
|
||||||
|
#include <cstdio>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#ifdef HAVE_UNISTD_H
|
||||||
|
#include <unistd.h>
|
||||||
|
#endif // HAVE_UNISTD_H
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
using dtl::Diff;
|
||||||
|
|
||||||
|
typedef unsigned char elem;
|
||||||
|
typedef vector< elem > sequence;
|
||||||
|
|
||||||
|
static int create_byte_seq(const char *fs, sequence& seq);
|
||||||
|
static int create_byte_seq(const char *fs, sequence& seq)
|
||||||
|
{
|
||||||
|
int fd;
|
||||||
|
int siz;
|
||||||
|
elem buf[BUFSIZ];
|
||||||
|
if ((fd = open(fs, O_RDONLY)) == -1) {
|
||||||
|
cout << "Opening failed." << endl;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
while ((siz = read(fd, buf, sizeof(buf))) > 0) {
|
||||||
|
for (int i=0;i<siz;++i) {
|
||||||
|
seq.push_back(buf[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (siz < 0) {
|
||||||
|
close(fd);
|
||||||
|
cout << "Read error." << endl;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
close(fd);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
|
||||||
|
if (isFewArgs(argc)) {
|
||||||
|
cerr << "Too few arguments." << endl;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
string fs1(argv[1]);
|
||||||
|
string fs2(argv[2]);
|
||||||
|
sequence seq1;
|
||||||
|
sequence seq2;
|
||||||
|
|
||||||
|
create_byte_seq(fs1.c_str(), seq1);
|
||||||
|
create_byte_seq(fs2.c_str(), seq2);
|
||||||
|
|
||||||
|
Diff< elem, sequence > d(seq1, seq2);
|
||||||
|
d.compose();
|
||||||
|
|
||||||
|
if (d.getEditDistance() == 0) {
|
||||||
|
cout << fs1 << " is the same as " << fs2 << endl;
|
||||||
|
} else {
|
||||||
|
cout << fs1 << " is different from " << fs2 << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
20
examples/common.cpp
Normal file
20
examples/common.cpp
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
|
||||||
|
#include "common.hpp"
|
||||||
|
|
||||||
|
bool isFileExist (string& fs) {
|
||||||
|
FILE *fp;
|
||||||
|
if ((fp = fopen(fs.c_str(), "r")) == NULL) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
fclose(fp);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isFewArgs (int argc, int limit) {
|
||||||
|
bool ret = false;
|
||||||
|
if (argc < limit) {
|
||||||
|
ret = true;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
13
examples/common.hpp
Normal file
13
examples/common.hpp
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
|
||||||
|
#ifndef DTL_EXAMPLE_COMMON_H
|
||||||
|
#define DTL_EXAMPLE_COMMON_H
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <cstdio>
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
bool isFileExist (string& fs);
|
||||||
|
bool isFewArgs (int argc, int limit = 3);
|
||||||
|
|
||||||
|
#endif
|
73
examples/fpatch.cpp
Normal file
73
examples/fpatch.cpp
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
|
||||||
|
#include <dtl/dtl.hpp>
|
||||||
|
#include "common.hpp"
|
||||||
|
#include <iostream>
|
||||||
|
#include <sstream>
|
||||||
|
#include <fstream>
|
||||||
|
#include <vector>
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
using dtl::Diff;
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]){
|
||||||
|
|
||||||
|
if (isFewArgs(argc)) {
|
||||||
|
cerr << "Too few arguments." << endl;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
string A(argv[1]);
|
||||||
|
string B(argv[2]);
|
||||||
|
bool fileExist = true;
|
||||||
|
|
||||||
|
if (!isFileExist(A)) {
|
||||||
|
cerr << "file A does not exist" << endl;
|
||||||
|
fileExist = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isFileExist(B)) {
|
||||||
|
cerr << "file B does not exist" << endl;
|
||||||
|
fileExist = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!fileExist) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef string elem;
|
||||||
|
typedef vector< elem > sequence;
|
||||||
|
|
||||||
|
ifstream Aifs(A.c_str());
|
||||||
|
ifstream Bifs(B.c_str());
|
||||||
|
elem buf;
|
||||||
|
sequence ALines, BLines;
|
||||||
|
ostringstream ossLine, ossInfo;
|
||||||
|
|
||||||
|
while(getline(Aifs, buf)){
|
||||||
|
ALines.push_back(buf);
|
||||||
|
}
|
||||||
|
while(getline(Bifs, buf)){
|
||||||
|
BLines.push_back(buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
Diff< elem > d(ALines, BLines);
|
||||||
|
d.compose();
|
||||||
|
|
||||||
|
sequence s1 = ALines;
|
||||||
|
sequence s2 = d.patch(s1);
|
||||||
|
|
||||||
|
// fpatch
|
||||||
|
assert(BLines == s2);
|
||||||
|
cout << "fpatch succeeded" << endl;
|
||||||
|
|
||||||
|
d.composeUnifiedHunks();
|
||||||
|
sequence s3 = d.uniPatch(s1);
|
||||||
|
|
||||||
|
// unipatch
|
||||||
|
assert(BLines == s3);
|
||||||
|
cout << "unipatch succeeded" << endl;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
49
examples/intdiff.cpp
Normal file
49
examples/intdiff.cpp
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <vector>
|
||||||
|
#include <dtl/dtl.hpp>
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
using dtl::Diff;
|
||||||
|
|
||||||
|
int main(int, char**){
|
||||||
|
|
||||||
|
int a[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
|
||||||
|
int b[] = {3, 5, 1, 4, 5, 1, 7, 9, 6, 10};
|
||||||
|
int asiz = sizeof(a) / sizeof(int);
|
||||||
|
int bsiz = sizeof(b) / sizeof(int);
|
||||||
|
for (int i=0;i<asiz;++i) {
|
||||||
|
cout << a[i] << " ";
|
||||||
|
}
|
||||||
|
cout << endl;
|
||||||
|
for (int i=0;i<bsiz;++i) {
|
||||||
|
cout << b[i] << " ";
|
||||||
|
}
|
||||||
|
cout << endl;
|
||||||
|
|
||||||
|
typedef int elem;
|
||||||
|
typedef vector< int > sequence;
|
||||||
|
|
||||||
|
sequence A(&a[0], &a[asiz]);
|
||||||
|
sequence B(&b[0], &b[bsiz]);
|
||||||
|
Diff< elem > d(A, B);
|
||||||
|
d.compose();
|
||||||
|
|
||||||
|
// editDistance
|
||||||
|
cout << "editDistance:" << d.getEditDistance() << endl;
|
||||||
|
|
||||||
|
// Longest Common Subsequence
|
||||||
|
sequence lcs_v = d.getLcsVec();
|
||||||
|
cout << "LCS: ";
|
||||||
|
for (sequence::iterator vit=lcs_v.begin();vit!=lcs_v.end();++vit) {
|
||||||
|
cout << *vit << " ";
|
||||||
|
}
|
||||||
|
cout << endl;
|
||||||
|
|
||||||
|
// Shortest Edit Script
|
||||||
|
cout << "SES" << endl;
|
||||||
|
d.printSES();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
57
examples/intdiff3.cpp
Normal file
57
examples/intdiff3.cpp
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
|
||||||
|
#include <dtl/dtl.hpp>
|
||||||
|
#include <iostream>
|
||||||
|
#include <vector>
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
using dtl::Diff3;
|
||||||
|
|
||||||
|
int main(int, char**) {
|
||||||
|
|
||||||
|
int a[10] = {1, 2, 3, 4, 5, 6, 7, 3, 9, 10};
|
||||||
|
int b[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
|
||||||
|
int c[10] = {1, 2, 3, 9, 5, 6, 7, 8, 9, 10};
|
||||||
|
int answer[10] = {1, 2, 3, 9, 5, 6, 7, 3, 9, 10};
|
||||||
|
|
||||||
|
cout << "a:";
|
||||||
|
for (int i=0;i<10;++i) {
|
||||||
|
cout << a[i] << " ";
|
||||||
|
}
|
||||||
|
cout << endl;
|
||||||
|
cout << "b:";
|
||||||
|
for (int i=0;i<10;++i) {
|
||||||
|
cout << b[i] << " ";
|
||||||
|
}
|
||||||
|
cout << endl;
|
||||||
|
cout << "c:";
|
||||||
|
for (int i=0;i<10;++i) {
|
||||||
|
cout << c[i] << " ";
|
||||||
|
}
|
||||||
|
cout << endl;
|
||||||
|
|
||||||
|
typedef int elem;
|
||||||
|
typedef vector< int > sequence;
|
||||||
|
sequence A(&a[0], &a[10]);
|
||||||
|
sequence B(&b[0], &b[10]);
|
||||||
|
sequence C(&c[0], &c[10]);
|
||||||
|
sequence Answer(&answer[0], &answer[10]);
|
||||||
|
Diff3< elem > diff3(A, B, C);
|
||||||
|
diff3.compose();
|
||||||
|
if (!diff3.merge()) {
|
||||||
|
cerr << "conflict." << endl;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
sequence s = diff3.getMergedSequence();
|
||||||
|
cout << "s:";
|
||||||
|
for (sequence::iterator it=s.begin();it!=s.end();++it) {
|
||||||
|
cout << *it << " ";
|
||||||
|
}
|
||||||
|
cout << endl;
|
||||||
|
|
||||||
|
assert(s == Answer);
|
||||||
|
cout << "intdiff3 OK" << endl;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
44
examples/patch.cpp
Normal file
44
examples/patch.cpp
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
|
||||||
|
#include <dtl/dtl.hpp>
|
||||||
|
#include "common.hpp"
|
||||||
|
#include <iostream>
|
||||||
|
#include <vector>
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
using dtl::Diff;
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) {
|
||||||
|
|
||||||
|
if (isFewArgs(argc)) {
|
||||||
|
cerr << "Too few arguments." << endl;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef char elem;
|
||||||
|
typedef string sequence;
|
||||||
|
|
||||||
|
sequence A(argv[1]);
|
||||||
|
sequence B(argv[2]);
|
||||||
|
|
||||||
|
Diff< elem, sequence > d(A, B);
|
||||||
|
d.compose();
|
||||||
|
|
||||||
|
sequence s1(A);
|
||||||
|
sequence s2 = d.patch(s1);
|
||||||
|
d.composeUnifiedHunks();
|
||||||
|
sequence s3 = d.uniPatch(s1);
|
||||||
|
|
||||||
|
cout << "before:" << s1 << endl;
|
||||||
|
cout << "after :" << s2 << endl;
|
||||||
|
assert(B == s2);
|
||||||
|
cout << "patch succeeded" << endl;
|
||||||
|
|
||||||
|
cout << "before:" << s1 << endl;
|
||||||
|
cout << "after :" << s3 << endl;
|
||||||
|
assert(B == s3);
|
||||||
|
cout << "unipatch succeeded" << endl;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
26
examples/printers.hpp
Normal file
26
examples/printers.hpp
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
#ifndef DTL_PRINTERS
|
||||||
|
#define DTL_PRINTERS
|
||||||
|
|
||||||
|
template <typename sesElem, typename stream = ostream >
|
||||||
|
class customChangePrinter : public Printer < sesElem, stream >
|
||||||
|
{
|
||||||
|
public :
|
||||||
|
customChangePrinter () : Printer < sesElem, stream > () {}
|
||||||
|
customChangePrinter (stream& out) : Printer < sesElem, stream > (out) {}
|
||||||
|
~customChangePrinter () {}
|
||||||
|
void operator() (const sesElem& se) const {
|
||||||
|
switch (se.second.type) {
|
||||||
|
case SES_ADD:
|
||||||
|
this->out_ << "Add: " << se.first << endl;
|
||||||
|
break;
|
||||||
|
case SES_DELETE:
|
||||||
|
this->out_ << "Delete: " << se.first << endl;
|
||||||
|
break;
|
||||||
|
case SES_COMMON:
|
||||||
|
this->out_ << "Common: " << se.first << endl;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // DTL_PRINTERS
|
35
examples/st2ses.cpp
Normal file
35
examples/st2ses.cpp
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
|
||||||
|
#include <dtl/dtl.hpp>
|
||||||
|
#include "common.hpp"
|
||||||
|
#include <iostream>
|
||||||
|
#include <fstream>
|
||||||
|
#include <sstream>
|
||||||
|
#include <vector>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
using namespace dtl;
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]){
|
||||||
|
|
||||||
|
if (isFewArgs(argc, 2)) {
|
||||||
|
cerr << "Too few arguments." << endl;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef string elem;
|
||||||
|
typedef vector< string > sequence;
|
||||||
|
|
||||||
|
string s(argv[1]);
|
||||||
|
|
||||||
|
if (!isFileExist(s)) {
|
||||||
|
cerr << s << " is invalid." << endl;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ifstream fs(s.c_str());
|
||||||
|
const Ses< elem > ses = Diff< elem, sequence >::composeSesFromStream< ifstream >(fs);
|
||||||
|
dtl::Diff< elem, sequence >::printSES(ses);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
42
examples/strdiff.cpp
Normal file
42
examples/strdiff.cpp
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
|
||||||
|
#include <dtl/dtl.hpp>
|
||||||
|
#include "common.hpp"
|
||||||
|
#include <iostream>
|
||||||
|
#include <vector>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
using dtl::Diff;
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]){
|
||||||
|
|
||||||
|
if (isFewArgs(argc)) {
|
||||||
|
cerr << "Too few arguments." << endl;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef char elem;
|
||||||
|
typedef string sequence;
|
||||||
|
|
||||||
|
sequence A(argv[1]);
|
||||||
|
sequence B(argv[2]);
|
||||||
|
|
||||||
|
Diff< elem, sequence > d(A, B);
|
||||||
|
//d.onOnlyEditDistance();
|
||||||
|
d.compose();
|
||||||
|
|
||||||
|
// editDistance
|
||||||
|
cout << "editDistance:" << d.getEditDistance() << endl;
|
||||||
|
|
||||||
|
// Longest Common Subsequence
|
||||||
|
vector< elem > lcs_v = d.getLcsVec();
|
||||||
|
sequence lcs_s(lcs_v.begin(), lcs_v.end());
|
||||||
|
cout << "LCS:" << lcs_s << endl;
|
||||||
|
|
||||||
|
// Shortest Edit Script
|
||||||
|
cout << "SES" << endl;
|
||||||
|
d.printSES();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
35
examples/strdiff3.cpp
Normal file
35
examples/strdiff3.cpp
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
|
||||||
|
#include <dtl/dtl.hpp>
|
||||||
|
#include "common.hpp"
|
||||||
|
#include <iostream>
|
||||||
|
#include <vector>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
using dtl::Diff3;
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]){
|
||||||
|
|
||||||
|
if (isFewArgs(argc, 4)) {
|
||||||
|
cerr << "Too few arguments." << endl;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef char elem;
|
||||||
|
typedef string sequence;
|
||||||
|
|
||||||
|
sequence A(argv[1]);
|
||||||
|
sequence B(argv[2]);
|
||||||
|
sequence C(argv[3]);
|
||||||
|
|
||||||
|
Diff3< elem, sequence > diff3(A, B, C);
|
||||||
|
diff3.compose();
|
||||||
|
if (!diff3.merge()) {
|
||||||
|
cerr << "conflict." << endl;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
cout << "result:" << diff3.getMergedSequence() << endl;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
40
examples/strdiff_cp.cpp
Normal file
40
examples/strdiff_cp.cpp
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
|
||||||
|
#include <dtl/dtl.hpp>
|
||||||
|
#include "common.hpp"
|
||||||
|
#include <iostream>
|
||||||
|
#include <sstream>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
using dtl::Diff;
|
||||||
|
using dtl::SES_ADD;
|
||||||
|
using dtl::SES_DELETE;
|
||||||
|
using dtl::SES_COMMON;
|
||||||
|
using dtl::Printer;
|
||||||
|
|
||||||
|
#include "printers.hpp"
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]){
|
||||||
|
|
||||||
|
if (isFewArgs(argc)) {
|
||||||
|
cerr << "Too few arguments." << endl;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef char elem;
|
||||||
|
typedef string sequence;
|
||||||
|
|
||||||
|
sequence A(argv[1]);
|
||||||
|
sequence B(argv[2]);
|
||||||
|
|
||||||
|
Diff< elem, sequence > d(A, B);
|
||||||
|
d.compose();
|
||||||
|
|
||||||
|
// Shortest Edit Script
|
||||||
|
cout << "SES" << endl;
|
||||||
|
|
||||||
|
d.printSES < ostream, customChangePrinter > (cout);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
111
examples/unidiff.cpp
Normal file
111
examples/unidiff.cpp
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
|
||||||
|
#include <dtl/dtl.hpp>
|
||||||
|
#include "common.hpp"
|
||||||
|
#include <iostream>
|
||||||
|
#include <fstream>
|
||||||
|
#include <sstream>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include <time.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
using dtl::Diff;
|
||||||
|
using dtl::elemInfo;
|
||||||
|
using dtl::uniHunk;
|
||||||
|
|
||||||
|
static void showStats (string fp1, string fp2);
|
||||||
|
static void unifiedDiff (string fp1, string fp2);
|
||||||
|
|
||||||
|
static void showStats (string fp1, string fp2)
|
||||||
|
{
|
||||||
|
const int MAX_LENGTH = 255;
|
||||||
|
char time_format[] = "%Y-%m-%d %H:%M:%S %z";
|
||||||
|
time_t rawtime[2];
|
||||||
|
struct tm *timeinfo[2];
|
||||||
|
struct stat st[2];
|
||||||
|
|
||||||
|
if (stat(fp1.c_str(), &st[0]) == -1) {
|
||||||
|
cerr << "argv1 is invalid." << endl;
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
if (stat(fp2.c_str(), &st[1]) == -1) {
|
||||||
|
cerr << "argv2 is invalid" << endl;
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
char buf[2][MAX_LENGTH + 1];
|
||||||
|
rawtime[0] = st[0].st_mtime;
|
||||||
|
timeinfo[0] = localtime(&rawtime[0]);
|
||||||
|
strftime(buf[0], MAX_LENGTH, time_format, timeinfo[0]);
|
||||||
|
cout << "--- " << fp1 << '\t' << buf[0] << endl;
|
||||||
|
rawtime[1] = st[1].st_mtime;
|
||||||
|
timeinfo[1] = localtime(&rawtime[1]);
|
||||||
|
strftime(buf[1], MAX_LENGTH, time_format, timeinfo[1]);
|
||||||
|
cout << "+++ " << fp2 << '\t' << buf[1] << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void unifiedDiff (string fp1, string fp2)
|
||||||
|
{
|
||||||
|
typedef string elem;
|
||||||
|
typedef vector< elem > sequence;
|
||||||
|
typedef pair< elem, elemInfo > sesElem;
|
||||||
|
|
||||||
|
ifstream Aifs(fp1.c_str());
|
||||||
|
ifstream Bifs(fp2.c_str());
|
||||||
|
elem buf;
|
||||||
|
sequence ALines, BLines;
|
||||||
|
|
||||||
|
while(getline(Aifs, buf)){
|
||||||
|
ALines.push_back(buf);
|
||||||
|
}
|
||||||
|
while(getline(Bifs, buf)){
|
||||||
|
BLines.push_back(buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
Diff< elem > diff(ALines, BLines);
|
||||||
|
diff.onHuge();
|
||||||
|
//diff.onUnserious();
|
||||||
|
diff.compose();
|
||||||
|
|
||||||
|
// type unihunk definition test
|
||||||
|
uniHunk< sesElem > hunk;
|
||||||
|
|
||||||
|
if (diff.getEditDistance() > 0) {
|
||||||
|
showStats(fp1, fp2); // show file info
|
||||||
|
}
|
||||||
|
|
||||||
|
diff.composeUnifiedHunks();
|
||||||
|
diff.printUnifiedFormat();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
if (isFewArgs(argc)) {
|
||||||
|
cerr << "Too few arguments." << endl;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
string s1(argv[1]);
|
||||||
|
string s2(argv[2]);
|
||||||
|
bool fileExist = true;
|
||||||
|
|
||||||
|
if (!isFileExist(s1)) {
|
||||||
|
cerr << s1 << " is invalid." << endl;
|
||||||
|
fileExist = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isFileExist(s2)) {
|
||||||
|
cerr << s2 << " is invalid." << endl;
|
||||||
|
fileExist = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!fileExist) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
unifiedDiff(s1, s2);
|
||||||
|
return 0;
|
||||||
|
}
|
40
examples/unistrdiff.cpp
Normal file
40
examples/unistrdiff.cpp
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
|
||||||
|
#include <dtl/dtl.hpp>
|
||||||
|
#include "common.hpp"
|
||||||
|
#include <iostream>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
using dtl::Diff;
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]){
|
||||||
|
|
||||||
|
if (isFewArgs(argc)) {
|
||||||
|
cerr << "Too few arguments." << endl;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef char elem;
|
||||||
|
typedef string sequence;
|
||||||
|
|
||||||
|
sequence A(argv[1]);
|
||||||
|
sequence B(argv[2]);
|
||||||
|
|
||||||
|
Diff<elem, sequence > d(A, B);
|
||||||
|
d.compose();
|
||||||
|
d.composeUnifiedHunks();
|
||||||
|
|
||||||
|
// editDistance
|
||||||
|
cout << "editDistance:" << d.getEditDistance() << endl;
|
||||||
|
|
||||||
|
// Longest Common Subsequence
|
||||||
|
vector<elem> lcs_v = d.getLcsVec();
|
||||||
|
sequence lcs_s(lcs_v.begin(), lcs_v.end());
|
||||||
|
cout << "LCS:" << lcs_s << endl;
|
||||||
|
|
||||||
|
// print Unified Format
|
||||||
|
d.printUnifiedFormat();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
144
test/Intdifftest.cpp
Normal file
144
test/Intdifftest.cpp
Normal file
@ -0,0 +1,144 @@
|
|||||||
|
#include "dtl_test_common.hpp"
|
||||||
|
|
||||||
|
class Intdifftest : public ::testing::Test
|
||||||
|
{
|
||||||
|
protected :
|
||||||
|
dtl_test_typedefs(int, vector< int >)
|
||||||
|
typedef struct case_t {
|
||||||
|
sequence A;
|
||||||
|
sequence B;
|
||||||
|
size_t editdis;
|
||||||
|
elemVec lcs_v;
|
||||||
|
sequence lcs_s;
|
||||||
|
sesElemVec ses_seq;
|
||||||
|
uniHunkVec hunk_v;
|
||||||
|
size_t editdis_ses;
|
||||||
|
size_t editdis_uni;
|
||||||
|
string path_rses;
|
||||||
|
string path_rhunks;
|
||||||
|
} case_t;
|
||||||
|
typedef vector< case_t > caseVec;
|
||||||
|
caseVec cases;
|
||||||
|
|
||||||
|
case_t createCase (const sequence a, const sequence b, string test_name) {
|
||||||
|
case_t c;
|
||||||
|
string diff_name("intdiff");
|
||||||
|
Diff< elem > diff(a, b);
|
||||||
|
diff.compose();
|
||||||
|
diff.composeUnifiedHunks();
|
||||||
|
|
||||||
|
if (test_name != "") {
|
||||||
|
string path_lses = create_path(test_name, diff_name, TYPE_DIFF_SES);
|
||||||
|
string path_rses = create_path(test_name, diff_name, TYPE_DIFF_SES, true);
|
||||||
|
string path_lhunks = create_path(test_name, diff_name, TYPE_DIFF_UNI);
|
||||||
|
string path_rhunks = create_path(test_name, diff_name, TYPE_DIFF_UNI, true);
|
||||||
|
|
||||||
|
create_file< elem, sequence, Compare< elem > >(path_rses, diff, TYPE_DIFF_SES);
|
||||||
|
create_file< elem, sequence, Compare< elem > >(path_rhunks, diff, TYPE_DIFF_UNI);
|
||||||
|
c.editdis_ses = cal_diff_uni(path_lses, path_rses);
|
||||||
|
c.editdis_uni = cal_diff_uni(path_lhunks, path_rhunks);
|
||||||
|
c.path_rses = path_rses;
|
||||||
|
c.path_rhunks = path_rhunks;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
c.A = a;
|
||||||
|
c.B = b;
|
||||||
|
c.editdis = diff.getEditDistance();
|
||||||
|
c.lcs_v = diff.getLcsVec();
|
||||||
|
c.ses_seq = diff.getSes().getSequence();
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetUp() {
|
||||||
|
cases.push_back(createCase(sequence(0), sequence(0), "diff_test0"));
|
||||||
|
sequence B1;
|
||||||
|
B1.push_back(1);
|
||||||
|
cases.push_back(createCase(sequence(0), B1, "diff_test1"));
|
||||||
|
sequence A2;
|
||||||
|
A2.push_back(1);
|
||||||
|
cases.push_back(createCase(A2, sequence(0), "diff_test2"));
|
||||||
|
int a4[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
|
||||||
|
int b4[] = {3, 5, 1, 4, 5, 1, 7, 9, 6, 10};
|
||||||
|
int a4siz = sizeof(a4) / sizeof(int);
|
||||||
|
int b4siz = sizeof(b4) / sizeof(int);
|
||||||
|
sequence A4(&a4[0], &a4[a4siz]);
|
||||||
|
sequence B4(&b4[0], &b4[b4siz]);
|
||||||
|
cases.push_back(createCase(A4, B4, "diff_test3"));
|
||||||
|
int a5[] = {1, 2, 3, 4, 5};
|
||||||
|
int b5[] = {3, 5, 1, 4, 5};
|
||||||
|
int a5siz = sizeof(a5) / sizeof(int);
|
||||||
|
int b5siz = sizeof(b5) / sizeof(int);
|
||||||
|
sequence A5(&a5[0], &a5[a5siz]);
|
||||||
|
sequence B5(&b5[0], &b5[b5siz]);
|
||||||
|
cases.push_back(createCase(A5, B5, "diff_test4"));
|
||||||
|
}
|
||||||
|
|
||||||
|
void TearDown () {
|
||||||
|
for_each(cases.begin(), cases.end(), Remover< case_t >());
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Intdifftest
|
||||||
|
* check list is following
|
||||||
|
* - editdistance
|
||||||
|
* - LCS
|
||||||
|
* - SES
|
||||||
|
*/
|
||||||
|
TEST_F (Intdifftest, diff_test0) {
|
||||||
|
EXPECT_EQ(0, cases[0].editdis);
|
||||||
|
|
||||||
|
EXPECT_TRUE(cases[0].lcs_v.empty());
|
||||||
|
|
||||||
|
ASSERT_EQ(0, cases[0].editdis_ses);
|
||||||
|
|
||||||
|
ASSERT_EQ(0, cases[0].editdis_uni);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F (Intdifftest, diff_test1) {
|
||||||
|
EXPECT_EQ(1, cases[1].editdis);
|
||||||
|
|
||||||
|
EXPECT_TRUE(cases[1].lcs_v.empty());
|
||||||
|
|
||||||
|
ASSERT_EQ(0, cases[1].editdis_ses);
|
||||||
|
|
||||||
|
ASSERT_EQ(0, cases[1].editdis_uni);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F (Intdifftest, diff_test2) {
|
||||||
|
EXPECT_EQ(1, cases[2].editdis);
|
||||||
|
|
||||||
|
EXPECT_TRUE(cases[2].lcs_v.empty());
|
||||||
|
|
||||||
|
ASSERT_EQ(0, cases[2].editdis_ses);
|
||||||
|
|
||||||
|
ASSERT_EQ(0, cases[2].editdis_uni);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F (Intdifftest, diff_test3) {
|
||||||
|
EXPECT_EQ(8, cases[3].editdis);
|
||||||
|
|
||||||
|
EXPECT_EQ(3, cases[3].lcs_v[0]);
|
||||||
|
EXPECT_EQ(4, cases[3].lcs_v[1]);
|
||||||
|
EXPECT_EQ(5, cases[3].lcs_v[2]);
|
||||||
|
EXPECT_EQ(7, cases[3].lcs_v[3]);
|
||||||
|
EXPECT_EQ(9, cases[3].lcs_v[4]);
|
||||||
|
|
||||||
|
ASSERT_EQ(0, cases[3].editdis_ses);
|
||||||
|
|
||||||
|
ASSERT_EQ(0, cases[3].editdis_uni);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F (Intdifftest, diff_test4) {
|
||||||
|
EXPECT_EQ(4, cases[4].editdis);
|
||||||
|
|
||||||
|
EXPECT_EQ(3, cases[4].lcs_v[0]);
|
||||||
|
EXPECT_EQ(4, cases[4].lcs_v[1]);
|
||||||
|
EXPECT_EQ(5, cases[4].lcs_v[2]);
|
||||||
|
|
||||||
|
ASSERT_EQ(0, cases[4].editdis_ses);
|
||||||
|
|
||||||
|
ASSERT_EQ(0, cases[4].editdis_uni);
|
||||||
|
}
|
116
test/Objdifftest.cpp
Normal file
116
test/Objdifftest.cpp
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
#include "dtl_test_common.hpp"
|
||||||
|
#include "comparators.hpp"
|
||||||
|
|
||||||
|
class Objdifftest : public ::testing::Test
|
||||||
|
{
|
||||||
|
protected :
|
||||||
|
dtl_test_typedefs(string, vector<elem>)
|
||||||
|
typedef struct case_t {
|
||||||
|
sequence A;
|
||||||
|
sequence B;
|
||||||
|
sesElemVec expected;
|
||||||
|
sesElemVec ses_seq;
|
||||||
|
} case_t;
|
||||||
|
typedef vector< case_t > caseVec;
|
||||||
|
|
||||||
|
caseVec obj_diff_cases;
|
||||||
|
|
||||||
|
template < typename comparator >
|
||||||
|
case_t createCase (const sequence a, const sequence b, sesElemVec ses, string test_name) {
|
||||||
|
case_t c;
|
||||||
|
elemVec lcs_v;
|
||||||
|
string diff_name("objdiff");
|
||||||
|
|
||||||
|
Diff< elem, sequence, comparator > diff(a, b, true);
|
||||||
|
|
||||||
|
diff.compose();
|
||||||
|
|
||||||
|
c.A = a;
|
||||||
|
c.B = b;
|
||||||
|
c.ses_seq = diff.getSes().getSequence();
|
||||||
|
c.expected = ses;
|
||||||
|
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetUp(void) {
|
||||||
|
{
|
||||||
|
string array1[] = {"the", "quick", "brown"};
|
||||||
|
string array2[] = {"The", "Quick", "Fox"};
|
||||||
|
|
||||||
|
sequence A(array1, array1 + (sizeof(array1) / sizeof(array1[0])));
|
||||||
|
sequence B(array2, array2 + (sizeof(array2) / sizeof(array2[0])));
|
||||||
|
|
||||||
|
dtl::Ses< elem > ses;
|
||||||
|
ses.addSequence("the", 1, 1, dtl::SES_COMMON);
|
||||||
|
ses.addSequence("quick", 2, 2, dtl::SES_COMMON);
|
||||||
|
ses.addSequence("brown", 3, 0, dtl::SES_DELETE);
|
||||||
|
ses.addSequence("Fox", 0, 3, dtl::SES_ADD);
|
||||||
|
|
||||||
|
obj_diff_cases.push_back(createCase< StringCaseInsensitive >(A, B, ses.getSequence(), "objdiff_test0_pattern"));
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
string array1[] = {"b", "c", "e", "g"};
|
||||||
|
string array2[] = {"a", "d", "e", "f", "h"};
|
||||||
|
|
||||||
|
sequence A(array1, array1 + (sizeof(array1) / sizeof(array1[0])));
|
||||||
|
sequence B(array2, array2 + (sizeof(array2) / sizeof(array2[0])));
|
||||||
|
|
||||||
|
dtl::Ses< elem > ses;
|
||||||
|
ses.addSequence("b", 1, 0, dtl::SES_DELETE);
|
||||||
|
ses.addSequence("c", 2, 0, dtl::SES_DELETE);
|
||||||
|
ses.addSequence("a", 0, 1, dtl::SES_ADD);
|
||||||
|
ses.addSequence("d", 0, 2, dtl::SES_ADD);
|
||||||
|
ses.addSequence("e", 3, 3, dtl::SES_COMMON);
|
||||||
|
ses.addSequence("g", 4, 0, dtl::SES_DELETE);
|
||||||
|
ses.addSequence("f", 0, 4, dtl::SES_ADD);
|
||||||
|
ses.addSequence("h", 0, 5, dtl::SES_ADD);
|
||||||
|
|
||||||
|
obj_diff_cases.push_back(createCase< StringCaseInsensitive >(A, B, ses.getSequence(), "objdiff_test1_unswapped"));
|
||||||
|
}
|
||||||
|
{
|
||||||
|
string array1[] = {"a", "d", "e", "f", "h"};
|
||||||
|
string array2[] = {"b", "c", "e", "g"};
|
||||||
|
|
||||||
|
sequence A(array1, array1 + (sizeof(array1) / sizeof(array1[0])));
|
||||||
|
sequence B(array2, array2 + (sizeof(array2) / sizeof(array2[0])));
|
||||||
|
|
||||||
|
dtl::Ses< elem > ses;
|
||||||
|
ses.addSequence("a", 1, 0, dtl::SES_DELETE);
|
||||||
|
ses.addSequence("d", 2, 0, dtl::SES_DELETE);
|
||||||
|
ses.addSequence("b", 0, 1, dtl::SES_ADD);
|
||||||
|
ses.addSequence("c", 0, 2, dtl::SES_ADD);
|
||||||
|
ses.addSequence("e", 3, 3, dtl::SES_COMMON);
|
||||||
|
ses.addSequence("f", 4, 0, dtl::SES_DELETE);
|
||||||
|
ses.addSequence("h", 5, 0, dtl::SES_DELETE);
|
||||||
|
ses.addSequence("g", 0, 4, dtl::SES_ADD);
|
||||||
|
|
||||||
|
obj_diff_cases.push_back(createCase< StringCaseInsensitive >(A, B, ses.getSequence(), "objdiff_test2_swapped"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TearDown () {
|
||||||
|
//for_each(obj_diff_cases.begin(), obj_diff_cases.end(), Remover< case_t >());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Objdifftest
|
||||||
|
* check list:
|
||||||
|
* - SES pattern "SES_COMMON, SES_DELETE, SES_ADD"
|
||||||
|
* - Indepence of results from swapping
|
||||||
|
*/
|
||||||
|
|
||||||
|
TEST_F (Objdifftest, objdiff_test0_pattern) {
|
||||||
|
EXPECT_EQ(obj_diff_cases[0].expected, obj_diff_cases[0].ses_seq);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F (Objdifftest, objdiff_test1_unswapped) {
|
||||||
|
EXPECT_EQ(obj_diff_cases[1].expected, obj_diff_cases[1].ses_seq);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F (Objdifftest, objdiff_test2_swapped) {
|
||||||
|
EXPECT_EQ(obj_diff_cases[2].expected, obj_diff_cases[2].ses_seq);
|
||||||
|
}
|
98
test/Patchtest.cpp
Normal file
98
test/Patchtest.cpp
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
#include "dtl_test_common.hpp"
|
||||||
|
|
||||||
|
class Patchtest : public ::testing::Test
|
||||||
|
{
|
||||||
|
protected :
|
||||||
|
dtl_test_typedefs(char, string)
|
||||||
|
typedef struct case_t {
|
||||||
|
sequence A;
|
||||||
|
sequence B;
|
||||||
|
Diff< elem, sequence > diff;
|
||||||
|
} case_t;
|
||||||
|
typedef vector< case_t > caseVec;
|
||||||
|
|
||||||
|
caseVec cases;
|
||||||
|
|
||||||
|
case_t createCase (sequence a, sequence b) {
|
||||||
|
case_t c;
|
||||||
|
c.A = a;
|
||||||
|
c.B = b;
|
||||||
|
c.diff = Diff< elem, sequence >(a, b);
|
||||||
|
c.diff.compose();
|
||||||
|
c.diff.composeUnifiedHunks();
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetUp() {
|
||||||
|
cases.push_back(createCase("abc", "abd")); // 0
|
||||||
|
cases.push_back(createCase("acbdeacbed", "acebdabbabed")); // 1
|
||||||
|
cases.push_back(createCase("abcdef", "dacfea")); // 2
|
||||||
|
cases.push_back(createCase("abcbda", "bdcaba")); // 3
|
||||||
|
cases.push_back(createCase("bokko", "bokkko")); // 4
|
||||||
|
cases.push_back(createCase("", "")); // 5
|
||||||
|
cases.push_back(createCase("a", "")); // 6
|
||||||
|
cases.push_back(createCase("", "b")); // 7
|
||||||
|
cases.push_back(createCase("abcdefq3wefarhgorequgho4euhfteowauhfwehogfewrquhoi23hroewhoahfotrhguoiewahrgqqabcdef",
|
||||||
|
"3abcdef4976fd86ouofita67t85r876e5e746578tgliuhopoqqabcdef")); // 8
|
||||||
|
cases.push_back(createCase("abcqqqeqqqccc", "abdqqqeqqqddd")); // 9
|
||||||
|
}
|
||||||
|
|
||||||
|
void TearDown () {}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Patchtest
|
||||||
|
* check list is following
|
||||||
|
* - patch function
|
||||||
|
* - uniPatch function
|
||||||
|
*/
|
||||||
|
TEST_F (Patchtest, patch_test0) {
|
||||||
|
ASSERT_EQ(cases[0].B, cases[0].diff.patch(cases[0].A));
|
||||||
|
ASSERT_EQ(cases[0].B, cases[0].diff.uniPatch(cases[0].A));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F (Patchtest, patch_test1) {
|
||||||
|
ASSERT_EQ(cases[1].B, cases[1].diff.patch(cases[1].A));
|
||||||
|
ASSERT_EQ(cases[1].B, cases[1].diff.uniPatch(cases[1].A));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F (Patchtest, patch_test2) {
|
||||||
|
ASSERT_EQ(cases[2].B, cases[2].diff.patch(cases[2].A));
|
||||||
|
ASSERT_EQ(cases[2].B, cases[2].diff.uniPatch(cases[2].A));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F (Patchtest, patch_test3) {
|
||||||
|
ASSERT_EQ(cases[3].B, cases[3].diff.patch(cases[3].A));
|
||||||
|
ASSERT_EQ(cases[3].B, cases[3].diff.uniPatch(cases[3].A));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F (Patchtest, patch_test4) {
|
||||||
|
ASSERT_EQ(cases[4].B, cases[4].diff.patch(cases[4].A));
|
||||||
|
ASSERT_EQ(cases[4].B, cases[4].diff.uniPatch(cases[4].A));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F (Patchtest, patch_test5) {
|
||||||
|
ASSERT_EQ(cases[5].B, cases[5].diff.patch(cases[5].A));
|
||||||
|
ASSERT_EQ(cases[5].B, cases[5].diff.uniPatch(cases[5].A));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F (Patchtest, patch_test6) {
|
||||||
|
ASSERT_EQ(cases[6].B, cases[6].diff.patch(cases[6].A));
|
||||||
|
ASSERT_EQ(cases[6].B, cases[6].diff.uniPatch(cases[6].A));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F (Patchtest, patch_test7) {
|
||||||
|
ASSERT_EQ(cases[7].B, cases[7].diff.patch(cases[7].A));
|
||||||
|
ASSERT_EQ(cases[7].B, cases[7].diff.uniPatch(cases[7].A));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F (Patchtest, patch_test8) {
|
||||||
|
ASSERT_EQ(cases[8].B, cases[8].diff.patch(cases[8].A));
|
||||||
|
ASSERT_EQ(cases[8].B, cases[8].diff.uniPatch(cases[8].A));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F (Patchtest, patch_test9) {
|
||||||
|
ASSERT_EQ(cases[9].B, cases[9].diff.patch(cases[9].A));
|
||||||
|
ASSERT_EQ(cases[9].B, cases[9].diff.uniPatch(cases[9].A));
|
||||||
|
}
|
53
test/SConstruct
Normal file
53
test/SConstruct
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# SConstrunct for dtl test
|
||||||
|
|
||||||
|
import os
|
||||||
|
|
||||||
|
def path_chomp(path):
|
||||||
|
if path[-1] == '/':
|
||||||
|
return path[:-1]
|
||||||
|
return path
|
||||||
|
|
||||||
|
if not 'GTEST_ROOT' in os.environ:
|
||||||
|
print "set environment variable 'GTEST_ROOT'"
|
||||||
|
Exit(1)
|
||||||
|
|
||||||
|
gtest_root = path_chomp(os.environ['GTEST_ROOT'])
|
||||||
|
if gtest_root[-1] == '/':
|
||||||
|
gtest_root = gtest_root[:-1]
|
||||||
|
|
||||||
|
gtest_includes = gtest_root + '/include'
|
||||||
|
gtest_libs = gtest_root + '/lib/.libs'
|
||||||
|
|
||||||
|
flags = ['-Wall', '-O2']
|
||||||
|
libs = ['stdc++', 'pthread']
|
||||||
|
includes = ['..', gtest_includes]
|
||||||
|
target = 'dtl_test'
|
||||||
|
|
||||||
|
env = Environment(CPPFLAGS=flags,
|
||||||
|
CPPPATH=includes,
|
||||||
|
LIBPATH=[gtest_libs],
|
||||||
|
)
|
||||||
|
|
||||||
|
conf = Configure(env);
|
||||||
|
|
||||||
|
if not conf.CheckCXX():
|
||||||
|
print "c++ compiler is not installed!"
|
||||||
|
Exit(1)
|
||||||
|
|
||||||
|
for lib in libs:
|
||||||
|
if not conf.CheckLib(lib):
|
||||||
|
print "library " + lib + " not installed!"
|
||||||
|
Exit(1)
|
||||||
|
|
||||||
|
conf.Finish()
|
||||||
|
|
||||||
|
test = env.Program(target,
|
||||||
|
[Glob('*.cpp'), gtest_libs + '/libgtest.a']
|
||||||
|
)
|
||||||
|
|
||||||
|
test_alias = env.Alias('check',
|
||||||
|
test,
|
||||||
|
test[0].abspath)
|
||||||
|
|
||||||
|
env.AlwaysBuild(test_alias)
|
208
test/Strdiff3test.cpp
Normal file
208
test/Strdiff3test.cpp
Normal file
@ -0,0 +1,208 @@
|
|||||||
|
#include "dtl_test_common.hpp"
|
||||||
|
#include "comparators.hpp"
|
||||||
|
|
||||||
|
class Strdiff3test : public ::testing::Test
|
||||||
|
{
|
||||||
|
protected :
|
||||||
|
dtl_test_typedefs(char, string)
|
||||||
|
typedef struct case_t {
|
||||||
|
sequence S;
|
||||||
|
bool is_merge_success;
|
||||||
|
sequence merged_seq;
|
||||||
|
} case_t;
|
||||||
|
typedef vector< case_t > caseVec;
|
||||||
|
|
||||||
|
caseVec merge_cases;
|
||||||
|
caseVec detect_cases;
|
||||||
|
caseVec custom_cases;
|
||||||
|
|
||||||
|
template < typename comparator >
|
||||||
|
case_t createCase (sequence a, sequence b, sequence c, sequence s) {
|
||||||
|
Diff3< elem, sequence, comparator > diff3(a, b, c);
|
||||||
|
case_t ct;
|
||||||
|
|
||||||
|
diff3.compose();
|
||||||
|
|
||||||
|
ct.S = s;
|
||||||
|
ct.is_merge_success = diff3.merge();
|
||||||
|
ct.merged_seq = diff3.getMergedSequence();
|
||||||
|
return ct;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetUp() {
|
||||||
|
// merge test
|
||||||
|
merge_cases.push_back(createCase< Compare < elem > >("ab", "b", "bc", "abc")); // 0
|
||||||
|
merge_cases.push_back(createCase< Compare < elem > >("bc", "b", "ab", "abc")); // 1
|
||||||
|
merge_cases.push_back(createCase< Compare < elem > >("qqqabc", "abc", "abcdef", "qqqabcdef")); // 2
|
||||||
|
merge_cases.push_back(createCase< Compare < elem > >("abcdef", "abc", "qqqabc", "qqqabcdef")); // 3
|
||||||
|
merge_cases.push_back(createCase< Compare < elem > >("aaacccbbb", "aaabbb", "aaabbbqqq", "aaacccbbbqqq")); // 4
|
||||||
|
merge_cases.push_back(createCase< Compare < elem > >("aaabbbqqq", "aaabbb", "aaacccbbb", "aaacccbbbqqq")); // 5
|
||||||
|
merge_cases.push_back(createCase< Compare < elem > >("aeaacccbbb", "aaabbb", "aaabbbqqq", "aeaacccbbbqqq")); // 6
|
||||||
|
merge_cases.push_back(createCase< Compare < elem > >("aaabbbqqq", "aaabbb", "aeaacccbbb", "aeaacccbbbqqq")); // 7
|
||||||
|
merge_cases.push_back(createCase< Compare < elem > >("aeaacccbbb", "aaabbb", "aaabebbqqq", "aeaacccbebbqqq")); // 8
|
||||||
|
merge_cases.push_back(createCase< Compare < elem > >("aaabebbqqq", "aaabbb", "aeaacccbbb", "aeaacccbebbqqq")); // 9
|
||||||
|
merge_cases.push_back(createCase< Compare < elem > >("aaacccbbb", "aaabbb", "aeaabbbqqq", "aeaacccbbbqqq")); // 10
|
||||||
|
merge_cases.push_back(createCase< Compare < elem > >("aeaabbbqqq", "aaabbb", "aaacccbbb", "aeaacccbbbqqq")); // 11
|
||||||
|
merge_cases.push_back(createCase< Compare < elem > >("aaacccbbb", "aaabbb", "aaabeebbeeqqq","aaacccbeebbeeqqq")); // 12
|
||||||
|
merge_cases.push_back(createCase< Compare < elem > >("aaabeebbeeqqq", "aaabbb", "aaacccbbb", "aaacccbeebbeeqqq")); // 13
|
||||||
|
merge_cases.push_back(createCase< Compare < elem > >("aiueo", "aeo", "aeKokaki", "aiueKokaki")); // 14
|
||||||
|
merge_cases.push_back(createCase< Compare < elem > >("aeKokaki", "aeo", "aiueo", "aiueKokaki")); // 15
|
||||||
|
merge_cases.push_back(createCase< Compare < elem > >("1234567390", "1234567890", "1239567890", "1239567390")); // 16
|
||||||
|
merge_cases.push_back(createCase< Compare < elem > >("1239567890", "1234567890", "1234567390", "1239567390")); // 17
|
||||||
|
merge_cases.push_back(createCase< Compare < elem > >("qabcdef", "abcdef", "ab", "qab")); // 18
|
||||||
|
merge_cases.push_back(createCase< Compare < elem > >("ab", "abcdef", "qabcdef", "qab")); // 19
|
||||||
|
merge_cases.push_back(createCase< Compare < elem > >("abcdf", "abcdef", "acdef", "acdf")); // 20
|
||||||
|
merge_cases.push_back(createCase< Compare < elem > >("acdef", "abcdef", "abcdf", "acdf")); // 21
|
||||||
|
merge_cases.push_back(createCase< Compare < elem > >("acdef", "abcdef", "abcdfaa", "acdfaa")); // 22
|
||||||
|
merge_cases.push_back(createCase< Compare < elem > >("abcdfaa", "abcdef", "acdef", "acdfaa")); // 23
|
||||||
|
|
||||||
|
// detect confliction test
|
||||||
|
detect_cases.push_back(createCase< Compare < elem > >("adc", "abc", "aec", "")); // 0
|
||||||
|
detect_cases.push_back(createCase< Compare < elem > >("abqdcf", "abcdef", "abqqef", "")); // 1
|
||||||
|
|
||||||
|
// use custom comparator
|
||||||
|
custom_cases.push_back(createCase< CaseInsensitive >("abc", "abc", "abC", "abc"));
|
||||||
|
}
|
||||||
|
|
||||||
|
void TearDown () {}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Strdiff3test
|
||||||
|
* check list is following
|
||||||
|
* - merge function
|
||||||
|
* - detect confliction
|
||||||
|
*/
|
||||||
|
TEST_F (Strdiff3test, merge_test0) {
|
||||||
|
ASSERT_TRUE(merge_cases[0].is_merge_success);
|
||||||
|
ASSERT_EQ(merge_cases[0].S, merge_cases[0].merged_seq);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F (Strdiff3test, merge_test1) {
|
||||||
|
ASSERT_TRUE(merge_cases[1].is_merge_success);
|
||||||
|
ASSERT_EQ(merge_cases[1].S, merge_cases[1].merged_seq);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F (Strdiff3test, merge_test2) {
|
||||||
|
ASSERT_TRUE(merge_cases[2].is_merge_success);
|
||||||
|
ASSERT_EQ(merge_cases[2].S, merge_cases[2].merged_seq);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F (Strdiff3test, merge_test3) {
|
||||||
|
ASSERT_TRUE(merge_cases[3].is_merge_success);
|
||||||
|
ASSERT_EQ(merge_cases[3].S, merge_cases[3].merged_seq);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F (Strdiff3test, merge_test4) {
|
||||||
|
ASSERT_TRUE(merge_cases[4].is_merge_success);
|
||||||
|
ASSERT_EQ(merge_cases[4].S, merge_cases[4].merged_seq);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F (Strdiff3test, merge_test5) {
|
||||||
|
ASSERT_TRUE(merge_cases[5].is_merge_success);
|
||||||
|
ASSERT_EQ(merge_cases[5].S, merge_cases[5].merged_seq);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F (Strdiff3test, merge_test6) {
|
||||||
|
ASSERT_TRUE(merge_cases[6].is_merge_success);
|
||||||
|
ASSERT_EQ(merge_cases[6].S, merge_cases[6].merged_seq);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F (Strdiff3test, merge_test7) {
|
||||||
|
ASSERT_TRUE(merge_cases[7].is_merge_success);
|
||||||
|
ASSERT_EQ(merge_cases[7].S, merge_cases[7].merged_seq);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F (Strdiff3test, merge_test8) {
|
||||||
|
ASSERT_TRUE(merge_cases[8].is_merge_success);
|
||||||
|
ASSERT_EQ(merge_cases[8].S, merge_cases[8].merged_seq);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F (Strdiff3test, merge_test9) {
|
||||||
|
ASSERT_TRUE(merge_cases[9].is_merge_success);
|
||||||
|
ASSERT_EQ(merge_cases[9].S, merge_cases[9].merged_seq);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F (Strdiff3test, merge_test10) {
|
||||||
|
ASSERT_TRUE(merge_cases[10].is_merge_success);
|
||||||
|
ASSERT_EQ(merge_cases[10].S, merge_cases[10].merged_seq);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F (Strdiff3test, merge_test11) {
|
||||||
|
ASSERT_TRUE(merge_cases[11].is_merge_success);
|
||||||
|
ASSERT_EQ(merge_cases[11].S, merge_cases[11].merged_seq);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F (Strdiff3test, merge_test12) {
|
||||||
|
ASSERT_TRUE(merge_cases[12].is_merge_success);
|
||||||
|
ASSERT_EQ(merge_cases[12].S, merge_cases[12].merged_seq);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F (Strdiff3test, merge_test13) {
|
||||||
|
ASSERT_TRUE(merge_cases[13].is_merge_success);
|
||||||
|
ASSERT_EQ(merge_cases[13].S, merge_cases[13].merged_seq);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F (Strdiff3test, merge_test14) {
|
||||||
|
ASSERT_TRUE(merge_cases[14].is_merge_success);
|
||||||
|
ASSERT_EQ(merge_cases[14].S, merge_cases[14].merged_seq);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F (Strdiff3test, merge_test15) {
|
||||||
|
ASSERT_TRUE(merge_cases[15].is_merge_success);
|
||||||
|
ASSERT_EQ(merge_cases[15].S, merge_cases[15].merged_seq);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F (Strdiff3test, merge_test16) {
|
||||||
|
ASSERT_TRUE(merge_cases[16].is_merge_success);
|
||||||
|
ASSERT_EQ(merge_cases[16].S, merge_cases[16].merged_seq);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F (Strdiff3test, merge_test17) {
|
||||||
|
ASSERT_TRUE(merge_cases[17].is_merge_success);
|
||||||
|
ASSERT_EQ(merge_cases[17].S, merge_cases[17].merged_seq);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F (Strdiff3test, merge_test18) {
|
||||||
|
ASSERT_TRUE(merge_cases[18].is_merge_success);
|
||||||
|
ASSERT_EQ(merge_cases[18].S, merge_cases[18].merged_seq);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F (Strdiff3test, merge_test19) {
|
||||||
|
ASSERT_TRUE(merge_cases[19].is_merge_success);
|
||||||
|
ASSERT_EQ(merge_cases[19].S, merge_cases[19].merged_seq);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F (Strdiff3test, merge_test20) {
|
||||||
|
ASSERT_TRUE(merge_cases[20].is_merge_success);
|
||||||
|
ASSERT_EQ(merge_cases[20].S, merge_cases[20].merged_seq);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F (Strdiff3test, merge_test21) {
|
||||||
|
ASSERT_TRUE(merge_cases[21].is_merge_success);
|
||||||
|
ASSERT_EQ( merge_cases[21].S, merge_cases[21].merged_seq);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F (Strdiff3test, merge_test22) {
|
||||||
|
ASSERT_TRUE(merge_cases[22].is_merge_success);
|
||||||
|
ASSERT_EQ( merge_cases[22].S, merge_cases[22].merged_seq);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F (Strdiff3test, merge_test23) {
|
||||||
|
ASSERT_TRUE(merge_cases[23].is_merge_success);
|
||||||
|
ASSERT_EQ(merge_cases[23].S, merge_cases[23].merged_seq);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F (Strdiff3test, detect_confliction_test0) {
|
||||||
|
ASSERT_FALSE(detect_cases[0].is_merge_success);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F (Strdiff3test, detect_confliction_test1) {
|
||||||
|
ASSERT_FALSE(detect_cases[1].is_merge_success);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F (Strdiff3test, custom_comparator_test0) {
|
||||||
|
ASSERT_TRUE(custom_cases[0].is_merge_success);
|
||||||
|
ASSERT_EQ(custom_cases[0].S, custom_cases[0].merged_seq);
|
||||||
|
}
|
299
test/Strdifftest.cpp
Normal file
299
test/Strdifftest.cpp
Normal file
@ -0,0 +1,299 @@
|
|||||||
|
#include "dtl_test_common.hpp"
|
||||||
|
#include "comparators.hpp"
|
||||||
|
|
||||||
|
class Strdifftest : public ::testing::Test
|
||||||
|
{
|
||||||
|
protected :
|
||||||
|
dtl_test_typedefs(char, string)
|
||||||
|
typedef struct case_t {
|
||||||
|
sequence A;
|
||||||
|
sequence B;
|
||||||
|
size_t editdis;
|
||||||
|
elemVec lcs_v;
|
||||||
|
sequence lcs_s;
|
||||||
|
sesElemVec ses_seq;
|
||||||
|
uniHunkVec hunk_v;
|
||||||
|
size_t editdis_ses;
|
||||||
|
size_t editdis_uni;
|
||||||
|
string path_rses;
|
||||||
|
string path_rhunks;
|
||||||
|
} case_t;
|
||||||
|
typedef vector< case_t > caseVec;
|
||||||
|
|
||||||
|
caseVec diff_cases;
|
||||||
|
caseVec only_editdis_cases;
|
||||||
|
caseVec custom_cases;
|
||||||
|
|
||||||
|
template < typename comparator >
|
||||||
|
case_t createCase (const sequence a, const sequence b, string test_name, bool onlyEditdis = false) {
|
||||||
|
case_t c;
|
||||||
|
elemVec lcs_v;
|
||||||
|
string diff_name("strdiff");
|
||||||
|
|
||||||
|
Diff< elem, sequence, comparator > diff(a, b);
|
||||||
|
if (onlyEditdis) {
|
||||||
|
diff.onOnlyEditDistance();
|
||||||
|
}
|
||||||
|
|
||||||
|
diff.compose();
|
||||||
|
diff.composeUnifiedHunks();
|
||||||
|
lcs_v = diff.getLcsVec();
|
||||||
|
|
||||||
|
if (test_name != "") {
|
||||||
|
string path_lses = create_path(test_name, diff_name, TYPE_DIFF_SES);
|
||||||
|
string path_rses = create_path(test_name, diff_name, TYPE_DIFF_SES, true);
|
||||||
|
string path_lhunks = create_path(test_name, diff_name, TYPE_DIFF_UNI);
|
||||||
|
string path_rhunks = create_path(test_name, diff_name, TYPE_DIFF_UNI, true);
|
||||||
|
diff_resultset_exist_check(path_lses);
|
||||||
|
diff_resultset_exist_check(path_lhunks);
|
||||||
|
|
||||||
|
create_file< elem, sequence, comparator >(path_rses, diff, TYPE_DIFF_SES);
|
||||||
|
create_file< elem, sequence, comparator >(path_rhunks, diff, TYPE_DIFF_UNI);
|
||||||
|
|
||||||
|
c.editdis_ses = cal_diff_uni(path_lses, path_rses);
|
||||||
|
c.editdis_uni = cal_diff_uni(path_lhunks, path_rhunks);
|
||||||
|
c.path_rses = path_rses;
|
||||||
|
c.path_rhunks = path_rhunks;
|
||||||
|
}
|
||||||
|
|
||||||
|
c.A = a;
|
||||||
|
c.B = b;
|
||||||
|
c.editdis = diff.getEditDistance();
|
||||||
|
c.lcs_s = sequence(lcs_v.begin(), lcs_v.end());
|
||||||
|
c.ses_seq = diff.getSes().getSequence();
|
||||||
|
c.hunk_v = diff.getUniHunks();
|
||||||
|
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetUp(void) {
|
||||||
|
diff_cases.push_back(createCase< Compare< elem > >("abc", "abd", "diff_test0"));
|
||||||
|
diff_cases.push_back(createCase< Compare< elem > >("acbdeacbed", "acebdabbabed", "diff_test1"));
|
||||||
|
diff_cases.push_back(createCase< Compare< elem > >("abcdef", "dacfea", "diff_test2"));
|
||||||
|
diff_cases.push_back(createCase< Compare< elem > >("abcbda", "bdcaba", "diff_test3"));
|
||||||
|
diff_cases.push_back(createCase< Compare< elem > >("bokko", "bokkko", "diff_test4"));
|
||||||
|
diff_cases.push_back(createCase< Compare< elem > >("", "", "diff_test5"));
|
||||||
|
diff_cases.push_back(createCase< Compare< elem > >("a", "", "diff_test6"));
|
||||||
|
diff_cases.push_back(createCase< Compare< elem > >("", "b", "diff_test7"));
|
||||||
|
diff_cases.push_back(createCase< Compare< elem > >("acbdeaqqqqqqqcbed", "acebdabbqqqqqqqabed", "diff_test8"));
|
||||||
|
|
||||||
|
only_editdis_cases.push_back(createCase< Compare< elem > >("abc", "abd", "", true));
|
||||||
|
only_editdis_cases.push_back(createCase< Compare< elem > >("acbdeacbed", "acebdabbabed", "", true));
|
||||||
|
only_editdis_cases.push_back(createCase< Compare< elem > >("abcdef", "dacfea", "", true));
|
||||||
|
only_editdis_cases.push_back(createCase< Compare< elem > >("abcbda", "bdcaba", "", true));
|
||||||
|
only_editdis_cases.push_back(createCase< Compare< elem > >("bokko", "bokkko", "", true));
|
||||||
|
only_editdis_cases.push_back(createCase< Compare< elem > >("", "", "", true));
|
||||||
|
only_editdis_cases.push_back(createCase< Compare< elem > >("a", "", "", true));
|
||||||
|
only_editdis_cases.push_back(createCase< Compare< elem > >("", "b", "", true));
|
||||||
|
only_editdis_cases.push_back(createCase< Compare< elem > >("acbdeaqqqqqqqcbed", "acebdabbqqqqqqqabed", "", true));
|
||||||
|
|
||||||
|
custom_cases.push_back(createCase< CaseInsensitive >("abc", "Abc", "custom_test0"));
|
||||||
|
}
|
||||||
|
|
||||||
|
void TearDown () {
|
||||||
|
for_each(diff_cases.begin(), diff_cases.end(), Remover< case_t >());
|
||||||
|
for_each(custom_cases.begin(), custom_cases.end(), Remover< case_t >());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Strdifftest
|
||||||
|
* check list is following
|
||||||
|
* - editdistance
|
||||||
|
* - LCS
|
||||||
|
* - SES
|
||||||
|
* - Unified Format Difference
|
||||||
|
* - onOnlyEditDistance
|
||||||
|
*/
|
||||||
|
|
||||||
|
TEST_F (Strdifftest, diff_test0) {
|
||||||
|
|
||||||
|
EXPECT_EQ(2, diff_cases[0].editdis);
|
||||||
|
|
||||||
|
EXPECT_EQ("ab", diff_cases[0].lcs_s);
|
||||||
|
|
||||||
|
ASSERT_EQ(0, diff_cases[0].editdis_ses);
|
||||||
|
|
||||||
|
ASSERT_EQ(0, diff_cases[0].editdis_uni);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F (Strdifftest, diff_test1) {
|
||||||
|
EXPECT_EQ(6, diff_cases[1].editdis);
|
||||||
|
|
||||||
|
EXPECT_EQ("acbdabed", diff_cases[1].lcs_s);
|
||||||
|
|
||||||
|
ASSERT_EQ(0, diff_cases[1].editdis_ses);
|
||||||
|
|
||||||
|
ASSERT_EQ(0, diff_cases[1].editdis_uni);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F (Strdifftest, diff_test2) {
|
||||||
|
EXPECT_EQ(6, diff_cases[2].editdis);
|
||||||
|
|
||||||
|
EXPECT_EQ("acf", diff_cases[2].lcs_s);
|
||||||
|
|
||||||
|
ASSERT_EQ(0, diff_cases[2].editdis_ses);
|
||||||
|
|
||||||
|
ASSERT_EQ(0, diff_cases[2].editdis_uni);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F (Strdifftest, diff_test3) {
|
||||||
|
EXPECT_EQ(4, diff_cases[3].editdis);
|
||||||
|
|
||||||
|
EXPECT_EQ("bcba", diff_cases[3].lcs_s);
|
||||||
|
|
||||||
|
ASSERT_EQ(0, diff_cases[3].editdis_ses);
|
||||||
|
|
||||||
|
ASSERT_EQ(0, diff_cases[3].editdis_uni);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F (Strdifftest, diff_test4) {
|
||||||
|
EXPECT_EQ(1, diff_cases[4].editdis);
|
||||||
|
|
||||||
|
EXPECT_EQ("bokko", diff_cases[4].lcs_s);
|
||||||
|
|
||||||
|
ASSERT_EQ(0, diff_cases[4].editdis_ses);
|
||||||
|
|
||||||
|
ASSERT_EQ(0, diff_cases[4].editdis_uni);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F (Strdifftest, diff_test5) {
|
||||||
|
EXPECT_EQ(0, diff_cases[5].editdis);
|
||||||
|
|
||||||
|
EXPECT_EQ("", diff_cases[5].lcs_s);
|
||||||
|
|
||||||
|
ASSERT_EQ(0, diff_cases[5].editdis_ses);
|
||||||
|
|
||||||
|
ASSERT_EQ(0, diff_cases[5].editdis_uni);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F (Strdifftest, diff_test6) {
|
||||||
|
EXPECT_EQ(1, diff_cases[6].editdis);
|
||||||
|
|
||||||
|
EXPECT_EQ("", diff_cases[6].lcs_s);
|
||||||
|
|
||||||
|
ASSERT_EQ(0, diff_cases[6].editdis_ses);
|
||||||
|
|
||||||
|
ASSERT_EQ(0, diff_cases[6].editdis_uni);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F (Strdifftest, diff_test7) {
|
||||||
|
EXPECT_EQ(1, diff_cases[7].editdis);
|
||||||
|
|
||||||
|
EXPECT_EQ("", diff_cases[7].lcs_s);
|
||||||
|
|
||||||
|
ASSERT_EQ(0, diff_cases[7].editdis_ses);
|
||||||
|
|
||||||
|
ASSERT_EQ(0, diff_cases[7].editdis_uni);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F (Strdifftest, diff_test8) {
|
||||||
|
EXPECT_EQ(6, diff_cases[8].editdis);
|
||||||
|
|
||||||
|
EXPECT_EQ("acbdaqqqqqqqbed", diff_cases[8].lcs_s);
|
||||||
|
|
||||||
|
ASSERT_EQ(0, diff_cases[8].editdis_ses);
|
||||||
|
|
||||||
|
ASSERT_EQ(0, diff_cases[8].editdis_uni);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F (Strdifftest, only_editdis_test0) {
|
||||||
|
EXPECT_EQ(2, only_editdis_cases[0].editdis);
|
||||||
|
|
||||||
|
EXPECT_EQ("", only_editdis_cases[0].lcs_s);
|
||||||
|
|
||||||
|
ASSERT_TRUE(only_editdis_cases[0].ses_seq.empty());
|
||||||
|
|
||||||
|
ASSERT_TRUE(only_editdis_cases[0].hunk_v.empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F (Strdifftest, only_editdis_test1) {
|
||||||
|
EXPECT_EQ(6, only_editdis_cases[1].editdis);
|
||||||
|
|
||||||
|
EXPECT_EQ("", only_editdis_cases[1].lcs_s);
|
||||||
|
|
||||||
|
ASSERT_TRUE(only_editdis_cases[1].ses_seq.empty());
|
||||||
|
|
||||||
|
ASSERT_TRUE(only_editdis_cases[1].hunk_v.empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F (Strdifftest, only_editdis_test2) {
|
||||||
|
EXPECT_EQ(6, only_editdis_cases[2].editdis);
|
||||||
|
|
||||||
|
EXPECT_EQ("", only_editdis_cases[2].lcs_s);
|
||||||
|
|
||||||
|
ASSERT_TRUE(only_editdis_cases[2].ses_seq.empty());
|
||||||
|
|
||||||
|
ASSERT_TRUE(only_editdis_cases[2].hunk_v.empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F (Strdifftest, only_editdis_test3) {
|
||||||
|
EXPECT_EQ(4, only_editdis_cases[3].editdis);
|
||||||
|
|
||||||
|
EXPECT_EQ("", only_editdis_cases[3].lcs_s);
|
||||||
|
|
||||||
|
ASSERT_TRUE(only_editdis_cases[3].ses_seq.empty());
|
||||||
|
|
||||||
|
ASSERT_TRUE(only_editdis_cases[3].hunk_v.empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F (Strdifftest, only_editdis_test4) {
|
||||||
|
EXPECT_EQ(1, only_editdis_cases[4].editdis);
|
||||||
|
|
||||||
|
EXPECT_EQ("", only_editdis_cases[4].lcs_s);
|
||||||
|
|
||||||
|
ASSERT_TRUE(only_editdis_cases[4].ses_seq.empty());
|
||||||
|
|
||||||
|
ASSERT_TRUE(only_editdis_cases[4].hunk_v.empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F (Strdifftest, only_editdis_test5) {
|
||||||
|
EXPECT_EQ(0, only_editdis_cases[5].editdis);
|
||||||
|
|
||||||
|
EXPECT_EQ("", only_editdis_cases[5].lcs_s);
|
||||||
|
|
||||||
|
ASSERT_TRUE(only_editdis_cases[5].ses_seq.empty());
|
||||||
|
|
||||||
|
ASSERT_TRUE(only_editdis_cases[5].hunk_v.empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F (Strdifftest, only_editdis_test6) {
|
||||||
|
EXPECT_EQ(1, only_editdis_cases[6].editdis);
|
||||||
|
|
||||||
|
EXPECT_EQ("", only_editdis_cases[6].lcs_s);
|
||||||
|
|
||||||
|
ASSERT_TRUE(only_editdis_cases[6].ses_seq.empty());
|
||||||
|
|
||||||
|
ASSERT_TRUE(only_editdis_cases[6].hunk_v.empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F (Strdifftest, only_editdis_test7) {
|
||||||
|
EXPECT_EQ(1, only_editdis_cases[7].editdis);
|
||||||
|
|
||||||
|
EXPECT_EQ("", only_editdis_cases[7].lcs_s);
|
||||||
|
|
||||||
|
ASSERT_TRUE(only_editdis_cases[7].ses_seq.empty());
|
||||||
|
|
||||||
|
ASSERT_TRUE(only_editdis_cases[7].hunk_v.empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F (Strdifftest, only_editdis_test8) {
|
||||||
|
EXPECT_EQ(6, only_editdis_cases[8].editdis);
|
||||||
|
|
||||||
|
EXPECT_EQ("", only_editdis_cases[8].lcs_s);
|
||||||
|
|
||||||
|
ASSERT_TRUE(only_editdis_cases[8].ses_seq.empty());
|
||||||
|
|
||||||
|
ASSERT_TRUE(only_editdis_cases[8].hunk_v.empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F (Strdifftest, custom_comparator_test0) {
|
||||||
|
EXPECT_EQ(0, custom_cases[0].editdis);
|
||||||
|
|
||||||
|
EXPECT_EQ("abc", custom_cases[0].lcs_s);
|
||||||
|
|
||||||
|
ASSERT_EQ(0, custom_cases[0].editdis_ses);
|
||||||
|
|
||||||
|
ASSERT_TRUE(custom_cases[0].hunk_v.empty());
|
||||||
|
}
|
24
test/comparators.hpp
Normal file
24
test/comparators.hpp
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
#ifndef DTL_COMPARATORS
|
||||||
|
#define DTL_COMPARATORS
|
||||||
|
|
||||||
|
class CaseInsensitive: public dtl::Compare<char> {
|
||||||
|
public:
|
||||||
|
virtual bool impl(const char& a, const char& b) const {
|
||||||
|
return tolower(a) == tolower(b);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class StringCaseInsensitive: public dtl::Compare<string> {
|
||||||
|
public:
|
||||||
|
virtual bool impl(const string& a, const string& b) const {
|
||||||
|
if (a.length() == b.length()) {
|
||||||
|
bool equal = (strncasecmp(a.c_str(), b.c_str(), a.length()) == 0);
|
||||||
|
return equal;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // DTL_COMPARATORS
|
10
test/dtl_test.cpp
Normal file
10
test/dtl_test.cpp
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
/**
|
||||||
|
* It is necessary to use googletest to run tests.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
|
int main (int argc, char *argv[]) {
|
||||||
|
::testing::InitGoogleTest(&argc, argv);
|
||||||
|
return RUN_ALL_TESTS();
|
||||||
|
}
|
56
test/dtl_test_common.cpp
Normal file
56
test/dtl_test_common.cpp
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
|
||||||
|
#include "dtl_test_common.hpp"
|
||||||
|
|
||||||
|
string create_path (const string& test_name, string diff_name, enum type_diff t, bool is_use_suffix) {
|
||||||
|
string ret;
|
||||||
|
switch (t) {
|
||||||
|
case TYPE_DIFF_SES:
|
||||||
|
ret = (getcwd(NULL, 0) + string("/") + string("ses") + string("/") + diff_name + string("/") + test_name);
|
||||||
|
break;
|
||||||
|
case TYPE_DIFF_UNI:
|
||||||
|
ret = (getcwd(NULL, 0) + string("/") + string("hunks") + string("/") + diff_name + string("/") + test_name);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
ret += is_use_suffix ? "_" : "";
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t cal_diff_uni (const string& path_l, const string& path_r) {
|
||||||
|
string buf;
|
||||||
|
ifstream lifs(path_l.c_str());
|
||||||
|
ifstream rifs(path_r.c_str());
|
||||||
|
|
||||||
|
vector< string > llines;
|
||||||
|
vector< string > rlines;
|
||||||
|
|
||||||
|
while (getline(lifs, buf)) {
|
||||||
|
llines.push_back(buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
while (getline(rifs, buf)) {
|
||||||
|
rlines.push_back(buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
Diff< string, vector< string > > diff_uni(llines, rlines);
|
||||||
|
diff_uni.compose();
|
||||||
|
return diff_uni.getEditDistance();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_file_exist (string& fs) {
|
||||||
|
FILE *fp;
|
||||||
|
if ((fp = fopen(fs.c_str(), "r")) == NULL) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
fclose(fp);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void diff_resultset_exist_check (string &fs) {
|
||||||
|
if (!is_file_exist(fs)) {
|
||||||
|
cerr << "======================================================Error!!!======================================================" << endl;
|
||||||
|
cerr << "diff result set:" << fs << " is not found." << endl;
|
||||||
|
cerr << "======================================================Error!!!======================================================" << endl;
|
||||||
|
cerr << "excute dtl_test in dtl/test!" << endl;
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
}
|
70
test/dtl_test_common.hpp
Normal file
70
test/dtl_test_common.hpp
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
|
||||||
|
#ifndef DTL_TEST_COMMON
|
||||||
|
#define DTL_TEST_COMMON
|
||||||
|
|
||||||
|
#include <gtest/gtest.h>
|
||||||
|
#include <cstdio>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include <utility>
|
||||||
|
#include <iostream>
|
||||||
|
#include <fstream>
|
||||||
|
#include <dtl/dtl.hpp>
|
||||||
|
|
||||||
|
using std::cerr;
|
||||||
|
using std::endl;
|
||||||
|
using std::string;
|
||||||
|
using std::vector;
|
||||||
|
using std::pair;
|
||||||
|
using std::ifstream;
|
||||||
|
using std::ofstream;
|
||||||
|
|
||||||
|
using dtl::Diff;
|
||||||
|
using dtl::Diff3;
|
||||||
|
using dtl::Compare;
|
||||||
|
using dtl::SES_COMMON;
|
||||||
|
using dtl::SES_ADD;
|
||||||
|
using dtl::SES_DELETE;
|
||||||
|
using dtl::elemInfo;
|
||||||
|
using dtl::uniHunk;
|
||||||
|
|
||||||
|
#define dtl_test_typedefs(e_type, seq_type) \
|
||||||
|
typedef e_type elem; \
|
||||||
|
typedef seq_type sequence; \
|
||||||
|
typedef pair< elem, elemInfo > sesElem; \
|
||||||
|
typedef vector< elem > elemVec; \
|
||||||
|
typedef vector< sesElem > sesElemVec; \
|
||||||
|
typedef vector< uniHunk< sesElem > > uniHunkVec;
|
||||||
|
|
||||||
|
enum type_diff { TYPE_DIFF_SES, TYPE_DIFF_UNI };
|
||||||
|
|
||||||
|
string create_path (const string& test_name, string diff_name, enum type_diff t, bool is_use_suffix = false);
|
||||||
|
size_t cal_diff_uni (const string& path_l, const string& path_r);
|
||||||
|
bool is_file_exist (string& fs);
|
||||||
|
void diff_resultset_exist_check (string &fs);
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
class Remover {
|
||||||
|
public :
|
||||||
|
void operator()(const T& v){
|
||||||
|
remove(v.path_rses.c_str());
|
||||||
|
remove(v.path_rhunks.c_str());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template < typename elem, typename sequence, typename comparator >
|
||||||
|
void create_file (const string& path, Diff< elem, sequence, comparator >& diff, enum type_diff t) {
|
||||||
|
ofstream ofs;
|
||||||
|
ofs.open(path.c_str());
|
||||||
|
switch (t) {
|
||||||
|
case TYPE_DIFF_SES:
|
||||||
|
diff.printSES(ofs);
|
||||||
|
break;
|
||||||
|
case TYPE_DIFF_UNI:
|
||||||
|
diff.printUnifiedFormat(ofs);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
ofs.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // DTL_TEST_COMMON
|
0
test/hunks/intdiff/diff_test0
Normal file
0
test/hunks/intdiff/diff_test0
Normal file
2
test/hunks/intdiff/diff_test1
Normal file
2
test/hunks/intdiff/diff_test1
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
@@ -1,0 +1,1 @@
|
||||||
|
+1
|
2
test/hunks/intdiff/diff_test2
Normal file
2
test/hunks/intdiff/diff_test2
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
@@ -1,1 +1,0 @@
|
||||||
|
-1
|
15
test/hunks/intdiff/diff_test3
Normal file
15
test/hunks/intdiff/diff_test3
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
@@ -1,10 +1,10 @@
|
||||||
|
-1
|
||||||
|
-2
|
||||||
|
3
|
||||||
|
+5
|
||||||
|
+1
|
||||||
|
4
|
||||||
|
5
|
||||||
|
-6
|
||||||
|
+1
|
||||||
|
7
|
||||||
|
-8
|
||||||
|
9
|
||||||
|
+6
|
||||||
|
10
|
8
test/hunks/intdiff/diff_test4
Normal file
8
test/hunks/intdiff/diff_test4
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
@@ -1,5 +1,5 @@
|
||||||
|
-1
|
||||||
|
-2
|
||||||
|
3
|
||||||
|
+5
|
||||||
|
+1
|
||||||
|
4
|
||||||
|
5
|
0
test/hunks/strdiff/custom_test0
Normal file
0
test/hunks/strdiff/custom_test0
Normal file
5
test/hunks/strdiff/diff_test0
Normal file
5
test/hunks/strdiff/diff_test0
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
@@ -1,3 +1,3 @@
|
||||||
|
a
|
||||||
|
b
|
||||||
|
-c
|
||||||
|
+d
|
15
test/hunks/strdiff/diff_test1
Normal file
15
test/hunks/strdiff/diff_test1
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
@@ -1,10 +1,12 @@
|
||||||
|
a
|
||||||
|
c
|
||||||
|
+e
|
||||||
|
b
|
||||||
|
d
|
||||||
|
-e
|
||||||
|
a
|
||||||
|
-c
|
||||||
|
b
|
||||||
|
+b
|
||||||
|
+a
|
||||||
|
+b
|
||||||
|
e
|
||||||
|
d
|
10
test/hunks/strdiff/diff_test2
Normal file
10
test/hunks/strdiff/diff_test2
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
@@ -1,6 +1,6 @@
|
||||||
|
+d
|
||||||
|
a
|
||||||
|
-b
|
||||||
|
c
|
||||||
|
-d
|
||||||
|
-e
|
||||||
|
f
|
||||||
|
+e
|
||||||
|
+a
|
9
test/hunks/strdiff/diff_test3
Normal file
9
test/hunks/strdiff/diff_test3
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
@@ -1,6 +1,6 @@
|
||||||
|
-a
|
||||||
|
b
|
||||||
|
+d
|
||||||
|
c
|
||||||
|
+a
|
||||||
|
b
|
||||||
|
-d
|
||||||
|
a
|
6
test/hunks/strdiff/diff_test4
Normal file
6
test/hunks/strdiff/diff_test4
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
@@ -2,4 +2,5 @@
|
||||||
|
o
|
||||||
|
k
|
||||||
|
k
|
||||||
|
+k
|
||||||
|
o
|
0
test/hunks/strdiff/diff_test5
Normal file
0
test/hunks/strdiff/diff_test5
Normal file
2
test/hunks/strdiff/diff_test6
Normal file
2
test/hunks/strdiff/diff_test6
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
@@ -1,1 +1,0 @@
|
||||||
|
-a
|
2
test/hunks/strdiff/diff_test7
Normal file
2
test/hunks/strdiff/diff_test7
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
@@ -1,0 +1,1 @@
|
||||||
|
+b
|
22
test/hunks/strdiff/diff_test8
Normal file
22
test/hunks/strdiff/diff_test8
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
@@ -1,9 +1,11 @@
|
||||||
|
a
|
||||||
|
c
|
||||||
|
+e
|
||||||
|
b
|
||||||
|
d
|
||||||
|
-e
|
||||||
|
a
|
||||||
|
+b
|
||||||
|
+b
|
||||||
|
q
|
||||||
|
q
|
||||||
|
q
|
||||||
|
@@ -11,7 +13,7 @@
|
||||||
|
q
|
||||||
|
q
|
||||||
|
q
|
||||||
|
-c
|
||||||
|
+a
|
||||||
|
b
|
||||||
|
e
|
||||||
|
d
|
0
test/ses/intdiff/diff_test0
Normal file
0
test/ses/intdiff/diff_test0
Normal file
1
test/ses/intdiff/diff_test1
Normal file
1
test/ses/intdiff/diff_test1
Normal file
@ -0,0 +1 @@
|
|||||||
|
+1
|
1
test/ses/intdiff/diff_test2
Normal file
1
test/ses/intdiff/diff_test2
Normal file
@ -0,0 +1 @@
|
|||||||
|
-1
|
14
test/ses/intdiff/diff_test3
Normal file
14
test/ses/intdiff/diff_test3
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
-1
|
||||||
|
-2
|
||||||
|
3
|
||||||
|
+5
|
||||||
|
+1
|
||||||
|
4
|
||||||
|
5
|
||||||
|
-6
|
||||||
|
+1
|
||||||
|
7
|
||||||
|
-8
|
||||||
|
9
|
||||||
|
+6
|
||||||
|
10
|
7
test/ses/intdiff/diff_test4
Normal file
7
test/ses/intdiff/diff_test4
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
-1
|
||||||
|
-2
|
||||||
|
3
|
||||||
|
+5
|
||||||
|
+1
|
||||||
|
4
|
||||||
|
5
|
3
test/ses/strdiff/custom_test0
Normal file
3
test/ses/strdiff/custom_test0
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
a
|
||||||
|
b
|
||||||
|
c
|
4
test/ses/strdiff/diff_test0
Normal file
4
test/ses/strdiff/diff_test0
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
a
|
||||||
|
b
|
||||||
|
-c
|
||||||
|
+d
|
14
test/ses/strdiff/diff_test1
Normal file
14
test/ses/strdiff/diff_test1
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
a
|
||||||
|
c
|
||||||
|
+e
|
||||||
|
b
|
||||||
|
d
|
||||||
|
-e
|
||||||
|
a
|
||||||
|
-c
|
||||||
|
b
|
||||||
|
+b
|
||||||
|
+a
|
||||||
|
+b
|
||||||
|
e
|
||||||
|
d
|
9
test/ses/strdiff/diff_test2
Normal file
9
test/ses/strdiff/diff_test2
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
+d
|
||||||
|
a
|
||||||
|
-b
|
||||||
|
c
|
||||||
|
-d
|
||||||
|
-e
|
||||||
|
f
|
||||||
|
+e
|
||||||
|
+a
|
8
test/ses/strdiff/diff_test3
Normal file
8
test/ses/strdiff/diff_test3
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
-a
|
||||||
|
b
|
||||||
|
+d
|
||||||
|
c
|
||||||
|
+a
|
||||||
|
b
|
||||||
|
-d
|
||||||
|
a
|
6
test/ses/strdiff/diff_test4
Normal file
6
test/ses/strdiff/diff_test4
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
b
|
||||||
|
o
|
||||||
|
k
|
||||||
|
k
|
||||||
|
+k
|
||||||
|
o
|
0
test/ses/strdiff/diff_test5
Normal file
0
test/ses/strdiff/diff_test5
Normal file
1
test/ses/strdiff/diff_test6
Normal file
1
test/ses/strdiff/diff_test6
Normal file
@ -0,0 +1 @@
|
|||||||
|
-a
|
1
test/ses/strdiff/diff_test7
Normal file
1
test/ses/strdiff/diff_test7
Normal file
@ -0,0 +1 @@
|
|||||||
|
+b
|
21
test/ses/strdiff/diff_test8
Normal file
21
test/ses/strdiff/diff_test8
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
a
|
||||||
|
c
|
||||||
|
+e
|
||||||
|
b
|
||||||
|
d
|
||||||
|
-e
|
||||||
|
a
|
||||||
|
+b
|
||||||
|
+b
|
||||||
|
q
|
||||||
|
q
|
||||||
|
q
|
||||||
|
q
|
||||||
|
q
|
||||||
|
q
|
||||||
|
q
|
||||||
|
+a
|
||||||
|
-c
|
||||||
|
b
|
||||||
|
e
|
||||||
|
d
|
Loading…
x
Reference in New Issue
Block a user