Compare commits

..

37 Commits

Author SHA1 Message Date
5e5f04b401 cleanup 2024-06-03 15:11:19 -05:00
5ce91ebc95 refactor version 2024-06-03 15:05:59 -05:00
83ba09dba0 cleanup 2024-06-03 15:02:18 -05:00
a704d27523 added _ 2024-06-03 14:56:54 -05:00
b93926744b lowercase source files 2024-06-03 14:55:17 -05:00
bd427975ef updated changelog 2024-06-03 14:49:28 -05:00
597d2250ff cleanup 2024-06-03 14:46:33 -05:00
5d99bb9142 refactor 2024-06-03 14:46:13 -05:00
58419fd545 updates 2024-06-03 14:41:00 -05:00
9cb9e6e968 added install 2024-06-03 10:48:07 -05:00
3186185a28 fix 2024-06-03 10:40:39 -05:00
d305ed01ac refactor 2024-06-03 10:05:35 -05:00
087f132a32 move to cmake 2024-06-03 09:59:35 -05:00
d1c056e734 update 2024-06-03 08:41:33 -05:00
94d86a1c9f formatting and fixes 2024-06-03 08:20:20 -05:00
0e4c24a23d Update README.md 2024-06-03 13:05:47 +00:00
2e266fa5ee Update dtl/Diff.hpp 2024-06-03 13:03:47 +00:00
988e91555f Update dtl/Diff.hpp 2024-06-03 13:01:48 +00:00
Tatsuhiko Kubo
cd45dd4808 v1.20 2022-04-11 20:47:20 +09:00
Tatsuhiko Kubo
946dc4cecb test: update googletest. 2022-04-11 09:19:34 +09:00
Tatsuhiko Kubo
ebd9a49db9 bugfix: fixed invalid offset in unified format difference when difference is too large. 2022-04-11 09:18:51 +09:00
Tatsuhiko Kubo
18e674e4a6 doc: rm travis-ci.org link. 2021-05-31 22:01:33 +09:00
Tatsuhiko Kubo
0551c22f5e doc: typo fixed. 2021-04-04 02:46:19 +09:00
Tatsuhiko Kubo
32787c066d gitignore: added the new pattern. 2021-04-04 02:44:37 +09:00
Tatsuhiko Kubo
ab0b64b43a scons: print sentence is not available in python3. 2021-04-04 02:42:21 +09:00
Tatsuhiko Kubo
831aeecf1f
Merge pull request #10 from cubicdaiya/switch-github-actions
ci: switch to GitHub Actions.
2021-02-17 23:27:57 +09:00
Tatsuhiko Kubo
ebbde693a5 ci: switch to GitHub Actions. 2021-02-17 23:26:09 +09:00
Tatsuhiko Kubo
b83e617aab
Merge pull request #7 from wlawski/custom-storage
Allow saving SES to provided data storage
2020-09-22 13:37:29 +09:00
Wiktor Lawski
ea5975a080 Add strdiff_storage to list of build targets of SCons 2020-09-21 21:25:20 +02:00
Tatsuhiko Kubo
ef50138616
Merge pull request #6 from wlawski/custom-change-printer-example-improvement
Make custom change printer example more mature
2020-09-21 15:35:11 +09:00
Wiktor Lawski
ca3fa6846a Allow saving SES to provided data storage
It is not always efficient (or possible) to use standard output
streams. Moreover, such generated result may be now further
processed.
2020-09-12 19:50:31 +02:00
Wiktor Lawski
afddfbccf6 Make custom change printer example more mature
printers.hpp does not depend anymore on includes or usings order
inside strdiff_cp.cpp file.
2020-09-12 16:47:17 +02:00
Tatsuhiko Kubo
6b030d6397 travis-ci: fixed CI failure. 2019-09-29 23:18:04 +09:00
Tatsuhiko Kubo
1bcddbf879
Merge pull request #4 from jamesjer/master
test: use python 3 compatible print statements.
2019-09-29 23:15:45 +09:00
Jerry James
61c30c7836 test: use python 3 compatible print statements. 2019-09-16 12:13:18 -06:00
Tatsuhiko Kubo
9cf6da7279 doc: fixed link. 2017-07-16 23:33:21 +09:00
Tatsuhiko Kubo
45c54b42d3 doc: adjusted indent. 2017-07-16 23:32:29 +09:00
58 changed files with 3464 additions and 3205 deletions

127
.clang-format Normal file
View File

@ -0,0 +1,127 @@
---
Language: Cpp
# BasedOnStyle: LLVM
AccessModifierOffset: -2
AlignAfterOpenBracket: Align
AlignConsecutiveMacros: false
AlignConsecutiveAssignments: false
AlignConsecutiveDeclarations: false
AlignEscapedNewlines: Right
AlignOperands: true
AlignTrailingComments: true
AllowAllArgumentsOnNextLine: true
AllowAllConstructorInitializersOnNextLine: true
AllowAllParametersOfDeclarationOnNextLine: true
AllowShortBlocksOnASingleLine: false
AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: All
AllowShortLambdasOnASingleLine: All
AllowShortIfStatementsOnASingleLine: Never
AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: false
AlwaysBreakTemplateDeclarations: MultiLine
BinPackArguments: true
BinPackParameters: true
BraceWrapping:
AfterCaseLabel: false
AfterClass: false
AfterControlStatement: false
AfterEnum: false
AfterFunction: false
AfterNamespace: false
AfterObjCDeclaration: false
AfterStruct: false
AfterUnion: false
AfterExternBlock: false
BeforeCatch: false
BeforeElse: false
IndentBraces: false
SplitEmptyFunction: true
SplitEmptyRecord: true
SplitEmptyNamespace: true
BreakBeforeBinaryOperators: None
BreakBeforeBraces: Attach
BreakBeforeInheritanceComma: false
BreakInheritanceList: BeforeColon
BreakBeforeTernaryOperators: true
BreakConstructorInitializersBeforeComma: false
BreakConstructorInitializers: BeforeColon
BreakAfterJavaFieldAnnotations: false
BreakStringLiterals: true
ColumnLimit: 80
CommentPragmas: '^ IWYU pragma:'
CompactNamespaces: false
ConstructorInitializerAllOnOneLineOrOnePerLine: true
ConstructorInitializerIndentWidth: 4
ContinuationIndentWidth: 4
Cpp11BracedListStyle: true
DerivePointerAlignment: false
DisableFormat: false
ExperimentalAutoDetectBinPacking: false
FixNamespaceComments: true
ForEachMacros:
- foreach
- Q_FOREACH
- BOOST_FOREACH
IncludeBlocks: Preserve
IncludeCategories:
- Regex: '^"(llvm|llvm-c|clang|clang-c)/'
Priority: 2
- Regex: '^(<|"(gtest|gmock|isl|json)/)'
Priority: 3
- Regex: '.*'
Priority: 1
IncludeIsMainRegex: '(Test)?$'
IndentCaseLabels: false
IndentPPDirectives: None
IndentWidth: 2
IndentWrappedFunctionNames: false
JavaScriptQuotes: Leave
JavaScriptWrapImports: true
KeepEmptyLinesAtTheStartOfBlocks: true
MacroBlockBegin: ''
MacroBlockEnd: ''
MaxEmptyLinesToKeep: 1
NamespaceIndentation: None
ObjCBinPackProtocolList: Auto
ObjCBlockIndentWidth: 2
ObjCSpaceAfterProperty: false
ObjCSpaceBeforeProtocolList: true
PenaltyBreakAssignment: 2
PenaltyBreakBeforeFirstCallParameter: 19
PenaltyBreakComment: 300
PenaltyBreakFirstLessLess: 120
PenaltyBreakString: 1000
PenaltyBreakTemplateDeclaration: 10
PenaltyExcessCharacter: 1000000
PenaltyReturnTypeOnItsOwnLine: 60
PointerAlignment: Right
ReflowComments: true
SortIncludes: false
SortUsingDeclarations: true
SpaceAfterCStyleCast: false
SpaceAfterLogicalNot: false
SpaceAfterTemplateKeyword: true
SpaceBeforeAssignmentOperators: true
SpaceBeforeCpp11BracedList: false
SpaceBeforeCtorInitializerColon: true
SpaceBeforeInheritanceColon: true
SpaceBeforeParens: ControlStatements
SpaceBeforeRangeBasedForLoopColon: true
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 1
SpacesInAngles: false
SpacesInContainerLiterals: true
SpacesInCStyleCastParentheses: false
SpacesInParentheses: false
SpacesInSquareBrackets: false
Standard: Auto
StatementMacros:
- Q_UNUSED
- QT_REQUIRE_VERSION
TabWidth: 8
UseTab: Never
...

10
.clang-tidy Normal file
View File

@ -0,0 +1,10 @@
---
Checks: '-*,clang-diagnostic-*,clang-analyzer-*,bugprone-*,concurrency-*,cppcoreguidelines-*,modernize-*,readability-*,-readability-redundant-access-specifiers,-readability-function-cognitive-complexity'
ExtraArgs: '-Wno-unknown-warning-option'
FormatStyle: none
HeaderFileExtensions: ['', 'h','hh','hpp','hxx']
HeaderFilterRegex: ''
ImplementationFileExtensions: ['c','cc','cpp','cxx']
User: 'scott.e.graves@protonmail.com'
WarningsAsErrors: ''
...

19
.cspell/words.txt Normal file
View File

@ -0,0 +1,19 @@
bdiff
cmake_current_source_dir
dhave_unistd_h
dhave_unistd_h
endfunction
fpatch
gtest
have_unistd_h
intdiff
intdifftest
kubo
objdifftest
patchtest
st2ses
strdiff
strdifftest
tatsuhiko
unidiff
unistrdiff

30
.github/workflows/cpp.yml vendored Normal file
View File

@ -0,0 +1,30 @@
name: C++
on: [push]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Install scons and gtest
run: |
sudo apt-get install -y scons
sudo apt-get install -y cmake scons
wget https://github.com/google/googletest/archive/release-1.11.0.zip
unzip -q release-1.11.0.zip
cd googletest-release-1.11.0
cmake .
make
sudo make install
- name: Build examples
run: |
cd examples
scons
- name: Test
run: |
cd test
scons check

48
.gitignore vendored
View File

@ -1,31 +1,37 @@
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
*~
.DS_Store
.cache/
.sconf_temp
.sconsign.dblite
.semantic.cache
GPATH
GRTAGS
GSYMS
GTAGS
TAGS
dtl_test
.sconsign.dblite
.sconf_temp
config.log
^\#
\#$
\.\#
^\#
build/
compile_commands.json
config.log
cspell.json
dtl_test
examples/bdiff
examples/fpatch
examples/intdiff
examples/intdiff3
examples/patch
examples/st2ses
examples/strdiff
examples/strdiff3
examples/strdiff_cp
examples/strdiff_storage
examples/unidiff
examples/unistrdiff
include/dtl/variables.hpp
test/*/*/*_
test/strdiff3_test

View File

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

45
CMakeLists.txt Normal file
View File

