Initial commit

This commit is contained in:
Tiberiu Chibici 2019-10-26 16:16:22 +03:00
commit 0095dcdcb3
87 changed files with 5446 additions and 0 deletions

53
.gitignore vendored Normal file
View File

@ -0,0 +1,53 @@
# C++ objects and libs
*.slo
*.lo
*.o
*.a
*.la
*.lai
*.so
*.so.*
*.dll
*.dylib
# Qt-es
object_script.*.Release
object_script.*.Debug
*_plugin_import.cpp
/.qmake.cache
/.qmake.stash
*.pro.user
*.pro.user.*
*.qbs.user
*.qbs.user.*
*.moc
moc_*.cpp
moc_*.h
qrc_*.cpp
ui_*.h
*.qmlc
*.jsc
Makefile*
*build-*
*.qm
*.prl
# Qt unit tests
target_wrapper.*
# QtCreator
*.autosave
# QtCreator Qml
*.qmlproject.user
*.qmlproject.user.*
# QtCreator CMake
CMakeLists.txt.user*
# QtCreator 4.8< compilation database
compile_commands.json
# QtCreator local machine specific files for imported projects
*creator.user*

24
AutoTyper.pro Normal file
View File

@ -0,0 +1,24 @@
TEMPLATE = app
CONFIG += console c++11
CONFIG -= app_bundle
CONFIG -= qt
LIBS += -lX11 -lXtst
INCLUDEPATH += Libs/dtl-1.19
SOURCES += \
main.cpp \
typer.cpp \
stringutils.cpp \
keyhandler.cpp \
vimtyper.cpp \
xkeyhandler.cpp \
humanizerkeyhandler.cpp
HEADERS += \
stringutils.h \
typer.h \
keyhandler.h \
vimtyper.h \
xkeyhandler.h \
humanizerkeyhandler.h

31
Libs/dtl-1.19/.gitignore vendored Normal file
View 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
^\#
\#$
\.\#

18
Libs/dtl-1.19/.travis.yml Normal file
View File

@ -0,0 +1,18 @@
language: cpp
compiler:
- gcc
- clang
before_script:
- sudo apt-get install -y cmake
- wget https://github.com/google/googletest/archive/release-1.8.0.zip
- unzip -q release-1.8.0.zip
- cd googletest-release-1.8.0
- cmake .
- make
- sudo make install
- cd ..
script:
- cd examples
- scons
- cd ../test
- scons check

View File

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

30
Libs/dtl-1.19/COPYING Normal file
View File

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

258
Libs/dtl-1.19/ChangeLog Normal file
View 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.

687
Libs/dtl-1.19/README.md Normal file
View File

