init
This commit is contained in:
		
							
								
								
									
										31
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,31 @@ | ||||
| examples/unidiff | ||||
| examples/unistrdiff | ||||
| examples/strdiff | ||||
| examples/strdiff_cp | ||||
| examples/strdiff3 | ||||
| examples/intdiff | ||||
| examples/bdiff | ||||
| examples/intdiff3 | ||||
| examples/patch | ||||
| examples/fpatch | ||||
| examples/st2ses | ||||
| test/strdiff3_test | ||||
| test/*/*/*_ | ||||
| *.o | ||||
| *.orig | ||||
| *~ | ||||
| .semantic.cache | ||||
| .DS_Store | ||||
| *.swp | ||||
| GPATH | ||||
| GRTAGS | ||||
| GSYMS | ||||
| GTAGS | ||||
| TAGS | ||||
| dtl_test | ||||
| .sconsign.dblite | ||||
| .sconf_temp | ||||
| config.log | ||||
| ^\# | ||||
| \#$ | ||||
| \.\# | ||||
							
								
								
									
										16
									
								
								.travis.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								.travis.yml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,16 @@ | ||||
| language: cpp | ||||
| compiler: | ||||
|   - gcc | ||||
|   - clang | ||||
| before_script: | ||||
|   - wget http://googletest.googlecode.com/files/gtest-1.7.0.zip | ||||
|   - unzip -q gtest-1.7.0.zip | ||||
|   - cd gtest-1.7.0 | ||||
|   - ./configure | ||||
|   - make | ||||
|   - cd .. | ||||
| script: | ||||
|   - cd examples | ||||
|   - scons | ||||
|   - cd ../test | ||||
|   - GTEST_ROOT=$PWD/../gtest-1.7.0 scons check | ||||
							
								
								
									
										2
									
								
								CONTRIBUTORS
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								CONTRIBUTORS
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,2 @@ | ||||
| Tatsuhiko Kubo <cubicdaiya@gmail.com> | ||||
| Jan Weiß <jan@geheimwerk.de> | ||||
							
								
								
									
										30
									
								
								COPYING
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								COPYING
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,30 @@ | ||||
| In short, Diff Template Library is distributed under so called "BSD license", | ||||
|  | ||||
| Copyright (c) 2015 Tatsuhiko Kubo <cubicdaiya@gmail.com> | ||||
| All rights reserved. | ||||
|  | ||||
| Redistribution and use in source and binary forms, with or without modification,  | ||||
| are permitted provided that the following conditions are met: | ||||
|  | ||||
|  * Redistributions of source code must retain the above copyright notice,  | ||||
|    this list of conditions and the following disclaimer. | ||||
|  | ||||
|  * Redistributions in binary form must reproduce the above copyright notice,  | ||||
|    this list of conditions and the following disclaimer in the documentation  | ||||
|    and/or other materials provided with the distribution. | ||||
|  | ||||
|  * Neither the name of the authors nor the names of its contributors  | ||||
|    may be used to endorse or promote products derived from this software  | ||||
|    without specific prior written permission. | ||||
|  | ||||
| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS  | ||||
| "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT  | ||||
| LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR  | ||||
| A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT  | ||||
| OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,  | ||||
| SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED  | ||||
| TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR  | ||||
| PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF  | ||||
| LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING  | ||||
| NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS  | ||||
| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||
							
								
								
									
										258
									
								
								ChangeLog
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										258
									
								
								ChangeLog
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,258 @@ | ||||
| 2015-05-03 Tatsuhiko Kubo <cubicdaiya@gmail.com> | ||||
|  | ||||
| 	* added some minor changes. | ||||
|  | ||||
| 	* 1.19 released | ||||
|  | ||||
| 2013-01-10 Tatsuhiko Kubo <cubicdaiya@gmail.com> | ||||
|  | ||||
| 	* add printSES function for custom Printer Thanks to Hu Shubin | ||||
|  | ||||
| 	* remove files related mercurial | ||||
|  | ||||
| 	* 1.18 released | ||||
|  | ||||
| 2012-11-18 Tatsuhiko Kubo <cubicdaiya@gmail.com> | ||||
|  | ||||
| 	* add version-string variable | ||||
|  | ||||
| 	* replace get_current_dir_name to getcwd(get_current_dir_name is not in Mountain Lion) | ||||
|  | ||||
| 	* fix small typo | ||||
|  | ||||
| 	* 1.17 released | ||||
|  | ||||
| 2012-10-26 Tatsuhiko Kubo <cubicdaiya@gmail.com>, Jan Weiß <jan@geheimwerk.de> | ||||
|  | ||||
| 	* Improving comments | ||||
|  | ||||
| 	* rewrite README with markdown-style | ||||
|  | ||||
| 	* support gtest1.6 | ||||
|  | ||||
| 	* allow clients to handle if DTL swaps the arrays it is passed | ||||
|  | ||||
| 	* fix incorrect results for SES_COMMON when swapped | ||||
|  | ||||
| 	* add explicit initialization of ses | ||||
|  | ||||
| 	* implement option to force the order of sesElem objects in the ses | ||||
|  | ||||
| 	* fix problem -> issues/4(test succeeds when result-file does not exist) | ||||
|  | ||||
| 	* 1.16 released | ||||
|  | ||||
| 2011-11-10 Tatsuhiko Kubo <cubicdaiya@gmail.com> | ||||
|  | ||||
| 	* remove unused variable | ||||
|  | ||||
| 	* 1.15 released | ||||
|  | ||||
| 2011-06-18 Tatsuhiko Kubo <cubicdaiya@gmail.com> | ||||
|  | ||||
| 	* fix Issue #7 (isOnlyOneOperation returns incorrect value) | ||||
|  | ||||
| 	* 1.14 released | ||||
|  | ||||
| 2011-04-10 Tatsuhiko Kubo <cubicdaiya@gmail.com> | ||||
|  | ||||
| 	* add check for libraries with SCons | ||||
|  | ||||
| 	* add installer with SCons | ||||
|  | ||||
| 	* add sample of diff(bdiff) | ||||
|  | ||||
| 	* 1.13 released | ||||
|  | ||||
| 2011-01-23 Tatsuhiko Kubo <cubicdaiya@gmail.com> | ||||
|  | ||||
| 	* forget to add template parameter of stream for print methods of printUnifiedFormat | ||||
|  | ||||
| 	* 1.12 released | ||||
|  | ||||
| 2011-01-01 Tatsuhiko Kubo <cubicdaiya@gmail.com> | ||||
|  | ||||
| 	* add template parameter of stream for print methods | ||||
|  | ||||
| 	* function of importing ses | ||||
|  | ||||
| 	* 1.11 released | ||||
|  | ||||
| 2010-11-23 Tatsuhiko Kubo <cubicdaiya@gmail.com> | ||||
|  | ||||
| 	* use static_cast instead of C-style cast | ||||
|  | ||||
| 	* remove specifyConfliction | ||||
|  | ||||
| 	* 1.10 released | ||||
|  | ||||
| 2010-09-20 Tatsuhiko Kubo <cubicdaiya@gmail.com> | ||||
|  | ||||
| 	* fix bug of specifyConfliction | ||||
|  | ||||
| 	* add parameter for Diff3's comparator | ||||
|  | ||||
| 	* fix the bug which uniPatch fails | ||||
|  | ||||
| 	* add debug option for examples | ||||
|  | ||||
| 	* divide test sources | ||||
|  | ||||
| 	* 1.09 released | ||||
|  | ||||
| 2010-08-29 Tatsuhiko Kubo <cubicdaiya@gmail.com> | ||||
|  | ||||
| 	* fix the problem that comparator parameter is completely ignored. | ||||
|  | ||||
| 	* remove the warning 'comparison of unsigned expression >= 0 is always true' ( use -W ) | ||||
|  | ||||
| 	* move directory 'src' to 'dtl' | ||||
|  | ||||
| 	* remove Makefile for examples and test | ||||
|  | ||||
| 	* 1.08 released | ||||
|  | ||||
| 2010-07-11 Tatsuhiko Kubo <cubicdaiya@gmail.com> | ||||
|  | ||||
| 	* fix potential risk on 64bit environment(size of 'int' and size of 'size_t') | ||||
|  | ||||
| 	* add scons | ||||
|  | ||||
| 	* fix bug of specifyConfliction | ||||
|  | ||||
| 	* fix memory leak when onlyEditDistance is true | ||||
|  | ||||
| 	* change indent size from 2 to 4 | ||||
|  | ||||
| 	* 1.07 released | ||||
|  | ||||
| 2010-05-01 Tatsuhiko Kubo <cubicdaiya@gmail.com> | ||||
|  | ||||
| 	* add specifyConfliction | ||||
|  | ||||
| 	* 1.06 released | ||||
|  | ||||
| 2010-04-13 Tatsuhiko Kubo <cubicdaiya@gmail.com> | ||||
|  | ||||
| 	* constructors takes referenced parameter | ||||
|  | ||||
| 	* fix seg fault bug (http://code.google.com/p/dtl-cpp/issues/detail?id=2) | ||||
|  | ||||
| 	* 1.05 released | ||||
|  | ||||
| 2009-12-01 Tatsuhiko Kubo <cubicdaiya@gmail.com> | ||||
|  | ||||
| 	* add test programs with googletest | ||||
|  | ||||
| 	* add sample of diff(uintdiff) | ||||
|  | ||||
| 	* 1.04 released | ||||
|  | ||||
| 2009-10-02 Tatsuhiko Kubo <cubicdaiya@gmail.com> | ||||
|  | ||||
| 	* add function getLcsVec | ||||
|  | ||||
| 	* divide header files | ||||
|  | ||||
| 	* 1.03 released | ||||
|  | ||||
| 2009-09-08 Tatsuhiko Kubo <cubicdaiya@gmail.com> | ||||
|  | ||||
|         * rename editType to edit_t | ||||
|  | ||||
|         * add print functions | ||||
|  | ||||
|         * add functor of compare | ||||
|  | ||||
|         * use 'using' declaration | ||||
|  | ||||
|         * refactoring | ||||
|  | ||||
|         * add ignore patterns for Mercurial | ||||
|  | ||||
|         * 1.02 released. | ||||
|  | ||||
| 2009-08-08 Tatsuhiko Kubo <cubicdaiya@gmail.com> | ||||
|  | ||||
|         * append appropriate const keyword | ||||
|  | ||||
|         * refactoring | ||||
|  | ||||
|         * 1.01 released. | ||||
|  | ||||
| 2009-07-04 Tatsuhiko Kubo <cubicdaiya@gmail.com> | ||||
|  | ||||
|         * resolve problem memory leak occurs when default copy constructor set in motion. | ||||
|  | ||||
|         * 1.00 released. | ||||
|  | ||||
| 2009-06-08 Tatsuhiko Kubo <cubicdaiya@gmail.com> | ||||
|  | ||||
|         * enhance readability | ||||
|  | ||||
|         * change behavior when conflicted | ||||
|  | ||||
|         * decliment parameter for patch function | ||||
|  | ||||
|         * 0.07 released. | ||||
|  | ||||
| 2009-05-08 Tatsuhiko Kubo <cubicdaiya@gmail.com> | ||||
|  | ||||
|         * add flag for recording only editdistance | ||||
|  | ||||
|         * add sample of unidiff for string (unistrdiff) | ||||
|  | ||||
|         * add unserious diff. ver 0.03 has this feture. | ||||
|  | ||||
|         * fix bug for merge | ||||
|  | ||||
|         * add function getUniHunks | ||||
|  | ||||
|         * 0.06 released. | ||||
|  | ||||
| 2008-12-12 Tatsuhiko Kubo <cubicdaiya@gmail.com> | ||||
|  | ||||
|         * add sample of diff3 (strdiff3, intdiff3) | ||||
|  | ||||
|         * add diff3 | ||||
|  | ||||
|         * + -> - to - -> + with Unified Diff Format | ||||
|  | ||||
|         * add function uniPatch. this function can patch with Unified Diff Format Data Structure | ||||
|  | ||||
|         * dtl Import Unified Diff Format Data Structure from unidiff.cpp. | ||||
|  | ||||
|         * fix bug. function check whether file exists(common.cpp) | ||||
|  | ||||
|         * 0.05 released. | ||||
|  | ||||
| 2008-11-10 Tatsuhiko Kubo <cubicdaiya@gmail.com> | ||||
|  | ||||
|         * Improves accuracy of diff | ||||
|  | ||||
|         * fix serious memory bug for patch | ||||
|  | ||||
|         * changed type of argument in function fileExists(common.hpp, common.cpp) | ||||
|  | ||||
|         * 0.04 released. | ||||
|  | ||||
| 2008-11-06 Tatsuhiko Kubo <cubicdaiya@gmail.com> | ||||
|  | ||||
|         * add erorr check for sample programs | ||||
|  | ||||
|         * 0.03 released. | ||||
|  | ||||
| 2008-10-31 Tatsuhiko Kubo <cubicdaiya@gmail.com> | ||||
|  | ||||
|         * rename ChangLog to ChangeLog | ||||
|  | ||||
|         * modifiy README | ||||
|  | ||||
|         * output OK message on patch and fpatch | ||||
|  | ||||
|         * 0.02 released. | ||||
|  | ||||
| 2008-10-30 Tatsuhiko Kubo <cubicdaiya@gmail.com> | ||||
|  | ||||
|         * 0.01 released. | ||||
|  | ||||
							
								
								
									
										683
									
								
								README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										683
									
								
								README.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,683 @@ | ||||
| # dtl | ||||
|  | ||||
| [](https://travis-ci.org/cubicdaiya/dtl) | ||||
|  | ||||
| `dtl` is the diff template library written in C++. The name of template is derived C++'s Template. | ||||
|  | ||||
| # Table of contents | ||||
|  | ||||
|  * [Features](#features) | ||||
|  * [Getting started](#getting-started) | ||||
|   * [Compare two strings](#compare-two-strings) | ||||
|   * [Compare two data has arbitrary type](#compare-two-data-has-arbitrary-type) | ||||
|   * [Merge three sequences](#merge-three-sequences) | ||||
|   * [Patch function](#patch-function) | ||||
|   * [Difference as Unified Format](#difference-as-unified-format) | ||||
|   * [Compare large sequences](#compare-large-sequences) | ||||
|   * [Unserious difference](#unserious-difference) | ||||
|   * [Calculate only Edit Distance](#calculate-only-edit-distance) | ||||
|  * [Algorithm](#algorithm) | ||||
|   * [Computational complexity](#computational-complexity) | ||||
|   * [Comparison when difference between two sequences is very large](#comparison-when-difference-between-two-sequences-is-very-large) | ||||
|   * [Implementations with various programming languages](#implementations-with-various-programming-languages) | ||||
|  * [Examples](#examples) | ||||
|   * [strdiff](#strdiff) | ||||
|   * [intdiff](#intdiff) | ||||
|   * [unidiff](#unidiff) | ||||
|   * [unistrdiff](#unistrdiff) | ||||
|   * [strdiff3](#strdiff3) | ||||
|   * [intdiff3](#intdiff3) | ||||
|   * [patch](#patch) | ||||
|   * [fpatch](#fpatch) | ||||
|  * [Running tests](#running-tests) | ||||
|   * [Building test programs](#building-test-programs) | ||||
|   * [Running test programs](#running-test-programs) | ||||
|  * [License](#license) | ||||
|  | ||||
| # Features | ||||
|  | ||||
| `dtl` provides the functions for comparing two sequences have arbitrary type. But sequences must support random access\_iterator. | ||||
|  | ||||
| # Getting started | ||||
|  | ||||
| To start using this library, all you need to do is include `dtl.hpp`. | ||||
|  | ||||
| ```c++ | ||||
| #include "dtl/dtl.hpp" | ||||
| ``` | ||||
|  | ||||
| ## Compare two strings | ||||
|  | ||||
| First of all, calculate the difference between two strings. | ||||
|  | ||||
| ```c++ | ||||
| typedef char elem; | ||||
| typedef std::string sequence; | ||||
| sequence A("abc"); | ||||
| sequence B("abd"); | ||||
| dtl::Diff< elem, sequence > d(A, B); | ||||
| d.compose(); | ||||
| ``` | ||||
|  | ||||
| When the above code is run, `dtl` calculates the difference between A and B as Edit Distance and LCS and SES. | ||||
|  | ||||
| The meaning of these three terms is below. | ||||
|  | ||||
| | Edit Distance | Edit Distance is numerical value for declaring a difference between two sequences. | | ||||
| |:--------------|:-----------------------------------------------------------------------------------| | ||||
| | LCS           | LCS stands for Longest Common Subsequence.                                         | | ||||
| | SES           | SES stands for Shortest Edit Script. I mean SES is the shortest course of action for tranlating one sequence into another sequence.| | ||||
|  | ||||
| If one sequence is "abc" and another sequence is "abd", Edit Distance and LCS and SES is below. | ||||
|  | ||||
| | Edit Distance | 2               | | ||||
| |:--------------|:----------------| | ||||
| | LCS           | ab              | | ||||
| | SES           | C a C b D c A d | | ||||
|  | ||||
|  * 「C」:Common | ||||
|  * 「D」:Delete | ||||
|  * 「A」:ADD | ||||
|  | ||||
| If you want to know in more detail, please see [examples/strdiff.cpp](https://github.com/cubicdaiya/dtl/blob/master/examples/strdiff.cpp). | ||||
|  | ||||
| This calculates Edit Distance and LCS and SES of two strings received as command line arguments and prints each. | ||||
|  | ||||
| When one string is "abc" and another string "abd", the output of `strdiff` is below. | ||||
|  | ||||
| ```bash | ||||
| $ ./strdiff abc abd | ||||
| editDistance:2 | ||||
| LCS:ab | ||||
| SES | ||||
|  a | ||||
|  b | ||||
| -c | ||||
| +d | ||||
| $ | ||||
| ``` | ||||
|  | ||||
| ## Compare two data has arbitrary type | ||||
|  | ||||
| `dtl` can compare data has aribtrary type because of the C++'s template. | ||||
|  | ||||
| But the compared data type must support the random access\_iterator. | ||||
|  | ||||
| In the previous example, the string data compared, | ||||
|  | ||||
| `dtl` can also compare two int vectors like the example below. | ||||
|  | ||||
| ```c++ | ||||
| int a[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; | ||||
| int b[10] = {3, 5, 1, 4, 5, 1, 7, 9, 6, 10}; | ||||
| std::vector<int> A(&a[0], &a[10]); | ||||
| std::vector<int> B(&b[0], &b[10]); | ||||
| dtl::Diff< int > d(A, B); | ||||
| d.compose(); | ||||
| ``` | ||||
|  | ||||
| If you want to know in more detail, please see [examples/intdiff.cpp](https://github.com/cubicdaiya/dtl/blob/master/examples/intdiff.cpp). | ||||
|  | ||||
| ## Merge three sequences | ||||
|  | ||||
| `dtl` has the diff3 function. | ||||
|  | ||||
| This function is that `dtl` merges three sequences. | ||||
|  | ||||
| Additionally `dtl` detects the confliction. | ||||
|  | ||||
| ```c++ | ||||
| typedef char elem; | ||||
| typedef std::string sequence; | ||||
| sequence A("qqqabc"); | ||||
| sequence B("abc"); | ||||
| sequence C("abcdef"); | ||||
| dtl::Diff3<elem, sequence> diff3(A, B, C); | ||||
| diff3.compose(); | ||||
| if (!diff3.merge()) { | ||||
|   std::cerr << "conflict." << std::endl; | ||||
|   return -1; | ||||
| } | ||||
| std::cout << "result:" << diff3.getMergedSequence() << std::endl; | ||||
| ``` | ||||
|  | ||||
| When the above code is run, the output is below. | ||||
|  | ||||
| ```console | ||||
| result:qqqabcdef | ||||
| ``` | ||||
|  | ||||
| If you want to know in more detail, please see [examples/strdiff3.cpp](https://github.com/cubicdaiya/dtl/blob/master/examples/strdiff3.cpp). | ||||
|  | ||||
| ## Patch function | ||||
|  | ||||
| `dtl` can also translates one sequence to another sequence with SES. | ||||
|  | ||||
| ```c++ | ||||
| typedef char elem; | ||||
| typedef std::string sequence; | ||||
| sequence A("abc"); | ||||
| sequence B("abd"); | ||||
| dtl::Diff<elem, sequence> d(A, B); | ||||
| d.compose(); | ||||
| string s1(A); | ||||
| string s2 = d.patch(s1); | ||||
| ``` | ||||
|  | ||||
| When the above code is run, s2 becomes "abd". | ||||
| The SES of A("abc") and B("abd") is below. | ||||
|  | ||||
| ```console | ||||
| Common a | ||||
| Common b | ||||
| Delete c | ||||
| Add    d | ||||
| ``` | ||||
|  | ||||
| The patch function translates a sequence as argument with SES. | ||||
| For this example, "abc" is translated to "abd" with above SES. | ||||
|  | ||||
| Please see dtl's header files about the data structure of SES. | ||||
|  | ||||
| ## Difference as Unified Format | ||||
|  | ||||
| `dtl` can also treat difference as Unified Format. See the example below. | ||||
|  | ||||
| ```c++ | ||||
| typedef char elem; | ||||
| typedef std::string sequence; | ||||
| sequence A("acbdeaqqqqqqqcbed"); | ||||
| sequence B("acebdabbqqqqqqqabed"); | ||||
| dtl::Diff<elem, sequence > d(A, B); | ||||
| d.compose();             // construct an edit distance and LCS and SES | ||||
| d.composeUnifiedHunks(); // construct a difference as Unified Format with SES. | ||||
| d.printUnifiedFormat();  // print a difference as Unified Format. | ||||
| ``` | ||||
|  | ||||
| The difference as Unified Format of "acbdeaqqqqqqqcbed" and "acebdabbqqqqqqqabed" is below. | ||||
|  | ||||
| ```diff | ||||
| @@ -1,9 +1,11 @@ | ||||
|  a | ||||
|  c | ||||
| +e | ||||
|  b | ||||
|  d | ||||
| -e | ||||
|  a | ||||
| +b | ||||
| +b | ||||
|  q | ||||
|  q | ||||
|  q | ||||
| @@ -11,7 +13,7 @@ | ||||
|  q | ||||
|  q | ||||
|  q | ||||
| -c | ||||
| +a | ||||
|  b | ||||
|  e | ||||
|  d | ||||
| ``` | ||||
|  | ||||
| The data structure Unified Format is below. | ||||
|  | ||||
| ```c++ | ||||
| /** | ||||
|  * Structure of Unified Format Hunk | ||||
|  */ | ||||
| template <typename sesElem> | ||||
| struct uniHunk { | ||||
|   int a, b, c, d;                   // @@ -a,b +c,d @@ | ||||
|   std::vector<sesElem> common[2];   // anteroposterior commons on changes | ||||
|   std::vector<sesElem> change;      // changes | ||||
|   int inc_dec_count;                // count of increace and decrease | ||||
| }; | ||||
| ``` | ||||
|  | ||||
| The actual blocks of Unified Format is this structure's vector. | ||||
|  | ||||
| If you want to know in more detail, please see [examples/unistrdiff.cpp](https://github.com/cubicdaiya/dtl/blob/master/examples/unistrdiff.cpp) | ||||
| and [examples/unidiff.cpp](https://github.com/cubicdaiya/dtl/blob/master/examples/unidiff.cpp) and dtl's header files. | ||||
|  | ||||
| In addtion, `dtl` has the function translates one sequence to another sequence with Unified Format. | ||||
|  | ||||
| ```c++ | ||||
| typedef char elem; | ||||
| typedef std::string sequence; | ||||
| sequence A("abc"); | ||||
| sequence B("abd"); | ||||
| dtl::Diff<elem, sequence> d(A, B); | ||||
| d.compose(); | ||||
| d.composeUnifiedHunks() | ||||
| string s1(A); | ||||
| string s2 = d.UniPatch(s1); | ||||
| ``` | ||||
|  | ||||
| When the above code is run, s2 becomes "abd". | ||||
| The uniPatch function translates a sequence as argument with Unified Format blocks. | ||||
|  | ||||
| For this example, "abc" is translated to "abd" with the Unified Format block below. | ||||
|  | ||||
| ```diff | ||||
| @@ -1,3 +1,3 @@ | ||||
|  a | ||||
|  b | ||||
| -c | ||||
| +d | ||||
| ``` | ||||
|  | ||||
| ## Compare large sequences | ||||
|  | ||||
| When compare two large sequences, `dtl` can optimizes the calculation of difference with the onHuge function. | ||||
|  | ||||
| But this function is could use when the compared data type is std::vector. | ||||
|  | ||||
| When you use this function, you may call this function before calling compose function. | ||||
|  | ||||
| ```c++ | ||||
| typedef char elem; | ||||
| typedef  std::vector<elem> sequence; | ||||
| sequence A; | ||||
| sequence B; | ||||
| /* ・・・ */ | ||||
| dtl::Diff< elem, sequence > d(A, B); | ||||
| d.onHuge(); | ||||
| d.compose(); | ||||
| ``` | ||||
|  | ||||
| ## Unserious difference | ||||
|  | ||||
| The calculation of difference is very heavy. | ||||
| `dtl` uses An O(NP) Sequence Comparison Algorithm. | ||||
|  | ||||
| Though this Algorithm is sufficiently fast, | ||||
| when difference between two sequences is very large, | ||||
|  | ||||
| the calculation of LCS and SES needs massive amounts of memory. | ||||
|  | ||||
| `dtl` avoids above-described problem by dividing each sequence into plural subsequences | ||||
| and joining the difference of each subsequence finally. | ||||
|  | ||||
| As this way repeats allocating massive amounts of memory, | ||||
| `dtl` provides other way. It is the way of calculating unserious difference. | ||||
|  | ||||
| For example, The normal SES of "abc" and "abd" is below. | ||||
|  | ||||
| ```console | ||||
| Common a | ||||
| Common b | ||||
| Delete c | ||||
| Add    d | ||||
| ``` | ||||
|  | ||||
| The unserious SES of "abc" and "abd" is below. | ||||
|  | ||||
| ```console | ||||
| Delete a | ||||
| Delete b | ||||
| Delete c | ||||
| Add    a | ||||
| Add    b | ||||
| Add    d | ||||
| ``` | ||||
|  | ||||
| Of course, when "abc" and "abd" are compared with `dtl`, above difference is not derived. | ||||
|  | ||||
| `dtl` calculates the unserious difference when `dtl` judges the calculation of LCS and SES | ||||
| needs massive amounts of memory and unserious difference function is ON. | ||||
|  | ||||
| `dtl` joins the calculated difference before `dtl` judges it and unserious difference finally. | ||||
|  | ||||
| As a result, all difference is not unserious difference when unserious difference function is ON. | ||||
|  | ||||
| When you use this function, you may call this function before calling compose function. | ||||
|  | ||||
| ```c++ | ||||
| typedef char elem; | ||||
| typedef std::string sequence; | ||||
| sequence A("abc"); | ||||
| sequence B("abd"); | ||||
| dtl::Diff< elem, sequence > d(A, B); | ||||
| d.onUnserious(); | ||||
| d.compose(); | ||||
| ``` | ||||
|  | ||||
| ## Calculate only Edit Distance | ||||
|  | ||||
| As using onOnlyEditDistance, `dtl` calculates the only edit distance. | ||||
|  | ||||
| If you need only edit distance, you may use this function, | ||||
| because the calculation of edit distance is lighter than the calculation of LCS and SES. | ||||
|  | ||||
| When you use this function, you may call this function before calling compose function. | ||||
|  | ||||
| ```c++ | ||||
| typedef char elem; | ||||
| typedef std::string sequence; | ||||
| sequence A("abc"); | ||||
| sequence B("abd"); | ||||
| dtl::Diff< elem, sequence > d(A, B); | ||||
| d.onOnlyEditDistance(); | ||||
| d.compose(); | ||||
| ``` | ||||
|  | ||||
| # Algorithm | ||||
|  | ||||
| The algorithm `dtl` uses is based on "An O(NP) Sequence Comparison Algorithm" by described by Sun Wu, Udi Manber and Gene Myers. | ||||
|  | ||||
| An O(NP) Sequence Comparison Algorithm(following, Wu's O(NP) Algorithm) is the efficient algorithm for comparing two sequences. | ||||
|  | ||||
| ## Computational complexity | ||||
|  | ||||
| The computational complexity of Wu's O(NP) Algorithm is averagely O(N+PD), in the worst case, is O(NP). | ||||
|  | ||||
| ## Comparison when difference between two sequences is very large | ||||
|  | ||||
| Calculating LCS and SES efficiently at any time is a little difficult. | ||||
|  | ||||
| Because that the calculation of LCS and SES needs massive amounts of memory when a difference between two sequences is very large. | ||||
|  | ||||
| The program uses that algorithm don't consider that will burst in the worst case. | ||||
|  | ||||
| `dtl` avoids above-described problem by dividing each sequence into plural subsequences and joining the difference of each subsequence finally.(This feature is supported after version 0.04) | ||||
|  | ||||
| ## Implementations with various programming languages | ||||
|  | ||||
| There are the Wu's O(NP) Algorithm implementations with various programming languages below. | ||||
|  | ||||
| https://github.com/cubicdaiya/onp | ||||
|  | ||||
| # Examples | ||||
|  | ||||
| There are examples in [dtl/examples](https://github.com/cubicdaiya/dtl/tree/master/examples). | ||||
| `dtl` uses SCons for building examples and tests. If you build and run examples and tests, install SCons. | ||||
|  | ||||
| ## strdiff | ||||
|  | ||||
| `strdiff` calculates a difference between two string sequences, but multi byte is not supported. | ||||
|  | ||||
| ```bash | ||||
| $ cd dtl/examples | ||||
| $ scons strdiff | ||||
| $ ./strdiff acbdeacbed acebdabbabed | ||||
| editDistance:6 | ||||
| LCS:acbdabed | ||||
| SES | ||||
|   a | ||||
|   c | ||||
| + e | ||||
|   b | ||||
|   d | ||||
| - e | ||||
|   a | ||||
| - c | ||||
|   b | ||||
| + b | ||||
| + a | ||||
| + b | ||||
|   e | ||||
|   d | ||||
| $ | ||||
| ``` | ||||
|  | ||||
| ## intdiff | ||||
|  | ||||
| `intdiff` calculates a diffrence between two int arrays sequences. | ||||
|  | ||||
| ```bash | ||||
| $ cd dtl/examples | ||||
| $ scons intdiff | ||||
| $ ./intdiff # There are data in intdiff.cpp | ||||
| 1 2 3 4 5 6 7 8 9 10  | ||||
| 3 5 1 4 5 1 7 9 6 10  | ||||
| editDistance:8 | ||||
| LCS: 3 4 5 7 9 10  | ||||
| SES | ||||
| - 1 | ||||
| - 2 | ||||
|   3 | ||||
| + 5 | ||||
| + 1 | ||||
|   4 | ||||
|   5 | ||||
| - 6 | ||||
| + 1 | ||||
|   7 | ||||
| - 8 | ||||
|   9 | ||||
| + 6 | ||||
|   10 | ||||
| $ | ||||
| ``` | ||||
|  | ||||
| ## unidiff | ||||
|  | ||||
| `unidiff` calculates a diffrence between two text file sequences, | ||||
| and output the difference between files with unified format. | ||||
|  | ||||
| ```bash | ||||
| $ cd dtl/examples | ||||
| $ scons unidiff | ||||
| $ cat a.txt | ||||
| a | ||||
| e | ||||
| c | ||||
| z | ||||
| z | ||||
| d | ||||
| e | ||||
| f | ||||
| a | ||||
| b | ||||
| c | ||||
| d | ||||
| e | ||||
| f | ||||
| g | ||||
| h | ||||
| i | ||||
| $ cat b.txt | ||||
| a | ||||
| d | ||||
| e | ||||
| c | ||||
| f | ||||
| e | ||||
| a | ||||
| b | ||||
| c | ||||
| d | ||||
| e | ||||
| f | ||||
| g | ||||
| h | ||||
| i | ||||
| $ ./unidiff a.txt b.txt | ||||
| --- a.txt       2008-08-26 07:03:28 +0900 | ||||
| +++ b.txt       2008-08-26 03:02:42 +0900 | ||||
| @@ -1,11 +1,9 @@ | ||||
|  a | ||||
| -e | ||||
| -c | ||||
| -z | ||||
| -z | ||||
|  d | ||||
|  e | ||||
| +c | ||||
|  f | ||||
| +e | ||||
|  a | ||||
|  b | ||||
|  c | ||||
| $ | ||||
| ``` | ||||
|  | ||||
| ## unistrdiff | ||||
|  | ||||
| `unistrdiff` calculates a diffrence between two string sequences. | ||||
| and output the difference between strings with unified format. | ||||
|  | ||||
| ```bash | ||||
| $ cd dtl/examples | ||||
| $ scons unistrdiff | ||||
| $ ./unistrdiff acbdeacbed acebdabbabed | ||||
| editDistance:6 | ||||
| LCS:acbdabed | ||||
| @@ -1,10 +1,12 @@ | ||||
|  a | ||||
|  c | ||||
| +e | ||||
|  b | ||||
|  d | ||||
| -e | ||||
|  a | ||||
| -c | ||||
|  b | ||||
| +b | ||||
| +a | ||||
| +b | ||||
|  e | ||||
|  d | ||||
| $ | ||||
| ``` | ||||
|  | ||||
| ## strdiff3 | ||||
|  | ||||
| `strdiff3` merges three string sequence and output the merged sequence. | ||||
| When the confliction has occured, output the string "conflict.". | ||||
|  | ||||
| ```bash | ||||
| $ cd dtl/examples | ||||
| $ scons strdiff3 | ||||
| $ ./strdiff3 qabc abc abcdef | ||||
| result:qabcdef | ||||
| $ | ||||
| ``` | ||||
|  | ||||
| There is a output below when conflict occured. | ||||
|  | ||||
| ```bash | ||||
| $ ./strdiff3 adc abc aec | ||||
| conflict. | ||||
| $ | ||||
| ``` | ||||
|  | ||||
| ## intdiff3 | ||||
|  | ||||
| `intdiff3` merges three integer sequence(vector) and output the merged sequence. | ||||
|  | ||||
| ```bash | ||||
| $ cd dtl/examples | ||||
| $ scons intdiff3 | ||||
| $ ./intdiff3 | ||||
| a:1 2 3 4 5 6 7 3 9 10 | ||||
| b:1 2 3 4 5 6 7 8 9 10 | ||||
| c:1 2 3 9 5 6 7 8 9 10 | ||||
| s:1 2 3 9 5 6 7 3 9 10 | ||||
| intdiff3 OK | ||||
| $ | ||||
| ``` | ||||
|  | ||||
| ## patch | ||||
|  | ||||
| `patch` is the test program. Supposing that there are two strings is called by A and B, | ||||
| `patch` translates A to B with Shortest Edit Script or unified format difference. | ||||
|  | ||||
| ```bash | ||||
| $ cd dtl/examples | ||||
| $ scons patch | ||||
| $ ./patch abc abd | ||||
| before:abc | ||||
| after :abd | ||||
| patch successed | ||||
| before:abc | ||||
| after :abd | ||||
| unipatch successed | ||||
| $ | ||||
| ``` | ||||
|  | ||||
| ## fpatch | ||||
|  | ||||
| `fpatch` is the test program. Supposing that there are two files is called by A and B, | ||||
| `fpatch` translates A to B with Shortest Edit Script or unified format difference. | ||||
|  | ||||
| ```bash | ||||
| $ cd dtl/examples | ||||
| $ scons fpatch | ||||
| $ cat a.txt | ||||
| a | ||||
| e | ||||
| c | ||||
| z | ||||
| z | ||||
| d | ||||
| e | ||||
| f | ||||
| a | ||||
| b | ||||
| c | ||||
| d | ||||
| e | ||||
| f | ||||
| g | ||||
| h | ||||
| i | ||||
| $ cat b.txt | ||||
| $ cat b.txt | ||||
| a | ||||
| d | ||||
| e | ||||
| c | ||||
| f | ||||
| e | ||||
| a | ||||
| b | ||||
| c | ||||
| d | ||||
| e | ||||
| f | ||||
| g | ||||
| h | ||||
| i | ||||
| $ ./fpatch a.txt b.txt | ||||
| fpatch successed | ||||
| unipatch successed | ||||
| $ | ||||
| ``` | ||||
|  | ||||
| # Running tests | ||||
|  | ||||
| `dtl` uses [googletest](http://code.google.com/p/googletest/) and [SCons](http://www.scons.org/) with testing dtl-self. | ||||
|  | ||||
| # Building test programs | ||||
|  | ||||
| If you build test programs for `dtl`, run `scons` in test direcotry. | ||||
|  | ||||
| ```bash | ||||
| $ GTEST_ROOT=${gtest_root_dir} scons | ||||
| ``` | ||||
|  | ||||
| # Running test programs | ||||
|  | ||||
| If you run all tests for `dtl`, run 'scons check' in test direcotry. (it is necessary that gtest is compiled) | ||||
|  | ||||
| ```bash | ||||
| $ GTEST_ROOT=${gtest_root_dir} scons check | ||||
| ``` | ||||
|  | ||||
| If you run sectional tests, you may exeucte `dtl_test` directly after you run `scons`. | ||||
| Following command is the example for testing only Strdifftest. | ||||
|  | ||||
| ```bash | ||||
| $ ./dtl_test --gtest_filter='Strdifftest.*' | ||||
| ``` | ||||
|  | ||||
| `--gtest-filters` is the function of googletest. googletest has many useful functions for testing software flexibly. | ||||
| If you want to know other functions of googletest, run `./dtl_test --help`. | ||||
|  | ||||
|  | ||||
| # License | ||||
|  | ||||
| Please read the file [COPYING](https://github.com/cubicdaiya/dtl/blob/master/COPYING). | ||||
							
								
								
									
										7
									
								
								SConstruct
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								SConstruct
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,7 @@ | ||||
| import os | ||||
|  | ||||
| # install script | ||||
|  | ||||
| prefix  = ARGUMENTS.get('prefix', '/usr/local') | ||||
| headers = Glob('dtl/*.hpp') | ||||
| Alias('install', Install(os.path.join(prefix, 'dtl', 'include'), headers)) | ||||
							
								
								
									
										692
									
								
								dtl/Diff.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										692
									
								
								dtl/Diff.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,692 @@ | ||||
| /** | ||||
|    dtl -- Diff Template Library | ||||
|     | ||||
|    In short, Diff Template Library is distributed under so called "BSD license", | ||||
|     | ||||
|    Copyright (c) 2015 Tatsuhiko Kubo <cubicdaiya@gmail.com> | ||||
|    All rights reserved. | ||||
|     | ||||
|    Redistribution and use in source and binary forms, with or without modification, | ||||
|    are permitted provided that the following conditions are met: | ||||
|     | ||||
|    * Redistributions of source code must retain the above copyright notice, | ||||
|    this list of conditions and the following disclaimer. | ||||
|     | ||||
|    * Redistributions in binary form must reproduce the above copyright notice, | ||||
|    this list of conditions and the following disclaimer in the documentation | ||||
|    and/or other materials provided with the distribution. | ||||
|     | ||||
|    * Neither the name of the authors nor the names of its contributors | ||||
|    may be used to endorse or promote products derived from this software  | ||||
|    without specific prior written permission. | ||||
|     | ||||
|    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||||
|    "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||||
|    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||||
|    A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||||
|    OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||||
|    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED | ||||
|    TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | ||||
|    PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | ||||
|    LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | ||||
|    NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||||
|    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||
| */ | ||||
|  | ||||
| /* If you use this library, you must include dtl.hpp only. */ | ||||
|  | ||||
| #ifndef DTL_DIFF_H | ||||
| #define DTL_DIFF_H | ||||
|  | ||||
| namespace dtl { | ||||
|      | ||||
|     /** | ||||
|      * diff class template | ||||
|      * sequence must support random_access_iterator. | ||||
|      */ | ||||
|     template <typename elem, typename sequence = vector< elem >, typename comparator = Compare< elem > > | ||||
|     class Diff | ||||
|     { | ||||
|     private : | ||||
|         dtl_typedefs(elem, sequence) | ||||
|         sequence           A; | ||||
|         sequence           B; | ||||
|         size_t             M; | ||||
|         size_t             N; | ||||
|         size_t             delta; | ||||
|         size_t             offset; | ||||
|         long long          *fp; | ||||
|         long long          editDistance; | ||||
|         Lcs< elem >        lcs; | ||||
|         Ses< elem >        ses; | ||||
|         editPath           path; | ||||
|         editPathCordinates pathCordinates; | ||||
|         bool               swapped; | ||||
|         bool               huge; | ||||
|         bool               trivial; | ||||
|         bool               editDistanceOnly; | ||||
|         uniHunkVec         uniHunks; | ||||
|         comparator         cmp; | ||||
|     public : | ||||
|         Diff () {} | ||||
|          | ||||
|         Diff (const sequence& a,  | ||||
|               const sequence& b) : A(a), B(b), ses(false) { | ||||
|             init(); | ||||
|         } | ||||
|          | ||||
|         Diff (const sequence& a, | ||||
|               const sequence& b, | ||||
|               bool deletesFirst) : A(a), B(b), ses(deletesFirst) { | ||||
|             init(); | ||||
|         } | ||||
|          | ||||
|         Diff (const sequence& a, | ||||
|               const sequence& b,  | ||||
|               const comparator& comp) : A(a), B(b), ses(false), cmp(comp) { | ||||
|             init(); | ||||
|         } | ||||
|          | ||||
|         Diff (const sequence& a,  | ||||
|               const sequence& b,  | ||||
|               bool deleteFirst, | ||||
|               const comparator& comp) : A(a), B(b), ses(deleteFirst), cmp(comp) { | ||||
|             init(); | ||||
|         } | ||||
|          | ||||
|         ~Diff() {} | ||||
|          | ||||
|         long long getEditDistance () const { | ||||
|             return editDistance; | ||||
|         } | ||||
|          | ||||
|         Lcs< elem > getLcs () const { | ||||
|             return lcs; | ||||
|         } | ||||
|          | ||||
|         elemVec getLcsVec () const { | ||||
|             return lcs.getSequence(); | ||||
|         } | ||||
|          | ||||
|         Ses< elem > getSes () const { | ||||
|             return ses; | ||||
|         } | ||||
|          | ||||
|         uniHunkVec getUniHunks () const { | ||||
|             return uniHunks; | ||||
|         } | ||||
|          | ||||
|         /* These should be deprecated */ | ||||
|         bool isHuge () const { | ||||
|             return huge; | ||||
|         } | ||||
|          | ||||
|         void onHuge () { | ||||
|             this->huge = true; | ||||
|         } | ||||
|          | ||||
|         void offHuge () { | ||||
|             this->huge = false; | ||||
|         } | ||||
|          | ||||
|         bool isUnserious () const { | ||||
|             return trivial; | ||||
|         } | ||||
|          | ||||
|         void onUnserious () { | ||||
|             this->trivial = true; | ||||
|         } | ||||
|          | ||||
|         void offUnserious () { | ||||
|             this->trivial = false; | ||||
|         } | ||||
|          | ||||
|         void onOnlyEditDistance () { | ||||
|             this->editDistanceOnly = true; | ||||
|         } | ||||
|          | ||||
|         /* These are the replacements for the above */ | ||||
|         bool hugeEnabled () const { | ||||
|             return huge; | ||||
|         } | ||||
|          | ||||
|         void enableHuge () { | ||||
|             this->huge = true; | ||||
|         } | ||||
|          | ||||
|         void disableHuge () { | ||||
|             this->huge = false; | ||||
|         } | ||||
|          | ||||
|         bool trivialEnabled () const { | ||||
|             return trivial; | ||||
|         } | ||||
|          | ||||
|         void enableTrivial () const { | ||||
|             this->trivial = true; | ||||
|         } | ||||
|          | ||||
|         void disableTrivial () { | ||||
|             this->trivial = false; | ||||
|         } | ||||
|          | ||||
|         void editDistanceOnlyEnabled () { | ||||
|             this->editDistanceOnly = true; | ||||
|         } | ||||
|          | ||||
|         /** | ||||
|          * patching with Unified Format Hunks | ||||
|          */ | ||||
|         sequence uniPatch (const sequence& seq) { | ||||
|             elemList        seqLst(seq.begin(), seq.end()); | ||||
|             sesElemVec      shunk; | ||||
|             sesElemVec_iter vsesIt; | ||||
|             elemList_iter   lstIt         = seqLst.begin(); | ||||
|             long long       inc_dec_total = 0; | ||||
|             long long       gap           = 1; | ||||
|             for (uniHunkVec_iter it=uniHunks.begin();it!=uniHunks.end();++it) { | ||||
|                 joinSesVec(shunk, it->common[0]); | ||||
|                 joinSesVec(shunk, it->change); | ||||
|                 joinSesVec(shunk, it->common[1]); | ||||
|                 it->a         += inc_dec_total; | ||||
|                 inc_dec_total += it->inc_dec_count; | ||||
|                 for (long long i=0;i<it->a - gap;++i) { | ||||
|                     ++lstIt; | ||||
|                 } | ||||
|                 gap = it->a + it->b + it->inc_dec_count; | ||||
|                 vsesIt = shunk.begin(); | ||||
|                 while (vsesIt!=shunk.end()) { | ||||
|                     switch (vsesIt->second.type) { | ||||
|                     case SES_ADD : | ||||
|                         seqLst.insert(lstIt, vsesIt->first); | ||||
|                         break; | ||||
|                     case SES_DELETE : | ||||
|                         if (lstIt != seqLst.end()) { | ||||
|                             lstIt = seqLst.erase(lstIt); | ||||
|                         } | ||||
|                         break; | ||||
|                     case SES_COMMON : | ||||
|                         if (lstIt != seqLst.end()) { | ||||
|                             ++lstIt; | ||||
|                         } | ||||
|                         break; | ||||
|                     default : | ||||
|                         // no fall-through | ||||
|                         break; | ||||
|                     } | ||||
|                     ++vsesIt; | ||||
|                 } | ||||
|                 shunk.clear(); | ||||
|             } | ||||
|              | ||||
|             sequence patchedSeq(seqLst.begin(), seqLst.end()); | ||||
|             return patchedSeq; | ||||
|         } | ||||
|          | ||||
|         /** | ||||
|          * patching with Shortest Edit Script (SES) | ||||
|          */ | ||||
|         sequence patch (const sequence& seq) const { | ||||
|             sesElemVec    sesSeq = ses.getSequence(); | ||||
|             elemList      seqLst(seq.begin(), seq.end()); | ||||
|             elemList_iter lstIt  = seqLst.begin(); | ||||
|             for (sesElemVec_iter sesIt=sesSeq.begin();sesIt!=sesSeq.end();++sesIt) { | ||||
|                 switch (sesIt->second.type) { | ||||
|                 case SES_ADD : | ||||
|                     seqLst.insert(lstIt, sesIt->first); | ||||
|                     break; | ||||
|                 case SES_DELETE : | ||||
|                     lstIt = seqLst.erase(lstIt); | ||||
|                     break; | ||||
|                 case SES_COMMON : | ||||
|                     ++lstIt; | ||||
|                     break; | ||||
|                 default : | ||||
|                     // no through | ||||
|                     break; | ||||
|                 } | ||||
|             } | ||||
|             sequence patchedSeq(seqLst.begin(), seqLst.end()); | ||||
|             return patchedSeq; | ||||
|         } | ||||
|          | ||||
|         /** | ||||
|          * compose Longest Common Subsequence and Shortest Edit Script. | ||||
|          * The algorithm implemented here is based on "An O(NP) Sequence Comparison Algorithm" | ||||
|          * described by Sun Wu, Udi Manber and Gene Myers | ||||
|          */ | ||||
|         void compose() { | ||||
|              | ||||
|             if (isHuge()) { | ||||
|                 pathCordinates.reserve(MAX_CORDINATES_SIZE); | ||||
|             } | ||||
|              | ||||
|             long long p = -1; | ||||
|             fp = new long long[M + N + 3]; | ||||
|             fill(&fp[0], &fp[M + N + 3], -1); | ||||
|             path = editPath(M + N + 3); | ||||
|             fill(path.begin(), path.end(), -1); | ||||
|         ONP: | ||||
|             do { | ||||
|                 ++p; | ||||
|                 for (long long k=-p;k<=static_cast<long long>(delta)-1;++k) { | ||||
|                     fp[k+offset] = snake(k, fp[k-1+offset]+1, fp[k+1+offset]); | ||||
|                 } | ||||
|                 for (long long k=static_cast<long long>(delta)+p;k>=static_cast<long long>(delta)+1;--k) { | ||||
|                     fp[k+offset] = snake(k, fp[k-1+offset]+1, fp[k+1+offset]); | ||||
|                 } | ||||
|                 fp[delta+offset] = snake(static_cast<long long>(delta), fp[delta-1+offset]+1, fp[delta+1+offset]); | ||||
|             } while (fp[delta+offset] != static_cast<long long>(N) && pathCordinates.size() < MAX_CORDINATES_SIZE); | ||||
|              | ||||
|             editDistance += static_cast<long long>(delta) + 2 * p; | ||||
|             long long r = path[delta+offset]; | ||||
|             P cordinate; | ||||
|             editPathCordinates epc(0); | ||||
|              | ||||
|             // recording edit distance only | ||||
|             if (editDistanceOnly) { | ||||
|                 delete[] this->fp; | ||||
|                 return; | ||||
|             } | ||||
|              | ||||
|             while(r != -1) { | ||||
|                 cordinate.x = pathCordinates[(size_t)r].x; | ||||
|                 cordinate.y = pathCordinates[(size_t)r].y; | ||||
|                 epc.push_back(cordinate); | ||||
|                 r = pathCordinates[(size_t)r].k; | ||||
|             } | ||||
|              | ||||
|             // record Longest Common Subsequence & Shortest Edit Script | ||||
|             if (!recordSequence(epc)) { | ||||
|                 pathCordinates.resize(0); | ||||
|                 epc.resize(0); | ||||
|                 p = -1; | ||||
|                 goto ONP; | ||||
|             } | ||||
|             delete[] this->fp; | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * print difference between A and B as an SES | ||||
|          */ | ||||
|         template < typename stream > | ||||
|         void printSES (stream& out) const { | ||||
|             sesElemVec ses_v = ses.getSequence(); | ||||
|             for_each(ses_v.begin(), ses_v.end(), ChangePrinter< sesElem, stream >(out)); | ||||
|         } | ||||
|          | ||||
|         void printSES (ostream& out = cout) const { | ||||
|             printSES< ostream >(out); | ||||
|         } | ||||
|          | ||||
|         /** | ||||
|          * print differences given an SES | ||||
|          */ | ||||
|         template < typename stream > | ||||
|         static void printSES (const Ses< elem >& s, stream& out) { | ||||
|             sesElemVec ses_v = s.getSequence(); | ||||
|             for_each(ses_v.begin(), ses_v.end(), ChangePrinter< sesElem, stream >(out)); | ||||
|         } | ||||
|          | ||||
|         static void printSES (const Ses< elem >& s, ostream& out = cout) { | ||||
|             printSES< ostream >(s, out); | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * print difference between A and B as an SES with custom printer | ||||
|          */ | ||||
|         template < typename stream, template < typename SEET, typename STRT > class PT > | ||||
|         void printSES (stream& out) const { | ||||
|             sesElemVec ses_v = ses.getSequence (); | ||||
|             for_each (ses_v.begin (), ses_v.end(), PT < sesElem, stream > (out)); | ||||
|         } | ||||
|          | ||||
|         /** | ||||
|          * print difference between A and B in the Unified Format | ||||
|          */ | ||||
|         template < typename stream > | ||||
|         void printUnifiedFormat (stream& out) const { | ||||
|             for_each(uniHunks.begin(), uniHunks.end(), UniHunkPrinter< sesElem, stream >(out)); | ||||
|         } | ||||
|          | ||||
|         void printUnifiedFormat (ostream& out = cout) const { | ||||
|             printUnifiedFormat< ostream >(out); | ||||
|         } | ||||
|          | ||||
|         /** | ||||
|          * print unified format difference with given unified format hunks | ||||
|          */ | ||||
|         template < typename stream > | ||||
|         static void printUnifiedFormat (const uniHunkVec& hunks, stream& out) { | ||||
|             for_each(hunks.begin(), hunks.end(), UniHunkPrinter< sesElem >(out)); | ||||
|         } | ||||
|  | ||||
|         static void printUnifiedFormat (const uniHunkVec& hunks, ostream& out = cout) { | ||||
|             printUnifiedFormat< ostream >(hunks, out); | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * compose Unified Format Hunks from Shortest Edit Script | ||||
|          */ | ||||
|         void composeUnifiedHunks () { | ||||
|             sesElemVec         common[2]; | ||||
|             sesElemVec         change; | ||||
|             sesElemVec         ses_v  = ses.getSequence(); | ||||
|             long long          l_cnt  = 1; | ||||
|             long long          length = distance(ses_v.begin(), ses_v.end()); | ||||
|             long long          middle = 0; | ||||
|             bool               isMiddle, isAfter; | ||||
|             elemInfo           einfo; | ||||
|             long long          a, b, c, d;        // @@ -a,b +c,d @@ | ||||
|             long long          inc_dec_count = 0; | ||||
|             uniHunk< sesElem > hunk; | ||||
|             sesElemVec         adds; | ||||
|             sesElemVec         deletes; | ||||
|              | ||||
|             isMiddle = isAfter = false; | ||||
|             a = b = c = d = 0; | ||||
|              | ||||
|             for (sesElemVec_iter it=ses_v.begin();it!=ses_v.end();++it, ++l_cnt) { | ||||
|                 einfo = it->second; | ||||
|                 switch (einfo.type) { | ||||
|                 case SES_ADD : | ||||
|                     middle = 0; | ||||
|                     ++inc_dec_count; | ||||
|                     adds.push_back(*it); | ||||
|                     if (!isMiddle)       isMiddle = true; | ||||
|                     if (isMiddle)        ++d; | ||||
|                     if (l_cnt >= length) { | ||||
|                         joinSesVec(change, deletes); | ||||
|                         joinSesVec(change, adds); | ||||
|                         isAfter = true; | ||||
|                     } | ||||
|                     break; | ||||
|                 case SES_DELETE : | ||||
|                     middle = 0; | ||||
|                     --inc_dec_count; | ||||
|                     deletes.push_back(*it); | ||||
|                     if (!isMiddle)       isMiddle = true; | ||||
|                     if (isMiddle)        ++b; | ||||
|                     if (l_cnt >= length) { | ||||
|                         joinSesVec(change, deletes); | ||||
|                         joinSesVec(change, adds); | ||||
|                         isAfter = true; | ||||
|                     } | ||||
|                     break; | ||||
|                 case SES_COMMON : | ||||
|                     ++b;++d; | ||||
|                     if (common[1].empty() && adds.empty() && deletes.empty() && change.empty()) { | ||||
|                         if (static_cast<long long>(common[0].size()) < DTL_CONTEXT_SIZE) { | ||||
|                             if (a == 0 && c == 0) { | ||||
|                                 if (!wasSwapped()) { | ||||
|                                     a = einfo.beforeIdx; | ||||
|                                     c = einfo.afterIdx; | ||||
|                                 } else { | ||||
|                                     a = einfo.afterIdx; | ||||
|                                     c = einfo.beforeIdx; | ||||
|                                 } | ||||
|                             } | ||||
|                             common[0].push_back(*it); | ||||
|                         } else { | ||||
|                             rotate(common[0].begin(), common[0].begin() + 1, common[0].end()); | ||||
|                             common[0].pop_back(); | ||||
|                             common[0].push_back(*it); | ||||
|                             ++a;++c; | ||||
|                             --b;--d; | ||||
|                         } | ||||
|                     } | ||||
|                     if (isMiddle && !isAfter) { | ||||
|                         ++middle; | ||||
|                         joinSesVec(change, deletes); | ||||
|                         joinSesVec(change, adds); | ||||
|                         change.push_back(*it); | ||||
|                         if (middle >= DTL_SEPARATE_SIZE || l_cnt >= length) { | ||||
|                             isAfter = true; | ||||
|                         } | ||||
|                         adds.clear(); | ||||
|                         deletes.clear(); | ||||
|                     } | ||||
|                     break; | ||||
|                 default : | ||||
|                     // no through | ||||
|                     break; | ||||
|                 } | ||||
|                 // compose unified format hunk | ||||
|                 if (isAfter && !change.empty()) { | ||||
|                     sesElemVec_iter cit = it; | ||||
|                     long long       cnt = 0; | ||||
|                     for (long long i=0;i<DTL_SEPARATE_SIZE && (cit != ses_v.end());++i, ++cit) { | ||||
|                         if (cit->second.type == SES_COMMON) { | ||||
|                             ++cnt; | ||||
|                         } | ||||
|                     } | ||||
|                     if (cnt < DTL_SEPARATE_SIZE && l_cnt < length) { | ||||
|                         middle = 0; | ||||
|                         isAfter = false; | ||||
|                         continue; | ||||
|                     } | ||||
|                     if (static_cast<long long>(common[0].size()) >= DTL_SEPARATE_SIZE) { | ||||
|                         long long c0size = static_cast<long long>(common[0].size()); | ||||
|                         rotate(common[0].begin(),  | ||||
|                                common[0].begin() + (size_t)c0size - DTL_SEPARATE_SIZE,  | ||||
|                                common[0].end()); | ||||
|                         for (long long i=0;i<c0size - DTL_SEPARATE_SIZE;++i) { | ||||
|                             common[0].pop_back(); | ||||
|                         } | ||||
|                         a += c0size - DTL_SEPARATE_SIZE; | ||||
|                         c += c0size - DTL_SEPARATE_SIZE; | ||||
|                     } | ||||
|                     if (a == 0) ++a; | ||||
|                     if (c == 0) ++c; | ||||
|                     if (wasSwapped()) swap(a, c); | ||||
|                     hunk.a = a; | ||||
|                     hunk.b = b; | ||||
|                     hunk.c = c; | ||||
|                     hunk.d = d; | ||||
|                     hunk.common[0]     = common[0]; | ||||
|                     hunk.change        = change; | ||||
|                     hunk.common[1]     = common[1]; | ||||
|                     hunk.inc_dec_count = inc_dec_count; | ||||
|                     uniHunks.push_back(hunk); | ||||
|                     isMiddle = false; | ||||
|                     isAfter  = false; | ||||
|                     common[0].clear(); | ||||
|                     common[1].clear(); | ||||
|                     adds.clear(); | ||||
|                     deletes.clear(); | ||||
|                     change.clear(); | ||||
|                     a = b = c = d = middle = inc_dec_count = 0; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|          | ||||
|         /** | ||||
|          * compose ses from stream | ||||
|          */ | ||||
|         template <typename stream> | ||||
|         static Ses< elem > composeSesFromStream (stream& st) | ||||
|         { | ||||
|             elem        line; | ||||
|             Ses< elem > ret; | ||||
|             long long   x_idx, y_idx; | ||||
|             x_idx = y_idx = 1; | ||||
|             while (getline(st, line)) { | ||||
|                 elem mark(line.begin(), line.begin() + 1); | ||||
|                 elem e(line.begin() + 1, line.end()); | ||||
|                 if (mark == SES_MARK_DELETE) { | ||||
|                     ret.addSequence(e, x_idx, 0, SES_DELETE); | ||||
|                     ++x_idx; | ||||
|                 } else if (mark == SES_MARK_ADD) { | ||||
|                     ret.addSequence(e, y_idx, 0, SES_ADD); | ||||
|                     ++y_idx; | ||||
|                 } else if (mark == SES_MARK_COMMON) { | ||||
|                     ret.addSequence(e, x_idx, y_idx, SES_COMMON); | ||||
|                     ++x_idx; | ||||
|                     ++y_idx; | ||||
|                 } | ||||
|             } | ||||
|             return ret; | ||||
|         } | ||||
|          | ||||
|     private : | ||||
|         /** | ||||
|          * initialize | ||||
|          */ | ||||
|         void init () { | ||||
|             M = distance(A.begin(), A.end()); | ||||
|             N = distance(B.begin(), B.end()); | ||||
|             if (M < N) { | ||||
|                 swapped = false; | ||||
|             } else { | ||||
|                 swap(A, B); | ||||
|                 swap(M, N); | ||||
|                 swapped = true; | ||||
|             } | ||||
|             editDistance     = 0; | ||||
|             delta            = N - M; | ||||
|             offset           = M + 1; | ||||
|             huge             = false; | ||||
|             trivial          = false; | ||||
|             editDistanceOnly = false; | ||||
|             fp               = NULL; | ||||
|         } | ||||
|          | ||||
|         /** | ||||
|          * search shortest path and record the path | ||||
|          */ | ||||
|         long long snake(const long long& k, const long long& above, const long long& below) { | ||||
|             long long r = above > below ? path[(size_t)k-1+offset] : path[(size_t)k+1+offset]; | ||||
|             long long y = max(above, below); | ||||
|             long long x = y - k; | ||||
|             while ((size_t)x < M && (size_t)y < N && (swapped ? cmp.impl(B[(size_t)y], A[(size_t)x]) : cmp.impl(A[(size_t)x], B[(size_t)y]))) { | ||||
|                 ++x;++y; | ||||
|             } | ||||
|              | ||||
|             path[(size_t)k+offset] = static_cast<long long>(pathCordinates.size()); | ||||
|             if (!editDistanceOnly) { | ||||
|                 P p; | ||||
|                 p.x = x;p.y = y;p.k = r; | ||||
|                 pathCordinates.push_back(p);       | ||||
|             } | ||||
|             return y; | ||||
|         } | ||||
|          | ||||
|         /** | ||||
|          * record SES and LCS | ||||
|          */ | ||||
|         bool recordSequence (const editPathCordinates& v) { | ||||
|             sequence_const_iter x(A.begin()); | ||||
|             sequence_const_iter y(B.begin()); | ||||
|             long long           x_idx,  y_idx;  // line number for Unified Format | ||||
|             long long           px_idx, py_idx; // cordinates | ||||
|             bool                complete = false; | ||||
|             x_idx  = y_idx  = 1; | ||||
|             px_idx = py_idx = 0; | ||||
|             for (size_t i=v.size()-1;!complete;--i) { | ||||
|                 while(px_idx < v[i].x || py_idx < v[i].y) { | ||||
|                     if (v[i].y - v[i].x > py_idx - px_idx) { | ||||
|                         if (!wasSwapped()) { | ||||
|                             ses.addSequence(*y, 0, y_idx, SES_ADD); | ||||
|                         } else { | ||||
|                             ses.addSequence(*y, y_idx, 0, SES_DELETE); | ||||
|                         } | ||||
|                         ++y; | ||||
|                         ++y_idx; | ||||
|                         ++py_idx; | ||||
|                     } else if (v[i].y - v[i].x < py_idx - px_idx) { | ||||
|                         if (!wasSwapped()) { | ||||
|                             ses.addSequence(*x, x_idx, 0, SES_DELETE); | ||||
|                         } else { | ||||
|                             ses.addSequence(*x, 0, x_idx, SES_ADD); | ||||
|                         } | ||||
|                         ++x; | ||||
|                         ++x_idx; | ||||
|                         ++px_idx; | ||||
|                     } else { | ||||
|                         if (!wasSwapped()) { | ||||
|                             lcs.addSequence(*x); | ||||
|                             ses.addSequence(*x, x_idx, y_idx, SES_COMMON); | ||||
|                         } else { | ||||
|                             lcs.addSequence(*y); | ||||
|                             ses.addSequence(*y, y_idx, x_idx, SES_COMMON); | ||||
|                         } | ||||
|                         ++x; | ||||
|                         ++y; | ||||
|                         ++x_idx; | ||||
|                         ++y_idx; | ||||
|                         ++px_idx; | ||||
|                         ++py_idx; | ||||
|                     } | ||||
|                 } | ||||
|                 if (i == 0) complete = true; | ||||
|             } | ||||
|              | ||||
|             if (x_idx > static_cast<long long>(M) && y_idx > static_cast<long long>(N)) { | ||||
|                 // all recording succeeded | ||||
|             } else { | ||||
|                 // trivial difference | ||||
|                 if (trivialEnabled()) { | ||||
|                     if (!wasSwapped()) { | ||||
|                         recordOddSequence(x_idx, M, x, SES_DELETE); | ||||
|                         recordOddSequence(y_idx, N, y, SES_ADD); | ||||
|                     } else { | ||||
|                         recordOddSequence(x_idx, M, x, SES_ADD); | ||||
|                         recordOddSequence(y_idx, N, y, SES_DELETE); | ||||
|                     } | ||||
|                     return true; | ||||
|                 } | ||||
|                  | ||||
|                 // nontrivial difference | ||||
|                 sequence A_(A.begin() + (size_t)x_idx - 1, A.end()); | ||||
|                 sequence B_(B.begin() + (size_t)y_idx - 1, B.end()); | ||||
|                 A        = A_; | ||||
|                 B        = B_; | ||||
|                 M        = distance(A.begin(), A.end()); | ||||
|                 N        = distance(B.begin(), B.end()); | ||||
|                 delta    = N - M; | ||||
|                 offset   = M + 1; | ||||
|                 delete[] fp; | ||||
|                 fp = new long long[M + N + 3]; | ||||
|                 fill(&fp[0], &fp[M + N + 3], -1); | ||||
|                 fill(path.begin(), path.end(), -1); | ||||
|                 return false; | ||||
|             } | ||||
|             return true; | ||||
|         } | ||||
|          | ||||
|         /** | ||||
|          * record odd sequence in SES | ||||
|          */ | ||||
|         void inline recordOddSequence (long long idx, long long length, sequence_const_iter it, const edit_t et) { | ||||
|             while(idx < length){ | ||||
|                 ses.addSequence(*it, idx, 0, et); | ||||
|                 ++it; | ||||
|                 ++idx; | ||||
|                 ++editDistance; | ||||
|             } | ||||
|             ses.addSequence(*it, idx, 0, et); | ||||
|             ++editDistance; | ||||
|         } | ||||
|          | ||||
|         /** | ||||
|          * join SES vectors | ||||
|          */ | ||||
|         void inline joinSesVec (sesElemVec& s1, sesElemVec& s2) const { | ||||
|             if (!s2.empty()) { | ||||
|                 for (sesElemVec_iter vit=s2.begin();vit!=s2.end();++vit) { | ||||
|                     s1.push_back(*vit); | ||||
|                 } | ||||
|             }       | ||||
|         } | ||||
|          | ||||
|         /** | ||||
|          * check if the sequences have been swapped | ||||
|          */ | ||||
|         bool inline wasSwapped () const { | ||||
|             return swapped; | ||||
|         } | ||||
|  | ||||
|     }; | ||||
| } | ||||
|  | ||||
| #endif // DTL_DIFF_H | ||||
							
								
								
									
										245
									
								
								dtl/Diff3.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										245
									
								
								dtl/Diff3.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,245 @@ | ||||
| /** | ||||
|    dtl -- Diff Template Library | ||||
|     | ||||
|    In short, Diff Template Library is distributed under so called "BSD license", | ||||
|     | ||||
|    Copyright (c) 2015 Tatsuhiko Kubo <cubicdaiya@gmail.com> | ||||
|    All rights reserved. | ||||
|     | ||||
|    Redistribution and use in source and binary forms, with or without modification, | ||||
|    are permitted provided that the following conditions are met: | ||||
|     | ||||
|    * Redistributions of source code must retain the above copyright notice, | ||||
|    this list of conditions and the following disclaimer. | ||||
|     | ||||
|    * Redistributions in binary form must reproduce the above copyright notice, | ||||
|    this list of conditions and the following disclaimer in the documentation | ||||
|    and/or other materials provided with the distribution. | ||||
|     | ||||
|    * Neither the name of the authors nor the names of its contributors | ||||
|    may be used to endorse or promote products derived from this software  | ||||
|    without specific prior written permission. | ||||
|     | ||||
|    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||||
|    "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||||
|    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||||
|    A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||||
|    OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||||
|    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED | ||||
|    TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | ||||
|    PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | ||||
|    LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | ||||
|    NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||||
|    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||
| */ | ||||
|  | ||||
| /* If you use this library, you must include dtl.hpp only. */ | ||||
|  | ||||
| #ifndef DTL_DIFF3_H | ||||
| #define DTL_DIFF3_H | ||||
|  | ||||
| namespace dtl { | ||||
|      | ||||
|     /** | ||||
|      * diff3 class template | ||||
|      * sequence must support random_access_iterator. | ||||
|      */ | ||||
|     template <typename elem, typename sequence = vector< elem >, typename comparator = Compare< elem > > | ||||
|     class Diff3 | ||||
|     { | ||||
|     private: | ||||
|         dtl_typedefs(elem, sequence) | ||||
|         sequence                           A; | ||||
|         sequence                           B; | ||||
|         sequence                           C; | ||||
|         sequence                           S; | ||||
|         Diff< elem, sequence, comparator > diff_ba; | ||||
|         Diff< elem, sequence, comparator > diff_bc; | ||||
|         bool                               conflict; | ||||
|         elem                               csepabegin; | ||||
|         elem                               csepa; | ||||
|         elem                               csepaend; | ||||
|     public : | ||||
|         Diff3 () {} | ||||
|         Diff3 (const sequence& a,  | ||||
|                const sequence& b,  | ||||
|                const sequence& c) : A(a), B(b), C(c),  | ||||
|                                     diff_ba(b, a), diff_bc(b, c),  | ||||
|                                     conflict(false) {}  | ||||
|          | ||||
|         ~Diff3 () {} | ||||
|          | ||||
|         bool isConflict () const { | ||||
|             return conflict; | ||||
|         } | ||||
|          | ||||
|         sequence getMergedSequence () const { | ||||
|             return S; | ||||
|         } | ||||
|          | ||||
|         /** | ||||
|          * merge changes B and C into A | ||||
|          */ | ||||
|         bool merge () { | ||||
|             if (diff_ba.getEditDistance() == 0) {     // A == B | ||||
|                 if (diff_bc.getEditDistance() == 0) { // A == B == C | ||||
|                     S = B; | ||||
|                     return true; | ||||
|                 } | ||||
|                 S = C; | ||||
|                 return true; | ||||
|             } else {                                  // A != B | ||||
|                 if (diff_bc.getEditDistance() == 0) { // A != B == C | ||||
|                     S = A;                               | ||||
|                     return true; | ||||
|                 } else {                              // A != B != C | ||||
|                     S = merge_(); | ||||
|                     if (isConflict()) {               // conflict occured | ||||
|                         return false; | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|             return true; | ||||
|         } | ||||
|          | ||||
|         /** | ||||
|          * compose differences | ||||
|          */ | ||||
|         void compose () { | ||||
|             diff_ba.compose(); | ||||
|             diff_bc.compose(); | ||||
|         } | ||||
|          | ||||
|     private : | ||||
|         /** | ||||
|          * merge implementation | ||||
|          */ | ||||
|         sequence merge_ () { | ||||
|             elemVec         seq; | ||||
|             Ses< elem >     ses_ba   = diff_ba.getSes(); | ||||
|             Ses< elem >     ses_bc   = diff_bc.getSes(); | ||||
|             sesElemVec      ses_ba_v = ses_ba.getSequence(); | ||||
|             sesElemVec      ses_bc_v = ses_bc.getSequence(); | ||||
|             sesElemVec_iter ba_it    = ses_ba_v.begin(); | ||||
|             sesElemVec_iter bc_it    = ses_bc_v.begin(); | ||||
|             sesElemVec_iter ba_end   = ses_ba_v.end(); | ||||
|             sesElemVec_iter bc_end   = ses_bc_v.end(); | ||||
|              | ||||
|             while (!isEnd(ba_end, ba_it) || !isEnd(bc_end, bc_it)) { | ||||
|                 while (true) { | ||||
|                     if (!isEnd(ba_end, ba_it)            &&  | ||||
|                         !isEnd(bc_end, bc_it)            && | ||||
|                         ba_it->first == bc_it->first     &&  | ||||
|                         ba_it->second.type == SES_COMMON &&  | ||||
|                         bc_it->second.type == SES_COMMON) { | ||||
|                         // do nothing | ||||
|                     } else { | ||||
|                         break; | ||||
|                     } | ||||
|                     if      (!isEnd(ba_end, ba_it)) seq.push_back(ba_it->first); | ||||
|                     else if (!isEnd(bc_end, bc_it)) seq.push_back(bc_it->first); | ||||
|                     forwardUntilEnd(ba_end, ba_it); | ||||
|                     forwardUntilEnd(bc_end, bc_it); | ||||
|                 } | ||||
|                 if (isEnd(ba_end, ba_it) || isEnd(bc_end, bc_it)) break; | ||||
|                 if (   ba_it->second.type == SES_COMMON  | ||||
|                        && bc_it->second.type == SES_DELETE) { | ||||
|                     forwardUntilEnd(ba_end, ba_it); | ||||
|                     forwardUntilEnd(bc_end, bc_it); | ||||
|                 } else if (ba_it->second.type == SES_COMMON &&  | ||||
|                            bc_it->second.type == SES_ADD) { | ||||
|                     seq.push_back(bc_it->first); | ||||
|                     forwardUntilEnd(bc_end, bc_it); | ||||
|                 } else if (ba_it->second.type == SES_DELETE &&  | ||||
|                            bc_it->second.type == SES_COMMON) { | ||||
|                     forwardUntilEnd(ba_end, ba_it); | ||||
|                     forwardUntilEnd(bc_end, bc_it); | ||||
|                 } else if (ba_it->second.type == SES_DELETE &&  | ||||
|                            bc_it->second.type == SES_DELETE) { | ||||
|                     if (ba_it->first == bc_it->first) { | ||||
|                         forwardUntilEnd(ba_end, ba_it); | ||||
|                         forwardUntilEnd(bc_end, bc_it); | ||||
|                     } else { | ||||
|                         // conflict | ||||
|                         conflict = true; | ||||
|                         return B; | ||||
|                     } | ||||
|                 } else if (ba_it->second.type == SES_DELETE &&  | ||||
|                            bc_it->second.type == SES_ADD) { | ||||
|                     // conflict | ||||
|                     conflict = true; | ||||
|                     return B; | ||||
|                 } else if (ba_it->second.type == SES_ADD &&  | ||||
|                            bc_it->second.type == SES_COMMON) { | ||||
|                     seq.push_back(ba_it->first); | ||||
|                     forwardUntilEnd(ba_end, ba_it); | ||||
|                 } else if (ba_it->second.type == SES_ADD &&  | ||||
|                            bc_it->second.type == SES_DELETE) { | ||||
|                     // conflict | ||||
|                     conflict = true; | ||||
|                     return B; | ||||
|                 } else if (ba_it->second.type == SES_ADD &&  | ||||
|                            bc_it->second.type == SES_ADD) { | ||||
|                     if (ba_it->first == bc_it->first) { | ||||
|                         seq.push_back(ba_it->first); | ||||
|                         forwardUntilEnd(ba_end, ba_it); | ||||
|                         forwardUntilEnd(bc_end, bc_it); | ||||
|                     } else { | ||||
|                         // conflict | ||||
|                         conflict = true; | ||||
|                         return B; | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|              | ||||
|             if (isEnd(ba_end, ba_it)) { | ||||
|                 addDecentSequence(bc_end, bc_it, seq); | ||||
|             } else if (isEnd(bc_end, bc_it)) { | ||||
|                 addDecentSequence(ba_end, ba_it, seq); | ||||
|             } | ||||
|              | ||||
|             sequence mergedSeq(seq.begin(), seq.end()); | ||||
|             return mergedSeq; | ||||
|         } | ||||
|          | ||||
|         /** | ||||
|          * join elem vectors | ||||
|          */ | ||||
|         void inline joinElemVec (elemVec& s1, elemVec& s2) const { | ||||
|             if (!s2.empty()) { | ||||
|                 for (elemVec_iter vit=s2.begin();vit!=s2.end();++vit) { | ||||
|                     s1.push_back(*vit); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|          | ||||
|         /** | ||||
|          * check if sequence is at end | ||||
|          */ | ||||
|         template <typename T_iter> | ||||
|         bool inline isEnd (const T_iter& end, const T_iter& it) const { | ||||
|             return it == end ? true : false; | ||||
|         } | ||||
|          | ||||
|         /** | ||||
|          * increment iterator until iterator is at end | ||||
|          */ | ||||
|         template <typename T_iter> | ||||
|         void inline forwardUntilEnd (const T_iter& end, T_iter& it) const { | ||||
|             if (!isEnd(end, it)) ++it; | ||||
|         } | ||||
|          | ||||
|         /** | ||||
|          * add elements whose SES's type is ADD | ||||
|          */ | ||||
|         void inline addDecentSequence (const sesElemVec_iter& end, sesElemVec_iter& it, elemVec& seq) const { | ||||
|             while (!isEnd(end, it)) { | ||||
|                 if (it->second.type == SES_ADD) seq.push_back(it->first); | ||||
|                 ++it; | ||||
|             }       | ||||
|         } | ||||
|          | ||||
|     }; | ||||
| } | ||||
|  | ||||
| #endif // DTL_DIFF3_H | ||||
							
								
								
									
										55
									
								
								dtl/Lcs.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										55
									
								
								dtl/Lcs.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,55 @@ | ||||
| /** | ||||
|    dtl -- Diff Template Library | ||||
|     | ||||
|    In short, Diff Template Library is distributed under so called "BSD license", | ||||
|     | ||||
|    Copyright (c) 2015 Tatsuhiko Kubo <cubicdaiya@gmail.com> | ||||
|    All rights reserved. | ||||
|     | ||||
|    Redistribution and use in source and binary forms, with or without modification, | ||||
|    are permitted provided that the following conditions are met: | ||||
|     | ||||
|    * Redistributions of source code must retain the above copyright notice, | ||||
|    this list of conditions and the following disclaimer. | ||||
|     | ||||
|    * Redistributions in binary form must reproduce the above copyright notice, | ||||
|    this list of conditions and the following disclaimer in the documentation | ||||
|    and/or other materials provided with the distribution. | ||||
|     | ||||
|    * Neither the name of the authors nor the names of its contributors | ||||
|    may be used to endorse or promote products derived from this software  | ||||
|    without specific prior written permission. | ||||
|     | ||||
|    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||||
|    "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||||
|    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||||
|    A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||||
|    OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||||
|    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED | ||||
|    TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | ||||
|    PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | ||||
|    LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | ||||
|    NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||||
|    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||
| */ | ||||
|  | ||||
| /* If you use this library, you must include dtl.hpp only. */ | ||||
|  | ||||
| #ifndef DTL_LCS_H | ||||
| #define DTL_LCS_H | ||||
|  | ||||
| namespace dtl { | ||||
|      | ||||
|     /** | ||||
|      * Longest Common Subsequence template class | ||||
|      */ | ||||
|     template <typename elem> | ||||
|     class Lcs : public Sequence< elem > | ||||
|     { | ||||
|     public : | ||||
|         Lcs ()  {} | ||||
|         ~Lcs () {} | ||||
|     }; | ||||
| } | ||||
|  | ||||
| #endif // DTL_LCS_H | ||||
							
								
								
									
										65
									
								
								dtl/Sequence.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										65
									
								
								dtl/Sequence.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,65 @@ | ||||
| /** | ||||
|    dtl -- Diff Template Library | ||||
|     | ||||
|    In short, Diff Template Library is distributed under so called "BSD license", | ||||
|     | ||||
|    Copyright (c) 2015 Tatsuhiko Kubo <cubicdaiya@gmail.com> | ||||
|    All rights reserved. | ||||
|     | ||||
|    Redistribution and use in source and binary forms, with or without modification, | ||||
|    are permitted provided that the following conditions are met: | ||||
|     | ||||
|    * Redistributions of source code must retain the above copyright notice, | ||||
|    this list of conditions and the following disclaimer. | ||||
|     | ||||
|    * Redistributions in binary form must reproduce the above copyright notice, | ||||
|    this list of conditions and the following disclaimer in the documentation | ||||
|    and/or other materials provided with the distribution. | ||||
|     | ||||
|    * Neither the name of the authors nor the names of its contributors | ||||
|    may be used to endorse or promote products derived from this software  | ||||
|    without specific prior written permission. | ||||
|     | ||||
|    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||||
|    "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||||
|    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||||
|    A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||||
|    OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||||
|    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED | ||||
|    TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | ||||
|    PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | ||||
|    LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | ||||
|    NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||||
|    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||
| */ | ||||
|  | ||||
| /* If you use this library, you must include dtl.hpp only. */ | ||||
|  | ||||
| #ifndef DTL_SEQUENCE_H | ||||
| #define DTL_SEQUENCE_H | ||||
|  | ||||
| namespace dtl { | ||||
|      | ||||
|     /**   | ||||
|      * sequence class template | ||||
|      */ | ||||
|     template <typename elem> | ||||
|     class Sequence | ||||
|     { | ||||
|     public : | ||||
|         typedef vector< elem > elemVec; | ||||
|         Sequence () {} | ||||
|         virtual ~Sequence () {} | ||||
|          | ||||
|         elemVec getSequence () const { | ||||
|             return sequence; | ||||
|         } | ||||
|         void addSequence (elem e) { | ||||
|             sequence.push_back(e); | ||||
|         } | ||||
|     protected : | ||||
|         elemVec sequence; | ||||
|     }; | ||||
| } | ||||
|  | ||||
| #endif // DTL_SEQUENCE_H | ||||
							
								
								
									
										132
									
								
								dtl/Ses.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										132
									
								
								dtl/Ses.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,132 @@ | ||||
| /** | ||||
|    dtl -- Diff Template Library | ||||
|     | ||||
|    In short, Diff Template Library is distributed under so called "BSD license", | ||||
|     | ||||
|    Copyright (c) 2015 Tatsuhiko Kubo <cubicdaiya@gmail.com> | ||||
|    All rights reserved. | ||||
|     | ||||
|    Redistribution and use in source and binary forms, with or without modification, | ||||
|    are permitted provided that the following conditions are met: | ||||
|     | ||||
|    * Redistributions of source code must retain the above copyright notice, | ||||
|    this list of conditions and the following disclaimer. | ||||
|     | ||||
|    * Redistributions in binary form must reproduce the above copyright notice, | ||||
|    this list of conditions and the following disclaimer in the documentation | ||||
|    and/or other materials provided with the distribution. | ||||
|     | ||||
|    * Neither the name of the authors nor the names of its contributors | ||||
|    may be used to endorse or promote products derived from this software  | ||||
|    without specific prior written permission. | ||||
|     | ||||
|    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||||
|    "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||||
|    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||||
|    A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||||
|    OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||||
|    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED | ||||
|    TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | ||||
|    PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | ||||
|    LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | ||||
|    NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||||
|    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||
| */ | ||||
|  | ||||
| /* If you use this library, you must include dtl.hpp only. */ | ||||
|  | ||||
| #ifndef DTL_SES_H | ||||
| #define DTL_SES_H | ||||
|  | ||||
| namespace dtl { | ||||
|      | ||||
|     /** | ||||
|      * Shortest Edit Script template class | ||||
|      */ | ||||
|     template <typename elem> | ||||
|     class Ses : public Sequence< elem > | ||||
|     { | ||||
|     private : | ||||
|         typedef pair< elem, elemInfo > sesElem; | ||||
|         typedef vector< sesElem >      sesElemVec; | ||||
|     public : | ||||
|          | ||||
|         Ses () : onlyAdd(true), onlyDelete(true), onlyCopy(true), deletesFirst(false) { | ||||
|             nextDeleteIdx = 0; | ||||
|         } | ||||
|         Ses (bool moveDel) : onlyAdd(true), onlyDelete(true), onlyCopy(true), deletesFirst(moveDel) { | ||||
|             nextDeleteIdx = 0; | ||||
|         } | ||||
|         ~Ses () {} | ||||
|          | ||||
|         bool isOnlyAdd () const { | ||||
|             return onlyAdd; | ||||
|         } | ||||
|          | ||||
|         bool isOnlyDelete () const { | ||||
|             return onlyDelete; | ||||
|         } | ||||
|          | ||||
|         bool isOnlyCopy () const { | ||||
|             return onlyCopy; | ||||
|         } | ||||
|          | ||||
|         bool isOnlyOneOperation () const { | ||||
|             return isOnlyAdd() || isOnlyDelete() || isOnlyCopy(); | ||||
|         } | ||||
|          | ||||
|         bool isChange () const { | ||||
|             return !onlyCopy; | ||||
|         } | ||||
|          | ||||
|         using Sequence< elem >::addSequence; | ||||
|         void addSequence (elem e, long long beforeIdx, long long afterIdx, const edit_t type) { | ||||
|             elemInfo info; | ||||
|             info.beforeIdx = beforeIdx; | ||||
|             info.afterIdx  = afterIdx; | ||||
|             info.type      = type; | ||||
|             sesElem pe(e, info); | ||||
|             if (!deletesFirst) { | ||||
|                 sequence.push_back(pe); | ||||
|             } | ||||
|             switch (type) { | ||||
|             case SES_DELETE: | ||||
|                 onlyCopy   = false; | ||||
|                 onlyAdd    = false; | ||||
|                 if (deletesFirst) { | ||||
|                     sequence.insert(sequence.begin() + nextDeleteIdx, pe); | ||||
|                     nextDeleteIdx++; | ||||
|                 } | ||||
|                 break; | ||||
|             case SES_COMMON: | ||||
|                 onlyAdd    = false; | ||||
|                 onlyDelete = false; | ||||
|                 if (deletesFirst) { | ||||
|                     sequence.push_back(pe); | ||||
|                     nextDeleteIdx = sequence.size(); | ||||
|                 } | ||||
|                 break; | ||||
|             case SES_ADD: | ||||
|                 onlyDelete = false; | ||||
|                 onlyCopy   = false; | ||||
|                 if (deletesFirst) { | ||||
|                     sequence.push_back(pe); | ||||
|                 } | ||||
|                 break; | ||||
|             } | ||||
|         } | ||||
|          | ||||
|         sesElemVec getSequence () const { | ||||
|             return sequence; | ||||
|         } | ||||
|     private : | ||||
|         sesElemVec sequence; | ||||
|         bool       onlyAdd; | ||||
|         bool       onlyDelete; | ||||
|         bool       onlyCopy; | ||||
|         bool       deletesFirst; | ||||
|         size_t     nextDeleteIdx; | ||||
|     }; | ||||
| } | ||||
|  | ||||
| #endif // DTL_SES_H | ||||
							
								
								
									
										47
									
								
								dtl/dtl.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								dtl/dtl.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,47 @@ | ||||
| /** | ||||
|    dtl -- Diff Template Library | ||||
|     | ||||
|    In short, Diff Template Library is distributed under so called "BSD license", | ||||
|     | ||||
|    Copyright (c) 2015 Tatsuhiko Kubo <cubicdaiya@gmail.com> | ||||
|    All rights reserved. | ||||
|     | ||||
|    Redistribution and use in source and binary forms, with or without modification, | ||||
|    are permitted provided that the following conditions are met: | ||||
|     | ||||
|    * Redistributions of source code must retain the above copyright notice, | ||||
|    this list of conditions and the following disclaimer. | ||||
|     | ||||
|    * Redistributions in binary form must reproduce the above copyright notice, | ||||
|    this list of conditions and the following disclaimer in the documentation | ||||
|    and/or other materials provided with the distribution. | ||||
|     | ||||
|    * Neither the name of the authors nor the names of its contributors | ||||
|    may be used to endorse or promote products derived from this software  | ||||
|    without specific prior written permission. | ||||
|     | ||||
|    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||||
|    "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||||
|    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||||
|    A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||||
|    OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||||
|    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED | ||||
|    TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | ||||
|    PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | ||||
|    LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | ||||
|    NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||||
|    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||
| */ | ||||
|  | ||||
| #ifndef DTL_H | ||||
| #define DTL_H | ||||
|  | ||||
| #include "variables.hpp" | ||||
| #include "functors.hpp" | ||||
| #include "Sequence.hpp" | ||||
| #include "Lcs.hpp" | ||||
| #include "Ses.hpp" | ||||
| #include "Diff.hpp" | ||||
| #include "Diff3.hpp" | ||||
|  | ||||
| #endif // DTL_H | ||||
							
								
								
									
										137
									
								
								dtl/functors.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										137
									
								
								dtl/functors.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,137 @@ | ||||
| /** | ||||
|    dtl -- Diff Template Library | ||||
|     | ||||
|    In short, Diff Template Library is distributed under so called "BSD license", | ||||
|     | ||||
|    Copyright (c) 2015 Tatsuhiko Kubo <cubicdaiya@gmail.com> | ||||
|    All rights reserved. | ||||
|     | ||||
|    Redistribution and use in source and binary forms, with or without modification, | ||||
|    are permitted provided that the following conditions are met: | ||||
|     | ||||
|    * Redistributions of source code must retain the above copyright notice, | ||||
|    this list of conditions and the following disclaimer. | ||||
|     | ||||
|    * Redistributions in binary form must reproduce the above copyright notice, | ||||
|    this list of conditions and the following disclaimer in the documentation | ||||
|    and/or other materials provided with the distribution. | ||||
|     | ||||
|    * Neither the name of the authors nor the names of its contributors | ||||
|    may be used to endorse or promote products derived from this software  | ||||
|    without specific prior written permission. | ||||
|     | ||||
|    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||||
|    "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||||
|    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||||
|    A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||||
|    OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||||
|    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED | ||||
|    TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | ||||
|    PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | ||||
|    LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | ||||
|    NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||||
|    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||
| */ | ||||
|  | ||||
| /* If you use this library, you must include dtl.hpp only. */ | ||||
|  | ||||
| #ifndef DTL_FUNCTORS_H | ||||
| #define DTL_FUNCTORS_H | ||||
|  | ||||
| namespace dtl { | ||||
|      | ||||
|     /** | ||||
|      * printer class template | ||||
|      */ | ||||
|     template <typename sesElem, typename stream = ostream > | ||||
|     class Printer | ||||
|     { | ||||
|     public : | ||||
|         Printer ()            : out_(cout) {} | ||||
|         Printer (stream& out) : out_(out)  {} | ||||
|         virtual ~Printer () {} | ||||
|         virtual void operator() (const sesElem& se) const = 0; | ||||
|     protected : | ||||
|         stream& out_; | ||||
|     }; | ||||
|      | ||||
|     /** | ||||
|      * common element printer class template | ||||
|      */ | ||||
|     template <typename sesElem, typename stream = ostream > | ||||
|     class CommonPrinter : public Printer < sesElem, stream > | ||||
|     { | ||||
|     public : | ||||
|         CommonPrinter  ()            : Printer < sesElem, stream > ()    {} | ||||
|         CommonPrinter  (stream& out) : Printer < sesElem, stream > (out) {} | ||||
|         ~CommonPrinter () {} | ||||
|         void operator() (const sesElem& se) const { | ||||
|             this->out_ << SES_MARK_COMMON << se.first << endl;     | ||||
|         } | ||||
|     }; | ||||
|      | ||||
|     /** | ||||
|      * ses element printer class template | ||||
|      */ | ||||
|     template <typename sesElem, typename stream = ostream > | ||||
|     class ChangePrinter : public Printer < sesElem, stream > | ||||
|     { | ||||
|     public : | ||||
|         ChangePrinter  ()            : Printer < sesElem, stream > ()    {} | ||||
|         ChangePrinter  (stream& out) : Printer < sesElem, stream > (out) {} | ||||
|         ~ChangePrinter () {} | ||||
|         void operator() (const sesElem& se) const { | ||||
|             switch (se.second.type) { | ||||
|             case SES_ADD: | ||||
|                 this->out_ << SES_MARK_ADD    << se.first << endl; | ||||
|                 break; | ||||
|             case SES_DELETE: | ||||
|                 this->out_ << SES_MARK_DELETE << se.first << endl; | ||||
|                 break; | ||||
|             case SES_COMMON: | ||||
|                 this->out_ << SES_MARK_COMMON << se.first << endl; | ||||
|                 break; | ||||
|             } | ||||
|         } | ||||
|     }; | ||||
|      | ||||
|     /** | ||||
|      * unified format element printer class template | ||||
|      */ | ||||
|     template <typename sesElem, typename stream = ostream > | ||||
|     class UniHunkPrinter | ||||
|     { | ||||
|     public : | ||||
|         UniHunkPrinter  ()            : out_(cout) {} | ||||
|         UniHunkPrinter  (stream& out) : out_(out)  {} | ||||
|         ~UniHunkPrinter () {} | ||||
|         void operator() (const uniHunk< sesElem >& hunk) const { | ||||
|             out_ << "@@" | ||||
|                  << " -"  << hunk.a << "," << hunk.b | ||||
|                  << " +"  << hunk.c << "," << hunk.d | ||||
|                  << " @@" << endl; | ||||
|              | ||||
|             for_each(hunk.common[0].begin(), hunk.common[0].end(), CommonPrinter< sesElem, stream >(out_)); | ||||
|             for_each(hunk.change.begin(),    hunk.change.end(),    ChangePrinter< sesElem, stream >(out_)); | ||||
|             for_each(hunk.common[1].begin(), hunk.common[1].end(), CommonPrinter< sesElem, stream >(out_)); | ||||
|         } | ||||
|     private : | ||||
|         stream& out_; | ||||
|     }; | ||||
|      | ||||
|     /** | ||||
|      * compare class template | ||||
|      */ | ||||
|     template <typename elem> | ||||
|     class Compare | ||||
|     { | ||||
|     public : | ||||
|         Compare () {} | ||||
|         virtual ~Compare () {} | ||||
|         virtual inline bool impl (const elem& e1, const elem& e2) const { | ||||
|             return e1 == e2; | ||||
|         } | ||||
|     }; | ||||
| } | ||||
|  | ||||
| #endif // DTL_FUNCTORS_H | ||||
							
								
								
									
										142
									
								
								dtl/variables.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										142
									
								
								dtl/variables.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,142 @@ | ||||
| /** | ||||
|    dtl -- Diff Template Library | ||||
|     | ||||
|    In short, Diff Template Library is distributed under so called "BSD license", | ||||
|     | ||||
|    Copyright (c) 2015 Tatsuhiko Kubo <cubicdaiya@gmail.com> | ||||
|    All rights reserved. | ||||
|     | ||||
|    Redistribution and use in source and binary forms, with or without modification, | ||||
|    are permitted provided that the following conditions are met: | ||||
|     | ||||
|    * Redistributions of source code must retain the above copyright notice, | ||||
|    this list of conditions and the following disclaimer. | ||||
|     | ||||
|    * Redistributions in binary form must reproduce the above copyright notice, | ||||
|    this list of conditions and the following disclaimer in the documentation | ||||
|    and/or other materials provided with the distribution. | ||||
|     | ||||
|    * Neither the name of the authors nor the names of its contributors | ||||
|    may be used to endorse or promote products derived from this software  | ||||
|    without specific prior written permission. | ||||
|     | ||||
|    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||||
|    "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||||
|    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||||
|    A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||||
|    OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||||
|    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED | ||||
|    TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | ||||
|    PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | ||||
|    LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | ||||
|    NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||||
|    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||
| */ | ||||
|  | ||||
| /* If you use this library, you must include dtl.hpp only. */ | ||||
|  | ||||
| #ifndef DTL_VARIABLES_H | ||||
| #define DTL_VARIABLES_H | ||||
|  | ||||
| #include <vector> | ||||
| #include <list> | ||||
| #include <string> | ||||
| #include <algorithm> | ||||
| #include <iostream> | ||||
|  | ||||
| namespace dtl { | ||||
|      | ||||
|     using std::vector; | ||||
|     using std::string; | ||||
|     using std::pair; | ||||
|     using std::ostream; | ||||
|     using std::list; | ||||
|     using std::for_each; | ||||
|     using std::distance; | ||||
|     using std::fill; | ||||
|     using std::cout; | ||||
|     using std::endl; | ||||
|     using std::rotate; | ||||
|     using std::swap; | ||||
|     using std::max; | ||||
|  | ||||
|     /** | ||||
|      * version string | ||||
|      */ | ||||
|     const string version = "1.19"; | ||||
|  | ||||
|     /** | ||||
|      * type of edit for SES | ||||
|      */ | ||||
|     typedef int edit_t; | ||||
|     const   edit_t SES_DELETE = -1; | ||||
|     const   edit_t SES_COMMON = 0; | ||||
|     const   edit_t SES_ADD    = 1; | ||||
|      | ||||
|     /** | ||||
|      * mark of SES | ||||
|      */ | ||||
| #define SES_MARK_DELETE "-" | ||||
| #define SES_MARK_COMMON " " | ||||
| #define SES_MARK_ADD    "+" | ||||
|  | ||||
|     /** | ||||
|      * info for Unified Format | ||||
|      */ | ||||
|     typedef struct eleminfo { | ||||
|         long long beforeIdx;           // index of prev sequence | ||||
|         long long afterIdx;            // index of after sequence | ||||
|         edit_t    type;                // type of edit(Add, Delete, Common) | ||||
|         bool operator==(const eleminfo& other) const{ | ||||
|             return (this->beforeIdx == other.beforeIdx && this->afterIdx == other.afterIdx && this->type == other.type); | ||||
|         } | ||||
|     } elemInfo; | ||||
|      | ||||
|     const long long DTL_SEPARATE_SIZE = 3; | ||||
|     const long long DTL_CONTEXT_SIZE  = 3; | ||||
|      | ||||
|     /** | ||||
|      * cordinate for registering route | ||||
|      */ | ||||
|     typedef struct Point { | ||||
|         long long x;                         // x cordinate | ||||
|         long long y;                         // y cordinate | ||||
|         long long k;                         // vertex | ||||
|     } P; | ||||
|      | ||||
|     /** | ||||
|      * limit of cordinate size | ||||
|      */ | ||||
|     const unsigned long long MAX_CORDINATES_SIZE = 2000000; | ||||
|      | ||||
|     typedef vector< long long > editPath; | ||||
|     typedef vector< P >         editPathCordinates; | ||||
|      | ||||
|     /** | ||||
|      * Structure of Unified Format Hunk | ||||
|      */ | ||||
|     template <typename sesElem> | ||||
|     struct uniHunk { | ||||
|         long long a, b, c, d;        // @@ -a,b +c,d @@ | ||||
|         vector< sesElem > common[2]; // anteroposterior commons on changes | ||||
|         vector< sesElem > change;    // changes | ||||
|         long long inc_dec_count;     // count of increace and decrease | ||||
|     }; | ||||
|  | ||||
| #define dtl_typedefs(elem, sequence)                                    \ | ||||
|     typedef pair< elem, elemInfo >            sesElem;                  \ | ||||
|     typedef vector< sesElem >                 sesElemVec;               \ | ||||
|     typedef vector< uniHunk< sesElem > >      uniHunkVec;               \ | ||||
|     typedef list< elem >                      elemList;                 \ | ||||
|     typedef vector< elem >                    elemVec;                  \ | ||||
|     typedef typename uniHunkVec::iterator     uniHunkVec_iter;          \ | ||||
|     typedef typename sesElemVec::iterator     sesElemVec_iter;          \ | ||||
|     typedef typename elemList::iterator       elemList_iter;            \ | ||||
|     typedef typename sequence::iterator       sequence_iter;            \ | ||||
|     typedef typename sequence::const_iterator sequence_const_iter;      \ | ||||
|     typedef typename elemVec::iterator        elemVec_iter; | ||||
|  | ||||
|  | ||||
| }  | ||||
|  | ||||
| #endif // DTL_VARIABLES_H | ||||
							
								
								
									
										42
									
								
								examples/SConstruct
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								examples/SConstruct
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,42 @@ | ||||
| import os | ||||
|  | ||||
| # SConstruct for dtl examples | ||||
|  | ||||
| env   = Environment(CPPPATH='..') | ||||
| debug = ARGUMENTS.get('debug', 'n') | ||||
| if debug == 'y' or debug == 'yes': | ||||
|     env.Append(CPPFLAGS = ['-Wall', '-g']) | ||||
| else: | ||||
|     env.Append(CPPFLAGS = ['-Wall', '-O2']) | ||||
|  | ||||
| if os.sys.platform != "win32": | ||||
|     env.Append(CPPDEFINES = ['HAVE_UNISTD_H']) | ||||
|  | ||||
| conf = Configure(env); | ||||
|  | ||||
| if not conf.CheckCXX(): | ||||
|     print "The C++ compiler is not installed!" | ||||
|     Exit(1) | ||||
|  | ||||
| libs = ['stdc++'] | ||||
| for lib in libs: | ||||
|     if not conf.CheckLib(lib): | ||||
|         print "library " + lib + " not installed!" | ||||
|         Exit(1) | ||||
|  | ||||
| conf.Finish() | ||||
|  | ||||
| targets = { 'strdiff'    : ['strdiff.cpp',    'common.cpp'], # diff between two string sequences | ||||
|             'intdiff'    : ['intdiff.cpp'],                  # diff between two integer sequences | ||||
|             'unidiff'    : ['unidiff.cpp',    'common.cpp'], # unified diff between two files | ||||
|             'unistrdiff' : ['unistrdiff.cpp', 'common.cpp'], # unified diff between two strings | ||||
|             'bdiff'      : ['bdiff.cpp',      'common.cpp'], # diff between two byte sequences | ||||
|             'strdiff3'   : ['strdiff3.cpp',   'common.cpp'], # three-way string diff program using dtl | ||||
|             'intdiff3'   : ['intdiff3.cpp'],                 # three-way integer diff program using dtl | ||||
|             'patch'      : ['patch.cpp',      'common.cpp'], # string patch program using dtl | ||||
|             'fpatch'     : ['fpatch.cpp',     'common.cpp'], # file patch program using dtl | ||||
|             'st2ses'     : ['st2ses.cpp',     'common.cpp'], # convert SES format file to SES instance | ||||
|             'strdiff_cp' : ['strdiff_cp.cpp', 'common.cpp'], # diff between two string sequences with custom printer | ||||
|             } | ||||
|  | ||||
| [ env.Program(target, targets[target]) for target in targets ] | ||||
							
								
								
									
										73
									
								
								examples/bdiff.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										73
									
								
								examples/bdiff.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,73 @@ | ||||
|  | ||||
| #include <dtl/dtl.hpp> | ||||
| #include "common.hpp" | ||||
|  | ||||
| #include <iostream> | ||||
| #include <vector> | ||||
| #include <string> | ||||
| #include <cstdio> | ||||
| #include <sys/types.h> | ||||
| #include <sys/stat.h> | ||||
| #include <fcntl.h> | ||||
| #ifdef HAVE_UNISTD_H | ||||
| #include <unistd.h> | ||||
| #endif // HAVE_UNISTD_H | ||||
|  | ||||
| using namespace std; | ||||
|  | ||||
| using dtl::Diff; | ||||
|  | ||||
| typedef unsigned char  elem; | ||||
| typedef vector< elem > sequence; | ||||
|  | ||||
| static int create_byte_seq(const char *fs, sequence& seq); | ||||
| static int create_byte_seq(const char *fs, sequence& seq) | ||||
| { | ||||
|     int  fd; | ||||
|     int  siz; | ||||
|     elem buf[BUFSIZ]; | ||||
|     if ((fd = open(fs, O_RDONLY)) == -1) { | ||||
|         cout << "Opening failed." << endl; | ||||
|         return -1; | ||||
|     } | ||||
|     while ((siz = read(fd, buf, sizeof(buf))) > 0) { | ||||
|         for (int i=0;i<siz;++i) { | ||||
|             seq.push_back(buf[i]); | ||||
|         } | ||||
|     } | ||||
|     if (siz < 0) { | ||||
|         close(fd); | ||||
|         cout << "Read error." << endl; | ||||
|         return -1; | ||||
|     } | ||||
|     close(fd); | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| int main(int argc, char *argv[]) | ||||
| { | ||||
|      | ||||
|     if (isFewArgs(argc)) { | ||||
|         cerr << "Too few arguments." << endl; | ||||
|         return -1; | ||||
|     } | ||||
|      | ||||
|     string   fs1(argv[1]); | ||||
|     string   fs2(argv[2]); | ||||
|     sequence seq1; | ||||
|     sequence seq2; | ||||
|      | ||||
|     create_byte_seq(fs1.c_str(), seq1); | ||||
|     create_byte_seq(fs2.c_str(), seq2); | ||||
|      | ||||
|     Diff< elem, sequence > d(seq1, seq2); | ||||
|     d.compose(); | ||||
|  | ||||
|     if (d.getEditDistance() == 0) { | ||||
|         cout << fs1 << " is the same as "    << fs2 << endl; | ||||
|     } else { | ||||
|         cout << fs1 << " is different from " << fs2 << endl; | ||||
|     } | ||||
|      | ||||
|     return 0; | ||||
| } | ||||
							
								
								
									
										20
									
								
								examples/common.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								examples/common.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,20 @@ | ||||
|  | ||||
| #include "common.hpp" | ||||
|  | ||||
| bool isFileExist (string& fs) { | ||||
|     FILE *fp; | ||||
|     if ((fp = fopen(fs.c_str(), "r")) == NULL) { | ||||
|         return false; | ||||
|     } | ||||
|     fclose(fp); | ||||
|     return true; | ||||
| } | ||||
|  | ||||
| bool isFewArgs (int argc, int limit) { | ||||
|     bool ret = false; | ||||
|     if (argc < limit) { | ||||
|         ret = true; | ||||
|     } | ||||
|     return ret; | ||||
| } | ||||
|  | ||||
							
								
								
									
										13
									
								
								examples/common.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								examples/common.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,13 @@ | ||||
|  | ||||
| #ifndef DTL_EXAMPLE_COMMON_H | ||||
| #define DTL_EXAMPLE_COMMON_H | ||||
|  | ||||
| #include <string> | ||||
| #include <cstdio> | ||||
|  | ||||
| using namespace std; | ||||
|  | ||||
| bool isFileExist (string& fs); | ||||
| bool isFewArgs (int argc, int limit = 3); | ||||
|  | ||||
| #endif | ||||
							
								
								
									
										73
									
								
								examples/fpatch.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										73
									
								
								examples/fpatch.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,73 @@ | ||||
|  | ||||
| #include <dtl/dtl.hpp> | ||||
| #include "common.hpp" | ||||
| #include <iostream> | ||||
| #include <sstream> | ||||
| #include <fstream> | ||||
| #include <vector> | ||||
| #include <cassert> | ||||
|  | ||||
| using namespace std; | ||||
|  | ||||
| using dtl::Diff; | ||||
|  | ||||
| int main(int argc, char *argv[]){ | ||||
|      | ||||
|     if (isFewArgs(argc)) { | ||||
|         cerr << "Too few arguments." << endl; | ||||
|         return -1; | ||||
|     } | ||||
|      | ||||
|     string A(argv[1]); | ||||
|     string B(argv[2]); | ||||
|     bool   fileExist = true; | ||||
|      | ||||
|     if (!isFileExist(A)) { | ||||
|         cerr << "file A does not exist" << endl; | ||||
|         fileExist = false; | ||||
|     } | ||||
|      | ||||
|     if (!isFileExist(B)) { | ||||
|         cerr << "file B does not exist" << endl; | ||||
|         fileExist = false; | ||||
|     } | ||||
|      | ||||
|     if (!fileExist) { | ||||
|         return -1; | ||||
|     } | ||||
|      | ||||
|     typedef string elem; | ||||
|     typedef vector< elem > sequence; | ||||
|  | ||||
|     ifstream      Aifs(A.c_str()); | ||||
|     ifstream      Bifs(B.c_str()); | ||||
|     elem          buf; | ||||
|     sequence      ALines,  BLines; | ||||
|     ostringstream ossLine, ossInfo; | ||||
|      | ||||
|     while(getline(Aifs, buf)){ | ||||
|         ALines.push_back(buf); | ||||
|     } | ||||
|     while(getline(Bifs, buf)){ | ||||
|         BLines.push_back(buf); | ||||
|     } | ||||
|      | ||||
|     Diff< elem > d(ALines, BLines); | ||||
|     d.compose(); | ||||
|      | ||||
|     sequence s1 = ALines; | ||||
|     sequence s2 = d.patch(s1); | ||||
|      | ||||
|     // fpatch  | ||||
|     assert(BLines == s2); | ||||
|     cout << "fpatch succeeded" << endl; | ||||
|      | ||||
|     d.composeUnifiedHunks(); | ||||
|     sequence s3 = d.uniPatch(s1); | ||||
|      | ||||
|     // unipatch  | ||||
|     assert(BLines == s3); | ||||
|     cout << "unipatch succeeded" << endl; | ||||
|      | ||||
|     return 0; | ||||
| } | ||||
							
								
								
									
										49
									
								
								examples/intdiff.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								examples/intdiff.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,49 @@ | ||||
|  | ||||
| #include <iostream> | ||||
| #include <vector> | ||||
| #include <dtl/dtl.hpp> | ||||
|  | ||||
| using namespace std; | ||||
|  | ||||
| using dtl::Diff; | ||||
|  | ||||
| int main(int, char**){ | ||||
|      | ||||
|     int a[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; | ||||
|     int b[] = {3, 5, 1, 4, 5, 1, 7, 9, 6, 10}; | ||||
|     int asiz = sizeof(a) / sizeof(int); | ||||
|     int bsiz = sizeof(b) / sizeof(int); | ||||
|     for (int i=0;i<asiz;++i) { | ||||
|         cout << a[i] << " "; | ||||
|     } | ||||
|     cout << endl; | ||||
|     for (int i=0;i<bsiz;++i) { | ||||
|         cout << b[i] << " "; | ||||
|     } | ||||
|     cout << endl; | ||||
|      | ||||
|     typedef  int elem; | ||||
|     typedef  vector< int > sequence; | ||||
|  | ||||
|     sequence A(&a[0], &a[asiz]); | ||||
|     sequence B(&b[0], &b[bsiz]); | ||||
|     Diff< elem > d(A, B); | ||||
|     d.compose(); | ||||
|  | ||||
|     // editDistance | ||||
|     cout << "editDistance:" << d.getEditDistance() << endl; | ||||
|  | ||||
|     // Longest Common Subsequence | ||||
|     sequence lcs_v = d.getLcsVec(); | ||||
|     cout << "LCS: "; | ||||
|     for (sequence::iterator vit=lcs_v.begin();vit!=lcs_v.end();++vit) { | ||||
|         cout << *vit << " "; | ||||
|     } | ||||
|     cout << endl; | ||||
|      | ||||
|     // Shortest Edit Script | ||||
|     cout << "SES" << endl; | ||||
|     d.printSES(); | ||||
|      | ||||
|     return 0; | ||||
| } | ||||
							
								
								
									
										57
									
								
								examples/intdiff3.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										57
									
								
								examples/intdiff3.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,57 @@ | ||||
|  | ||||
| #include <dtl/dtl.hpp> | ||||
| #include <iostream> | ||||
| #include <vector> | ||||
| #include <cassert> | ||||
|  | ||||
| using namespace std; | ||||
|  | ||||
| using dtl::Diff3; | ||||
|  | ||||
| int main(int, char**) { | ||||
|      | ||||
|     int a[10]      = {1, 2, 3, 4, 5, 6, 7, 3, 9, 10}; | ||||
|     int b[10]      = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; | ||||
|     int c[10]      = {1, 2, 3, 9, 5, 6, 7, 8, 9, 10}; | ||||
|     int answer[10] = {1, 2, 3, 9, 5, 6, 7, 3, 9, 10}; | ||||
|      | ||||
|     cout << "a:"; | ||||
|     for (int i=0;i<10;++i) { | ||||
|         cout << a[i] << " "; | ||||
|     } | ||||
|     cout << endl; | ||||
|     cout << "b:"; | ||||
|     for (int i=0;i<10;++i) { | ||||
|         cout << b[i] << " "; | ||||
|     } | ||||
|     cout << endl; | ||||
|     cout << "c:"; | ||||
|     for (int i=0;i<10;++i) { | ||||
|         cout << c[i] << " "; | ||||
|     } | ||||
|     cout << endl; | ||||
|      | ||||
|     typedef int elem; | ||||
|     typedef vector< int > sequence; | ||||
|     sequence A(&a[0], &a[10]); | ||||
|     sequence B(&b[0], &b[10]); | ||||
|     sequence C(&c[0], &c[10]); | ||||
|     sequence Answer(&answer[0], &answer[10]); | ||||
|     Diff3< elem > diff3(A, B, C); | ||||
|     diff3.compose(); | ||||
|     if (!diff3.merge()) { | ||||
|         cerr << "conflict." << endl; | ||||
|         return -1; | ||||
|     } | ||||
|     sequence s = diff3.getMergedSequence(); | ||||
|     cout << "s:"; | ||||
|     for (sequence::iterator it=s.begin();it!=s.end();++it) { | ||||
|         cout << *it << " "; | ||||
|     } | ||||
|     cout << endl; | ||||
|      | ||||
|     assert(s == Answer); | ||||
|     cout << "intdiff3 OK" << endl; | ||||
|      | ||||
|     return 0; | ||||
| } | ||||
							
								
								
									
										44
									
								
								examples/patch.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								examples/patch.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,44 @@ | ||||
|  | ||||
| #include <dtl/dtl.hpp> | ||||
| #include "common.hpp" | ||||
| #include <iostream> | ||||
| #include <vector> | ||||
| #include <cassert> | ||||
|  | ||||
| using namespace std; | ||||
|  | ||||
| using dtl::Diff; | ||||
|  | ||||
| int main(int argc, char *argv[]) { | ||||
|      | ||||
|     if (isFewArgs(argc)) { | ||||
|         cerr << "Too few arguments." << endl; | ||||
|         return -1; | ||||
|     } | ||||
|      | ||||
|     typedef char elem; | ||||
|     typedef string sequence; | ||||
|  | ||||
|     sequence A(argv[1]); | ||||
|     sequence B(argv[2]); | ||||
|      | ||||
|     Diff< elem, sequence > d(A, B); | ||||
|     d.compose(); | ||||
|      | ||||
|     sequence s1(A); | ||||
|     sequence s2 = d.patch(s1); | ||||
|     d.composeUnifiedHunks(); | ||||
|     sequence s3 = d.uniPatch(s1); | ||||
|      | ||||
|     cout << "before:" << s1 << endl; | ||||
|     cout << "after :" << s2 << endl; | ||||
|     assert(B == s2); | ||||
|     cout << "patch succeeded" << endl; | ||||
|      | ||||
|     cout << "before:" << s1 << endl; | ||||
|     cout << "after :" << s3 << endl; | ||||
|     assert(B == s3); | ||||
|     cout << "unipatch succeeded" << endl; | ||||
|      | ||||
|     return 0; | ||||
| } | ||||
							
								
								
									
										26
									
								
								examples/printers.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								examples/printers.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,26 @@ | ||||
| #ifndef DTL_PRINTERS | ||||
| #define DTL_PRINTERS | ||||
|  | ||||
| template <typename sesElem, typename stream = ostream > | ||||
| class customChangePrinter : public Printer < sesElem, stream > | ||||
| { | ||||
| public : | ||||
|     customChangePrinter () : Printer < sesElem, stream > () {} | ||||
|     customChangePrinter (stream& out) : Printer < sesElem, stream > (out) {} | ||||
|     ~customChangePrinter () {} | ||||
|     void operator() (const sesElem& se) const { | ||||
|         switch (se.second.type) { | ||||
|         case SES_ADD: | ||||
|             this->out_ << "Add: " << se.first << endl; | ||||
|             break; | ||||
|         case SES_DELETE: | ||||
|             this->out_ << "Delete: " << se.first << endl; | ||||
|             break; | ||||
|         case SES_COMMON: | ||||
|             this->out_ << "Common: " << se.first << endl; | ||||
|             break; | ||||
|         } | ||||
|     } | ||||
| }; | ||||
|  | ||||
| #endif // DTL_PRINTERS | ||||
							
								
								
									
										35
									
								
								examples/st2ses.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								examples/st2ses.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,35 @@ | ||||
|  | ||||
| #include <dtl/dtl.hpp> | ||||
| #include "common.hpp" | ||||
| #include <iostream> | ||||
| #include <fstream> | ||||
| #include <sstream> | ||||
| #include <vector> | ||||
| #include <string> | ||||
|  | ||||
| using namespace std; | ||||
| using namespace dtl; | ||||
|  | ||||
| int main(int argc, char *argv[]){ | ||||
|      | ||||
|     if (isFewArgs(argc, 2)) { | ||||
|         cerr << "Too few arguments." << endl; | ||||
|         return -1; | ||||
|     } | ||||
|  | ||||
|     typedef string elem; | ||||
|     typedef vector< string > sequence; | ||||
|  | ||||
|     string s(argv[1]); | ||||
|  | ||||
|     if (!isFileExist(s)) { | ||||
|         cerr << s << " is invalid." << endl; | ||||
|         return -1; | ||||
|     } | ||||
|  | ||||
|     ifstream fs(s.c_str()); | ||||
|     const Ses< elem > ses = Diff< elem, sequence >::composeSesFromStream< ifstream >(fs); | ||||
|     dtl::Diff< elem, sequence >::printSES(ses); | ||||
|      | ||||
|     return 0; | ||||
| } | ||||
							
								
								
									
										42
									
								
								examples/strdiff.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								examples/strdiff.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,42 @@ | ||||
|  | ||||
| #include <dtl/dtl.hpp> | ||||
| #include "common.hpp" | ||||
| #include <iostream> | ||||
| #include <vector> | ||||
| #include <string> | ||||
|  | ||||
| using namespace std; | ||||
|  | ||||
| using dtl::Diff; | ||||
|  | ||||
| int main(int argc, char *argv[]){ | ||||
|      | ||||
|     if (isFewArgs(argc)) { | ||||
|         cerr << "Too few arguments." << endl; | ||||
|         return -1; | ||||
|     } | ||||
|      | ||||
|     typedef char   elem; | ||||
|     typedef string sequence; | ||||
|  | ||||
|     sequence A(argv[1]); | ||||
|     sequence B(argv[2]); | ||||
|      | ||||
|     Diff< elem, sequence > d(A, B); | ||||
|     //d.onOnlyEditDistance(); | ||||
|     d.compose(); | ||||
|      | ||||
|     // editDistance | ||||
|     cout << "editDistance:" << d.getEditDistance() << endl; | ||||
|      | ||||
|     // Longest Common Subsequence | ||||
|     vector< elem > lcs_v = d.getLcsVec(); | ||||
|     sequence       lcs_s(lcs_v.begin(), lcs_v.end()); | ||||
|     cout << "LCS:" << lcs_s << endl; | ||||
|      | ||||
|     // Shortest Edit Script | ||||
|     cout << "SES" << endl; | ||||
|     d.printSES(); | ||||
|      | ||||
|     return 0; | ||||
| } | ||||
							
								
								
									
										35
									
								
								examples/strdiff3.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								examples/strdiff3.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,35 @@ | ||||
|  | ||||
| #include <dtl/dtl.hpp> | ||||
| #include "common.hpp" | ||||
| #include <iostream> | ||||
| #include <vector> | ||||
| #include <string> | ||||
|  | ||||
| using namespace std; | ||||
|  | ||||
| using dtl::Diff3; | ||||
|  | ||||
| int main(int argc, char *argv[]){ | ||||
|      | ||||
|     if (isFewArgs(argc, 4)) { | ||||
|         cerr << "Too few arguments." << endl; | ||||
|         return -1; | ||||
|     } | ||||
|      | ||||
|     typedef char   elem; | ||||
|     typedef string sequence; | ||||
|  | ||||
|     sequence A(argv[1]); | ||||
|     sequence B(argv[2]); | ||||
|     sequence C(argv[3]); | ||||
|      | ||||
|     Diff3< elem, sequence > diff3(A, B, C); | ||||
|     diff3.compose(); | ||||
|     if (!diff3.merge()) { | ||||
|         cerr << "conflict." << endl; | ||||
|         return 0; | ||||
|     } | ||||
|     cout << "result:" << diff3.getMergedSequence() << endl; | ||||
|      | ||||
|     return 0; | ||||
| } | ||||
							
								
								
									
										40
									
								
								examples/strdiff_cp.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								examples/strdiff_cp.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,40 @@ | ||||
|  | ||||
| #include <dtl/dtl.hpp> | ||||
| #include "common.hpp" | ||||
| #include <iostream> | ||||
| #include <sstream> | ||||
| #include <string> | ||||
|  | ||||
| using namespace std; | ||||
|  | ||||
| using dtl::Diff; | ||||
| using dtl::SES_ADD; | ||||
| using dtl::SES_DELETE; | ||||
| using dtl::SES_COMMON; | ||||
| using dtl::Printer; | ||||
|  | ||||
| #include "printers.hpp" | ||||
|  | ||||
| int main(int argc, char *argv[]){ | ||||
|      | ||||
|     if (isFewArgs(argc)) { | ||||
|         cerr << "Too few arguments." << endl; | ||||
|         return -1; | ||||
|     } | ||||
|      | ||||
|     typedef char   elem; | ||||
|     typedef string sequence; | ||||
|  | ||||
|     sequence A(argv[1]); | ||||
|     sequence B(argv[2]); | ||||
|      | ||||
|     Diff< elem, sequence > d(A, B); | ||||
|     d.compose(); | ||||
|      | ||||
|     // Shortest Edit Script | ||||
|     cout << "SES" << endl; | ||||
|  | ||||
|     d.printSES < ostream, customChangePrinter > (cout); | ||||
|      | ||||
|     return 0; | ||||
| } | ||||
							
								
								
									
										111
									
								
								examples/unidiff.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										111
									
								
								examples/unidiff.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,111 @@ | ||||
|  | ||||
| #include <dtl/dtl.hpp> | ||||
| #include "common.hpp" | ||||
| #include <iostream> | ||||
| #include <fstream> | ||||
| #include <sstream> | ||||
| #include <vector> | ||||
|  | ||||
| #include <time.h> | ||||
| #include <sys/stat.h> | ||||
|  | ||||
| using namespace std; | ||||
|  | ||||
| using dtl::Diff; | ||||
| using dtl::elemInfo; | ||||
| using dtl::uniHunk; | ||||
|  | ||||
| static void showStats (string fp1, string fp2); | ||||
| static void unifiedDiff (string fp1, string fp2);  | ||||
|  | ||||
| static void showStats (string fp1, string fp2)  | ||||
| { | ||||
|     const int    MAX_LENGTH    = 255; | ||||
|     char         time_format[] = "%Y-%m-%d %H:%M:%S %z"; | ||||
|     time_t       rawtime[2]; | ||||
|     struct tm   *timeinfo[2]; | ||||
|     struct stat  st[2]; | ||||
|      | ||||
|     if (stat(fp1.c_str(), &st[0]) == -1) { | ||||
|         cerr << "argv1 is invalid." << endl; | ||||
|         exit(-1); | ||||
|     } | ||||
|     if (stat(fp2.c_str(), &st[1]) == -1) { | ||||
|         cerr << "argv2 is invalid" << endl; | ||||
|         exit(-1); | ||||
|     } | ||||
|      | ||||
|     char buf[2][MAX_LENGTH + 1]; | ||||
|     rawtime[0] = st[0].st_mtime; | ||||
|     timeinfo[0] = localtime(&rawtime[0]); | ||||
|     strftime(buf[0], MAX_LENGTH, time_format, timeinfo[0]); | ||||
|     cout << "--- " << fp1 << '\t' << buf[0] << endl; | ||||
|     rawtime[1] = st[1].st_mtime; | ||||
|     timeinfo[1] = localtime(&rawtime[1]); | ||||
|     strftime(buf[1], MAX_LENGTH, time_format, timeinfo[1]); | ||||
|     cout << "+++ " << fp2 << '\t' << buf[1] << endl; | ||||
| } | ||||
|  | ||||
| static void unifiedDiff (string fp1, string fp2)  | ||||
| { | ||||
|     typedef string                 elem; | ||||
|     typedef vector< elem >         sequence; | ||||
|     typedef pair< elem, elemInfo > sesElem; | ||||
|  | ||||
|     ifstream      Aifs(fp1.c_str()); | ||||
|     ifstream      Bifs(fp2.c_str()); | ||||
|     elem          buf; | ||||
|     sequence      ALines, BLines; | ||||
|      | ||||
|     while(getline(Aifs, buf)){ | ||||
|         ALines.push_back(buf); | ||||
|     } | ||||
|     while(getline(Bifs, buf)){ | ||||
|         BLines.push_back(buf); | ||||
|     } | ||||
|      | ||||
|     Diff< elem > diff(ALines, BLines); | ||||
|     diff.onHuge(); | ||||
|     //diff.onUnserious(); | ||||
|     diff.compose(); | ||||
|      | ||||
|     // type unihunk definition test | ||||
|     uniHunk< sesElem > hunk; | ||||
|      | ||||
|     if (diff.getEditDistance() > 0) { | ||||
|         showStats(fp1, fp2);             // show file info | ||||
|     } | ||||
|      | ||||
|     diff.composeUnifiedHunks(); | ||||
|     diff.printUnifiedFormat(); | ||||
| } | ||||
|  | ||||
|  | ||||
| int main(int argc, char *argv[]) | ||||
| { | ||||
|     if (isFewArgs(argc)) { | ||||
|         cerr << "Too few arguments." << endl; | ||||
|         return -1; | ||||
|     } | ||||
|      | ||||
|     string s1(argv[1]); | ||||
|     string s2(argv[2]); | ||||
|     bool   fileExist = true; | ||||
|      | ||||
|     if (!isFileExist(s1)) { | ||||
|         cerr << s1 << " is invalid." << endl; | ||||
|         fileExist = false; | ||||
|     } | ||||
|      | ||||
|     if (!isFileExist(s2)) { | ||||
|         cerr << s2 << " is invalid." << endl; | ||||
|         fileExist = false; | ||||
|     } | ||||
|      | ||||
|     if (!fileExist) { | ||||
|         return -1; | ||||
|     } | ||||
|      | ||||
|     unifiedDiff(s1, s2); | ||||
|     return 0; | ||||
| } | ||||
							
								
								
									
										40
									
								
								examples/unistrdiff.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								examples/unistrdiff.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,40 @@ | ||||
|  | ||||
| #include <dtl/dtl.hpp> | ||||
| #include "common.hpp" | ||||
| #include <iostream> | ||||
| #include <vector> | ||||
|  | ||||
| using namespace std; | ||||
|  | ||||
| using dtl::Diff; | ||||
|  | ||||
| int main(int argc, char *argv[]){ | ||||
|      | ||||
|     if (isFewArgs(argc)) { | ||||
|         cerr << "Too few arguments." << endl; | ||||
|         return -1; | ||||
|     } | ||||
|      | ||||
|     typedef char elem; | ||||
|     typedef string sequence; | ||||
|  | ||||
|     sequence A(argv[1]); | ||||
|     sequence B(argv[2]); | ||||
|      | ||||
|     Diff<elem, sequence > d(A, B); | ||||
|     d.compose(); | ||||
|     d.composeUnifiedHunks(); | ||||
|      | ||||
|     // editDistance | ||||
|     cout << "editDistance:" << d.getEditDistance() << endl; | ||||
|      | ||||
|     // Longest Common Subsequence | ||||
|     vector<elem> lcs_v = d.getLcsVec(); | ||||
|     sequence     lcs_s(lcs_v.begin(), lcs_v.end()); | ||||
|     cout << "LCS:" << lcs_s << endl; | ||||
|      | ||||
|     // print Unified Format | ||||
|     d.printUnifiedFormat(); | ||||
|      | ||||
|     return 0; | ||||
| } | ||||
							
								
								
									
										144
									
								
								test/Intdifftest.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										144
									
								
								test/Intdifftest.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,144 @@ | ||||
| #include "dtl_test_common.hpp" | ||||
|  | ||||
| class Intdifftest : public ::testing::Test | ||||
| { | ||||
| protected : | ||||
|     dtl_test_typedefs(int, vector< int >) | ||||
|     typedef struct case_t { | ||||
|         sequence   A; | ||||
|         sequence   B; | ||||
|         size_t     editdis; | ||||
|         elemVec    lcs_v; | ||||
|         sequence   lcs_s; | ||||
|         sesElemVec ses_seq; | ||||
|         uniHunkVec hunk_v; | ||||
|         size_t     editdis_ses; | ||||
|         size_t     editdis_uni; | ||||
|         string     path_rses; | ||||
|         string     path_rhunks; | ||||
|     } case_t; | ||||
|     typedef vector< case_t > caseVec; | ||||
|     caseVec cases; | ||||
|      | ||||
|     case_t createCase (const sequence a, const sequence b, string test_name) { | ||||
|         case_t c; | ||||
|         string diff_name("intdiff"); | ||||
|         Diff< elem > diff(a, b); | ||||
|         diff.compose(); | ||||
|         diff.composeUnifiedHunks(); | ||||
|          | ||||
|         if (test_name != "") { | ||||
|             string path_lses   = create_path(test_name, diff_name, TYPE_DIFF_SES); | ||||
|             string path_rses   = create_path(test_name, diff_name, TYPE_DIFF_SES, true); | ||||
|             string path_lhunks = create_path(test_name, diff_name, TYPE_DIFF_UNI); | ||||
|             string path_rhunks = create_path(test_name, diff_name, TYPE_DIFF_UNI, true); | ||||
|  | ||||
|             create_file< elem, sequence, Compare< elem > >(path_rses,   diff, TYPE_DIFF_SES); | ||||
|             create_file< elem, sequence, Compare< elem > >(path_rhunks, diff, TYPE_DIFF_UNI); | ||||
|             c.editdis_ses = cal_diff_uni(path_lses,   path_rses); | ||||
|             c.editdis_uni = cal_diff_uni(path_lhunks, path_rhunks); | ||||
|             c.path_rses   = path_rses; | ||||
|             c.path_rhunks = path_rhunks; | ||||
|         } | ||||
|  | ||||
|  | ||||
|         c.A = a; | ||||
|         c.B = b; | ||||
|         c.editdis = diff.getEditDistance(); | ||||
|         c.lcs_v   = diff.getLcsVec(); | ||||
|         c.ses_seq = diff.getSes().getSequence(); | ||||
|         return c; | ||||
|     } | ||||
|      | ||||
|     void SetUp() { | ||||
|         cases.push_back(createCase(sequence(0), sequence(0), "diff_test0")); | ||||
|         sequence B1; | ||||
|         B1.push_back(1); | ||||
|         cases.push_back(createCase(sequence(0), B1, "diff_test1")); | ||||
|         sequence A2; | ||||
|         A2.push_back(1); | ||||
|         cases.push_back(createCase(A2, sequence(0), "diff_test2")); | ||||
|         int a4[]   = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; | ||||
|         int b4[]   = {3, 5, 1, 4, 5, 1, 7, 9, 6, 10}; | ||||
|         int a4siz  = sizeof(a4) / sizeof(int); | ||||
|         int b4siz  = sizeof(b4) / sizeof(int); | ||||
|         sequence A4(&a4[0], &a4[a4siz]); | ||||
|         sequence B4(&b4[0], &b4[b4siz]); | ||||
|         cases.push_back(createCase(A4, B4, "diff_test3")); | ||||
|         int a5[]   = {1, 2, 3, 4, 5}; | ||||
|         int b5[]   = {3, 5, 1, 4, 5}; | ||||
|         int a5siz  = sizeof(a5) / sizeof(int); | ||||
|         int b5siz  = sizeof(b5) / sizeof(int); | ||||
|         sequence A5(&a5[0], &a5[a5siz]); | ||||
|         sequence B5(&b5[0], &b5[b5siz]); | ||||
|         cases.push_back(createCase(A5, B5, "diff_test4")); | ||||
|     } | ||||
|      | ||||
|     void TearDown () { | ||||
|         for_each(cases.begin(), cases.end(), Remover< case_t >()); | ||||
|     } | ||||
|      | ||||
| }; | ||||
|  | ||||
| /** | ||||
|  * Intdifftest | ||||
|  * check list is following | ||||
|  * - editdistance | ||||
|  * - LCS | ||||
|  * - SES | ||||
|  */ | ||||
| TEST_F (Intdifftest, diff_test0) { | ||||
|     EXPECT_EQ(0, cases[0].editdis); | ||||
|      | ||||
|     EXPECT_TRUE(cases[0].lcs_v.empty()); | ||||
|      | ||||
|     ASSERT_EQ(0, cases[0].editdis_ses); | ||||
|  | ||||
|     ASSERT_EQ(0, cases[0].editdis_uni); | ||||
| } | ||||
|  | ||||
| TEST_F (Intdifftest, diff_test1) { | ||||
|     EXPECT_EQ(1, cases[1].editdis); | ||||
|      | ||||
|     EXPECT_TRUE(cases[1].lcs_v.empty()); | ||||
|      | ||||
|     ASSERT_EQ(0, cases[1].editdis_ses); | ||||
|  | ||||
|     ASSERT_EQ(0, cases[1].editdis_uni); | ||||
| } | ||||
|  | ||||
| TEST_F (Intdifftest, diff_test2) { | ||||
|     EXPECT_EQ(1, cases[2].editdis); | ||||
|      | ||||
|     EXPECT_TRUE(cases[2].lcs_v.empty()); | ||||
|      | ||||
|     ASSERT_EQ(0, cases[2].editdis_ses); | ||||
|  | ||||
|     ASSERT_EQ(0, cases[2].editdis_uni); | ||||
| } | ||||
|  | ||||
| TEST_F (Intdifftest, diff_test3) { | ||||
|     EXPECT_EQ(8, cases[3].editdis); | ||||
|      | ||||
|     EXPECT_EQ(3, cases[3].lcs_v[0]); | ||||
|     EXPECT_EQ(4, cases[3].lcs_v[1]); | ||||
|     EXPECT_EQ(5, cases[3].lcs_v[2]); | ||||
|     EXPECT_EQ(7, cases[3].lcs_v[3]); | ||||
|     EXPECT_EQ(9, cases[3].lcs_v[4]); | ||||
|      | ||||
|     ASSERT_EQ(0, cases[3].editdis_ses); | ||||
|  | ||||
|     ASSERT_EQ(0, cases[3].editdis_uni); | ||||
| } | ||||
|  | ||||
| TEST_F (Intdifftest, diff_test4) { | ||||
|     EXPECT_EQ(4, cases[4].editdis); | ||||
|      | ||||
|     EXPECT_EQ(3, cases[4].lcs_v[0]); | ||||
|     EXPECT_EQ(4, cases[4].lcs_v[1]); | ||||
|     EXPECT_EQ(5, cases[4].lcs_v[2]); | ||||
|      | ||||
|     ASSERT_EQ(0, cases[4].editdis_ses); | ||||
|  | ||||
|     ASSERT_EQ(0, cases[4].editdis_uni); | ||||
| } | ||||
							
								
								
									
										116
									
								
								test/Objdifftest.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										116
									
								
								test/Objdifftest.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,116 @@ | ||||
| #include "dtl_test_common.hpp" | ||||
| #include "comparators.hpp" | ||||
|  | ||||
| class Objdifftest : public ::testing::Test | ||||
| { | ||||
| protected : | ||||
|     dtl_test_typedefs(string, vector<elem>) | ||||
|     typedef struct case_t { | ||||
|         sequence   A; | ||||
|         sequence   B; | ||||
|         sesElemVec expected; | ||||
|         sesElemVec ses_seq; | ||||
|     } case_t; | ||||
|     typedef vector< case_t > caseVec; | ||||
|      | ||||
|     caseVec obj_diff_cases; | ||||
|      | ||||
|     template < typename comparator > | ||||
|     case_t createCase (const sequence a, const sequence b, sesElemVec ses, string test_name) { | ||||
|         case_t  c; | ||||
|         elemVec lcs_v; | ||||
|         string  diff_name("objdiff"); | ||||
|  | ||||
|         Diff< elem, sequence, comparator > diff(a, b, true); | ||||
|  | ||||
|         diff.compose(); | ||||
|          | ||||
|         c.A         = a; | ||||
|         c.B         = b; | ||||
|         c.ses_seq   = diff.getSes().getSequence(); | ||||
|         c.expected  = ses; | ||||
|          | ||||
|         return c; | ||||
|     } | ||||
|      | ||||
|     void SetUp(void) { | ||||
|         { | ||||
|             string array1[] = {"the", "quick", "brown"}; | ||||
|             string array2[] = {"The", "Quick", "Fox"}; | ||||
|              | ||||
|             sequence A(array1, array1 + (sizeof(array1) / sizeof(array1[0]))); | ||||
|             sequence B(array2, array2 + (sizeof(array2) / sizeof(array2[0]))); | ||||
|              | ||||
|             dtl::Ses< elem > ses; | ||||
|             ses.addSequence("the", 1, 1, dtl::SES_COMMON); | ||||
|             ses.addSequence("quick", 2, 2, dtl::SES_COMMON); | ||||
|             ses.addSequence("brown", 3, 0, dtl::SES_DELETE); | ||||
|             ses.addSequence("Fox", 0, 3, dtl::SES_ADD); | ||||
|              | ||||
|             obj_diff_cases.push_back(createCase< StringCaseInsensitive >(A, B, ses.getSequence(), "objdiff_test0_pattern")); | ||||
|         } | ||||
|          | ||||
|         { | ||||
|             string array1[] = {"b", "c", "e", "g"}; | ||||
|             string array2[] = {"a", "d", "e", "f", "h"}; | ||||
|              | ||||
|             sequence A(array1, array1 + (sizeof(array1) / sizeof(array1[0]))); | ||||
|             sequence B(array2, array2 + (sizeof(array2) / sizeof(array2[0]))); | ||||
|              | ||||
|             dtl::Ses< elem > ses; | ||||
|             ses.addSequence("b", 1, 0, dtl::SES_DELETE); | ||||
|             ses.addSequence("c", 2, 0, dtl::SES_DELETE); | ||||
|             ses.addSequence("a", 0, 1, dtl::SES_ADD); | ||||
|             ses.addSequence("d", 0, 2, dtl::SES_ADD); | ||||
|             ses.addSequence("e", 3, 3, dtl::SES_COMMON); | ||||
|             ses.addSequence("g", 4, 0, dtl::SES_DELETE); | ||||
|             ses.addSequence("f", 0, 4, dtl::SES_ADD); | ||||
|             ses.addSequence("h", 0, 5, dtl::SES_ADD); | ||||
|              | ||||
|             obj_diff_cases.push_back(createCase< StringCaseInsensitive >(A, B, ses.getSequence(), "objdiff_test1_unswapped")); | ||||
|         } | ||||
|         { | ||||
|             string array1[] = {"a", "d", "e", "f", "h"}; | ||||
|             string array2[] = {"b", "c", "e", "g"}; | ||||
|              | ||||
|             sequence A(array1, array1 + (sizeof(array1) / sizeof(array1[0]))); | ||||
|             sequence B(array2, array2 + (sizeof(array2) / sizeof(array2[0]))); | ||||
|              | ||||
|             dtl::Ses< elem > ses; | ||||
|             ses.addSequence("a", 1, 0, dtl::SES_DELETE); | ||||
|             ses.addSequence("d", 2, 0, dtl::SES_DELETE); | ||||
|             ses.addSequence("b", 0, 1, dtl::SES_ADD); | ||||
|             ses.addSequence("c", 0, 2, dtl::SES_ADD); | ||||
|             ses.addSequence("e", 3, 3, dtl::SES_COMMON); | ||||
|             ses.addSequence("f", 4, 0, dtl::SES_DELETE); | ||||
|             ses.addSequence("h", 5, 0, dtl::SES_DELETE); | ||||
|             ses.addSequence("g", 0, 4, dtl::SES_ADD); | ||||
|              | ||||
|             obj_diff_cases.push_back(createCase< StringCaseInsensitive >(A, B, ses.getSequence(), "objdiff_test2_swapped")); | ||||
|         } | ||||
|     } | ||||
|      | ||||
|     void TearDown () { | ||||
|         //for_each(obj_diff_cases.begin(), obj_diff_cases.end(), Remover< case_t >()); | ||||
|     } | ||||
| }; | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Objdifftest | ||||
|  * check list: | ||||
|  * - SES pattern "SES_COMMON, SES_DELETE, SES_ADD" | ||||
|  * - Indepence of results from swapping  | ||||
|  */ | ||||
|  | ||||
| TEST_F (Objdifftest, objdiff_test0_pattern) { | ||||
|     EXPECT_EQ(obj_diff_cases[0].expected, obj_diff_cases[0].ses_seq); | ||||
| } | ||||
|  | ||||
| TEST_F (Objdifftest, objdiff_test1_unswapped) { | ||||
|     EXPECT_EQ(obj_diff_cases[1].expected, obj_diff_cases[1].ses_seq); | ||||
| } | ||||
|  | ||||
| TEST_F (Objdifftest, objdiff_test2_swapped) { | ||||
|     EXPECT_EQ(obj_diff_cases[2].expected, obj_diff_cases[2].ses_seq); | ||||
| } | ||||
							
								
								
									
										98
									
								
								test/Patchtest.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										98
									
								
								test/Patchtest.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,98 @@ | ||||
| #include "dtl_test_common.hpp" | ||||
|  | ||||
| class Patchtest : public ::testing::Test | ||||
| { | ||||
| protected : | ||||
|     dtl_test_typedefs(char, string) | ||||
|     typedef struct case_t { | ||||
|         sequence A; | ||||
|         sequence B; | ||||
|         Diff< elem, sequence > diff; | ||||
|     } case_t; | ||||
|     typedef vector< case_t > caseVec; | ||||
|      | ||||
|     caseVec cases; | ||||
|      | ||||
|     case_t createCase (sequence a, sequence b) { | ||||
|         case_t c; | ||||
|         c.A = a; | ||||
|         c.B = b; | ||||
|         c.diff = Diff< elem, sequence >(a, b); | ||||
|         c.diff.compose(); | ||||
|         c.diff.composeUnifiedHunks(); | ||||
|         return c; | ||||
|     } | ||||
|      | ||||
|     void SetUp() { | ||||
|         cases.push_back(createCase("abc",           "abd"));           // 0 | ||||
|         cases.push_back(createCase("acbdeacbed",    "acebdabbabed"));  // 1 | ||||
|         cases.push_back(createCase("abcdef",        "dacfea"));        // 2 | ||||
|         cases.push_back(createCase("abcbda",        "bdcaba"));        // 3 | ||||
|         cases.push_back(createCase("bokko",         "bokkko"));        // 4 | ||||
|         cases.push_back(createCase("",              ""));              // 5 | ||||
|         cases.push_back(createCase("a",             ""));              // 6 | ||||
|         cases.push_back(createCase("",              "b"));             // 7 | ||||
|         cases.push_back(createCase("abcdefq3wefarhgorequgho4euhfteowauhfwehogfewrquhoi23hroewhoahfotrhguoiewahrgqqabcdef", | ||||
|                                    "3abcdef4976fd86ouofita67t85r876e5e746578tgliuhopoqqabcdef")); // 8 | ||||
|         cases.push_back(createCase("abcqqqeqqqccc", "abdqqqeqqqddd")); // 9 | ||||
|     } | ||||
|      | ||||
|     void TearDown () {} | ||||
|      | ||||
| }; | ||||
|  | ||||
| /** | ||||
|  * Patchtest | ||||
|  * check list is following | ||||
|  * - patch function | ||||
|  * - uniPatch function | ||||
|  */ | ||||
| TEST_F (Patchtest, patch_test0) { | ||||
|     ASSERT_EQ(cases[0].B, cases[0].diff.patch(cases[0].A)); | ||||
|     ASSERT_EQ(cases[0].B, cases[0].diff.uniPatch(cases[0].A)); | ||||
| } | ||||
|  | ||||
| TEST_F (Patchtest, patch_test1) { | ||||
|     ASSERT_EQ(cases[1].B, cases[1].diff.patch(cases[1].A)); | ||||
|     ASSERT_EQ(cases[1].B, cases[1].diff.uniPatch(cases[1].A)); | ||||
| } | ||||
|  | ||||
| TEST_F (Patchtest, patch_test2) { | ||||
|     ASSERT_EQ(cases[2].B, cases[2].diff.patch(cases[2].A)); | ||||
|     ASSERT_EQ(cases[2].B, cases[2].diff.uniPatch(cases[2].A)); | ||||
| } | ||||
|  | ||||
| TEST_F (Patchtest, patch_test3) { | ||||
|     ASSERT_EQ(cases[3].B, cases[3].diff.patch(cases[3].A)); | ||||
|     ASSERT_EQ(cases[3].B, cases[3].diff.uniPatch(cases[3].A)); | ||||
| } | ||||
|  | ||||
| TEST_F (Patchtest, patch_test4) { | ||||
|     ASSERT_EQ(cases[4].B, cases[4].diff.patch(cases[4].A)); | ||||
|     ASSERT_EQ(cases[4].B, cases[4].diff.uniPatch(cases[4].A)); | ||||
| } | ||||
|  | ||||
| TEST_F (Patchtest, patch_test5) { | ||||
|     ASSERT_EQ(cases[5].B, cases[5].diff.patch(cases[5].A)); | ||||
|     ASSERT_EQ(cases[5].B, cases[5].diff.uniPatch(cases[5].A)); | ||||
| } | ||||
|  | ||||
| TEST_F (Patchtest, patch_test6) { | ||||
|     ASSERT_EQ(cases[6].B, cases[6].diff.patch(cases[6].A)); | ||||
|     ASSERT_EQ(cases[6].B, cases[6].diff.uniPatch(cases[6].A)); | ||||
| } | ||||
|  | ||||
| TEST_F (Patchtest, patch_test7) { | ||||
|     ASSERT_EQ(cases[7].B, cases[7].diff.patch(cases[7].A)); | ||||
|     ASSERT_EQ(cases[7].B, cases[7].diff.uniPatch(cases[7].A)); | ||||
| } | ||||
|  | ||||
| TEST_F (Patchtest, patch_test8) { | ||||
|     ASSERT_EQ(cases[8].B, cases[8].diff.patch(cases[8].A)); | ||||
|     ASSERT_EQ(cases[8].B, cases[8].diff.uniPatch(cases[8].A)); | ||||
| } | ||||
|  | ||||
| TEST_F (Patchtest, patch_test9) { | ||||
|     ASSERT_EQ(cases[9].B, cases[9].diff.patch(cases[9].A)); | ||||
|     ASSERT_EQ(cases[9].B, cases[9].diff.uniPatch(cases[9].A)); | ||||
| } | ||||
							
								
								
									
										53
									
								
								test/SConstruct
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								test/SConstruct
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,53 @@ | ||||
| # -*- coding: utf-8 -*- | ||||
| # SConstrunct for dtl test | ||||
|  | ||||
| import os | ||||
|  | ||||
| def path_chomp(path): | ||||
|     if path[-1] == '/': | ||||
|         return path[:-1] | ||||
|     return path | ||||
|  | ||||
| if not 'GTEST_ROOT' in os.environ: | ||||
|     print "set environment variable 'GTEST_ROOT'" | ||||
|     Exit(1) | ||||
|  | ||||
| gtest_root = path_chomp(os.environ['GTEST_ROOT']) | ||||
| if gtest_root[-1] == '/': | ||||
|     gtest_root     = gtest_root[:-1] | ||||
|  | ||||
| gtest_includes = gtest_root + '/include' | ||||
| gtest_libs     = gtest_root + '/lib/.libs' | ||||
|  | ||||
| flags    = ['-Wall', '-O2'] | ||||
| libs     = ['stdc++', 'pthread'] | ||||
| includes = ['..', gtest_includes] | ||||
| target   = 'dtl_test' | ||||
|  | ||||
| env  = Environment(CPPFLAGS=flags, | ||||
|                    CPPPATH=includes, | ||||
|                    LIBPATH=[gtest_libs], | ||||
|                    ) | ||||
|  | ||||
| conf = Configure(env); | ||||
|  | ||||
| if not conf.CheckCXX(): | ||||
|     print "c++ compiler is not installed!" | ||||
|     Exit(1) | ||||
|  | ||||
| for lib in libs: | ||||
|     if not conf.CheckLib(lib): | ||||
|         print "library " + lib + " not installed!" | ||||
|         Exit(1) | ||||
|  | ||||
| conf.Finish() | ||||
|  | ||||
| test = env.Program(target, | ||||
|                    [Glob('*.cpp'), gtest_libs + '/libgtest.a'] | ||||
|                    ) | ||||
|  | ||||
| test_alias = env.Alias('check', | ||||
|                        test, | ||||
|                        test[0].abspath) | ||||
|  | ||||
| env.AlwaysBuild(test_alias) | ||||
							
								
								
									
										208
									
								
								test/Strdiff3test.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										208
									
								
								test/Strdiff3test.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,208 @@ | ||||
| #include "dtl_test_common.hpp" | ||||
| #include "comparators.hpp" | ||||
|  | ||||
| class Strdiff3test : public ::testing::Test | ||||
| { | ||||
| protected : | ||||
|     dtl_test_typedefs(char, string) | ||||
|     typedef struct case_t { | ||||
|         sequence S; | ||||
|         bool     is_merge_success; | ||||
|         sequence merged_seq; | ||||
|     } case_t; | ||||
|     typedef vector< case_t > caseVec; | ||||
|      | ||||
|     caseVec merge_cases; | ||||
|     caseVec detect_cases; | ||||
|     caseVec custom_cases; | ||||
|      | ||||
|     template < typename comparator > | ||||
|     case_t createCase (sequence a, sequence b, sequence c, sequence s) { | ||||
|         Diff3< elem, sequence, comparator > diff3(a, b, c); | ||||
|         case_t ct; | ||||
|  | ||||
|         diff3.compose(); | ||||
|  | ||||
|         ct.S                = s; | ||||
|         ct.is_merge_success = diff3.merge(); | ||||
|         ct.merged_seq       = diff3.getMergedSequence(); | ||||
|         return ct; | ||||
|     } | ||||
|      | ||||
|     void SetUp() { | ||||
|         // merge test | ||||
|         merge_cases.push_back(createCase< Compare < elem > >("ab",            "b",             "bc",           "abc"));              // 0 | ||||
|         merge_cases.push_back(createCase< Compare < elem > >("bc",            "b",             "ab",           "abc"));              // 1 | ||||
|         merge_cases.push_back(createCase< Compare < elem > >("qqqabc",        "abc",           "abcdef",       "qqqabcdef"));        // 2 | ||||
|         merge_cases.push_back(createCase< Compare < elem > >("abcdef",        "abc",           "qqqabc",       "qqqabcdef"));        // 3 | ||||
|         merge_cases.push_back(createCase< Compare < elem > >("aaacccbbb",     "aaabbb",        "aaabbbqqq",    "aaacccbbbqqq"));     // 4 | ||||
|         merge_cases.push_back(createCase< Compare < elem > >("aaabbbqqq",     "aaabbb",        "aaacccbbb",    "aaacccbbbqqq"));     // 5 | ||||
|         merge_cases.push_back(createCase< Compare < elem > >("aeaacccbbb",    "aaabbb",        "aaabbbqqq",    "aeaacccbbbqqq"));    // 6 | ||||
|         merge_cases.push_back(createCase< Compare < elem > >("aaabbbqqq",     "aaabbb",        "aeaacccbbb",   "aeaacccbbbqqq"));    // 7 | ||||
|         merge_cases.push_back(createCase< Compare < elem > >("aeaacccbbb",    "aaabbb",        "aaabebbqqq",   "aeaacccbebbqqq"));   // 8 | ||||
|         merge_cases.push_back(createCase< Compare < elem > >("aaabebbqqq",    "aaabbb",        "aeaacccbbb",   "aeaacccbebbqqq"));   // 9 | ||||
|         merge_cases.push_back(createCase< Compare < elem > >("aaacccbbb",     "aaabbb",        "aeaabbbqqq",   "aeaacccbbbqqq"));    // 10 | ||||
|         merge_cases.push_back(createCase< Compare < elem > >("aeaabbbqqq",    "aaabbb",        "aaacccbbb",    "aeaacccbbbqqq"));    // 11 | ||||
|         merge_cases.push_back(createCase< Compare < elem > >("aaacccbbb",     "aaabbb",        "aaabeebbeeqqq","aaacccbeebbeeqqq")); // 12 | ||||
|         merge_cases.push_back(createCase< Compare < elem > >("aaabeebbeeqqq", "aaabbb",        "aaacccbbb",    "aaacccbeebbeeqqq")); // 13 | ||||
|         merge_cases.push_back(createCase< Compare < elem > >("aiueo",         "aeo",           "aeKokaki",     "aiueKokaki"));       // 14 | ||||
|         merge_cases.push_back(createCase< Compare < elem > >("aeKokaki",      "aeo",           "aiueo",        "aiueKokaki"));       // 15 | ||||
|         merge_cases.push_back(createCase< Compare < elem > >("1234567390",    "1234567890",    "1239567890",   "1239567390"));       // 16 | ||||
|         merge_cases.push_back(createCase< Compare < elem > >("1239567890",    "1234567890",    "1234567390",   "1239567390"));       // 17 | ||||
|         merge_cases.push_back(createCase< Compare < elem > >("qabcdef",       "abcdef",        "ab",           "qab"));              // 18 | ||||
|         merge_cases.push_back(createCase< Compare < elem > >("ab",            "abcdef",        "qabcdef",      "qab"));              // 19 | ||||
|         merge_cases.push_back(createCase< Compare < elem > >("abcdf",         "abcdef",        "acdef",        "acdf"));             // 20 | ||||
|         merge_cases.push_back(createCase< Compare < elem > >("acdef",         "abcdef",        "abcdf",        "acdf"));             // 21 | ||||
|         merge_cases.push_back(createCase< Compare < elem > >("acdef",         "abcdef",        "abcdfaa",      "acdfaa"));           // 22 | ||||
|         merge_cases.push_back(createCase< Compare < elem > >("abcdfaa",       "abcdef",        "acdef",        "acdfaa"));           // 23 | ||||
|          | ||||
|         // detect confliction test | ||||
|         detect_cases.push_back(createCase< Compare < elem > >("adc",           "abc",          "aec",          ""));                 // 0 | ||||
|         detect_cases.push_back(createCase< Compare < elem > >("abqdcf",        "abcdef",       "abqqef",       ""));                 // 1 | ||||
|          | ||||
|         // use custom comparator | ||||
|         custom_cases.push_back(createCase< CaseInsensitive >("abc", "abc", "abC", "abc")); | ||||
|     } | ||||
|      | ||||
|     void TearDown () {} | ||||
|      | ||||
| }; | ||||
|  | ||||
| /** | ||||
|  * Strdiff3test | ||||
|  * check list is following | ||||
|  * - merge function | ||||
|  * - detect confliction | ||||
|  */ | ||||
| TEST_F (Strdiff3test, merge_test0) { | ||||
|     ASSERT_TRUE(merge_cases[0].is_merge_success); | ||||
|     ASSERT_EQ(merge_cases[0].S, merge_cases[0].merged_seq); | ||||
| } | ||||
|  | ||||
| TEST_F (Strdiff3test, merge_test1) { | ||||
|     ASSERT_TRUE(merge_cases[1].is_merge_success); | ||||
|     ASSERT_EQ(merge_cases[1].S, merge_cases[1].merged_seq); | ||||
| } | ||||
|  | ||||
| TEST_F (Strdiff3test, merge_test2) { | ||||
|     ASSERT_TRUE(merge_cases[2].is_merge_success); | ||||
|     ASSERT_EQ(merge_cases[2].S, merge_cases[2].merged_seq); | ||||
| } | ||||
|  | ||||
| TEST_F (Strdiff3test, merge_test3) { | ||||
|     ASSERT_TRUE(merge_cases[3].is_merge_success); | ||||
|     ASSERT_EQ(merge_cases[3].S, merge_cases[3].merged_seq); | ||||
| } | ||||
|  | ||||
| TEST_F (Strdiff3test, merge_test4) { | ||||
|     ASSERT_TRUE(merge_cases[4].is_merge_success); | ||||
|     ASSERT_EQ(merge_cases[4].S, merge_cases[4].merged_seq); | ||||
| } | ||||
|  | ||||
| TEST_F (Strdiff3test, merge_test5) { | ||||
|     ASSERT_TRUE(merge_cases[5].is_merge_success); | ||||
|     ASSERT_EQ(merge_cases[5].S, merge_cases[5].merged_seq); | ||||
| } | ||||
|  | ||||
| TEST_F (Strdiff3test, merge_test6) { | ||||
|     ASSERT_TRUE(merge_cases[6].is_merge_success); | ||||
|     ASSERT_EQ(merge_cases[6].S, merge_cases[6].merged_seq); | ||||
| } | ||||
|  | ||||
| TEST_F (Strdiff3test, merge_test7) { | ||||
|     ASSERT_TRUE(merge_cases[7].is_merge_success); | ||||
|     ASSERT_EQ(merge_cases[7].S, merge_cases[7].merged_seq); | ||||
| } | ||||
|  | ||||
| TEST_F (Strdiff3test, merge_test8) { | ||||
|     ASSERT_TRUE(merge_cases[8].is_merge_success); | ||||
|     ASSERT_EQ(merge_cases[8].S, merge_cases[8].merged_seq); | ||||
| } | ||||
|  | ||||
| TEST_F (Strdiff3test, merge_test9) { | ||||
|     ASSERT_TRUE(merge_cases[9].is_merge_success); | ||||
|     ASSERT_EQ(merge_cases[9].S, merge_cases[9].merged_seq); | ||||
| } | ||||
|  | ||||
| TEST_F (Strdiff3test, merge_test10) { | ||||
|     ASSERT_TRUE(merge_cases[10].is_merge_success); | ||||
|     ASSERT_EQ(merge_cases[10].S, merge_cases[10].merged_seq); | ||||
| } | ||||
|  | ||||
| TEST_F (Strdiff3test, merge_test11) { | ||||
|     ASSERT_TRUE(merge_cases[11].is_merge_success); | ||||
|     ASSERT_EQ(merge_cases[11].S, merge_cases[11].merged_seq); | ||||
| } | ||||
|  | ||||
| TEST_F (Strdiff3test, merge_test12) { | ||||
|     ASSERT_TRUE(merge_cases[12].is_merge_success); | ||||
|     ASSERT_EQ(merge_cases[12].S, merge_cases[12].merged_seq); | ||||
| } | ||||
|  | ||||
| TEST_F (Strdiff3test, merge_test13) { | ||||
|     ASSERT_TRUE(merge_cases[13].is_merge_success); | ||||
|     ASSERT_EQ(merge_cases[13].S, merge_cases[13].merged_seq); | ||||
| } | ||||
|  | ||||
| TEST_F (Strdiff3test, merge_test14) { | ||||
|     ASSERT_TRUE(merge_cases[14].is_merge_success); | ||||
|     ASSERT_EQ(merge_cases[14].S, merge_cases[14].merged_seq); | ||||
| } | ||||
|  | ||||
| TEST_F (Strdiff3test, merge_test15) { | ||||
|     ASSERT_TRUE(merge_cases[15].is_merge_success); | ||||
|     ASSERT_EQ(merge_cases[15].S, merge_cases[15].merged_seq); | ||||
| } | ||||
|  | ||||
| TEST_F (Strdiff3test, merge_test16) { | ||||
|     ASSERT_TRUE(merge_cases[16].is_merge_success); | ||||
|     ASSERT_EQ(merge_cases[16].S, merge_cases[16].merged_seq); | ||||
| } | ||||
|  | ||||
| TEST_F (Strdiff3test, merge_test17) { | ||||
|     ASSERT_TRUE(merge_cases[17].is_merge_success); | ||||
|     ASSERT_EQ(merge_cases[17].S, merge_cases[17].merged_seq); | ||||
| } | ||||
|  | ||||
| TEST_F (Strdiff3test, merge_test18) { | ||||
|     ASSERT_TRUE(merge_cases[18].is_merge_success); | ||||
|     ASSERT_EQ(merge_cases[18].S, merge_cases[18].merged_seq); | ||||
| } | ||||
|  | ||||
| TEST_F (Strdiff3test, merge_test19) { | ||||
|     ASSERT_TRUE(merge_cases[19].is_merge_success); | ||||
|     ASSERT_EQ(merge_cases[19].S, merge_cases[19].merged_seq); | ||||
| } | ||||
|  | ||||
| TEST_F (Strdiff3test, merge_test20) { | ||||
|     ASSERT_TRUE(merge_cases[20].is_merge_success); | ||||
|     ASSERT_EQ(merge_cases[20].S, merge_cases[20].merged_seq); | ||||
| } | ||||
|  | ||||
| TEST_F (Strdiff3test, merge_test21) { | ||||
|     ASSERT_TRUE(merge_cases[21].is_merge_success); | ||||
|     ASSERT_EQ( merge_cases[21].S, merge_cases[21].merged_seq); | ||||
| } | ||||
|  | ||||
| TEST_F (Strdiff3test, merge_test22) { | ||||
|     ASSERT_TRUE(merge_cases[22].is_merge_success); | ||||
|     ASSERT_EQ( merge_cases[22].S, merge_cases[22].merged_seq); | ||||
| } | ||||
|  | ||||
| TEST_F (Strdiff3test, merge_test23) { | ||||
|     ASSERT_TRUE(merge_cases[23].is_merge_success); | ||||
|     ASSERT_EQ(merge_cases[23].S, merge_cases[23].merged_seq); | ||||
| } | ||||
|  | ||||
| TEST_F (Strdiff3test, detect_confliction_test0) { | ||||
|     ASSERT_FALSE(detect_cases[0].is_merge_success); | ||||
| } | ||||
|  | ||||
| TEST_F (Strdiff3test, detect_confliction_test1) { | ||||
|     ASSERT_FALSE(detect_cases[1].is_merge_success); | ||||
| } | ||||
|  | ||||
| TEST_F (Strdiff3test, custom_comparator_test0) { | ||||
|     ASSERT_TRUE(custom_cases[0].is_merge_success); | ||||
|     ASSERT_EQ(custom_cases[0].S, custom_cases[0].merged_seq); | ||||
| } | ||||
							
								
								
									
										299
									
								
								test/Strdifftest.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										299
									
								
								test/Strdifftest.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,299 @@ | ||||
| #include "dtl_test_common.hpp" | ||||
| #include "comparators.hpp" | ||||
|  | ||||
| class Strdifftest : public ::testing::Test | ||||
| { | ||||
| protected : | ||||
|     dtl_test_typedefs(char, string) | ||||
|     typedef struct case_t { | ||||
|         sequence   A; | ||||
|         sequence   B; | ||||
|         size_t     editdis; | ||||
|         elemVec    lcs_v; | ||||
|         sequence   lcs_s; | ||||
|         sesElemVec ses_seq; | ||||
|         uniHunkVec hunk_v; | ||||
|         size_t     editdis_ses; | ||||
|         size_t     editdis_uni; | ||||
|         string     path_rses; | ||||
|         string     path_rhunks; | ||||
|     } case_t; | ||||
|     typedef vector< case_t > caseVec; | ||||
|      | ||||
|     caseVec diff_cases; | ||||
|     caseVec only_editdis_cases; | ||||
|     caseVec custom_cases; | ||||
|      | ||||
|     template < typename comparator > | ||||
|     case_t createCase (const sequence a, const sequence b, string test_name, bool onlyEditdis = false) { | ||||
|         case_t  c; | ||||
|         elemVec lcs_v; | ||||
|         string  diff_name("strdiff"); | ||||
|  | ||||
|         Diff< elem, sequence, comparator > diff(a, b); | ||||
|         if (onlyEditdis) { | ||||
|             diff.onOnlyEditDistance(); | ||||
|         } | ||||
|  | ||||
|         diff.compose(); | ||||
|         diff.composeUnifiedHunks(); | ||||
|         lcs_v = diff.getLcsVec(); | ||||
|          | ||||
|         if (test_name != "") { | ||||
|             string path_lses   = create_path(test_name, diff_name, TYPE_DIFF_SES); | ||||
|             string path_rses   = create_path(test_name, diff_name, TYPE_DIFF_SES, true); | ||||
|             string path_lhunks = create_path(test_name, diff_name, TYPE_DIFF_UNI); | ||||
|             string path_rhunks = create_path(test_name, diff_name, TYPE_DIFF_UNI, true); | ||||
|             diff_resultset_exist_check(path_lses); | ||||
|             diff_resultset_exist_check(path_lhunks); | ||||
|              | ||||
|             create_file< elem, sequence, comparator >(path_rses,   diff, TYPE_DIFF_SES); | ||||
|             create_file< elem, sequence, comparator >(path_rhunks, diff, TYPE_DIFF_UNI); | ||||
|              | ||||
|             c.editdis_ses = cal_diff_uni(path_lses,   path_rses); | ||||
|             c.editdis_uni = cal_diff_uni(path_lhunks, path_rhunks); | ||||
|             c.path_rses   = path_rses; | ||||
|             c.path_rhunks = path_rhunks; | ||||
|         } | ||||
|  | ||||
|         c.A       = a; | ||||
|         c.B       = b; | ||||
|         c.editdis = diff.getEditDistance(); | ||||
|         c.lcs_s   = sequence(lcs_v.begin(), lcs_v.end()); | ||||
|         c.ses_seq = diff.getSes().getSequence(); | ||||
|         c.hunk_v  = diff.getUniHunks(); | ||||
|          | ||||
|         return c; | ||||
|     } | ||||
|      | ||||
|     void SetUp(void) { | ||||
|         diff_cases.push_back(createCase< Compare< elem > >("abc",               "abd",                 "diff_test0")); | ||||
|         diff_cases.push_back(createCase< Compare< elem > >("acbdeacbed",        "acebdabbabed",        "diff_test1")); | ||||
|         diff_cases.push_back(createCase< Compare< elem > >("abcdef",            "dacfea",              "diff_test2")); | ||||
|         diff_cases.push_back(createCase< Compare< elem > >("abcbda",            "bdcaba",              "diff_test3")); | ||||
|         diff_cases.push_back(createCase< Compare< elem > >("bokko",             "bokkko",              "diff_test4")); | ||||
|         diff_cases.push_back(createCase< Compare< elem > >("",                  "",                    "diff_test5")); | ||||
|         diff_cases.push_back(createCase< Compare< elem > >("a",                 "",                    "diff_test6")); | ||||
|         diff_cases.push_back(createCase< Compare< elem > >("",                  "b",                   "diff_test7")); | ||||
|         diff_cases.push_back(createCase< Compare< elem > >("acbdeaqqqqqqqcbed", "acebdabbqqqqqqqabed", "diff_test8")); | ||||
|          | ||||
|         only_editdis_cases.push_back(createCase< Compare< elem > >("abc",               "abd",                 "", true)); | ||||
|         only_editdis_cases.push_back(createCase< Compare< elem > >("acbdeacbed",        "acebdabbabed",        "", true)); | ||||
|         only_editdis_cases.push_back(createCase< Compare< elem > >("abcdef",            "dacfea",              "", true)); | ||||
|         only_editdis_cases.push_back(createCase< Compare< elem > >("abcbda",            "bdcaba",              "", true)); | ||||
|         only_editdis_cases.push_back(createCase< Compare< elem > >("bokko",             "bokkko",              "", true)); | ||||
|         only_editdis_cases.push_back(createCase< Compare< elem > >("",                  "",                    "", true)); | ||||
|         only_editdis_cases.push_back(createCase< Compare< elem > >("a",                 "",                    "", true)); | ||||
|         only_editdis_cases.push_back(createCase< Compare< elem > >("",                  "b",                   "", true)); | ||||
|         only_editdis_cases.push_back(createCase< Compare< elem > >("acbdeaqqqqqqqcbed", "acebdabbqqqqqqqabed", "", true)); | ||||
|          | ||||
|         custom_cases.push_back(createCase< CaseInsensitive >("abc", "Abc", "custom_test0")); | ||||
|     } | ||||
|      | ||||
|     void TearDown () { | ||||
|         for_each(diff_cases.begin(), diff_cases.end(), Remover< case_t >()); | ||||
|         for_each(custom_cases.begin(), custom_cases.end(), Remover< case_t >()); | ||||
|     } | ||||
| }; | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Strdifftest | ||||
|  * check list is following | ||||
|  * - editdistance | ||||
|  * - LCS | ||||
|  * - SES | ||||
|  * - Unified Format Difference | ||||
|  * - onOnlyEditDistance | ||||
|  */ | ||||
|  | ||||
| TEST_F (Strdifftest, diff_test0) { | ||||
|      | ||||
|     EXPECT_EQ(2,    diff_cases[0].editdis); | ||||
|      | ||||
|     EXPECT_EQ("ab", diff_cases[0].lcs_s); | ||||
|      | ||||
|     ASSERT_EQ(0,    diff_cases[0].editdis_ses); | ||||
|  | ||||
|     ASSERT_EQ(0,    diff_cases[0].editdis_uni); | ||||
| } | ||||
|  | ||||
| TEST_F (Strdifftest, diff_test1) { | ||||
|     EXPECT_EQ(6,          diff_cases[1].editdis); | ||||
|      | ||||
|     EXPECT_EQ("acbdabed", diff_cases[1].lcs_s); | ||||
|      | ||||
|     ASSERT_EQ(0,          diff_cases[1].editdis_ses); | ||||
|      | ||||
|     ASSERT_EQ(0,          diff_cases[1].editdis_uni); | ||||
| } | ||||
|  | ||||
| TEST_F (Strdifftest, diff_test2) { | ||||
|     EXPECT_EQ(6,     diff_cases[2].editdis); | ||||
|      | ||||
|     EXPECT_EQ("acf", diff_cases[2].lcs_s); | ||||
|      | ||||
|     ASSERT_EQ(0,     diff_cases[2].editdis_ses); | ||||
|      | ||||
|     ASSERT_EQ(0,     diff_cases[2].editdis_uni); | ||||
| } | ||||
|  | ||||
| TEST_F (Strdifftest, diff_test3) { | ||||
|     EXPECT_EQ(4,      diff_cases[3].editdis); | ||||
|      | ||||
|     EXPECT_EQ("bcba", diff_cases[3].lcs_s); | ||||
|      | ||||
|     ASSERT_EQ(0,      diff_cases[3].editdis_ses); | ||||
|      | ||||
|     ASSERT_EQ(0,      diff_cases[3].editdis_uni); | ||||
| } | ||||
|  | ||||
| TEST_F (Strdifftest, diff_test4) { | ||||
|     EXPECT_EQ(1,       diff_cases[4].editdis); | ||||
|      | ||||
|     EXPECT_EQ("bokko", diff_cases[4].lcs_s); | ||||
|      | ||||
|     ASSERT_EQ(0,       diff_cases[4].editdis_ses); | ||||
|      | ||||
|     ASSERT_EQ(0,       diff_cases[4].editdis_uni); | ||||
| } | ||||
|  | ||||
| TEST_F (Strdifftest, diff_test5) { | ||||
|     EXPECT_EQ(0,  diff_cases[5].editdis); | ||||
|      | ||||
|     EXPECT_EQ("", diff_cases[5].lcs_s); | ||||
|      | ||||
|     ASSERT_EQ(0,  diff_cases[5].editdis_ses); | ||||
|      | ||||
|     ASSERT_EQ(0,  diff_cases[5].editdis_uni); | ||||
| } | ||||
|  | ||||
| TEST_F (Strdifftest, diff_test6) { | ||||
|     EXPECT_EQ(1,  diff_cases[6].editdis); | ||||
|      | ||||
|     EXPECT_EQ("", diff_cases[6].lcs_s); | ||||
|      | ||||
|     ASSERT_EQ(0,  diff_cases[6].editdis_ses); | ||||
|      | ||||
|     ASSERT_EQ(0,  diff_cases[6].editdis_uni); | ||||
| } | ||||
|  | ||||
| TEST_F (Strdifftest, diff_test7) { | ||||
|     EXPECT_EQ(1,  diff_cases[7].editdis); | ||||
|      | ||||
|     EXPECT_EQ("", diff_cases[7].lcs_s); | ||||
|      | ||||
|     ASSERT_EQ(0,  diff_cases[7].editdis_ses); | ||||
|      | ||||
|     ASSERT_EQ(0,  diff_cases[7].editdis_uni); | ||||
| } | ||||
|  | ||||
| TEST_F (Strdifftest, diff_test8) { | ||||
|     EXPECT_EQ(6,                 diff_cases[8].editdis); | ||||
|      | ||||
|     EXPECT_EQ("acbdaqqqqqqqbed", diff_cases[8].lcs_s); | ||||
|      | ||||
|     ASSERT_EQ(0,                 diff_cases[8].editdis_ses); | ||||
|  | ||||
|     ASSERT_EQ(0,                 diff_cases[8].editdis_uni); | ||||
| } | ||||
|  | ||||
| TEST_F (Strdifftest, only_editdis_test0) { | ||||
|     EXPECT_EQ(2,  only_editdis_cases[0].editdis); | ||||
|      | ||||
|     EXPECT_EQ("", only_editdis_cases[0].lcs_s); | ||||
|      | ||||
|     ASSERT_TRUE(only_editdis_cases[0].ses_seq.empty()); | ||||
|      | ||||
|     ASSERT_TRUE(only_editdis_cases[0].hunk_v.empty()); | ||||
| } | ||||
|  | ||||
| TEST_F (Strdifftest, only_editdis_test1) { | ||||
|     EXPECT_EQ(6,  only_editdis_cases[1].editdis); | ||||
|      | ||||
|     EXPECT_EQ("", only_editdis_cases[1].lcs_s); | ||||
|      | ||||
|     ASSERT_TRUE(only_editdis_cases[1].ses_seq.empty()); | ||||
|      | ||||
|     ASSERT_TRUE(only_editdis_cases[1].hunk_v.empty()); | ||||
| } | ||||
|  | ||||
| TEST_F (Strdifftest, only_editdis_test2) { | ||||
|     EXPECT_EQ(6,  only_editdis_cases[2].editdis); | ||||
|      | ||||
|     EXPECT_EQ("", only_editdis_cases[2].lcs_s); | ||||
|      | ||||
|     ASSERT_TRUE(only_editdis_cases[2].ses_seq.empty()); | ||||
|      | ||||
|     ASSERT_TRUE(only_editdis_cases[2].hunk_v.empty()); | ||||
| } | ||||
|  | ||||
| TEST_F (Strdifftest, only_editdis_test3) { | ||||
|     EXPECT_EQ(4,  only_editdis_cases[3].editdis); | ||||
|      | ||||
|     EXPECT_EQ("", only_editdis_cases[3].lcs_s); | ||||
|      | ||||
|     ASSERT_TRUE(only_editdis_cases[3].ses_seq.empty()); | ||||
|      | ||||
|     ASSERT_TRUE(only_editdis_cases[3].hunk_v.empty()); | ||||
| } | ||||
|  | ||||
| TEST_F (Strdifftest, only_editdis_test4) { | ||||
|     EXPECT_EQ(1,  only_editdis_cases[4].editdis); | ||||
|      | ||||
|     EXPECT_EQ("", only_editdis_cases[4].lcs_s); | ||||
|      | ||||
|     ASSERT_TRUE(only_editdis_cases[4].ses_seq.empty()); | ||||
|      | ||||
|     ASSERT_TRUE(only_editdis_cases[4].hunk_v.empty()); | ||||
| } | ||||
|  | ||||
| TEST_F (Strdifftest, only_editdis_test5) { | ||||
|     EXPECT_EQ(0,  only_editdis_cases[5].editdis); | ||||
|      | ||||
|     EXPECT_EQ("", only_editdis_cases[5].lcs_s); | ||||
|      | ||||
|     ASSERT_TRUE(only_editdis_cases[5].ses_seq.empty()); | ||||
|      | ||||
|     ASSERT_TRUE(only_editdis_cases[5].hunk_v.empty()); | ||||
| } | ||||
|  | ||||
| TEST_F (Strdifftest, only_editdis_test6) { | ||||
|     EXPECT_EQ(1,  only_editdis_cases[6].editdis); | ||||
|      | ||||
|     EXPECT_EQ("", only_editdis_cases[6].lcs_s); | ||||
|      | ||||
|     ASSERT_TRUE(only_editdis_cases[6].ses_seq.empty()); | ||||
|      | ||||
|     ASSERT_TRUE(only_editdis_cases[6].hunk_v.empty()); | ||||
| } | ||||
|  | ||||
| TEST_F (Strdifftest, only_editdis_test7) { | ||||
|     EXPECT_EQ(1,  only_editdis_cases[7].editdis); | ||||
|      | ||||
|     EXPECT_EQ("", only_editdis_cases[7].lcs_s); | ||||
|      | ||||
|     ASSERT_TRUE(only_editdis_cases[7].ses_seq.empty()); | ||||
|      | ||||
|     ASSERT_TRUE(only_editdis_cases[7].hunk_v.empty()); | ||||
| } | ||||
|  | ||||
| TEST_F (Strdifftest, only_editdis_test8) { | ||||
|     EXPECT_EQ(6,  only_editdis_cases[8].editdis); | ||||
|      | ||||
|     EXPECT_EQ("", only_editdis_cases[8].lcs_s); | ||||
|      | ||||
|     ASSERT_TRUE(only_editdis_cases[8].ses_seq.empty()); | ||||
|      | ||||
|     ASSERT_TRUE(only_editdis_cases[8].hunk_v.empty()); | ||||
| } | ||||
|  | ||||
| TEST_F (Strdifftest, custom_comparator_test0) { | ||||
|     EXPECT_EQ(0,     custom_cases[0].editdis); | ||||
|      | ||||
|     EXPECT_EQ("abc", custom_cases[0].lcs_s); | ||||
|  | ||||
|     ASSERT_EQ(0,     custom_cases[0].editdis_ses); | ||||
|      | ||||
|     ASSERT_TRUE(custom_cases[0].hunk_v.empty()); | ||||
| } | ||||
							
								
								
									
										24
									
								
								test/comparators.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								test/comparators.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,24 @@ | ||||
| #ifndef DTL_COMPARATORS | ||||
| #define DTL_COMPARATORS | ||||
|  | ||||
| class CaseInsensitive: public dtl::Compare<char> { | ||||
| public: | ||||
|     virtual bool impl(const char& a, const char& b) const { | ||||
|         return tolower(a) == tolower(b); | ||||
|     } | ||||
| }; | ||||
|  | ||||
| class StringCaseInsensitive: public dtl::Compare<string> { | ||||
| public: | ||||
|     virtual bool impl(const string& a, const string& b) const { | ||||
|         if (a.length() == b.length()) { | ||||
|             bool equal = (strncasecmp(a.c_str(), b.c_str(), a.length()) == 0); | ||||
|             return equal; | ||||
|         } | ||||
|         else { | ||||
|             return false; | ||||
|         } | ||||
|     } | ||||
| }; | ||||
|  | ||||
| #endif // DTL_COMPARATORS | ||||
							
								
								
									
										10
									
								
								test/dtl_test.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								test/dtl_test.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,10 @@ | ||||
| /** | ||||
|  * It is necessary to use googletest to run tests. | ||||
|  */ | ||||
|  | ||||
| #include <gtest/gtest.h> | ||||
|  | ||||
| int main (int argc, char *argv[]) { | ||||
|     ::testing::InitGoogleTest(&argc, argv); | ||||
|     return RUN_ALL_TESTS(); | ||||
| } | ||||
							
								
								
									
										56
									
								
								test/dtl_test_common.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										56
									
								
								test/dtl_test_common.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,56 @@ | ||||
|  | ||||
| #include "dtl_test_common.hpp" | ||||
|  | ||||
| string create_path (const string& test_name, string diff_name, enum type_diff t, bool is_use_suffix) { | ||||
|     string ret; | ||||
|     switch (t) { | ||||
|     case TYPE_DIFF_SES: | ||||
|         ret = (getcwd(NULL, 0) + string("/") + string("ses")   + string("/") + diff_name + string("/") + test_name); | ||||
|         break; | ||||
|     case TYPE_DIFF_UNI: | ||||
|         ret = (getcwd(NULL, 0) + string("/") + string("hunks") + string("/") + diff_name + string("/") + test_name); | ||||
|         break; | ||||
|     } | ||||
|     ret += is_use_suffix ? "_" : ""; | ||||
|     return ret; | ||||
| } | ||||
|  | ||||
| size_t cal_diff_uni (const string& path_l, const string& path_r) { | ||||
|     string   buf; | ||||
|     ifstream lifs(path_l.c_str()); | ||||
|     ifstream rifs(path_r.c_str()); | ||||
|  | ||||
|     vector< string > llines; | ||||
|     vector< string > rlines; | ||||
|  | ||||
|     while (getline(lifs, buf)) { | ||||
|         llines.push_back(buf); | ||||
|     } | ||||
|      | ||||
|     while (getline(rifs, buf)) { | ||||
|         rlines.push_back(buf); | ||||
|     } | ||||
|  | ||||
|     Diff< string, vector< string > > diff_uni(llines, rlines); | ||||
|     diff_uni.compose(); | ||||
|     return diff_uni.getEditDistance(); | ||||
| } | ||||
|  | ||||
| bool is_file_exist (string& fs) { | ||||
|     FILE *fp; | ||||
|     if ((fp = fopen(fs.c_str(), "r")) == NULL) { | ||||
|         return false; | ||||
|     } | ||||
|     fclose(fp); | ||||
|     return true; | ||||
| } | ||||
|  | ||||
| void diff_resultset_exist_check (string &fs) { | ||||
|     if (!is_file_exist(fs)) { | ||||
|         cerr << "======================================================Error!!!======================================================" << endl; | ||||
|         cerr << "diff result set:" << fs << " is not found." << endl; | ||||
|         cerr << "======================================================Error!!!======================================================" << endl; | ||||
|         cerr << "excute dtl_test in dtl/test!" << endl; | ||||
|         exit(EXIT_FAILURE); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										70
									
								
								test/dtl_test_common.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										70
									
								
								test/dtl_test_common.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,70 @@ | ||||
|  | ||||
| #ifndef DTL_TEST_COMMON | ||||
| #define DTL_TEST_COMMON | ||||
|  | ||||
| #include <gtest/gtest.h> | ||||
| #include <cstdio> | ||||
| #include <string> | ||||
| #include <vector> | ||||
| #include <utility> | ||||
| #include <iostream> | ||||
| #include <fstream> | ||||
| #include <dtl/dtl.hpp> | ||||
|  | ||||
| using std::cerr; | ||||
| using std::endl; | ||||
| using std::string; | ||||
| using std::vector; | ||||
| using std::pair; | ||||
| using std::ifstream; | ||||
| using std::ofstream; | ||||
|  | ||||
| using dtl::Diff; | ||||
| using dtl::Diff3; | ||||
| using dtl::Compare; | ||||
| using dtl::SES_COMMON; | ||||
| using dtl::SES_ADD; | ||||
| using dtl::SES_DELETE; | ||||
| using dtl::elemInfo; | ||||
| using dtl::uniHunk; | ||||
|  | ||||
| #define dtl_test_typedefs(e_type, seq_type)                         \ | ||||
|     typedef e_type                       elem;                      \ | ||||
|     typedef seq_type                     sequence;                  \ | ||||
|     typedef pair< elem, elemInfo >       sesElem;                   \ | ||||
|     typedef vector< elem >               elemVec;                   \ | ||||
|     typedef vector< sesElem >            sesElemVec;                \ | ||||
|     typedef vector< uniHunk< sesElem > > uniHunkVec; | ||||
|  | ||||
| enum type_diff { TYPE_DIFF_SES, TYPE_DIFF_UNI }; | ||||
|  | ||||
| string create_path (const string& test_name, string diff_name, enum type_diff t, bool is_use_suffix = false); | ||||
| size_t cal_diff_uni (const string& path_l, const string& path_r); | ||||
| bool is_file_exist (string& fs); | ||||
| void diff_resultset_exist_check (string &fs); | ||||
|  | ||||
| template <typename T> | ||||
| class Remover { | ||||
| public : | ||||
|     void operator()(const T& v){ | ||||
|         remove(v.path_rses.c_str()); | ||||
|         remove(v.path_rhunks.c_str()); | ||||
|     } | ||||
| }; | ||||
|  | ||||
| template < typename elem, typename sequence,  typename comparator > | ||||
| void create_file (const string& path, Diff< elem, sequence, comparator >& diff, enum type_diff t) { | ||||
|     ofstream ofs; | ||||
|     ofs.open(path.c_str()); | ||||
|     switch (t) { | ||||
|     case TYPE_DIFF_SES: | ||||
|         diff.printSES(ofs); | ||||
|         break; | ||||
|     case TYPE_DIFF_UNI: | ||||
|         diff.printUnifiedFormat(ofs); | ||||
|         break; | ||||
|     } | ||||
|     ofs.close(); | ||||
| } | ||||
|  | ||||
| #endif // DTL_TEST_COMMON | ||||
							
								
								
									
										0
									
								
								test/hunks/intdiff/diff_test0
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								test/hunks/intdiff/diff_test0
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										2
									
								
								test/hunks/intdiff/diff_test1
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								test/hunks/intdiff/diff_test1
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,2 @@ | ||||
| @@ -1,0 +1,1 @@ | ||||
| +1 | ||||
							
								
								
									
										2
									
								
								test/hunks/intdiff/diff_test2
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								test/hunks/intdiff/diff_test2
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,2 @@ | ||||
| @@ -1,1 +1,0 @@ | ||||
| -1 | ||||
							
								
								
									
										15
									
								
								test/hunks/intdiff/diff_test3
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								test/hunks/intdiff/diff_test3
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,15 @@ | ||||
| @@ -1,10 +1,10 @@ | ||||
| -1 | ||||
| -2 | ||||
|  3 | ||||
| +5 | ||||
| +1 | ||||
|  4 | ||||
|  5 | ||||
| -6 | ||||
| +1 | ||||
|  7 | ||||
| -8 | ||||
|  9 | ||||
| +6 | ||||
|  10 | ||||
							
								
								
									
										8
									
								
								test/hunks/intdiff/diff_test4
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								test/hunks/intdiff/diff_test4
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,8 @@ | ||||
| @@ -1,5 +1,5 @@ | ||||
| -1 | ||||
| -2 | ||||
|  3 | ||||
| +5 | ||||
| +1 | ||||
|  4 | ||||
|  5 | ||||
							
								
								
									
										0
									
								
								test/hunks/strdiff/custom_test0
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								test/hunks/strdiff/custom_test0
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										5
									
								
								test/hunks/strdiff/diff_test0
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								test/hunks/strdiff/diff_test0
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,5 @@ | ||||
| @@ -1,3 +1,3 @@ | ||||
|  a | ||||
|  b | ||||
| -c | ||||
| +d | ||||
							
								
								
									
										15
									
								
								test/hunks/strdiff/diff_test1
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								test/hunks/strdiff/diff_test1
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,15 @@ | ||||
| @@ -1,10 +1,12 @@ | ||||
|  a | ||||
|  c | ||||
| +e | ||||
|  b | ||||
|  d | ||||
| -e | ||||
|  a | ||||
| -c | ||||
|  b | ||||
| +b | ||||
| +a | ||||
| +b | ||||
|  e | ||||
|  d | ||||
							
								
								
									
										10
									
								
								test/hunks/strdiff/diff_test2
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								test/hunks/strdiff/diff_test2
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,10 @@ | ||||
| @@ -1,6 +1,6 @@ | ||||
| +d | ||||
|  a | ||||
| -b | ||||
|  c | ||||
| -d | ||||
| -e | ||||
|  f | ||||
| +e | ||||
| +a | ||||
							
								
								
									
										9
									
								
								test/hunks/strdiff/diff_test3
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								test/hunks/strdiff/diff_test3
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,9 @@ | ||||
| @@ -1,6 +1,6 @@ | ||||
| -a | ||||
|  b | ||||
| +d | ||||
|  c | ||||
| +a | ||||
|  b | ||||
| -d | ||||
|  a | ||||
							
								
								
									
										6
									
								
								test/hunks/strdiff/diff_test4
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								test/hunks/strdiff/diff_test4
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,6 @@ | ||||
| @@ -2,4 +2,5 @@ | ||||
|  o | ||||
|  k | ||||
|  k | ||||
| +k | ||||
|  o | ||||
							
								
								
									
										0
									
								
								test/hunks/strdiff/diff_test5
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								test/hunks/strdiff/diff_test5
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										2
									
								
								test/hunks/strdiff/diff_test6
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								test/hunks/strdiff/diff_test6
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,2 @@ | ||||
| @@ -1,1 +1,0 @@ | ||||
| -a | ||||
							
								
								
									
										2
									
								
								test/hunks/strdiff/diff_test7
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								test/hunks/strdiff/diff_test7
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,2 @@ | ||||
| @@ -1,0 +1,1 @@ | ||||
| +b | ||||
							
								
								
									
										22
									
								
								test/hunks/strdiff/diff_test8
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								test/hunks/strdiff/diff_test8
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,22 @@ | ||||
| @@ -1,9 +1,11 @@ | ||||
|  a | ||||
|  c | ||||
| +e | ||||
|  b | ||||
|  d | ||||
| -e | ||||
|  a | ||||
| +b | ||||
| +b | ||||
|  q | ||||
|  q | ||||
|  q | ||||
| @@ -11,7 +13,7 @@ | ||||
|  q | ||||
|  q | ||||
|  q | ||||
| -c | ||||
| +a | ||||
|  b | ||||
|  e | ||||
|  d | ||||
							
								
								
									
										0
									
								
								test/ses/intdiff/diff_test0
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								test/ses/intdiff/diff_test0
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										1
									
								
								test/ses/intdiff/diff_test1
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								test/ses/intdiff/diff_test1
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | ||||
| +1 | ||||
							
								
								
									
										1
									
								
								test/ses/intdiff/diff_test2
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								test/ses/intdiff/diff_test2
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | ||||
| -1 | ||||
							
								
								
									
										14
									
								
								test/ses/intdiff/diff_test3
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								test/ses/intdiff/diff_test3
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,14 @@ | ||||
| -1 | ||||
| -2 | ||||
|  3 | ||||
| +5 | ||||
| +1 | ||||
|  4 | ||||
|  5 | ||||
| -6 | ||||
| +1 | ||||
|  7 | ||||
| -8 | ||||
|  9 | ||||
| +6 | ||||
|  10 | ||||
							
								
								
									
										7
									
								
								test/ses/intdiff/diff_test4
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								test/ses/intdiff/diff_test4
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,7 @@ | ||||
| -1 | ||||
| -2 | ||||
|  3 | ||||
| +5 | ||||
| +1 | ||||
|  4 | ||||
|  5 | ||||
							
								
								
									
										3
									
								
								test/ses/strdiff/custom_test0
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								test/ses/strdiff/custom_test0
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,3 @@ | ||||
|  a | ||||
|  b | ||||
|  c | ||||
							
								
								
									
										4
									
								
								test/ses/strdiff/diff_test0
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								test/ses/strdiff/diff_test0
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,4 @@ | ||||
|  a | ||||
|  b | ||||
| -c | ||||
| +d | ||||
							
								
								
									
										14
									
								
								test/ses/strdiff/diff_test1
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								test/ses/strdiff/diff_test1
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,14 @@ | ||||
|  a | ||||
|  c | ||||
| +e | ||||
|  b | ||||
|  d | ||||
| -e | ||||
|  a | ||||
| -c | ||||
|  b | ||||
| +b | ||||
| +a | ||||
| +b | ||||
|  e | ||||
|  d | ||||
							
								
								
									
										9
									
								
								test/ses/strdiff/diff_test2
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								test/ses/strdiff/diff_test2
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,9 @@ | ||||
| +d | ||||
|  a | ||||
| -b | ||||
|  c | ||||
| -d | ||||
| -e | ||||
|  f | ||||
| +e | ||||
| +a | ||||
							
								
								
									
										8
									
								
								test/ses/strdiff/diff_test3
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								test/ses/strdiff/diff_test3
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,8 @@ | ||||
| -a | ||||
|  b | ||||
| +d | ||||
|  c | ||||
| +a | ||||
|  b | ||||
| -d | ||||
|  a | ||||
							
								
								
									
										6
									
								
								test/ses/strdiff/diff_test4
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								test/ses/strdiff/diff_test4
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,6 @@ | ||||
|  b | ||||
|  o | ||||
|  k | ||||
|  k | ||||
| +k | ||||
|  o | ||||
							
								
								
									
										0
									
								
								test/ses/strdiff/diff_test5
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								test/ses/strdiff/diff_test5
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										1
									
								
								test/ses/strdiff/diff_test6
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								test/ses/strdiff/diff_test6
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | ||||
| -a | ||||
							
								
								
									
										1
									
								
								test/ses/strdiff/diff_test7
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								test/ses/strdiff/diff_test7
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | ||||
| +b | ||||
							
								
								
									
										21
									
								
								test/ses/strdiff/diff_test8
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								test/ses/strdiff/diff_test8
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,21 @@ | ||||
|  a | ||||
|  c | ||||
| +e | ||||
|  b | ||||
|  d | ||||
| -e | ||||
|  a | ||||
| +b | ||||
| +b | ||||
|  q | ||||
|  q | ||||
|  q | ||||
|  q | ||||
|  q | ||||
|  q | ||||
|  q | ||||
| +a | ||||
| -c | ||||
|  b | ||||
|  e | ||||
|  d | ||||
		Reference in New Issue
	
	Block a user