@ -0,0 +1,45 @@
cmake_minimum_required(VERSION 3.20)
cmake_policy(SET CMP0048 NEW)
set(DTL_VERSION 2.01)
project(
dtl
VERSION ${DTL_VERSION}
)
include(CheckIncludeFile)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
check_include_file(unistd.h HAVE_UNISTD_H)
if(HAVE_UNISTD_H)
add_definitions(-DHAVE_UNISTD_H)
endif()
configure_file(
${CMAKE_CURRENT_SOURCE_DIR}/include/dtl/variables.hpp.in
${CMAKE_CURRENT_SOURCE_DIR}/include/dtl/variables.hpp
@ONLY
)
include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR}/include)
option(DTL_ENABLE_TESTING "Enable DTL unit tests" OFF)
if(DTL_ENABLE_TESTING)
include(test/CMakeLists.txt)
endif()
option(DTL_ENABLE_EXAMPLES "Enable DTL examples" OFF)
if(DTL_ENABLE_EXAMPLES)
include(examples/CMakeLists.txt)
endif()
install(
DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/include/
DESTINATION include
FILES_MATCHING PATTERN "*.hpp"
)

View File

@ -1,2 +1,3 @@
Tatsuhiko Kubo <cubicdaiya@gmail.com>
Jan Weiß <jan@geheimwerk.de>
Scott E. Graves <scott.e.graves@protonmail.com>

228
ChangeLog
View File