@ -0,0 +1,687 @@
# dtl
[![Build Status](https://travis-ci.org/cubicdaiya/dtl.png?branch=master)](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)
* [Old commit histories](#old-commit-histories)
* [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.
This function is available 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](http://scons.org/) 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](https://github.com/google/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
$ 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
$ 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`.
# Old commit histories
Please see [cubicdaiya/dtl-legacy](https://github.com/cubicdaiya/dtl-legacy).
# License
Please read the file [COPYING](https://github.com/cubicdaiya/dtl/blob/master/COPYING).

7
Libs/dtl-1.19/SConstruct Normal file
View 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
Libs/dtl-1.19/dtl/Diff.hpp Normal file
View File

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

245
Libs/dtl-1.19/dtl/Diff3.hpp Normal file
View File

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

55
Libs/dtl-1.19/dtl/Lcs.hpp Normal file
View File

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

View File

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

132
Libs/dtl-1.19/dtl/Ses.hpp Normal file
View File

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

47
Libs/dtl-1.19/dtl/dtl.hpp Normal file
View File

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

View File

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

View File

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

View 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 ]

View 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;
}

View 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;
}

View 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

View 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;
}

View 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;
}

View 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;
}

View 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;
}

View 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

View 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;
}

View 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;
}

View 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;
}

View 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;
}

View 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;
}

View 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;
}

View 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);
}

View 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);
}

View 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));
}

View File

@ -0,0 +1,41 @@
# -*- coding: utf-8 -*-
# SConstrunct for dtl test
import os
def path_chomp(path):
if path[-1] == '/':
return path[:-1]
return path
env = Environment(
CPPFLAGS=['-Wall', '-O2'],
CPPPATH=['..'],
)
conf = Configure(env);
if not conf.CheckCXX():
print "c++ compiler is not installed!"
Exit(1)
libs = ['stdc++', 'pthread', 'gtest']
for lib in libs:
if not conf.CheckLib(lib):
print "library " + lib + " not installed!"
Exit(1)
conf.Finish()
test = env.Program(
'dtl_test',
[Glob('*.cpp')],
)
test_alias = env.Alias(
'check',
test,
test[0].abspath
)
env.AlwaysBuild(test_alias)

View 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);
}

View 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());
}

View 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

View 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();
}

View 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);
}
}

View 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

View File

@ -0,0 +1,2 @@
@@ -1,0 +1,1 @@
+1

View File

@ -0,0 +1,2 @@
@@ -1,1 +1,0 @@
-1

View File

@ -0,0 +1,15 @@
@@ -1,10 +1,10 @@
-1
-2
3
+5
+1
4
5
-6
+1
7
-8
9
+6
10

View File

@ -0,0 +1,8 @@
@@ -1,5 +1,5 @@
-1
-2
3
+5
+1
4
5

View File

@ -0,0 +1,5 @@
@@ -1,3 +1,3 @@
a
b
-c
+d

View File

@ -0,0 +1,15 @@
@@ -1,10 +1,12 @@
a
c
+e
b
d
-e
a
-c
b
+b
+a
+b
e
d

View File

@ -0,0 +1,10 @@
@@ -1,6 +1,6 @@
+d
a
-b
c
-d
-e
f
+e
+a

View File

@ -0,0 +1,9 @@
@@ -1,6 +1,6 @@
-a
b
+d
c
+a
b
-d
a

View File

@ -0,0 +1,6 @@
@@ -2,4 +2,5 @@
o
k
k
+k
o

View File

@ -0,0 +1,2 @@
@@ -1,1 +1,0 @@
-a

View File

@ -0,0 +1,2 @@
@@ -1,0 +1,1 @@
+b

View 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

View File

@ -0,0 +1 @@
+1

View File

@ -0,0 +1 @@
-1

View File

@ -0,0 +1,14 @@
-1
-2
3
+5
+1
4
5
-6
+1
7
-8
9
+6
10

View File

@ -0,0 +1,7 @@
-1
-2
3
+5
+1
4
5

View File

@ -0,0 +1,3 @@
a
b
c

View File

@ -0,0 +1,4 @@
a
b
-c
+d

View File

@ -0,0 +1,14 @@
a
c
+e
b
d
-e
a
-c
b
+b
+a
+b
e
d

View File

@ -0,0 +1,9 @@
+d
a
-b
c
-d
-e
f
+e
+a

View File

@ -0,0 +1,8 @@
-a
b
+d
c
+a
b
-d
a

View File

@ -0,0 +1,6 @@
b
o
k
k
+k
o

View File

@ -0,0 +1 @@
-a

View File

@ -0,0 +1 @@
+b

View 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

34
humanizerkeyhandler.cpp Normal file
View File

@ -0,0 +1,34 @@
#include "humanizerkeyhandler.h"
#include <unistd.h>
HumanizerKeyHandler::HumanizerKeyHandler(std::unique_ptr<KeyHandler> keyHandler)
: m_keyHandler(std::move(keyHandler))
{
}
void HumanizerKeyHandler::Key(SpecialKey key, KeyModifiers mods)
{
m_keyHandler->Key(key, mods);
InsertDelay(0, key, mods);
}
void HumanizerKeyHandler::Key(char key, KeyModifiers mods)
{
m_keyHandler->Key(key, mods);
InsertDelay(key, SpecialKey::NONE, mods);
}
void HumanizerKeyHandler::InsertDelay(char, SpecialKey currentKeySpecial, KeyModifiers mods)
{
unsigned delay = minDelay + static_cast<unsigned>(rand()) % (maxDelay - minDelay);
if (currentKeySpecial == SpecialKey::RETURN) {
delay = delay * 2;
}
if (mods & KeyModifiers::KM_SHIFT_MASK) {
delay = (delay * 3) / 2;
}
if (currentKeySpecial == SpecialKey::HOME || currentKeySpecial == SpecialKey::END) {
delay = (delay * 3);
}
usleep(1000 * delay);
}

26
humanizerkeyhandler.h Normal file
View File

@ -0,0 +1,26 @@
#ifndef HUMANIZERKEYHANDLER_H
#define HUMANIZERKEYHANDLER_H
#include "keyhandler.h"
#include <memory>
class HumanizerKeyHandler : public KeyHandler
{
public:
HumanizerKeyHandler(std::unique_ptr<KeyHandler> keyHandler);
virtual ~HumanizerKeyHandler() override { }
virtual void Key(SpecialKey key, KeyModifiers mods = KeyModifiers::KM_NONE) override;
virtual void Key(char key, KeyModifiers mods = KeyModifiers::KM_NONE) override;
unsigned minDelay = 50;
unsigned maxDelay = 150;
bool insertMistakes = true;
private:
void InsertDelay(char currentKey, SpecialKey currentKeySpecial, KeyModifiers mods);
std::unique_ptr<KeyHandler> m_keyHandler;
};
#endif // HUMANIZERKEYHANDLER_H

86
keyhandler.cpp Normal file
View File

@ -0,0 +1,86 @@
#include "keyhandler.h"
#include <iostream>
#include <unistd.h>
KeyHandler::~KeyHandler()
{
}
void KeyHandler::Key(SpecialKey key, KeyModifiers mods)
{
WaitUntilNotPaused();
if (mods & KM_META_MASK) {
std::cout << "Meta+";
}
if (mods & KM_CTRL_MASK) {
std::cout << "Ctrl+";
}
if (mods & KM_ALT_MASK) {
std::cout << "Alt+";
}
if (mods & KM_SHIFT_MASK) {
std::cout << "Shift+";
}
switch (key) {
case SpecialKey::NONE:
break;
case SpecialKey::UP:
std::cout << "";
break;
case SpecialKey::DOWN:
std::cout << "";
break;
case SpecialKey::LEFT:
std::cout << "";
break;
case SpecialKey::RIGHT:
std::cout << "";
break;
case SpecialKey::HOME:
std::cout << "";
break;
case SpecialKey::END:
std::cout << "";
break;
case SpecialKey::RETURN:
std::cout << "\n";
break;
case SpecialKey::ESCAPE:
std::cout << "ESC\n";
break;
}
}
void KeyHandler::Key(char key, KeyModifiers mods)
{
WaitUntilNotPaused();
if (mods & KM_META_MASK) {
std::cout << "Meta+";
}
if (mods & KM_CTRL_MASK) {
std::cout << "Ctrl+";
}
if (mods & KM_ALT_MASK) {
std::cout << "Alt+";
}
if (mods & KM_SHIFT_MASK) {
std::cout << "Shift+";
}
std::cout << key;
}
void KeyHandler::TogglePaused()
{
m_paused = !m_paused;
std::cout << (m_paused ? "Paused\n" : "Resumed\n");
}
void KeyHandler::WaitUntilNotPaused()
{
while (m_paused) {
usleep(100000);
}
}

63
keyhandler.h Normal file
View File

@ -0,0 +1,63 @@
#ifndef KEYHANDLER_H
#define KEYHANDLER_H
#include <string>
enum class SpecialKey
{
NONE,
UP,
DOWN,
LEFT,
RIGHT,
HOME,
END,
RETURN,
ESCAPE
};
enum KeyModifiers
{
KM_NONE = 0,
KM_LSHIFT = 0x1,
KM_RSHIFT = 0x2,
KM_SHIFT = KM_LSHIFT,
KM_SHIFT_MASK = KM_LSHIFT | KM_RSHIFT,
KM_LCTRL = 0x4,
KM_RCTRL = 0x8,
KM_CTRL = KM_LCTRL,
KM_CTRL_MASK = KM_LCTRL | KM_RCTRL,
KM_LALT = 0x10,
KM_RALT = 0x20,
KM_ALT = KM_LALT,
KM_ALT_MASK = KM_LALT | KM_RALT,
KM_LMETA = 0x40,
KM_RMETA = 0x80,
KM_META = KM_LMETA,
KM_META_MASK = KM_LMETA | KM_RMETA,
};
class KeyHandler
{
public:
KeyHandler() : m_paused(false) { }
virtual ~KeyHandler();
virtual void Key(SpecialKey key, KeyModifiers mods = KeyModifiers::KM_NONE);
virtual void Key(char key, KeyModifiers mods = KeyModifiers::KM_NONE);
void TogglePaused();
protected:
void WaitUntilNotPaused();
private:
volatile bool m_paused;
};
#endif // KEYHANDLER_H

44
main.cpp Normal file
View File

@ -0,0 +1,44 @@
#include <iostream>
#include <memory>
#include <unistd.h>
#include <csignal>
#include "typer.h"
#include "vimtyper.h"
#include "keyhandler.h"
#include "humanizerkeyhandler.h"
#include "xkeyhandler.h"
using namespace std;
static std::unique_ptr<Typer> typer;
void onInterrupted(int)
{
if (typer) {
typer->TogglePaused();
}
}
int main(int argc, char** argv)
{
if (argc < 2) {
cout << "Usage: " << argv[0] << "<file>";
return 1;
}
signal(SIGINT, onInterrupted);
printf("Get ready!\n");
for (int i = 10; i >= 0; i--) {
printf("\rStarting in %d seconds...", i);
fflush(stdout);
sleep(1);
}
printf("\n");
std::unique_ptr<XKeyHandler> keyHandler(new XKeyHandler());
std::unique_ptr<HumanizerKeyHandler> humanizer(new HumanizerKeyHandler(std::move(keyHandler)));
typer.reset(new VimTyper(std::move(humanizer)));
typer->ProcessFile(argv[1]);
return 0;
}

2
oskeyhandler.cpp Normal file
View File

@ -0,0 +1,2 @@
#include "oskeyhandler.h"

12
oskeyhandler.h Normal file
View File

@ -0,0 +1,12 @@
#ifndef OSKEYHANDLER_H
#define OSKEYHANDLER_H
class OsKeyHandler
{
public:
virtual ~OsKeyHandler() { }
virtual void SendKey(char key) = 0;
};
#endif // OSKEYHANDLER_H

45
stringutils.cpp Normal file
View File

@ -0,0 +1,45 @@
#include "stringutils.h"
// Compute Levenshtein Distance
// Martin Ettl, 2012-10-05
size_t LevenshteinDistance(const std::string &s1, const std::string &s2)
{
const size_t m(s1.size());
const size_t n(s2.size());
if (m == 0) return n;
if (n == 0) return m;
size_t *costs = new size_t[n + 1];
for (size_t k = 0; k <= n; k++) costs[k] = k;
size_t i = 0;
for (std::string::const_iterator it1 = s1.begin(); it1 != s1.end(); ++it1, ++i)
{
costs[0] = i+1;
size_t corner = i;
size_t j = 0;
for (std::string::const_iterator it2 = s2.begin(); it2 != s2.end(); ++it2, ++j)
{
size_t upper = costs[j+1];
if (*it1 == *it2)
{
costs[j+1] = corner;
}
else
{
size_t t(upper < corner ? upper : corner);
costs[j + 1] = (costs[j] < t ? costs[j] : t) + 1;
}
corner = upper;
}
}
size_t result = costs[n];
delete [] costs;
return result;
}

52
stringutils.h Normal file
View File

@ -0,0 +1,52 @@
#ifndef STRINGUTILS_H
#define STRINGUTILS_H
#include <algorithm>
#include <cctype>
#include <locale>
// trim from start (in place)
static inline void ltrim(std::string &s)
{
s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](int ch) {
return !std::isspace(ch);
}));
}
// trim from end (in place)
static inline void rtrim(std::string &s)
{
s.erase(std::find_if(s.rbegin(), s.rend(), [](int ch) {
return !std::isspace(ch);
}).base(), s.end());
}
// trim from both ends (in place)
static inline void trim(std::string &s)
{
ltrim(s);
rtrim(s);
}
// trim from start (copying)
static inline std::string ltrim_copy(std::string s)
{
ltrim(s);
return s;
}
// trim from end (copying)
static inline std::string rtrim_copy(std::string s)
{
rtrim(s);
return s;
}
// trim from both ends (copying)
static inline std::string trim_copy(std::string s)
{
trim(s);
return s;
}
#endif // STRINGUTILS_H

279
typer.cpp Normal file
View File

@ -0,0 +1,279 @@
#include <fstream>
#include <iostream>
#include <sstream>
#include <unistd.h>
#include <map>
#include "stringutils.h"
#include "typer.h"
#include <dtl/dtl.hpp>
void Typer::ProcessFile(std::string fname)
{
m_scrRow = 0;
m_scrCol = 0;
ReadFile(fname);
ComputeDiffs();
OnStart();
for (size_t i = 0; i < m_lines.size(); i++)
{
Line& line = m_lines[i];
// std::cout << "---------\n";
// std::cout << "++ " << line.prio << " : " << line.index << " : [ ";
// for (size_t j = 0; j < SIMILARITY_LINE_COUNT; j++)
// std::cout << line.similarity[j] << " ";
// std::cout << "] : " << line.text << "\n\n";
std::pair<size_t, std::string> lineOut = std::make_pair(line.index, line.text);
// Find insertion position
auto insertRowIt = std::lower_bound(m_scrOutput.begin(), m_scrOutput.end(), lineOut);
size_t insertRow = static_cast<size_t>(insertRowIt - m_scrOutput.begin());
// Insert row - there are 5 cases
// 1. we are on the previous row: End, Return, type row
// 2. we are at (0, 0) and nothing is typed: type row
// 3. we are on insertRow, Home + type row + press Return
// 4. we must insert below last row, navigate to last row, End, Return, type row
// 5. we are anywhere else, navigate to (insertRow, 0), press Return, go up and type row
if (insertRow > 0 &&
m_scrRow == insertRow - 1)
{
NavigateToCol(COL_END);
Newline();
TypeString(line.text);
}
else if (m_scrOutput.empty())
{
TypeString(line.text);
}
else if (m_scrRow == insertRow &&
insertRow < m_scrOutput.size() &&
m_scrOutput[insertRow].second.empty())
{
NavigateToCol(COL_HOME);
TypeString(line.text);
Newline();
}
else if (insertRow == m_scrOutput.size())
{
NavigateTo(insertRow - 1, COL_END);
Newline();
TypeString(line.text);
}
else
{
NavigateTo(insertRow, COL_HOME);
Newline();
NavigateToRow(insertRow);
TypeString(line.text);
}
// Synchronize screen output
m_scrOutput.insert(insertRowIt, lineOut);
}
}
void Typer::TogglePaused()
{
m_keyHandler->TogglePaused();
}
int Typer::GetLinePriority(std::string &line)
{
int prio = 0;
if (line.empty()) {
return prio;
}
if (!std::isdigit(line[0])) {
return prio;
}
std::istringstream stream(line);
stream >> prio;
line = line.substr(static_cast<size_t>(stream.tellg()) + 1u);
return prio;
}
void Typer::ReadFile(std::string fname)
{
std::ifstream in;
std::string line;
int prio;
size_t index = 0;
in.open(fname, std::ios::in);
if (!in)
{
std::cerr << "Failed to open file " << fname << "\n";
exit(2);
}
std::map<std::pair<int, size_t>, std::string> lines;
while (std::getline(in, line))
{
trim(line);
prio = GetLinePriority(line);
lines.emplace(std::make_pair(prio, ++index), line);
}
// Put sorted lines in m_lines vector
for (auto line : lines)
m_lines.push_back(Line(line.first.first, line.first.second, line.second));
}
void Typer::ComputeDiffs()
{
for (size_t i = 0; i < m_lines.size(); i++)
{
m_lines[i].similarity.fill(0);
for (size_t j = 0; j < SIMILARITY_LINE_COUNT && j < i; j++)
{
std::string a = m_lines[i].text;
std::string b = m_lines[i - j - 1].text;
if (a.size() > 0 || b.size() > 10)
{
dtl::Diff<char, std::string> diff(a, b);
diff.onOnlyEditDistance();
diff.compose();
long long dist = diff.getEditDistance();
m_lines[i].similarity[j] = 1.0f - static_cast<float>(dist) / static_cast<float>(a.size() + b.size());
}
else
{
m_lines[i].similarity[j] = 1.0f;
}
}
}
}
void Typer::Newline()
{
KeyNewline();
m_scrRow++;
m_scrCol = 0;
}
void Typer::TypeString(std::string str)
{
KeyString(str);
m_scrCol = str.size();
}
void Typer::NavigateTo(size_t row, size_t col)
{
NavigateToRow(row);
NavigateToCol(col);
}
void Typer::NavigateToRow(size_t row)
{
if (m_scrRow < row)
{
for (; m_scrRow < row && m_scrRow < m_scrOutput.size(); m_scrRow++)
{
KeyDown();
m_scrCol = std::min(m_scrCol, m_scrOutput[m_scrRow].second.size());
}
}
else
{
for (; m_scrRow > row; m_scrRow--)
{
KeyUp();
m_scrCol = std::min(m_scrCol, m_scrOutput[m_scrRow].second.size());
}
}
m_scrCol = std::min(m_scrCol, m_scrOutput[m_scrRow].second.size());
}
void Typer::NavigateToCol(size_t col)
{
size_t rowLen = m_scrOutput[m_scrRow].second.size();
if (col == COL_HOME && m_scrCol != 0) {
KeyHome();
m_scrCol = 0;
}
else if (col == COL_END && m_scrCol != rowLen) {
KeyEnd();
m_scrCol = rowLen;
}
else if (m_scrCol < col) {
for (; m_scrCol < col && m_scrCol < rowLen; m_scrCol++) {
KeyRight();
}
}
else if (m_scrCol > col)
{
for (; m_scrCol > col; m_scrCol--) {
KeyLeft();
}
}
}
bool Typer::IsKeyShifted(char c)
{
static const std::string shiftedKeys = "~!@#$%^&*()_+{}:\"|<>?>";
if (isalpha(c)) {
return isupper(c);
}
if (isdigit(c)) {
return false;
}
return (shiftedKeys.find(c) != std::string::npos);
}
void Typer::KeyUp()
{
m_keyHandler->Key(SpecialKey::UP);
}
void Typer::KeyDown()
{
m_keyHandler->Key(SpecialKey::DOWN);
}
void Typer::KeyLeft()
{
m_keyHandler->Key(SpecialKey::LEFT);
}
void Typer::KeyRight()
{
m_keyHandler->Key(SpecialKey::RIGHT);
}
void Typer::KeyHome()
{
m_keyHandler->Key(SpecialKey::HOME);
}
void Typer::KeyEnd()
{
m_keyHandler->Key(SpecialKey::END);
}
void Typer::KeyNewline()
{
m_keyHandler->Key(SpecialKey::RETURN);
}
void Typer::KeyString(std::string str)
{
for (char c : str)
m_keyHandler->Key(c, IsKeyShifted(c) ? KM_SHIFT : KM_NONE);
}

76
typer.h Normal file
View File

@ -0,0 +1,76 @@
#ifndef TYPER_H
#define TYPER_H
#include <string>
#include <vector>
#include <array>
#include <memory>
#include <keyhandler.h>
#define SIMILARITY_LINE_COUNT 8
#define SIMILARITY_COPY_THRESHOLD 0.75f
#define BLOCK_UNSIMILAR_LIMIT 2
struct Line
{
int prio;
size_t index;
std::string text;
std::array<float, SIMILARITY_LINE_COUNT> similarity;
Line() { }
Line(int prio, size_t index, std::string text) : prio(prio), index(index), text(text) { }
};
class Typer
{
public:
Typer(std::unique_ptr<KeyHandler> keyHandler) : m_keyHandler(std::move(keyHandler)) { }
virtual ~Typer() { }
void ProcessFile(std::string fname);
void TogglePaused();
protected:
virtual void OnStart() { }
virtual void KeyUp();
virtual void KeyDown();
virtual void KeyLeft();
virtual void KeyRight();
virtual void KeyHome();
virtual void KeyEnd();
virtual void KeyNewline();
virtual void KeyString(std::string str);
private:
int GetLinePriority(std::string& line);
void ReadFile(std::string fname);
void ComputeDiffs();
// These methods type and also update the "screen"
void Newline();
void TypeString(std::string str);
void NavigateTo(size_t row, size_t col);
void NavigateToRow(size_t row);
void NavigateToCol(size_t col);
bool IsKeyShifted(char c);
// constants
static const size_t COL_END = static_cast<size_t>(-2);
static const size_t COL_HOME = static_cast<size_t>(-1);
protected:
// key handler
std::unique_ptr<KeyHandler> m_keyHandler;
private:
// lines to write
std::vector<Line> m_lines;
// current state of the screen
std::vector<std::pair<size_t, std::string>> m_scrOutput;
size_t m_scrCol, m_scrRow;
};
#endif // TYPER_H

18
vimtyper.cpp Normal file
View File

@ -0,0 +1,18 @@
#include "vimtyper.h"
#include <unistd.h>
void VimTyper::OnStart()
{
// Enter insert mode
m_keyHandler->Key(SpecialKey::ESCAPE);
usleep(500000);
// Disable autoindent
KeyString(":setl noai nocin nosi inde=");
KeyNewline();
usleep(300000);
// Enter insert mode
m_keyHandler->Key('A');
sleep(1);
}

17
vimtyper.h Normal file
View File

@ -0,0 +1,17 @@
#ifndef VIMTYPER_H
#define VIMTYPER_H
#include "typer.h"
class VimTyper : public Typer
{
public:
VimTyper(std::unique_ptr<KeyHandler> keyHandler) : Typer(std::move(keyHandler)) { }
virtual ~VimTyper() override { }
protected:
virtual void OnStart() override;
};
#endif // VIMTYPER_H

87
xkeyhandler.cpp Normal file
View File

@ -0,0 +1,87 @@
#include "xkeyhandler.h"
#include <X11/keysym.h>
#include <X11/extensions/XTest.h>
std::map<SpecialKey, KeySym> XKeyHandler::s_keymap = {
{ SpecialKey::UP, XK_Up },
{ SpecialKey::DOWN, XK_Down },
{ SpecialKey::LEFT, XK_Left },
{ SpecialKey::RIGHT, XK_Right },
{ SpecialKey::HOME, XK_Home },
{ SpecialKey::END, XK_End },
{ SpecialKey::RETURN, XK_Return },
{ SpecialKey::ESCAPE, XK_Escape },
};
XKeyHandler::XKeyHandler()
{
m_disp = XOpenDisplay(nullptr);
}
XKeyHandler::~XKeyHandler()
{
XCloseDisplay(m_disp);
}
void XKeyHandler::Key(SpecialKey key, KeyModifiers mods)
{
WaitUntilNotPaused();
HandleModifierKeys(mods, true);
KeyCode keyCode = XKeysymToKeycode(m_disp, s_keymap.at(key));
XTestFakeKeyEvent(m_disp, keyCode, true, 0);
XTestFakeKeyEvent(m_disp, keyCode, false, 0);
HandleModifierKeys(mods, false);
XFlush(m_disp);
}
void XKeyHandler::Key(char key, KeyModifiers mods)
{
WaitUntilNotPaused();
if (key >= 0x20) {
HandleModifierKeys(mods, true);
KeyCode keyCode = XKeysymToKeycode(m_disp, static_cast<KeySym>(key));
XTestFakeKeyEvent(m_disp, keyCode, true, 0);
XTestFakeKeyEvent(m_disp, keyCode, false, 0);
HandleModifierKeys(mods, false);
XFlush(m_disp);
}
}
void XKeyHandler::HandleModifierKeys(KeyModifiers mods, bool press)
{
// Modifier key up
if (mods & KM_LMETA) {
XTestFakeKeyEvent(m_disp, XKeysymToKeycode(m_disp, XK_Meta_L), press, 0);
}
if (mods & KM_RMETA) {
XTestFakeKeyEvent(m_disp, XKeysymToKeycode(m_disp, XK_Meta_R), press, 0);
}
if (mods & KM_LCTRL) {
XTestFakeKeyEvent(m_disp, XKeysymToKeycode(m_disp, XK_Control_L), press, 0);
}
if (mods & KM_RCTRL) {
XTestFakeKeyEvent(m_disp, XKeysymToKeycode(m_disp, XK_Control_R), press, 0);
}
if (mods & KM_LALT) {
XTestFakeKeyEvent(m_disp, XKeysymToKeycode(m_disp, XK_Alt_L), press, 0);
}
if (mods & KM_RALT) {
XTestFakeKeyEvent(m_disp, XKeysymToKeycode(m_disp, XK_Alt_R), press, 0);
}
if (mods & KM_LSHIFT) {
XTestFakeKeyEvent(m_disp, XKeysymToKeycode(m_disp, XK_Shift_L), press, 0);
}
if (mods & KM_RSHIFT) {
XTestFakeKeyEvent(m_disp, XKeysymToKeycode(m_disp, XK_Shift_R), press, 0);
}
}

26
xkeyhandler.h Normal file
View File

@ -0,0 +1,26 @@
#ifndef XKEYHANDLER_H
#define XKEYHANDLER_H
#include <X11/Xlib.h>
#include "keyhandler.h"
#include <map>
class XKeyHandler : public KeyHandler
{
public:
XKeyHandler();
virtual ~XKeyHandler() override;
virtual void Key(SpecialKey key, KeyModifiers mods = KeyModifiers::KM_NONE) override;
virtual void Key(char key, KeyModifiers mods = KeyModifiers::KM_NONE) override;
private:
void HandleModifierKeys(KeyModifiers mods, bool press);
static std::map<SpecialKey, KeySym> s_keymap;
Display* m_disp;
};
#endif // XKEYHANDLER_H