From 2d536772bad73de8cebcc7d5c88338f0fa3c9bd0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=ADn=20Lucas=20Golini?= Date: Tue, 24 Mar 2026 15:51:26 -0300 Subject: [PATCH] UIDiffView: Highlight sub-line differences. --- include/eepp/ui/tools/uidiffview.hpp | 2 + src/eepp/ui/tools/uidiffview.cpp | 101 ++- .../dtl.hpp => src/thirdparty/dtl/Diff.hpp | 720 ++---------------- src/thirdparty/dtl/Diff3.hpp | 245 ++++++ src/thirdparty/dtl/Lcs.hpp | 55 ++ src/thirdparty/dtl/Sequence.hpp | 65 ++ src/thirdparty/dtl/Ses.hpp | 132 ++++ src/thirdparty/dtl/dtl.hpp | 47 ++ src/thirdparty/dtl/functors.hpp | 151 ++++ src/thirdparty/dtl/variables.hpp | 142 ++++ 10 files changed, 1007 insertions(+), 653 deletions(-) rename include/eepp/thirdparty/dtl/dtl.hpp => src/thirdparty/dtl/Diff.hpp (57%) create mode 100644 src/thirdparty/dtl/Diff3.hpp create mode 100644 src/thirdparty/dtl/Lcs.hpp create mode 100644 src/thirdparty/dtl/Sequence.hpp create mode 100644 src/thirdparty/dtl/Ses.hpp create mode 100644 src/thirdparty/dtl/dtl.hpp create mode 100644 src/thirdparty/dtl/functors.hpp create mode 100644 src/thirdparty/dtl/variables.hpp diff --git a/include/eepp/ui/tools/uidiffview.hpp b/include/eepp/ui/tools/uidiffview.hpp index e0658b9fa..0dd2c1d61 100644 --- a/include/eepp/ui/tools/uidiffview.hpp +++ b/include/eepp/ui/tools/uidiffview.hpp @@ -34,6 +34,7 @@ class EE_API UIDiffView : public UIWidget { String text; Int64 oldLineNum{ 0 }; Int64 newLineNum{ 0 }; + std::vector subLineChanges; }; const std::vector& getDiffLines() const { return mLines; } @@ -63,6 +64,7 @@ class EE_API UIDiffView : public UIWidget { void createEditor( UICodeEditor*& editor, std::unique_ptr& plugin ); void syncScroll( UICodeEditor* source, UICodeEditor* target, bool emitEvent = false ); void updateModeButton(); + void computeSubLineDiff( DiffLine& oldLine, DiffLine& newLine ); }; }}} // namespace EE::UI::Tools diff --git a/src/eepp/ui/tools/uidiffview.cpp b/src/eepp/ui/tools/uidiffview.cpp index 43bc4cc9d..fff036309 100644 --- a/src/eepp/ui/tools/uidiffview.cpp +++ b/src/eepp/ui/tools/uidiffview.cpp @@ -3,27 +3,30 @@ #include #include #include -#include #include #include #include #include #include +#include + namespace EE { namespace UI { namespace Tools { class UIDiffEditorPlugin : public UICodeEditorPlugin { public: UIDiffEditorPlugin( UIDiffView* view ) : mView( view ) {} - inline Color getBackgroundColor( UIDiffView::DiffLineType type ) { + inline Color getBackgroundColor( UIDiffView::DiffLineType type, bool isHighlight = false ) { + static constexpr auto NORMAL_ALPHA = 40; + static constexpr auto HIGHLIGHT_ALPHA = 80; switch ( type ) { case UIDiffView::DiffLineType::Added: - return Color( 0, 150, 32, 30 ); + return Color( 0, 150, 32, isHighlight ? HIGHLIGHT_ALPHA : NORMAL_ALPHA ); case UIDiffView::DiffLineType::Removed: - return Color( 180, 0, 32, 30 ); + return Color( 180, 0, 32, isHighlight ? HIGHLIGHT_ALPHA : NORMAL_ALPHA ); case UIDiffView::DiffLineType::Header: - return Color( 100, 100, 100, 30 ); + return Color( 100, 100, 100, isHighlight ? HIGHLIGHT_ALPHA : NORMAL_ALPHA ); case UIDiffView::DiffLineType::Common: break; } @@ -62,6 +65,24 @@ class UIDiffEditorPlugin : public UICodeEditorPlugin { p.setColor( bgColor ); p.drawRectangle( Rectf( Vector2f( editor->getScreenPos().x, position.y ), Sizef( editor->getPixelsSize().getWidth(), lineHeight ) ) ); + + if ( !line.subLineChanges.empty() ) { + p.setColor( getBackgroundColor( line.type, true ) ); + + for ( const auto& range : line.subLineChanges ) { + Vector2f startPos = + editor + ->getTextPositionOffset( { index, range.start().column() }, lineHeight ) + .asFloat(); + + Vector2f endPos = + editor->getTextPositionOffset( { index, range.end().column() }, lineHeight ) + .asFloat(); + + p.drawRectangle( Rectf( { position.x + startPos.x, position.y }, + { endPos.x - startPos.x, lineHeight } ) ); + } + } } } @@ -250,6 +271,68 @@ void UIDiffView::onSizeChange() { updateModeButton(); } +void UIDiffView::computeSubLineDiff( DiffLine& oldLine, DiffLine& newLine ) { + dtl::Diff diff( oldLine.text.view(), + newLine.text.view() ); + diff.compose(); + auto ses = diff.getSes().getSequence(); + + Int64 oldIdx = 0; + Int64 newIdx = 0; + for ( const auto& pair : ses ) { + switch ( pair.second.type ) { + case dtl::SES_COMMON: + oldIdx++; + newIdx++; + break; + case dtl::SES_ADD: + if ( !newLine.subLineChanges.empty() && + newLine.subLineChanges.back().end().column() == newIdx ) { + newLine.subLineChanges.back().setEnd( { 0, newIdx + 1 } ); + } else { + newLine.subLineChanges.push_back( { { 0, newIdx }, { 0, newIdx + 1 } } ); + } + newIdx++; + break; + case dtl::SES_DELETE: + if ( !oldLine.subLineChanges.empty() && + oldLine.subLineChanges.back().end().column() == oldIdx ) { + oldLine.subLineChanges.back().setEnd( { 0, oldIdx + 1 } ); + } else { + oldLine.subLineChanges.push_back( { { 0, oldIdx }, { 0, oldIdx + 1 } } ); + } + oldIdx++; + break; + } + } +} + +static void applySubLineDiff( + std::vector& lines, + std::function computeSubLineDiff ) { + size_t i = 0; + while ( i < lines.size() ) { + if ( lines[i].type == UIDiffView::DiffLineType::Removed ) { + size_t j = i; + while ( j < lines.size() && lines[j].type == UIDiffView::DiffLineType::Removed ) + j++; + size_t k = j; + while ( k < lines.size() && lines[k].type == UIDiffView::DiffLineType::Added ) + k++; + + size_t numRemoved = j - i; + size_t numAdded = k - j; + size_t numToCompare = std::min( numRemoved, numAdded ); + for ( size_t m = 0; m < numToCompare; m++ ) { + computeSubLineDiff( lines[i + m], lines[j + m] ); + } + i = k; + } else { + i++; + } + } +} + void UIDiffView::loadFromPatch( const std::string& patchText ) { mLines.clear(); auto lines = String::split( patchText, '\n' ); @@ -334,6 +417,10 @@ void UIDiffView::loadFromPatch( const std::string& patchText ) { mLines.push_back( dline ); } + applySubLineDiff( mLines, [this]( DiffLine& oldLine, DiffLine& newLine ) { + computeSubLineDiff( oldLine, newLine ); + } ); + mEditor->getDocument().reset(); mEditor->getDocument().textInput( cleanText ); mLeftEditor->getDocument().reset(); @@ -396,6 +483,10 @@ void UIDiffView::loadFromStrings( const std::string& oldText, const std::string& mLines.push_back( dline ); } + applySubLineDiff( mLines, [this]( DiffLine& oldLine, DiffLine& newLine ) { + computeSubLineDiff( oldLine, newLine ); + } ); + mEditor->getDocument().reset(); mEditor->getDocument().textInput( cleanText ); mLeftEditor->getDocument().reset(); diff --git a/include/eepp/thirdparty/dtl/dtl.hpp b/src/thirdparty/dtl/Diff.hpp similarity index 57% rename from include/eepp/thirdparty/dtl/dtl.hpp rename to src/thirdparty/dtl/Diff.hpp index 0be6e7565..bae7e67ee 100644 --- a/include/eepp/thirdparty/dtl/dtl.hpp +++ b/src/thirdparty/dtl/Diff.hpp @@ -1,25 +1,25 @@ /** dtl -- Diff Template Library - + In short, Diff Template Library is distributed under so called "BSD license", - + Copyright (c) 2015 Tatsuhiko Kubo 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 + 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 @@ -33,380 +33,13 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef DTL_H -#define DTL_H - - -#ifndef DTL_VARIABLES_H -#define DTL_VARIABLES_H - -#include -#include -#include -#include -#include - -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.21"; - - /** - * 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 - 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 - -#ifndef DTL_FUNCTORS_H -#define DTL_FUNCTORS_H - -namespace dtl { - - /** - * printer class template - */ - template - 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 - 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 - 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 - 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 - 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 - class Compare - { - public : - Compare () {} - virtual ~Compare () {} - virtual inline bool impl (const elem& e1, const elem& e2) const { - return e1 == e2; - } - }; -} - -#endif // DTL_FUNCTORS_H - -#ifndef DTL_SEQUENCE_H -#define DTL_SEQUENCE_H - -namespace dtl { - - /** - * sequence class template - */ - template - class Sequence - { - public : - typedef vector< elem > elemVec; - Sequence () {} - virtual ~Sequence () {} - - elemVec getSequence () const { - return sequence; - } - void addSequence (elem e) { - sequence.push_back(e); - } - protected : - elemVec sequence; - }; -} - -#endif // DTL_SEQUENCE_H - -#ifndef DTL_LCS_H -#define DTL_LCS_H - -namespace dtl { - - /** - * Longest Common Subsequence template class - */ - template - class Lcs : public Sequence< elem > - { - public : - Lcs () {} - ~Lcs () {} - }; -} - -#endif // DTL_LCS_H - -#ifndef DTL_SES_H -#define DTL_SES_H - -namespace dtl { - - /** - * Shortest Edit Script template class - */ - template - 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 +/* 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. @@ -438,111 +71,111 @@ namespace dtl { long long oy; public : Diff () {} - - Diff (const sequence& a, + + 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 sequence& b, const comparator& comp) : A(a), B(b), ses(false), cmp(comp) { init(); } - - Diff (const sequence& a, - const sequence& b, + + 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 */ @@ -587,11 +220,11 @@ namespace dtl { } shunk.clear(); } - + sequence patchedSeq(seqLst.begin(), seqLst.end()); return patchedSeq; } - + /** * patching with Shortest Edit Script (SES) */ @@ -618,14 +251,14 @@ namespace dtl { 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); } @@ -647,25 +280,25 @@ namespace dtl { } fp[delta+offset] = snake(static_cast(delta), fp[delta-1+offset]+1, fp[delta+1+offset]); } while (fp[delta+offset] != static_cast(N) && pathCordinates.size() < MAX_CORDINATES_SIZE); - + editDistance += static_cast(delta) + 2 * p; long long r = path[delta+offset]; - P cordinate; + 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); @@ -684,11 +317,11 @@ namespace dtl { 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 */ @@ -697,7 +330,7 @@ namespace dtl { 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); } @@ -719,7 +352,7 @@ namespace dtl { 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 */ @@ -727,11 +360,11 @@ namespace dtl { 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 */ @@ -761,10 +394,10 @@ namespace dtl { 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) { @@ -846,8 +479,8 @@ namespace dtl { } if (static_cast(common[0].size()) >= DTL_SEPARATE_SIZE) { long long c0size = static_cast(common[0].size()); - rotate(common[0].begin(), - common[0].begin() + (size_t)c0size - DTL_SEPARATE_SIZE, + rotate(common[0].begin(), + common[0].begin() + (size_t)c0size - DTL_SEPARATE_SIZE, common[0].end()); for (long long i=0;i(pathCordinates.size()); if (!editDistanceOnly) { P p; p.x = x;p.y = y;p.k = r; - pathCordinates.push_back(p); + pathCordinates.push_back(p); } return y; } - + /** * record SES and LCS */ @@ -999,7 +634,7 @@ namespace dtl { } if (i == 0) complete = true; } - + if (x_idx > static_cast(M) && y_idx > static_cast(N)) { // all recording succeeded } else { @@ -1014,7 +649,7 @@ namespace dtl { } 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()); @@ -1034,7 +669,7 @@ namespace dtl { } return true; } - + /** * record odd sequence in SES */ @@ -1048,7 +683,7 @@ namespace dtl { ses.addSequence(*it, idx, 0, et); ++editDistance; } - + /** * join SES vectors */ @@ -1057,9 +692,9 @@ namespace dtl { for (sesElemVec_iter vit=s2.begin();vit!=s2.end();++vit) { s1.push_back(*vit); } - } + } } - + /** * check if the sequences have been swapped */ @@ -1071,214 +706,3 @@ namespace dtl { } #endif // DTL_DIFF_H - -#ifndef DTL_DIFF3_H -#define DTL_DIFF3_H - -namespace dtl { - - /** - * diff3 class template - * sequence must support random_access_iterator. - */ - template , 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 - 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 - 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 - -#endif // DTL_H diff --git a/src/thirdparty/dtl/Diff3.hpp b/src/thirdparty/dtl/Diff3.hpp new file mode 100644 index 000000000..854864efd --- /dev/null +++ b/src/thirdparty/dtl/Diff3.hpp @@ -0,0 +1,245 @@ +/** + dtl -- Diff Template Library + + In short, Diff Template Library is distributed under so called "BSD license", + + Copyright (c) 2015 Tatsuhiko Kubo + 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 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 + 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 + 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 diff --git a/src/thirdparty/dtl/Lcs.hpp b/src/thirdparty/dtl/Lcs.hpp new file mode 100644 index 000000000..e47c2381a --- /dev/null +++ b/src/thirdparty/dtl/Lcs.hpp @@ -0,0 +1,55 @@ +/** + dtl -- Diff Template Library + + In short, Diff Template Library is distributed under so called "BSD license", + + Copyright (c) 2015 Tatsuhiko Kubo + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + * Neither the name of the authors nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/* If you use this library, you must include dtl.hpp only. */ + +#ifndef DTL_LCS_H +#define DTL_LCS_H + +namespace dtl { + + /** + * Longest Common Subsequence template class + */ + template + class Lcs : public Sequence< elem > + { + public : + Lcs () {} + ~Lcs () {} + }; +} + +#endif // DTL_LCS_H diff --git a/src/thirdparty/dtl/Sequence.hpp b/src/thirdparty/dtl/Sequence.hpp new file mode 100644 index 000000000..eeab0ed77 --- /dev/null +++ b/src/thirdparty/dtl/Sequence.hpp @@ -0,0 +1,65 @@ +/** + dtl -- Diff Template Library + + In short, Diff Template Library is distributed under so called "BSD license", + + Copyright (c) 2015 Tatsuhiko Kubo + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + * Neither the name of the authors nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/* If you use this library, you must include dtl.hpp only. */ + +#ifndef DTL_SEQUENCE_H +#define DTL_SEQUENCE_H + +namespace dtl { + + /** + * sequence class template + */ + template + class Sequence + { + public : + typedef vector< elem > elemVec; + Sequence () {} + virtual ~Sequence () {} + + elemVec getSequence () const { + return sequence; + } + void addSequence (elem e) { + sequence.push_back(e); + } + protected : + elemVec sequence; + }; +} + +#endif // DTL_SEQUENCE_H diff --git a/src/thirdparty/dtl/Ses.hpp b/src/thirdparty/dtl/Ses.hpp new file mode 100644 index 000000000..281144e06 --- /dev/null +++ b/src/thirdparty/dtl/Ses.hpp @@ -0,0 +1,132 @@ +/** + dtl -- Diff Template Library + + In short, Diff Template Library is distributed under so called "BSD license", + + Copyright (c) 2015 Tatsuhiko Kubo + 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 + 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 diff --git a/src/thirdparty/dtl/dtl.hpp b/src/thirdparty/dtl/dtl.hpp new file mode 100644 index 000000000..b6231ba79 --- /dev/null +++ b/src/thirdparty/dtl/dtl.hpp @@ -0,0 +1,47 @@ +/** + dtl -- Diff Template Library + + In short, Diff Template Library is distributed under so called "BSD license", + + Copyright (c) 2015 Tatsuhiko Kubo + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + * Neither the name of the authors nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef DTL_H +#define DTL_H + +#include "variables.hpp" +#include "functors.hpp" +#include "Sequence.hpp" +#include "Lcs.hpp" +#include "Ses.hpp" +#include "Diff.hpp" +#include "Diff3.hpp" + +#endif // DTL_H diff --git a/src/thirdparty/dtl/functors.hpp b/src/thirdparty/dtl/functors.hpp new file mode 100644 index 000000000..86d8709df --- /dev/null +++ b/src/thirdparty/dtl/functors.hpp @@ -0,0 +1,151 @@ +/** + dtl -- Diff Template Library + + In short, Diff Template Library is distributed under so called "BSD license", + + Copyright (c) 2015 Tatsuhiko Kubo + 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 + 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 + 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 + 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 + 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 + 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 + class Compare + { + public : + Compare () {} + virtual ~Compare () {} + virtual inline bool impl (const elem& e1, const elem& e2) const { + return e1 == e2; + } + }; +} + +#endif // DTL_FUNCTORS_H diff --git a/src/thirdparty/dtl/variables.hpp b/src/thirdparty/dtl/variables.hpp new file mode 100644 index 000000000..4f53a8878 --- /dev/null +++ b/src/thirdparty/dtl/variables.hpp @@ -0,0 +1,142 @@ +/** + dtl -- Diff Template Library + + In short, Diff Template Library is distributed under so called "BSD license", + + Copyright (c) 2015 Tatsuhiko Kubo + 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 +#include +#include +#include +#include + +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.21"; + + /** + * 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 + 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