@ -1,258 +1,280 @@
2024-06-03 Scott E. Graves <scott.e.graves@protonmail.com>
* added clang-format and clang-tidy
* lowercase all files names
* moved to CMake build system
* pr: fixed compilation issues
* https://github.com/cubicdaiya/dtl/pull/22
* https://github.com/cubicdaiya/dtl/pull/18
* pr: initialize variables
* https://github.com/cubicdaiya/dtl/pull/16
* 2.01 released
2022-04-11 Tatsuhiko Kubo <cubicdaiya@gmail.com>
* bugfix: fixed invalid offset in unified format difference when difference is too large.
* 1.20 released
2015-05-03 Tatsuhiko Kubo <cubicdaiya@gmail.com>
* added some minor changes.
* added some minor changes.
* 1.19 released
* 1.19 released
2013-01-10 Tatsuhiko Kubo <cubicdaiya@gmail.com>
* add printSES function for custom Printer Thanks to Hu Shubin
* add printSES function for custom Printer Thanks to Hu Shubin
* remove files related mercurial
* remove files related mercurial
* 1.18 released
* 1.18 released
2012-11-18 Tatsuhiko Kubo <cubicdaiya@gmail.com>
* add version-string variable
* add version-string variable
* replace get_current_dir_name to getcwd(get_current_dir_name is not in Mountain Lion)
* replace get_current_dir_name to getcwd(get_current_dir_name is not in Mountain Lion)
* fix small typo
* fix small typo
* 1.17 released
* 1.17 released
2012-10-26 Tatsuhiko Kubo <cubicdaiya@gmail.com>, Jan Weiß <jan@geheimwerk.de>
* Improving comments
* Improving comments
* rewrite README with markdown-style
* rewrite README with markdown-style
* support gtest1.6
* support gtest1.6
* allow clients to handle if DTL swaps the arrays it is passed
* allow clients to handle if DTL swaps the arrays it is passed
* fix incorrect results for SES_COMMON when swapped
* fix incorrect results for SES_COMMON when swapped
* add explicit initialization of ses
* add explicit initialization of ses
* implement option to force the order of sesElem objects in the 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)
* fix problem -> issues/4(test succeeds when result-file does not exist)
* 1.16 released
* 1.16 released
2011-11-10 Tatsuhiko Kubo <cubicdaiya@gmail.com>
* remove unused variable
* remove unused variable
* 1.15 released
* 1.15 released
2011-06-18 Tatsuhiko Kubo <cubicdaiya@gmail.com>
* fix Issue #7 (isOnlyOneOperation returns incorrect value)
* fix Issue #7 (isOnlyOneOperation returns incorrect value)
* 1.14 released
* 1.14 released
2011-04-10 Tatsuhiko Kubo <cubicdaiya@gmail.com>
* add check for libraries with SCons
* add check for libraries with SCons
* add installer with SCons
* add installer with SCons
* add sample of diff(bdiff)
* add sample of diff(bdiff)
* 1.13 released
* 1.13 released
2011-01-23 Tatsuhiko Kubo <cubicdaiya@gmail.com>
* forget to add template parameter of stream for print methods of printUnifiedFormat
* forget to add template parameter of stream for print methods of printUnifiedFormat
* 1.12 released
* 1.12 released
2011-01-01 Tatsuhiko Kubo <cubicdaiya@gmail.com>
* add template parameter of stream for print methods
* add template parameter of stream for print methods
* function of importing ses
* function of importing ses
* 1.11 released
* 1.11 released
2010-11-23 Tatsuhiko Kubo <cubicdaiya@gmail.com>
* use static_cast instead of C-style cast
* use static_cast instead of C-style cast
* remove specifyConfliction
* remove specifyConfliction
* 1.10 released
* 1.10 released
2010-09-20 Tatsuhiko Kubo <cubicdaiya@gmail.com>
* fix bug of specifyConfliction
* fix bug of specifyConfliction
* add parameter for Diff3's comparator
* add parameter for Diff3's comparator
* fix the bug which uniPatch fails
* fix the bug which uniPatch fails
* add debug option for examples
* add debug option for examples
* divide test sources
* divide test sources
* 1.09 released
* 1.09 released
2010-08-29 Tatsuhiko Kubo <cubicdaiya@gmail.com>
* fix the problem that comparator parameter is completely ignored.
* fix the problem that comparator parameter is completely ignored.
* remove the warning 'comparison of unsigned expression >= 0 is always true' ( use -W )
* remove the warning 'comparison of unsigned expression >= 0 is always true' ( use -W )
* move directory 'src' to 'dtl'
* move directory 'src' to 'dtl'
* remove Makefile for examples and test
* remove Makefile for examples and test
* 1.08 released
* 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')
* fix potential risk on 64bit environment(size of 'int' and size of 'size_t')
* add scons
* add scons
* fix bug of specifyConfliction
* fix bug of specifyConfliction
* fix memory leak when onlyEditDistance is true
* fix memory leak when onlyEditDistance is true
* change indent size from 2 to 4
* change indent size from 2 to 4
* 1.07 released
* 1.07 released
2010-05-01 Tatsuhiko Kubo <cubicdaiya@gmail.com>
* add specifyConfliction
* add specifyConfliction
* 1.06 released
* 1.06 released
2010-04-13 Tatsuhiko Kubo <cubicdaiya@gmail.com>
* constructors takes referenced parameter
* constructors takes referenced parameter
* fix seg fault bug (http://code.google.com/p/dtl-cpp/issues/detail?id=2)
* fix seg fault bug (http://code.google.com/p/dtl-cpp/issues/detail?id=2)
* 1.05 released
* 1.05 released
2009-12-01 Tatsuhiko Kubo <cubicdaiya@gmail.com>
* add test programs with googletest
* add test programs with googletest
* add sample of diff(uintdiff)
* add sample of diff(uintdiff)
* 1.04 released
* 1.04 released
2009-10-02 Tatsuhiko Kubo <cubicdaiya@gmail.com>
* add function getLcsVec
* add function getLcsVec
* divide header files
* divide header files
* 1.03 released
* 1.03 released
2009-09-08 Tatsuhiko Kubo <cubicdaiya@gmail.com>
* rename editType to edit_t
* rename editType to edit_t
* add print functions
* add print functions
* add functor of compare
* add functor of compare
* use 'using' declaration
* use 'using' declaration
* refactoring
* refactoring
* add ignore patterns for Mercurial
* add ignore patterns for Mercurial
* 1.02 released.
* 1.02 released.
2009-08-08 Tatsuhiko Kubo <cubicdaiya@gmail.com>
* append appropriate const keyword
* append appropriate const keyword
* refactoring
* refactoring
* 1.01 released.
* 1.01 released.
2009-07-04 Tatsuhiko Kubo <cubicdaiya@gmail.com>
* resolve problem memory leak occurs when default copy constructor set in motion.
* resolve problem memory leak occurs when default copy constructor set in motion.
* 1.00 released.
* 1.00 released.
2009-06-08 Tatsuhiko Kubo <cubicdaiya@gmail.com>
* enhance readability
* enhance readability
* change behavior when conflicted
* change behavior when conflicted
* decliment parameter for patch function
* decliment parameter for patch function
* 0.07 released.
* 0.07 released.
2009-05-08 Tatsuhiko Kubo <cubicdaiya@gmail.com>
* add flag for recording only editdistance
* add flag for recording only editdistance
* add sample of unidiff for string (unistrdiff)
* add sample of unidiff for string (unistrdiff)
* add unserious diff. ver 0.03 has this feture.
* add unserious diff. ver 0.03 has this feture.
* fix bug for merge
* fix bug for merge
* add function getUniHunks
* add function getUniHunks
* 0.06 released.
* 0.06 released.
2008-12-12 Tatsuhiko Kubo <cubicdaiya@gmail.com>
* add sample of diff3 (strdiff3, intdiff3)
* add sample of diff3 (strdiff3, intdiff3)
* add diff3
* add diff3
* + -> - to - -> + with Unified Diff Format
* + -> - to - -> + with Unified Diff Format
* add function uniPatch. this function can patch with Unified Diff Format Data Structure
* add function uniPatch. this function can patch with Unified Diff Format Data Structure
* dtl Import Unified Diff Format Data Structure from unidiff.cpp.
* dtl Import Unified Diff Format Data Structure from unidiff.cpp.
* fix bug. function check whether file exists(common.cpp)
* fix bug. function check whether file exists(common.cpp)
* 0.05 released.
* 0.05 released.
2008-11-10 Tatsuhiko Kubo <cubicdaiya@gmail.com>
* Improves accuracy of diff
* Improves accuracy of diff
* fix serious memory bug for patch
* fix serious memory bug for patch
* changed type of argument in function fileExists(common.hpp, common.cpp)
* changed type of argument in function fileExists(common.hpp, common.cpp)
* 0.04 released.
* 0.04 released.
2008-11-06 Tatsuhiko Kubo <cubicdaiya@gmail.com>
* add erorr check for sample programs
* add erorr check for sample programs
* 0.03 released.
* 0.03 released.
2008-10-31 Tatsuhiko Kubo <cubicdaiya@gmail.com>
* rename ChangLog to ChangeLog
* rename ChangLog to ChangeLog
* modifiy README
* modifiy README
* output OK message on patch and fpatch
* output OK message on patch and fpatch
* 0.02 released.
* 0.02 released.
2008-10-30 Tatsuhiko Kubo <cubicdaiya@gmail.com>
* 0.01 released.
* 0.01 released.

View File

@ -1,6 +1,4 @@
# dtl
[![Build Status](https://travis-ci.org/cubicdaiya/dtl.png?branch=master)](https://travis-ci.org/cubicdaiya/dtl)
# dtl - forked from [https://github.com/cubicdaiya/dtl](https://github.com/cubicdaiya/dtl)
`dtl` is the diff template library written in C++. The name of template is derived C++'s Template.
@ -8,30 +6,30 @@
* [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)
* [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)
* [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)
* [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)
* [Building test programs](#building-test-programs)
* [Running test programs](#running-test-programs)
* [Old commit histories](#old-commit-histories)
* [License](#license)
@ -253,7 +251,7 @@ dtl::Diff<elem, sequence> d(A, B);
d.compose();
d.composeUnifiedHunks()
string s1(A);
string s2 = d.UniPatch(s1);
string s2 = d.uniPatch(s1);
```
When the above code is run, s2 becomes "abd".

View File

@ -1,7 +0,0 @@
import os
# install script
prefix = ARGUMENTS.get('prefix', '/usr/local')
headers = Glob('dtl/*.hpp')
Alias('install', Install(os.path.join(prefix, 'dtl', 'include'), headers))

View File

@ -1,692 +0,0 @@
/**
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

View File

@ -1,245 +0,0 @@
/**
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

View File

@ -1,132 +0,0 @@
/**
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

View File

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

View File

@ -1,142 +0,0 @@
/**
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

23
examples/CMakeLists.txt Normal file
View File

@ -0,0 +1,23 @@
function(add_example_executable name)
add_executable(${name}
examples/${name}.cpp
examples/common.cpp
)
target_include_directories(${name} BEFORE PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/examples
)
endfunction()
add_example_executable(bdiff)
add_example_executable(fpatch)
add_example_executable(intdiff)
add_example_executable(intdiff3)
add_example_executable(patch)
add_example_executable(st2ses)
add_example_executable(strdiff)
add_example_executable(strdiff3)
add_example_executable(strdiff_cp)
add_example_executable(strdiff_storage)
add_example_executable(unidiff)
add_example_executable(unistrdiff)

View File

@ -1,42 +0,0 @@
import os
# SConstruct for dtl examples
env = Environment(CPPPATH='..')
debug = ARGUMENTS.get('debug', 'n')
if debug == 'y' or debug == 'yes':
env.Append(CPPFLAGS = ['-Wall', '-g'])
else:
env.Append(CPPFLAGS = ['-Wall', '-O2'])
if os.sys.platform != "win32":
env.Append(CPPDEFINES = ['HAVE_UNISTD_H'])
conf = Configure(env);
if not conf.CheckCXX():
print "The C++ compiler is not installed!"
Exit(1)
libs = ['stdc++']
for lib in libs:
if not conf.CheckLib(lib):
print "library " + lib + " not installed!"
Exit(1)
conf.Finish()
targets = { 'strdiff' : ['strdiff.cpp', 'common.cpp'], # diff between two string sequences
'intdiff' : ['intdiff.cpp'], # diff between two integer sequences
'unidiff' : ['unidiff.cpp', 'common.cpp'], # unified diff between two files
'unistrdiff' : ['unistrdiff.cpp', 'common.cpp'], # unified diff between two strings
'bdiff' : ['bdiff.cpp', 'common.cpp'], # diff between two byte sequences
'strdiff3' : ['strdiff3.cpp', 'common.cpp'], # three-way string diff program using dtl
'intdiff3' : ['intdiff3.cpp'], # three-way integer diff program using dtl
'patch' : ['patch.cpp', 'common.cpp'], # string patch program using dtl
'fpatch' : ['fpatch.cpp', 'common.cpp'], # file patch program using dtl
'st2ses' : ['st2ses.cpp', 'common.cpp'], # convert SES format file to SES instance
'strdiff_cp' : ['strdiff_cp.cpp', 'common.cpp'], # diff between two string sequences with custom printer
}
[ env.Program(target, targets[target]) for target in targets ]

View File

@ -1,73 +1,56 @@
#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;
typedef unsigned char elem;
typedef std::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;
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) {
std::cout << "Opening failed." << std::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);
return 0;
std::cout << "Read error." << std::endl;
return -1;
}
close(fd);
return 0;
}
int main(int argc, char *argv[])
{
int main(int argc, char *argv[]) {
if (isFewArgs(argc)) {
cerr << "Too few arguments." << endl;
return -1;
}
if (isFewArgs(argc)) {
std::cerr << "Too few arguments." << std::endl;
return -1;
}
string fs1(argv[1]);
string fs2(argv[2]);
sequence seq1;
sequence seq2;
std::string fs1(argv[1]);
std::string fs2(argv[2]);
sequence seq1;
sequence seq2;
create_byte_seq(fs1.c_str(), seq1);
create_byte_seq(fs2.c_str(), seq2);
create_byte_seq(fs1.c_str(), seq1);
create_byte_seq(fs2.c_str(), seq2);
Diff< elem, sequence > d(seq1, seq2);
d.compose();
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;
}
if (d.getEditDistance() == 0) {
std::cout << fs1 << " is the same as " << fs2 << std::endl;
} else {
std::cout << fs1 << " is different from " << fs2 << std::endl;
}
return 0;
return 0;
}

View File

@ -1,20 +1,18 @@
#include "common.hpp"
bool isFileExist (string& fs) {
FILE *fp;
if ((fp = fopen(fs.c_str(), "r")) == NULL) {
return false;
}
fclose(fp);
return true;
bool isFileExist(std::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;
bool isFewArgs(int argc, int limit) {
bool ret = false;
if (argc < limit) {
ret = true;
}
return ret;
}

View File

@ -1,13 +1,22 @@
#ifndef DTL_EXAMPLE_COMMON_H
#define DTL_EXAMPLE_COMMON_H
#include <string>
#include <cassert>
#include <cstdio>
#include <fstream>
#include <sstream>
using namespace std;
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <time.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif // HAVE_UNISTD_H
bool isFileExist (string& fs);
bool isFewArgs (int argc, int limit = 3);
#include "dtl/dtl.hpp"
bool isFileExist(std::string &fs);
bool isFewArgs(int argc, int limit = 3);
#endif

View File

@ -1,73 +1,64 @@
#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[]){
int main(int argc, char *argv[]) {
if (isFewArgs(argc)) {
cerr << "Too few arguments." << endl;
return -1;
}
if (isFewArgs(argc)) {
std::cerr << "Too few arguments." << std::endl;
return -1;
}
string A(argv[1]);
string B(argv[2]);
bool fileExist = true;
std::string A(argv[1]);
std::string B(argv[2]);
bool fileExist = true;
if (!isFileExist(A)) {
cerr << "file A does not exist" << endl;
fileExist = false;
}
if (!isFileExist(A)) {
std::cerr << "file A does not exist" << std::endl;
fileExist = false;
}
if (!isFileExist(B)) {
cerr << "file B does not exist" << endl;
fileExist = false;
}
if (!isFileExist(B)) {
std::cerr << "file B does not exist" << std::endl;
fileExist = false;
}
if (!fileExist) {
return -1;
}
if (!fileExist) {
return -1;
}
typedef string elem;
typedef vector< elem > sequence;
typedef std::string elem;
typedef std::vector<elem> sequence;
ifstream Aifs(A.c_str());
ifstream Bifs(B.c_str());
elem buf;
sequence ALines, BLines;
ostringstream ossLine, ossInfo;
std::ifstream Aifs(A.c_str());
std::ifstream Bifs(B.c_str());
elem buf;
sequence ALines, BLines;
std::ostringstream ossLine, ossInfo;
while(getline(Aifs, buf)){
ALines.push_back(buf);
}
while(getline(Bifs, buf)){
BLines.push_back(buf);
}
while (getline(Aifs, buf)) {
ALines.push_back(buf);
}
while (getline(Bifs, buf)) {
BLines.push_back(buf);
}
Diff< elem > d(ALines, BLines);
d.compose();
Diff<elem> d(ALines, BLines);
d.compose();
sequence s1 = ALines;
sequence s2 = d.patch(s1);
sequence s1 = ALines;
sequence s2 = d.patch(s1);
// fpatch
assert(BLines == s2);
cout << "fpatch succeeded" << endl;
// fpatch
assert(BLines == s2);
std::cout << "fpatch succeeded" << std::endl;
d.composeUnifiedHunks();
sequence s3 = d.uniPatch(s1);
d.composeUnifiedHunks();
sequence s3 = d.uniPatch(s1);
// unipatch
assert(BLines == s3);
cout << "unipatch succeeded" << endl;
// unipatch
assert(BLines == s3);
std::cout << "unipatch succeeded" << std::endl;
return 0;
return 0;
}

View File

@ -1,49 +1,44 @@
#include <iostream>
#include <vector>
#include <dtl/dtl.hpp>
using namespace std;
#include "common.hpp"
using dtl::Diff;
int main(int, char**){
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;
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) {
std::cout << a[i] << " ";
}
std::cout << std::endl;
for (int i = 0; i < bsiz; ++i) {
std::cout << b[i] << " ";
}
std::cout << std::endl;
typedef int elem;
typedef vector< int > sequence;
typedef int elem;
typedef std::vector<int> sequence;
sequence A(&a[0], &a[asiz]);
sequence B(&b[0], &b[bsiz]);
Diff< elem > d(A, B);
d.compose();
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;
// editDistance
std::cout << "editDistance:" << d.getEditDistance() << std::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;
// Longest Common Subsequence
sequence lcs_v = d.getLcsVec();
std::cout << "LCS: ";
for (sequence::iterator vit = lcs_v.begin(); vit != lcs_v.end(); ++vit) {
std::cout << *vit << " ";
}
std::cout << std::endl;
// Shortest Edit Script
cout << "SES" << endl;
d.printSES();
// Shortest Edit Script
std::cout << "SES" << std::endl;
d.printSES();
return 0;
return 0;
}

View File

@ -1,57 +1,51 @@
#include <dtl/dtl.hpp>
#include <iostream>
#include <vector>
#include <cassert>
using namespace std;
#include "common.hpp"
using dtl::Diff3;
int main(int, char**) {
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};
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;
std::cout << "a:";
for (int i = 0; i < 10; ++i) {
std::cout << a[i] << " ";
}
std::cout << std::endl;
std::cout << "b:";
for (int i = 0; i < 10; ++i) {
std::cout << b[i] << " ";
}
std::cout << std::endl;
std::cout << "c:";
for (int i = 0; i < 10; ++i) {
std::cout << c[i] << " ";
}
std::cout << std::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;
typedef int elem;
typedef std::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()) {
std::cerr << "conflict." << std::endl;
return -1;
}
sequence s = diff3.getMergedSequence();
std::cout << "s:";
for (sequence::iterator it = s.begin(); it != s.end(); ++it) {
std::cout << *it << " ";
}
std::cout << std::endl;
assert(s == Answer);
cout << "intdiff3 OK" << endl;
assert(s == Answer);
std::cout << "intdiff3 OK" << std::endl;
return 0;
return 0;
}

View File

@ -1,44 +1,37 @@
#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;
}
if (isFewArgs(argc)) {
std::cerr << "Too few arguments." << std::endl;
return -1;
}
typedef char elem;
typedef string sequence;
typedef char elem;
typedef std::string sequence;
sequence A(argv[1]);
sequence B(argv[2]);
sequence A(argv[1]);
sequence B(argv[2]);
Diff< elem, sequence > d(A, B);
d.compose();
Diff<elem, sequence> d(A, B);
d.compose();
sequence s1(A);
sequence s2 = d.patch(s1);
d.composeUnifiedHunks();
sequence s3 = d.uniPatch(s1);
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;
std::cout << "before:" << s1 << std::endl;
std::cout << "after :" << s2 << std::endl;
assert(B == s2);
std::cout << "patch succeeded" << std::endl;
cout << "before:" << s1 << endl;
cout << "after :" << s3 << endl;
assert(B == s3);
cout << "unipatch succeeded" << endl;
std::cout << "before:" << s1 << std::endl;
std::cout << "after :" << s3 << std::endl;
assert(B == s3);
std::cout << "unipatch succeeded" << std::endl;
return 0;
return 0;
}

View File

@ -1,26 +1,27 @@
#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;
}
#include "common.hpp"
template <typename sesElem, typename stream = std::ostream>
class customChangePrinter : public dtl::Printer<sesElem, stream> {
public:
customChangePrinter() : dtl::Printer<sesElem, stream>() {}
customChangePrinter(stream &out) : dtl::Printer<sesElem, stream>(out) {}
~customChangePrinter() {}
void operator()(const sesElem &se) const {
switch (se.second.type) {
case dtl::SES_ADD:
this->out_ << "Add: " << se.first << std::endl;
break;
case dtl::SES_DELETE:
this->out_ << "Delete: " << se.first << std::endl;
break;
case dtl::SES_COMMON:
this->out_ << "Common: " << se.first << std::endl;
break;
}
}
};
#endif // DTL_PRINTERS

View File

@ -1,35 +1,28 @@
#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[]){
int main(int argc, char *argv[]) {
if (isFewArgs(argc, 2)) {
cerr << "Too few arguments." << endl;
return -1;
}
if (isFewArgs(argc, 2)) {
std::cerr << "Too few arguments." << std::endl;
return -1;
}
typedef string elem;
typedef vector< string > sequence;
typedef std::string elem;
typedef std::vector<string> sequence;
string s(argv[1]);
std::string s(argv[1]);
if (!isFileExist(s)) {
cerr << s << " is invalid." << endl;
return -1;
}
if (!isFileExist(s)) {
std::cerr << s << " is invalid." << std::endl;
return -1;
}
ifstream fs(s.c_str());
const Ses< elem > ses = Diff< elem, sequence >::composeSesFromStream< ifstream >(fs);
dtl::Diff< elem, sequence >::printSES(ses);
std::ifstream fs(s.c_str());
const Ses<elem> ses =
Diff<elem, sequence>::composeSesFromStream<std::ifstream>(fs);
dtl::Diff<elem, sequence>::printSES(ses);
return 0;
return 0;
}

26
examples/storage.hpp Normal file
View File

@ -0,0 +1,26 @@
#ifndef DTL_STORAGE
#define DTL_STORAGE
#include "common.hpp"
template <typename sesElem, typename storedData>
class CustomStorage : public dtl::Storage<sesElem, storedData> {
public:
CustomStorage(storedData &sd) : dtl::Storage<sesElem, storedData>(sd) {}
~CustomStorage() {}
void operator()(const sesElem &se) const {
switch (se.second.type) {
case dtl::SES_ADD:
this->storedData_ = this->storedData_ + "Add: " + se.first + "\n";
break;
case dtl::SES_DELETE:
this->storedData_ = this->storedData_ + "Delete: " + se.first + "\n";
break;
case dtl::SES_COMMON:
this->storedData_ = this->storedData_ + "Common: " + se.first + "\n";
break;
}
}
};
#endif // DTL_STORAGE

View File

@ -1,42 +1,35 @@
#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[]){
int main(int argc, char *argv[]) {
if (isFewArgs(argc)) {
cerr << "Too few arguments." << endl;
return -1;
}
if (isFewArgs(argc)) {
std::cerr << "Too few arguments." << std::endl;
return -1;
}
typedef char elem;
typedef string sequence;
typedef char elem;
typedef std::string sequence;
sequence A(argv[1]);
sequence B(argv[2]);
sequence A(argv[1]);
sequence B(argv[2]);
Diff< elem, sequence > d(A, B);
//d.onOnlyEditDistance();
d.compose();
Diff<elem, sequence> d(A, B);
// d.onOnlyEditDistance();
d.compose();
// editDistance
cout << "editDistance:" << d.getEditDistance() << endl;
// editDistance
std::cout << "editDistance:" << d.getEditDistance() << std::endl;
// Longest Common Subsequence
vector< elem > lcs_v = d.getLcsVec();
sequence lcs_s(lcs_v.begin(), lcs_v.end());
cout << "LCS:" << lcs_s << endl;
// Longest Common Subsequence
std::vector<elem> lcs_v = d.getLcsVec();
sequence lcs_s(lcs_v.begin(), lcs_v.end());
std::cout << "LCS:" << lcs_s << std::endl;
// Shortest Edit Script
cout << "SES" << endl;
d.printSES();
// Shortest Edit Script
std::cout << "SES" << std::endl;
d.printSES();
return 0;
return 0;
}

View File

@ -1,35 +1,28 @@
#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[]){
int main(int argc, char *argv[]) {
if (isFewArgs(argc, 4)) {
cerr << "Too few arguments." << endl;
return -1;
}
if (isFewArgs(argc, 4)) {
std::cerr << "Too few arguments." << std::endl;
return -1;
}
typedef char elem;
typedef string sequence;
typedef char elem;
typedef std::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;
sequence A(argv[1]);
sequence B(argv[2]);
sequence C(argv[3]);
Diff3<elem, sequence> diff3(A, B, C);
diff3.compose();
if (!diff3.merge()) {
std::cerr << "conflict." << std::endl;
return 0;
}
std::cout << "result:" << diff3.getMergedSequence() << std::endl;
return 0;
}

View File

@ -1,40 +1,29 @@
#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[]){
using dtl::Diff;
if (isFewArgs(argc)) {
cerr << "Too few arguments." << endl;
return -1;
}
int main(int argc, char *argv[]) {
typedef char elem;
typedef string sequence;
if (isFewArgs(argc)) {
std::cerr << "Too few arguments." << std::endl;
return -1;
}
sequence A(argv[1]);
sequence B(argv[2]);
typedef char elem;
typedef std::string sequence;
Diff< elem, sequence > d(A, B);
d.compose();
sequence A(argv[1]);
sequence B(argv[2]);
// Shortest Edit Script
cout << "SES" << endl;
Diff<elem, sequence> d(A, B);
d.compose();
d.printSES < ostream, customChangePrinter > (cout);
// Shortest Edit Script
std::cout << "SES" << std::endl;
return 0;
d.printSES<std::ostream, customChangePrinter>(std::cout);
return 0;
}

View File

@ -0,0 +1,33 @@
#include "common.hpp"
#include "storage.hpp"
using dtl::Diff;
int main(int argc, char *argv[]) {
if (isFewArgs(argc)) {
std::cerr << "Too few arguments." << std::endl;
return -1;
}
typedef char elem;
typedef std::string sequence;
sequence A(argv[1]);
sequence B(argv[2]);
Diff<elem, sequence> d(A, B);
d.compose();
// Shortest Edit Script
std::cout << "SES" << std::endl;
std::string result;
d.storeSES<std::string, CustomStorage>(result);
std::cout << result;
return 0;
}

View File

@ -1,111 +1,96 @@
#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(std::string fp1, std::string fp2);
static void unifiedDiff(std::string fp1, std::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];
static void showStats(std::string fp1, std::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);
}
if (stat(fp1.c_str(), &st[0]) == -1) {
std::cerr << "argv1 is invalid." << std::endl;
exit(-1);
}
if (stat(fp2.c_str(), &st[1]) == -1) {
std::cerr << "argv2 is invalid" << std::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;
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]);
std::cout << "--- " << fp1 << '\t' << buf[0] << std::endl;
rawtime[1] = st[1].st_mtime;
timeinfo[1] = localtime(&rawtime[1]);
strftime(buf[1], MAX_LENGTH, time_format, timeinfo[1]);
std::cout << "+++ " << fp2 << '\t' << buf[1] << std::endl;
}
static void unifiedDiff (string fp1, string fp2)
{
typedef string elem;
typedef vector< elem > sequence;
typedef pair< elem, elemInfo > sesElem;
static void unifiedDiff(std::string fp1, std::string fp2) {
typedef std::string elem;
typedef std::vector<elem> sequence;
typedef std::pair<elem, elemInfo> sesElem;
ifstream Aifs(fp1.c_str());
ifstream Bifs(fp2.c_str());
elem buf;
sequence ALines, BLines;
std::ifstream Aifs(fp1.c_str());
std::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);
}
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();
Diff<elem> diff(ALines, BLines);
diff.onHuge();
// diff.onUnserious();
diff.compose();
// type unihunk definition test
uniHunk< sesElem > hunk;
// type unihunk definition test
uniHunk<sesElem> hunk;
if (diff.getEditDistance() > 0) {
showStats(fp1, fp2); // show file info
}
if (diff.getEditDistance() > 0) {
showStats(fp1, fp2); // show file info
}
diff.composeUnifiedHunks();
diff.printUnifiedFormat();
diff.composeUnifiedHunks();
diff.printUnifiedFormat();
}
int main(int argc, char *argv[]) {
if (isFewArgs(argc)) {
std::cerr << "Too few arguments." << std::endl;
return -1;
}
int main(int argc, char *argv[])
{
if (isFewArgs(argc)) {
cerr << "Too few arguments." << endl;
return -1;
}
std::string s1(argv[1]);
std::string s2(argv[2]);
bool fileExist = true;
string s1(argv[1]);
string s2(argv[2]);
bool fileExist = true;
if (!isFileExist(s1)) {
std::cerr << s1 << " is invalid." << std::endl;
fileExist = false;
}
if (!isFileExist(s1)) {
cerr << s1 << " is invalid." << endl;
fileExist = false;
}
if (!isFileExist(s2)) {
std::cerr << s2 << " is invalid." << std::endl;
fileExist = false;
}
if (!isFileExist(s2)) {
cerr << s2 << " is invalid." << endl;
fileExist = false;
}
if (!fileExist) {
return -1;
}
if (!fileExist) {
return -1;
}
unifiedDiff(s1, s2);
return 0;
unifiedDiff(s1, s2);
return 0;
}

View File

@ -1,40 +1,34 @@
#include <dtl/dtl.hpp>
#include "common.hpp"
#include <iostream>
#include <vector>
using namespace std;
using dtl::Diff;
int main(int argc, char *argv[]){
int main(int argc, char *argv[]) {
if (isFewArgs(argc)) {
cerr << "Too few arguments." << endl;
return -1;
}
if (isFewArgs(argc)) {
std::cerr << "Too few arguments." << std::endl;
return -1;
}
typedef char elem;
typedef string sequence;
typedef char elem;
typedef std::string sequence;
sequence A(argv[1]);
sequence B(argv[2]);
sequence A(argv[1]);
sequence B(argv[2]);
Diff<elem, sequence > d(A, B);
d.compose();
d.composeUnifiedHunks();
Diff<elem, sequence> d(A, B);
d.compose();
d.composeUnifiedHunks();
// editDistance
cout << "editDistance:" << d.getEditDistance() << endl;
// editDistance
std::cout << "editDistance:" << d.getEditDistance() << std::endl;
// Longest Common Subsequence
vector<elem> lcs_v = d.getLcsVec();
sequence lcs_s(lcs_v.begin(), lcs_v.end());
cout << "LCS:" << lcs_s << endl;
// Longest Common Subsequence
std::vector<elem> lcs_v = d.getLcsVec();
sequence lcs_s(lcs_v.begin(), lcs_v.end());
std::cout << "LCS:" << lcs_s << std::endl;
// print Unified Format
d.printUnifiedFormat();
// print Unified Format
d.printUnifiedFormat();
return 0;
return 0;
}

692
include/dtl/diff.hpp Normal file
View File

@ -0,0 +1,692 @@
/**
dtl -- Diff Template Library
In short, Diff Template Library is distributed under so called "BSD license",
Copyright (c) 2015 Tatsuhiko Kubo <cubicdaiya@gmail.com>
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the authors nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/* If you use this library, you must include dtl.hpp only. */
#ifndef DTL_DIFF_H
#define DTL_DIFF_H
#include "dtl/functors.hpp"
#include "dtl/lcs.hpp"
#include "dtl/ses.hpp"
#include "dtl/variables.hpp"
namespace dtl {
/**
* diff class template
* sequence must support random_access_iterator.
*/
template <typename elem, typename sequence = std::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;
long long ox;
long long oy;
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() { 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);
}
ox = 0;
oy = 0;
long long p = -1;
fp = new long long[M + N + 3];
std::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));
}
/**
* store difference between A and B as an SES with custom storage
*/
template <typename storedData,
template <typename SEET, typename STRT> class ST>
void storeSES(storedData &sd) const {
sesElemVec ses_v = ses.getSequence();
for_each(ses_v.begin(), ses_v.end(), ST<sesElem, storedData>(sd));
}
/**
* 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 = std::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 {
std::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())
std::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 (std::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 = std::distance(B.begin(), B.end());
if (M < N) {
swapped = false;
} else {
swap(A, B);
std::swap(M, N);
swapped = true;
}
editDistance = 0;
delta = N - M;
offset = M + 1;
huge = false;
trivial = false;
editDistanceOnly = false;
fp = NULL;
ox = 0;
oy = 0;
}
/**
* 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 = std::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 + oy, SES_ADD);
} else {
ses.addSequence(*y, y_idx + oy, 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 + ox, 0, SES_DELETE);
} else {
ses.addSequence(*x, 0, x_idx + ox, SES_ADD);
}
++x;
++x_idx;
++px_idx;
} else {
if (!wasSwapped()) {
lcs.addSequence(*x);
ses.addSequence(*x, x_idx + ox, y_idx + oy, SES_COMMON);
} else {
lcs.addSequence(*y);
ses.addSequence(*y, y_idx + oy, x_idx + ox, 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 = std::distance(B.begin(), B.end());
delta = N - M;
offset = M + 1;
delete[] fp;
fp = new long long[M + N + 3];
std::fill(&fp[0], &fp[M + N + 3], -1);
fill(path.begin(), path.end(), -1);
ox = x_idx - 1;
oy = y_idx - 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; }
};
} // namespace dtl
#endif // DTL_DIFF_H

243
include/dtl/diff3.hpp Normal file
View File

@ -0,0 +1,243 @@
/**
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
#include "dtl/diff.hpp"
namespace dtl {
/**
* diff3 class template
* sequence must support random_access_iterator.
*/
template <typename elem, typename sequence = std::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;
}
}
};
} // namespace dtl
#endif // DTL_DIFF3_H

View File

@ -6,8 +6,8 @@
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:
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.
@ -36,12 +36,12 @@
#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"
#include "dtl/diff.hpp"
#include "dtl/diff3.hpp"
#include "dtl/functors.hpp"
#include "dtl/lcs.hpp"
#include "dtl/sequence.hpp"
#include "dtl/ses.hpp"
#include "dtl/variables.hpp"
#endif // DTL_H

150
include/dtl/functors.hpp Normal file
View File

@ -0,0 +1,150 @@
/**
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
#include <iostream>
#include "dtl/variables.hpp"
namespace dtl {
/**
* printer class template
*/
template <typename sesElem, typename stream = std::ostream> class Printer {
public:
Printer() : out_(std::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 = std::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 = std::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_;
};
/**
* storage class template
*/
template <typename sesElem, typename storedData> class Storage {
public:
Storage(storedData &sd) : storedData_(sd) {}
virtual ~Storage() {}
virtual void operator()(const sesElem &se) const = 0;
protected:
storedData &storedData_;
};
/**
* 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;
}
};
} // namespace dtl
#endif // DTL_FUNCTORS_H

View File

@ -6,8 +6,8 @@
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:
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.
@ -38,18 +38,18 @@
#ifndef DTL_LCS_H
#define DTL_LCS_H
#include "dtl/sequence.hpp"
namespace dtl {
/**
* Longest Common Subsequence template class
*/
template <typename elem>
class Lcs : public Sequence< elem >
{
public :
Lcs () {}
~Lcs () {}
};
}
/**
* Longest Common Subsequence template class
*/
template <typename elem> class Lcs : public Sequence<elem> {
public:
Lcs() {}
~Lcs() {}
};
} // namespace dtl
#endif // DTL_LCS_H

View File

@ -6,8 +6,8 @@
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:
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.
@ -38,28 +38,24 @@
#ifndef DTL_SEQUENCE_H
#define DTL_SEQUENCE_H
#include <vector>
namespace dtl {
/**
* sequence class template
*/
template <typename elem> class Sequence {
public:
typedef std::vector<elem> elemVec;
Sequence() {}
virtual ~Sequence() {}
/**
* 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); }
elemVec getSequence () const {
return sequence;
}
void addSequence (elem e) {
sequence.push_back(e);
}
protected :
elemVec sequence;
};
}
protected:
elemVec sequence;
};
} // namespace dtl
#endif // DTL_SEQUENCE_H

129
include/dtl/ses.hpp Normal file
View File

@ -0,0 +1,129 @@
/**
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
#include <utility>
#include <vector>
#include "dtl/sequence.hpp"
#include "dtl/variables.hpp"
namespace dtl {
/**
* Shortest Edit Script template class
*/
template <typename elem> class Ses : public Sequence<elem> {
private:
typedef std::pair<elem, elemInfo> sesElem;
typedef std::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;
};
} // namespace dtl
#endif // DTL_SES_H

View File

@ -0,0 +1,141 @@
/**
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 <algorithm>
#include <iostream>
#include <list>
#include <string>
#include <vector>
namespace dtl {
using std::cout;
using std::distance;
using std::endl;
using std::fill;
using std::for_each;
using std::list;
using std::max;
using std::ostream;
using std::pair;
using std::rotate;
using std::string;
using std::swap;
using std::vector;
/**
* version string
*/
const string version = "@DTL_VERSION@";
/**
* 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;
} // namespace dtl
#endif // DTL_VARIABLES_H

20
test/CMakeLists.txt Normal file
View File

@ -0,0 +1,20 @@
enable_testing()
find_package(GTest REQUIRED)
add_executable(dtl_test
test/dtl_test.cpp
test/dtl_test_common.cpp
test/int_diff_test.cpp
test/obj_diff_test.cpp
test/patch_test.cpp
test/str_diff3_test.cpp
test/str_diff_test.cpp
)
target_include_directories(dtl_test BEFORE PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/test
)
target_link_libraries(dtl_test GTest::gtest GTest::gtest_main)
add_test(AllTests dtl_test)

View File

@ -1,144 +0,0 @@
#include "dtl_test_common.hpp"
class Intdifftest : public ::testing::Test
{
protected :
dtl_test_typedefs(int, vector< int >)
typedef struct case_t {
sequence A;
sequence B;
size_t editdis;
elemVec lcs_v;
sequence lcs_s;
sesElemVec ses_seq;
uniHunkVec hunk_v;
size_t editdis_ses;
size_t editdis_uni;
string path_rses;
string path_rhunks;
} case_t;
typedef vector< case_t > caseVec;
caseVec cases;
case_t createCase (const sequence a, const sequence b, string test_name) {
case_t c;
string diff_name("intdiff");
Diff< elem > diff(a, b);
diff.compose();
diff.composeUnifiedHunks();
if (test_name != "") {
string path_lses = create_path(test_name, diff_name, TYPE_DIFF_SES);
string path_rses = create_path(test_name, diff_name, TYPE_DIFF_SES, true);
string path_lhunks = create_path(test_name, diff_name, TYPE_DIFF_UNI);
string path_rhunks = create_path(test_name, diff_name, TYPE_DIFF_UNI, true);
create_file< elem, sequence, Compare< elem > >(path_rses, diff, TYPE_DIFF_SES);
create_file< elem, sequence, Compare< elem > >(path_rhunks, diff, TYPE_DIFF_UNI);
c.editdis_ses = cal_diff_uni(path_lses, path_rses);
c.editdis_uni = cal_diff_uni(path_lhunks, path_rhunks);
c.path_rses = path_rses;
c.path_rhunks = path_rhunks;
}
c.A = a;
c.B = b;
c.editdis = diff.getEditDistance();
c.lcs_v = diff.getLcsVec();
c.ses_seq = diff.getSes().getSequence();
return c;
}
void SetUp() {
cases.push_back(createCase(sequence(0), sequence(0), "diff_test0"));
sequence B1;
B1.push_back(1);
cases.push_back(createCase(sequence(0), B1, "diff_test1"));
sequence A2;
A2.push_back(1);
cases.push_back(createCase(A2, sequence(0), "diff_test2"));
int a4[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
int b4[] = {3, 5, 1, 4, 5, 1, 7, 9, 6, 10};
int a4siz = sizeof(a4) / sizeof(int);
int b4siz = sizeof(b4) / sizeof(int);
sequence A4(&a4[0], &a4[a4siz]);
sequence B4(&b4[0], &b4[b4siz]);
cases.push_back(createCase(A4, B4, "diff_test3"));
int a5[] = {1, 2, 3, 4, 5};
int b5[] = {3, 5, 1, 4, 5};
int a5siz = sizeof(a5) / sizeof(int);
int b5siz = sizeof(b5) / sizeof(int);
sequence A5(&a5[0], &a5[a5siz]);
sequence B5(&b5[0], &b5[b5siz]);
cases.push_back(createCase(A5, B5, "diff_test4"));
}
void TearDown () {
for_each(cases.begin(), cases.end(), Remover< case_t >());
}
};
/**
* Intdifftest
* check list is following
* - editdistance
* - LCS
* - SES
*/
TEST_F (Intdifftest, diff_test0) {
EXPECT_EQ(0, cases[0].editdis);
EXPECT_TRUE(cases[0].lcs_v.empty());
ASSERT_EQ(0, cases[0].editdis_ses);
ASSERT_EQ(0, cases[0].editdis_uni);
}
TEST_F (Intdifftest, diff_test1) {
EXPECT_EQ(1, cases[1].editdis);
EXPECT_TRUE(cases[1].lcs_v.empty());
ASSERT_EQ(0, cases[1].editdis_ses);
ASSERT_EQ(0, cases[1].editdis_uni);
}
TEST_F (Intdifftest, diff_test2) {
EXPECT_EQ(1, cases[2].editdis);
EXPECT_TRUE(cases[2].lcs_v.empty());
ASSERT_EQ(0, cases[2].editdis_ses);
ASSERT_EQ(0, cases[2].editdis_uni);
}
TEST_F (Intdifftest, diff_test3) {
EXPECT_EQ(8, cases[3].editdis);
EXPECT_EQ(3, cases[3].lcs_v[0]);
EXPECT_EQ(4, cases[3].lcs_v[1]);
EXPECT_EQ(5, cases[3].lcs_v[2]);
EXPECT_EQ(7, cases[3].lcs_v[3]);
EXPECT_EQ(9, cases[3].lcs_v[4]);
ASSERT_EQ(0, cases[3].editdis_ses);
ASSERT_EQ(0, cases[3].editdis_uni);
}
TEST_F (Intdifftest, diff_test4) {
EXPECT_EQ(4, cases[4].editdis);
EXPECT_EQ(3, cases[4].lcs_v[0]);
EXPECT_EQ(4, cases[4].lcs_v[1]);
EXPECT_EQ(5, cases[4].lcs_v[2]);
ASSERT_EQ(0, cases[4].editdis_ses);
ASSERT_EQ(0, cases[4].editdis_uni);
}

View File

@ -1,116 +0,0 @@
#include "dtl_test_common.hpp"
#include "comparators.hpp"
class Objdifftest : public ::testing::Test
{
protected :
dtl_test_typedefs(string, vector<elem>)
typedef struct case_t {
sequence A;
sequence B;
sesElemVec expected;
sesElemVec ses_seq;
} case_t;
typedef vector< case_t > caseVec;
caseVec obj_diff_cases;
template < typename comparator >
case_t createCase (const sequence a, const sequence b, sesElemVec ses, string test_name) {
case_t c;
elemVec lcs_v;
string diff_name("objdiff");
Diff< elem, sequence, comparator > diff(a, b, true);
diff.compose();
c.A = a;
c.B = b;
c.ses_seq = diff.getSes().getSequence();
c.expected = ses;
return c;
}
void SetUp(void) {
{
string array1[] = {"the", "quick", "brown"};
string array2[] = {"The", "Quick", "Fox"};
sequence A(array1, array1 + (sizeof(array1) / sizeof(array1[0])));
sequence B(array2, array2 + (sizeof(array2) / sizeof(array2[0])));
dtl::Ses< elem > ses;
ses.addSequence("the", 1, 1, dtl::SES_COMMON);
ses.addSequence("quick", 2, 2, dtl::SES_COMMON);
ses.addSequence("brown", 3, 0, dtl::SES_DELETE);
ses.addSequence("Fox", 0, 3, dtl::SES_ADD);
obj_diff_cases.push_back(createCase< StringCaseInsensitive >(A, B, ses.getSequence(), "objdiff_test0_pattern"));
}
{
string array1[] = {"b", "c", "e", "g"};
string array2[] = {"a", "d", "e", "f", "h"};
sequence A(array1, array1 + (sizeof(array1) / sizeof(array1[0])));
sequence B(array2, array2 + (sizeof(array2) / sizeof(array2[0])));
dtl::Ses< elem > ses;
ses.addSequence("b", 1, 0, dtl::SES_DELETE);
ses.addSequence("c", 2, 0, dtl::SES_DELETE);
ses.addSequence("a", 0, 1, dtl::SES_ADD);
ses.addSequence("d", 0, 2, dtl::SES_ADD);
ses.addSequence("e", 3, 3, dtl::SES_COMMON);
ses.addSequence("g", 4, 0, dtl::SES_DELETE);
ses.addSequence("f", 0, 4, dtl::SES_ADD);
ses.addSequence("h", 0, 5, dtl::SES_ADD);
obj_diff_cases.push_back(createCase< StringCaseInsensitive >(A, B, ses.getSequence(), "objdiff_test1_unswapped"));
}
{
string array1[] = {"a", "d", "e", "f", "h"};
string array2[] = {"b", "c", "e", "g"};
sequence A(array1, array1 + (sizeof(array1) / sizeof(array1[0])));
sequence B(array2, array2 + (sizeof(array2) / sizeof(array2[0])));
dtl::Ses< elem > ses;
ses.addSequence("a", 1, 0, dtl::SES_DELETE);
ses.addSequence("d", 2, 0, dtl::SES_DELETE);
ses.addSequence("b", 0, 1, dtl::SES_ADD);
ses.addSequence("c", 0, 2, dtl::SES_ADD);
ses.addSequence("e", 3, 3, dtl::SES_COMMON);
ses.addSequence("f", 4, 0, dtl::SES_DELETE);
ses.addSequence("h", 5, 0, dtl::SES_DELETE);
ses.addSequence("g", 0, 4, dtl::SES_ADD);
obj_diff_cases.push_back(createCase< StringCaseInsensitive >(A, B, ses.getSequence(), "objdiff_test2_swapped"));
}
}
void TearDown () {
//for_each(obj_diff_cases.begin(), obj_diff_cases.end(), Remover< case_t >());
}
};
/**
* Objdifftest
* check list:
* - SES pattern "SES_COMMON, SES_DELETE, SES_ADD"
* - Indepence of results from swapping
*/
TEST_F (Objdifftest, objdiff_test0_pattern) {
EXPECT_EQ(obj_diff_cases[0].expected, obj_diff_cases[0].ses_seq);
}
TEST_F (Objdifftest, objdiff_test1_unswapped) {
EXPECT_EQ(obj_diff_cases[1].expected, obj_diff_cases[1].ses_seq);
}
TEST_F (Objdifftest, objdiff_test2_swapped) {
EXPECT_EQ(obj_diff_cases[2].expected, obj_diff_cases[2].ses_seq);
}

View File

@ -1,98 +0,0 @@
#include "dtl_test_common.hpp"
class Patchtest : public ::testing::Test
{
protected :
dtl_test_typedefs(char, string)
typedef struct case_t {
sequence A;
sequence B;
Diff< elem, sequence > diff;
} case_t;
typedef vector< case_t > caseVec;
caseVec cases;
case_t createCase (sequence a, sequence b) {
case_t c;
c.A = a;
c.B = b;
c.diff = Diff< elem, sequence >(a, b);
c.diff.compose();
c.diff.composeUnifiedHunks();
return c;
}
void SetUp() {
cases.push_back(createCase("abc", "abd")); // 0
cases.push_back(createCase("acbdeacbed", "acebdabbabed")); // 1
cases.push_back(createCase("abcdef", "dacfea")); // 2
cases.push_back(createCase("abcbda", "bdcaba")); // 3
cases.push_back(createCase("bokko", "bokkko")); // 4
cases.push_back(createCase("", "")); // 5
cases.push_back(createCase("a", "")); // 6
cases.push_back(createCase("", "b")); // 7
cases.push_back(createCase("abcdefq3wefarhgorequgho4euhfteowauhfwehogfewrquhoi23hroewhoahfotrhguoiewahrgqqabcdef",
"3abcdef4976fd86ouofita67t85r876e5e746578tgliuhopoqqabcdef")); // 8
cases.push_back(createCase("abcqqqeqqqccc", "abdqqqeqqqddd")); // 9
}
void TearDown () {}
};
/**
* Patchtest
* check list is following
* - patch function
* - uniPatch function
*/
TEST_F (Patchtest, patch_test0) {
ASSERT_EQ(cases[0].B, cases[0].diff.patch(cases[0].A));
ASSERT_EQ(cases[0].B, cases[0].diff.uniPatch(cases[0].A));
}
TEST_F (Patchtest, patch_test1) {
ASSERT_EQ(cases[1].B, cases[1].diff.patch(cases[1].A));
ASSERT_EQ(cases[1].B, cases[1].diff.uniPatch(cases[1].A));
}
TEST_F (Patchtest, patch_test2) {
ASSERT_EQ(cases[2].B, cases[2].diff.patch(cases[2].A));
ASSERT_EQ(cases[2].B, cases[2].diff.uniPatch(cases[2].A));
}
TEST_F (Patchtest, patch_test3) {
ASSERT_EQ(cases[3].B, cases[3].diff.patch(cases[3].A));
ASSERT_EQ(cases[3].B, cases[3].diff.uniPatch(cases[3].A));
}
TEST_F (Patchtest, patch_test4) {
ASSERT_EQ(cases[4].B, cases[4].diff.patch(cases[4].A));
ASSERT_EQ(cases[4].B, cases[4].diff.uniPatch(cases[4].A));
}
TEST_F (Patchtest, patch_test5) {
ASSERT_EQ(cases[5].B, cases[5].diff.patch(cases[5].A));
ASSERT_EQ(cases[5].B, cases[5].diff.uniPatch(cases[5].A));
}
TEST_F (Patchtest, patch_test6) {
ASSERT_EQ(cases[6].B, cases[6].diff.patch(cases[6].A));
ASSERT_EQ(cases[6].B, cases[6].diff.uniPatch(cases[6].A));
}
TEST_F (Patchtest, patch_test7) {
ASSERT_EQ(cases[7].B, cases[7].diff.patch(cases[7].A));
ASSERT_EQ(cases[7].B, cases[7].diff.uniPatch(cases[7].A));
}
TEST_F (Patchtest, patch_test8) {
ASSERT_EQ(cases[8].B, cases[8].diff.patch(cases[8].A));
ASSERT_EQ(cases[8].B, cases[8].diff.uniPatch(cases[8].A));
}
TEST_F (Patchtest, patch_test9) {
ASSERT_EQ(cases[9].B, cases[9].diff.patch(cases[9].A));
ASSERT_EQ(cases[9].B, cases[9].diff.uniPatch(cases[9].A));
}

View File

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

View File

@ -1,208 +0,0 @@
#include "dtl_test_common.hpp"
#include "comparators.hpp"
class Strdiff3test : public ::testing::Test
{
protected :
dtl_test_typedefs(char, string)
typedef struct case_t {
sequence S;
bool is_merge_success;
sequence merged_seq;
} case_t;
typedef vector< case_t > caseVec;
caseVec merge_cases;
caseVec detect_cases;
caseVec custom_cases;
template < typename comparator >
case_t createCase (sequence a, sequence b, sequence c, sequence s) {
Diff3< elem, sequence, comparator > diff3(a, b, c);
case_t ct;
diff3.compose();
ct.S = s;
ct.is_merge_success = diff3.merge();
ct.merged_seq = diff3.getMergedSequence();
return ct;
}
void SetUp() {
// merge test
merge_cases.push_back(createCase< Compare < elem > >("ab", "b", "bc", "abc")); // 0
merge_cases.push_back(createCase< Compare < elem > >("bc", "b", "ab", "abc")); // 1
merge_cases.push_back(createCase< Compare < elem > >("qqqabc", "abc", "abcdef", "qqqabcdef")); // 2
merge_cases.push_back(createCase< Compare < elem > >("abcdef", "abc", "qqqabc", "qqqabcdef")); // 3
merge_cases.push_back(createCase< Compare < elem > >("aaacccbbb", "aaabbb", "aaabbbqqq", "aaacccbbbqqq")); // 4
merge_cases.push_back(createCase< Compare < elem > >("aaabbbqqq", "aaabbb", "aaacccbbb", "aaacccbbbqqq")); // 5
merge_cases.push_back(createCase< Compare < elem > >("aeaacccbbb", "aaabbb", "aaabbbqqq", "aeaacccbbbqqq")); // 6
merge_cases.push_back(createCase< Compare < elem > >("aaabbbqqq", "aaabbb", "aeaacccbbb", "aeaacccbbbqqq")); // 7
merge_cases.push_back(createCase< Compare < elem > >("aeaacccbbb", "aaabbb", "aaabebbqqq", "aeaacccbebbqqq")); // 8
merge_cases.push_back(createCase< Compare < elem > >("aaabebbqqq", "aaabbb", "aeaacccbbb", "aeaacccbebbqqq")); // 9
merge_cases.push_back(createCase< Compare < elem > >("aaacccbbb", "aaabbb", "aeaabbbqqq", "aeaacccbbbqqq")); // 10
merge_cases.push_back(createCase< Compare < elem > >("aeaabbbqqq", "aaabbb", "aaacccbbb", "aeaacccbbbqqq")); // 11
merge_cases.push_back(createCase< Compare < elem > >("aaacccbbb", "aaabbb", "aaabeebbeeqqq","aaacccbeebbeeqqq")); // 12
merge_cases.push_back(createCase< Compare < elem > >("aaabeebbeeqqq", "aaabbb", "aaacccbbb", "aaacccbeebbeeqqq")); // 13
merge_cases.push_back(createCase< Compare < elem > >("aiueo", "aeo", "aeKokaki", "aiueKokaki")); // 14
merge_cases.push_back(createCase< Compare < elem > >("aeKokaki", "aeo", "aiueo", "aiueKokaki")); // 15
merge_cases.push_back(createCase< Compare < elem > >("1234567390", "1234567890", "1239567890", "1239567390")); // 16
merge_cases.push_back(createCase< Compare < elem > >("1239567890", "1234567890", "1234567390", "1239567390")); // 17
merge_cases.push_back(createCase< Compare < elem > >("qabcdef", "abcdef", "ab", "qab")); // 18
merge_cases.push_back(createCase< Compare < elem > >("ab", "abcdef", "qabcdef", "qab")); // 19
merge_cases.push_back(createCase< Compare < elem > >("abcdf", "abcdef", "acdef", "acdf")); // 20
merge_cases.push_back(createCase< Compare < elem > >("acdef", "abcdef", "abcdf", "acdf")); // 21
merge_cases.push_back(createCase< Compare < elem > >("acdef", "abcdef", "abcdfaa", "acdfaa")); // 22
merge_cases.push_back(createCase< Compare < elem > >("abcdfaa", "abcdef", "acdef", "acdfaa")); // 23
// detect confliction test
detect_cases.push_back(createCase< Compare < elem > >("adc", "abc", "aec", "")); // 0
detect_cases.push_back(createCase< Compare < elem > >("abqdcf", "abcdef", "abqqef", "")); // 1
// use custom comparator
custom_cases.push_back(createCase< CaseInsensitive >("abc", "abc", "abC", "abc"));
}
void TearDown () {}
};
/**
* Strdiff3test
* check list is following
* - merge function
* - detect confliction
*/
TEST_F (Strdiff3test, merge_test0) {
ASSERT_TRUE(merge_cases[0].is_merge_success);
ASSERT_EQ(merge_cases[0].S, merge_cases[0].merged_seq);
}
TEST_F (Strdiff3test, merge_test1) {
ASSERT_TRUE(merge_cases[1].is_merge_success);
ASSERT_EQ(merge_cases[1].S, merge_cases[1].merged_seq);
}
TEST_F (Strdiff3test, merge_test2) {
ASSERT_TRUE(merge_cases[2].is_merge_success);
ASSERT_EQ(merge_cases[2].S, merge_cases[2].merged_seq);
}
TEST_F (Strdiff3test, merge_test3) {
ASSERT_TRUE(merge_cases[3].is_merge_success);
ASSERT_EQ(merge_cases[3].S, merge_cases[3].merged_seq);
}
TEST_F (Strdiff3test, merge_test4) {
ASSERT_TRUE(merge_cases[4].is_merge_success);
ASSERT_EQ(merge_cases[4].S, merge_cases[4].merged_seq);
}
TEST_F (Strdiff3test, merge_test5) {
ASSERT_TRUE(merge_cases[5].is_merge_success);
ASSERT_EQ(merge_cases[5].S, merge_cases[5].merged_seq);
}
TEST_F (Strdiff3test, merge_test6) {
ASSERT_TRUE(merge_cases[6].is_merge_success);
ASSERT_EQ(merge_cases[6].S, merge_cases[6].merged_seq);
}
TEST_F (Strdiff3test, merge_test7) {
ASSERT_TRUE(merge_cases[7].is_merge_success);
ASSERT_EQ(merge_cases[7].S, merge_cases[7].merged_seq);
}
TEST_F (Strdiff3test, merge_test8) {
ASSERT_TRUE(merge_cases[8].is_merge_success);
ASSERT_EQ(merge_cases[8].S, merge_cases[8].merged_seq);
}
TEST_F (Strdiff3test, merge_test9) {
ASSERT_TRUE(merge_cases[9].is_merge_success);
ASSERT_EQ(merge_cases[9].S, merge_cases[9].merged_seq);
}
TEST_F (Strdiff3test, merge_test10) {
ASSERT_TRUE(merge_cases[10].is_merge_success);
ASSERT_EQ(merge_cases[10].S, merge_cases[10].merged_seq);
}
TEST_F (Strdiff3test, merge_test11) {
ASSERT_TRUE(merge_cases[11].is_merge_success);
ASSERT_EQ(merge_cases[11].S, merge_cases[11].merged_seq);
}
TEST_F (Strdiff3test, merge_test12) {
ASSERT_TRUE(merge_cases[12].is_merge_success);
ASSERT_EQ(merge_cases[12].S, merge_cases[12].merged_seq);
}
TEST_F (Strdiff3test, merge_test13) {
ASSERT_TRUE(merge_cases[13].is_merge_success);
ASSERT_EQ(merge_cases[13].S, merge_cases[13].merged_seq);
}
TEST_F (Strdiff3test, merge_test14) {
ASSERT_TRUE(merge_cases[14].is_merge_success);
ASSERT_EQ(merge_cases[14].S, merge_cases[14].merged_seq);
}
TEST_F (Strdiff3test, merge_test15) {
ASSERT_TRUE(merge_cases[15].is_merge_success);
ASSERT_EQ(merge_cases[15].S, merge_cases[15].merged_seq);
}
TEST_F (Strdiff3test, merge_test16) {
ASSERT_TRUE(merge_cases[16].is_merge_success);
ASSERT_EQ(merge_cases[16].S, merge_cases[16].merged_seq);
}
TEST_F (Strdiff3test, merge_test17) {
ASSERT_TRUE(merge_cases[17].is_merge_success);
ASSERT_EQ(merge_cases[17].S, merge_cases[17].merged_seq);
}
TEST_F (Strdiff3test, merge_test18) {
ASSERT_TRUE(merge_cases[18].is_merge_success);
ASSERT_EQ(merge_cases[18].S, merge_cases[18].merged_seq);
}
TEST_F (Strdiff3test, merge_test19) {
ASSERT_TRUE(merge_cases[19].is_merge_success);
ASSERT_EQ(merge_cases[19].S, merge_cases[19].merged_seq);
}
TEST_F (Strdiff3test, merge_test20) {
ASSERT_TRUE(merge_cases[20].is_merge_success);
ASSERT_EQ(merge_cases[20].S, merge_cases[20].merged_seq);
}
TEST_F (Strdiff3test, merge_test21) {
ASSERT_TRUE(merge_cases[21].is_merge_success);
ASSERT_EQ( merge_cases[21].S, merge_cases[21].merged_seq);
}
TEST_F (Strdiff3test, merge_test22) {
ASSERT_TRUE(merge_cases[22].is_merge_success);
ASSERT_EQ( merge_cases[22].S, merge_cases[22].merged_seq);
}
TEST_F (Strdiff3test, merge_test23) {
ASSERT_TRUE(merge_cases[23].is_merge_success);
ASSERT_EQ(merge_cases[23].S, merge_cases[23].merged_seq);
}
TEST_F (Strdiff3test, detect_confliction_test0) {
ASSERT_FALSE(detect_cases[0].is_merge_success);
}
TEST_F (Strdiff3test, detect_confliction_test1) {
ASSERT_FALSE(detect_cases[1].is_merge_success);
}
TEST_F (Strdiff3test, custom_comparator_test0) {
ASSERT_TRUE(custom_cases[0].is_merge_success);
ASSERT_EQ(custom_cases[0].S, custom_cases[0].merged_seq);
}

View File

@ -1,299 +0,0 @@
#include "dtl_test_common.hpp"
#include "comparators.hpp"
class Strdifftest : public ::testing::Test
{
protected :
dtl_test_typedefs(char, string)
typedef struct case_t {
sequence A;
sequence B;
size_t editdis;
elemVec lcs_v;
sequence lcs_s;
sesElemVec ses_seq;
uniHunkVec hunk_v;
size_t editdis_ses;
size_t editdis_uni;
string path_rses;
string path_rhunks;
} case_t;
typedef vector< case_t > caseVec;
caseVec diff_cases;
caseVec only_editdis_cases;
caseVec custom_cases;
template < typename comparator >
case_t createCase (const sequence a, const sequence b, string test_name, bool onlyEditdis = false) {
case_t c;
elemVec lcs_v;
string diff_name("strdiff");
Diff< elem, sequence, comparator > diff(a, b);
if (onlyEditdis) {
diff.onOnlyEditDistance();
}
diff.compose();
diff.composeUnifiedHunks();
lcs_v = diff.getLcsVec();
if (test_name != "") {
string path_lses = create_path(test_name, diff_name, TYPE_DIFF_SES);
string path_rses = create_path(test_name, diff_name, TYPE_DIFF_SES, true);
string path_lhunks = create_path(test_name, diff_name, TYPE_DIFF_UNI);
string path_rhunks = create_path(test_name, diff_name, TYPE_DIFF_UNI, true);
diff_resultset_exist_check(path_lses);
diff_resultset_exist_check(path_lhunks);
create_file< elem, sequence, comparator >(path_rses, diff, TYPE_DIFF_SES);
create_file< elem, sequence, comparator >(path_rhunks, diff, TYPE_DIFF_UNI);
c.editdis_ses = cal_diff_uni(path_lses, path_rses);
c.editdis_uni = cal_diff_uni(path_lhunks, path_rhunks);
c.path_rses = path_rses;
c.path_rhunks = path_rhunks;
}
c.A = a;
c.B = b;
c.editdis = diff.getEditDistance();
c.lcs_s = sequence(lcs_v.begin(), lcs_v.end());
c.ses_seq = diff.getSes().getSequence();
c.hunk_v = diff.getUniHunks();
return c;
}
void SetUp(void) {
diff_cases.push_back(createCase< Compare< elem > >("abc", "abd", "diff_test0"));
diff_cases.push_back(createCase< Compare< elem > >("acbdeacbed", "acebdabbabed", "diff_test1"));
diff_cases.push_back(createCase< Compare< elem > >("abcdef", "dacfea", "diff_test2"));
diff_cases.push_back(createCase< Compare< elem > >("abcbda", "bdcaba", "diff_test3"));
diff_cases.push_back(createCase< Compare< elem > >("bokko", "bokkko", "diff_test4"));
diff_cases.push_back(createCase< Compare< elem > >("", "", "diff_test5"));
diff_cases.push_back(createCase< Compare< elem > >("a", "", "diff_test6"));
diff_cases.push_back(createCase< Compare< elem > >("", "b", "diff_test7"));
diff_cases.push_back(createCase< Compare< elem > >("acbdeaqqqqqqqcbed", "acebdabbqqqqqqqabed", "diff_test8"));
only_editdis_cases.push_back(createCase< Compare< elem > >("abc", "abd", "", true));
only_editdis_cases.push_back(createCase< Compare< elem > >("acbdeacbed", "acebdabbabed", "", true));
only_editdis_cases.push_back(createCase< Compare< elem > >("abcdef", "dacfea", "", true));
only_editdis_cases.push_back(createCase< Compare< elem > >("abcbda", "bdcaba", "", true));
only_editdis_cases.push_back(createCase< Compare< elem > >("bokko", "bokkko", "", true));
only_editdis_cases.push_back(createCase< Compare< elem > >("", "", "", true));
only_editdis_cases.push_back(createCase< Compare< elem > >("a", "", "", true));
only_editdis_cases.push_back(createCase< Compare< elem > >("", "b", "", true));
only_editdis_cases.push_back(createCase< Compare< elem > >("acbdeaqqqqqqqcbed", "acebdabbqqqqqqqabed", "", true));
custom_cases.push_back(createCase< CaseInsensitive >("abc", "Abc", "custom_test0"));
}
void TearDown () {
for_each(diff_cases.begin(), diff_cases.end(), Remover< case_t >());
for_each(custom_cases.begin(), custom_cases.end(), Remover< case_t >());
}
};
/**
* Strdifftest
* check list is following
* - editdistance
* - LCS
* - SES
* - Unified Format Difference
* - onOnlyEditDistance
*/
TEST_F (Strdifftest, diff_test0) {
EXPECT_EQ(2, diff_cases[0].editdis);
EXPECT_EQ("ab", diff_cases[0].lcs_s);
ASSERT_EQ(0, diff_cases[0].editdis_ses);
ASSERT_EQ(0, diff_cases[0].editdis_uni);
}
TEST_F (Strdifftest, diff_test1) {
EXPECT_EQ(6, diff_cases[1].editdis);
EXPECT_EQ("acbdabed", diff_cases[1].lcs_s);
ASSERT_EQ(0, diff_cases[1].editdis_ses);
ASSERT_EQ(0, diff_cases[1].editdis_uni);
}
TEST_F (Strdifftest, diff_test2) {
EXPECT_EQ(6, diff_cases[2].editdis);
EXPECT_EQ("acf", diff_cases[2].lcs_s);
ASSERT_EQ(0, diff_cases[2].editdis_ses);
ASSERT_EQ(0, diff_cases[2].editdis_uni);
}
TEST_F (Strdifftest, diff_test3) {
EXPECT_EQ(4, diff_cases[3].editdis);
EXPECT_EQ("bcba", diff_cases[3].lcs_s);
ASSERT_EQ(0, diff_cases[3].editdis_ses);
ASSERT_EQ(0, diff_cases[3].editdis_uni);
}
TEST_F (Strdifftest, diff_test4) {
EXPECT_EQ(1, diff_cases[4].editdis);
EXPECT_EQ("bokko", diff_cases[4].lcs_s);
ASSERT_EQ(0, diff_cases[4].editdis_ses);
ASSERT_EQ(0, diff_cases[4].editdis_uni);
}
TEST_F (Strdifftest, diff_test5) {
EXPECT_EQ(0, diff_cases[5].editdis);
EXPECT_EQ("", diff_cases[5].lcs_s);
ASSERT_EQ(0, diff_cases[5].editdis_ses);
ASSERT_EQ(0, diff_cases[5].editdis_uni);
}
TEST_F (Strdifftest, diff_test6) {
EXPECT_EQ(1, diff_cases[6].editdis);
EXPECT_EQ("", diff_cases[6].lcs_s);
ASSERT_EQ(0, diff_cases[6].editdis_ses);
ASSERT_EQ(0, diff_cases[6].editdis_uni);
}
TEST_F (Strdifftest, diff_test7) {
EXPECT_EQ(1, diff_cases[7].editdis);
EXPECT_EQ("", diff_cases[7].lcs_s);
ASSERT_EQ(0, diff_cases[7].editdis_ses);
ASSERT_EQ(0, diff_cases[7].editdis_uni);
}
TEST_F (Strdifftest, diff_test8) {
EXPECT_EQ(6, diff_cases[8].editdis);
EXPECT_EQ("acbdaqqqqqqqbed", diff_cases[8].lcs_s);
ASSERT_EQ(0, diff_cases[8].editdis_ses);
ASSERT_EQ(0, diff_cases[8].editdis_uni);
}
TEST_F (Strdifftest, only_editdis_test0) {
EXPECT_EQ(2, only_editdis_cases[0].editdis);
EXPECT_EQ("", only_editdis_cases[0].lcs_s);
ASSERT_TRUE(only_editdis_cases[0].ses_seq.empty());
ASSERT_TRUE(only_editdis_cases[0].hunk_v.empty());
}
TEST_F (Strdifftest, only_editdis_test1) {
EXPECT_EQ(6, only_editdis_cases[1].editdis);
EXPECT_EQ("", only_editdis_cases[1].lcs_s);
ASSERT_TRUE(only_editdis_cases[1].ses_seq.empty());
ASSERT_TRUE(only_editdis_cases[1].hunk_v.empty());
}
TEST_F (Strdifftest, only_editdis_test2) {
EXPECT_EQ(6, only_editdis_cases[2].editdis);
EXPECT_EQ("", only_editdis_cases[2].lcs_s);
ASSERT_TRUE(only_editdis_cases[2].ses_seq.empty());
ASSERT_TRUE(only_editdis_cases[2].hunk_v.empty());
}
TEST_F (Strdifftest, only_editdis_test3) {
EXPECT_EQ(4, only_editdis_cases[3].editdis);
EXPECT_EQ("", only_editdis_cases[3].lcs_s);
ASSERT_TRUE(only_editdis_cases[3].ses_seq.empty());
ASSERT_TRUE(only_editdis_cases[3].hunk_v.empty());
}
TEST_F (Strdifftest, only_editdis_test4) {
EXPECT_EQ(1, only_editdis_cases[4].editdis);
EXPECT_EQ("", only_editdis_cases[4].lcs_s);
ASSERT_TRUE(only_editdis_cases[4].ses_seq.empty());
ASSERT_TRUE(only_editdis_cases[4].hunk_v.empty());
}
TEST_F (Strdifftest, only_editdis_test5) {
EXPECT_EQ(0, only_editdis_cases[5].editdis);
EXPECT_EQ("", only_editdis_cases[5].lcs_s);
ASSERT_TRUE(only_editdis_cases[5].ses_seq.empty());
ASSERT_TRUE(only_editdis_cases[5].hunk_v.empty());
}
TEST_F (Strdifftest, only_editdis_test6) {
EXPECT_EQ(1, only_editdis_cases[6].editdis);
EXPECT_EQ("", only_editdis_cases[6].lcs_s);
ASSERT_TRUE(only_editdis_cases[6].ses_seq.empty());
ASSERT_TRUE(only_editdis_cases[6].hunk_v.empty());
}
TEST_F (Strdifftest, only_editdis_test7) {
EXPECT_EQ(1, only_editdis_cases[7].editdis);
EXPECT_EQ("", only_editdis_cases[7].lcs_s);
ASSERT_TRUE(only_editdis_cases[7].ses_seq.empty());
ASSERT_TRUE(only_editdis_cases[7].hunk_v.empty());
}
TEST_F (Strdifftest, only_editdis_test8) {
EXPECT_EQ(6, only_editdis_cases[8].editdis);
EXPECT_EQ("", only_editdis_cases[8].lcs_s);
ASSERT_TRUE(only_editdis_cases[8].ses_seq.empty());
ASSERT_TRUE(only_editdis_cases[8].hunk_v.empty());
}
TEST_F (Strdifftest, custom_comparator_test0) {
EXPECT_EQ(0, custom_cases[0].editdis);
EXPECT_EQ("abc", custom_cases[0].lcs_s);
ASSERT_EQ(0, custom_cases[0].editdis_ses);
ASSERT_TRUE(custom_cases[0].hunk_v.empty());
}

View File

@ -1,24 +1,25 @@
#ifndef DTL_COMPARATORS
#define DTL_COMPARATORS
class CaseInsensitive: public dtl::Compare<char> {
#include "dtl/functors.hpp"
class CaseInsensitive : public dtl::Compare<char> {
public:
virtual bool impl(const char& a, const char& b) const {
return tolower(a) == tolower(b);
}
virtual bool impl(const char &a, const char &b) const {
return std::tolower(a) == std::tolower(b);
}
};
class StringCaseInsensitive: public dtl::Compare<string> {
class StringCaseInsensitive : public dtl::Compare<std::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;
}
virtual bool impl(const std::string &a, const std::string &b) const {
if (a.length() == b.length()) {
bool equal = (strncasecmp(a.c_str(), b.c_str(), a.length()) == 0);
return equal;
} else {
return false;
}
}
};
#endif // DTL_COMPARATORS

View File

@ -1,10 +1,6 @@
/**
* It is necessary to use googletest to run tests.
*/
#include "dtl_test_common.hpp"
#include <gtest/gtest.h>
int main (int argc, char *argv[]) {
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
int main(int argc, char *argv[]) {
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}

View File

@ -1,56 +1,62 @@
#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;
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());
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;
vector<string> llines;
vector<string> rlines;
while (getline(lifs, buf)) {
llines.push_back(buf);
}
while (getline(lifs, buf)) {
llines.push_back(buf);
}
while (getline(rifs, buf)) {
rlines.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();
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;
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);
}
void diff_resultset_exist_check(string &fs) {
if (!is_file_exist(fs)) {
cerr << "======================================================Error!!!===="
"=================================================="
<< endl;
cerr << "diff result set:" << fs << " is not found." << endl;
cerr << "======================================================Error!!!===="
"=================================================="
<< endl;
cerr << "excute dtl_test in dtl/test!" << endl;
exit(EXIT_FAILURE);
}
}

View File

@ -1,70 +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>
#include <gtest/gtest.h>
#include "dtl/dtl.hpp"
#include "comparators.hpp"
using std::cerr;
using std::endl;
using std::string;
using std::vector;
using std::pair;
using std::ifstream;
using std::ofstream;
using std::pair;
using std::string;
using std::vector;
using dtl::Compare;
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::SES_ADD;
using dtl::SES_COMMON;
using dtl::SES_DELETE;
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;
#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);
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 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();
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

141
test/int_diff_test.cpp Normal file
View File

@ -0,0 +1,141 @@
#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);
}

117
test/obj_diff_test.cpp Normal file
View File

@ -0,0 +1,117 @@
#include "dtl_test_common.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);
}

157
test/patch_test.cpp Normal file
View File

@ -0,0 +1,157 @@
#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(
"abcdefq3wefarhgorequgho4euhfteowauhfwehogfewrquhoi23hroewhoahfotrhguoi"
"ewahrgqqabcdef",
"3abcdef4976fd86ouofita67t85r876e5e746578tgliuhopoqqabcdef")); // 8
cases.push_back(createCase("abcqqqeqqqccc", "abdqqqeqqqddd")); // 9
cases.push_back(createCase(
"aaaaaaaaaaaaa>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"
">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"
">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"
">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"
">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"
">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"
">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"
">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"
">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"
">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"
">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"
">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"
">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"
">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"
">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"
">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"
">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"
">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"
">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"
">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"
">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"
">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"
">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"
">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"
">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"
">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"
">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"
">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"
">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"
">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"
">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"
">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"
">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"
"aaaadsafabcaaaaaaaaaaaaaaaaaaewaaabdaaaaaabbb",
"aaaaaaaaaaaaaaadasfdsafsadasdafbaaaaaaaaaaaaaaaaaeaaaaaaaaaae&&&&&&&&&"
"&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&"
"&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&"
"&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&"
"&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&"
"&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&"
"&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&"
"&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&"
"&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&"
"&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&"
"&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&"
"&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&"
"&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&"
"&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&"
"&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&"
"&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&"
"&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&"
"&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&"
"&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&"
"&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&saaabcaaaaaaccc")); // 10
}
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));
}
TEST_F(Patchtest, patch_test10) {
ASSERT_EQ(cases[10].B, cases[10].diff.patch(cases[10].A));
ASSERT_EQ(cases[10].B, cases[10].diff.uniPatch(cases[10].A));
}

231
test/str_diff3_test.cpp Normal file
View File

@ -0,0 +1,231 @@
#include "dtl_test_common.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);
}

309
test/str_diff_test.cpp Normal file
View File

@ -0,0 +1,309 @@
#include "dtl_test_common.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());
}