1 /*
2 SPDX-FileCopyrightText: 2001-2004,2009 Otto Bruggeman <bruggie@gmail.com>
3 SPDX-FileCopyrightText: 2001-2003 John Firebaugh <jfirebaugh@kde.org>
4 
5 SPDX-License-Identifier: GPL-2.0-or-later
6 */
7 
8 #ifndef DIFFERENCE_H
9 #define DIFFERENCE_H
10 
11 #include <QVector>
12 #include <QObject>
13 
14 #include "diff2_export.h"
15 #include "marker.h"
16 
17 // #include <komparediffdebug.h>
18 
19 class QString;
20 
21 namespace Diff2
22 {
23 
24 /**
25  * A difference string.
26  */
27 class DIFF2_EXPORT DifferenceString
28 {
29 public:
DifferenceString()30     DifferenceString()
31     {
32 //         qCDebug(LIBKOMPAREDIFF2) << "DifferenceString::DifferenceString()";
33     }
34     explicit DifferenceString(const QString& string, const MarkerList& markerList = MarkerList()) :
m_string(string)35         m_string(string),
36         m_markerList(markerList)
37     {
38 //         qCDebug(LIBKOMPAREDIFF2) << "DifferenceString::DifferenceString( " << string << ", " << markerList << " )";
39         calculateHash();
40     }
DifferenceString(const DifferenceString & ds)41     DifferenceString(const DifferenceString& ds) :
42         m_string(ds.m_string),
43         m_conflict(ds.m_conflict),
44         m_hash(ds.m_hash),
45         m_markerList(ds.m_markerList)
46     {
47 //         qCDebug(LIBKOMPAREDIFF2) << "DifferenceString::DifferenceString( const DifferenceString& " << ds << " )";
48     }
~DifferenceString()49     ~DifferenceString()
50     {
51         qDeleteAll(m_markerList);
52     }
53 
54 public:
string()55     const QString& string() const
56     {
57         return m_string;
58     }
conflictString()59     const QString& conflictString() const
60     {
61         return m_conflict;
62     }
markerList()63     const MarkerList& markerList()
64     {
65         return m_markerList;
66     }
setString(const QString & string)67     void setString(const QString& string)
68     {
69         m_string = string;
70         calculateHash();
71     }
setConflictString(const QString & conflict)72     void setConflictString(const QString& conflict)
73     {
74         m_conflict = conflict;
75     }
setMarkerList(const MarkerList & markerList)76     void setMarkerList(const MarkerList& markerList)
77     {
78         m_markerList = markerList;
79     }
prepend(Marker * marker)80     void prepend(Marker* marker)
81     {
82         m_markerList.prepend(marker);
83     }
84     bool operator==(const DifferenceString& ks)
85     {
86         if (m_hash != ks.m_hash)
87             return false;
88         return m_string == ks.m_string;
89     }
90 
91 protected:
calculateHash()92     void calculateHash()
93     {
94         unsigned short const* str = reinterpret_cast<unsigned short const*>(m_string.unicode());
95         const unsigned int len = m_string.length();
96 
97         m_hash = 1315423911;
98 
99         for (unsigned int i = 0; i < len; ++i)
100         {
101             m_hash ^= (m_hash << 5) + str[i] + (m_hash >> 2);
102         }
103     }
104 
105 private:
106     QString      m_string;
107     QString      m_conflict;
108     unsigned int m_hash;
109     MarkerList   m_markerList;
110 };
111 
112 using DifferenceStringList =              QVector<DifferenceString*>;
113 using DifferenceStringListIterator =      QVector<DifferenceString*>::iterator;
114 using DifferenceStringListConstIterator = QVector<DifferenceString*>::const_iterator;
115 
116 /**
117  * A difference.
118  */
119 class DIFF2_EXPORT Difference : public QObject
120 {
121     Q_OBJECT
122 public:
123     enum Type { Change, Insert, Delete, Unchanged };
124 
125 public:
126     Difference(int sourceLineNo, int destinationLineNo, int type = Difference::Unchanged);
127     ~Difference() override;
128 
129 public:
type()130     int type() const { return m_type; };
131 
sourceLineNumber()132     int sourceLineNumber() const { return m_sourceLineNo; }
destinationLineNumber()133     int destinationLineNumber() const { return m_destinationLineNo; }
134 
135     int sourceLineCount() const;
136     int destinationLineCount() const;
137 
138     int sourceLineEnd() const;
139     int destinationLineEnd() const;
140 
141     /// Destination line number that tracks applying/unapplying of other differences
142     /// Essentially a line number in a patch consisting of applied diffs only
trackingDestinationLineNumber()143     int trackingDestinationLineNumber() const { return m_trackingDestinationLineNo; }
144     int trackingDestinationLineEnd() const;
setTrackingDestinationLineNumber(int i)145     void setTrackingDestinationLineNumber(int i) { m_trackingDestinationLineNo = i; }
146 
sourceLineAt(int i)147     DifferenceString* sourceLineAt(int i) const { return m_sourceLines[i]; }
destinationLineAt(int i)148     DifferenceString* destinationLineAt(int i) const { return m_destinationLines[i]; }
149 
sourceLines()150     const DifferenceStringList sourceLines() const { return m_sourceLines; }
destinationLines()151     const DifferenceStringList destinationLines() const { return m_destinationLines; }
152 
hasConflict()153     bool hasConflict() const
154     {
155         return m_conflicts;
156     }
setConflict(bool conflicts)157     void setConflict(bool conflicts)
158     {
159         m_conflicts = conflicts;
160     }
161 
isUnsaved()162     bool isUnsaved() const
163     {
164         return m_unsaved;
165     }
setUnsaved(bool unsaved)166     void setUnsaved(bool unsaved)
167     {
168         m_unsaved = unsaved;
169     }
170 
171     void apply(bool apply);
172     /// Apply without emitting any signals
173     void applyQuietly(bool apply);
applied()174     bool applied() const { return m_applied; }
175 
setType(int type)176     void setType(int type) { m_type = type; }
177 
178     void addSourceLine(QString line);
179     void addDestinationLine(QString line);
180 
181     /** This method will calculate the differences between the individual strings and store them as Markers */
182     void determineInlineDifferences();
183 
184     QString recreateDifference() const;
185 
186 Q_SIGNALS:
187     void differenceApplied(Difference*);
188 
189 private:
190     int                   m_type;
191 
192     int                   m_sourceLineNo;
193     int                   m_destinationLineNo;
194     int                   m_trackingDestinationLineNo;
195 
196     DifferenceStringList  m_sourceLines;
197     DifferenceStringList  m_destinationLines;
198 
199     bool                  m_applied;
200     bool                  m_conflicts;
201     bool                  m_unsaved;
202 };
203 
204 using DifferenceList =              QList<Difference*>;
205 using DifferenceListIterator =      QList<Difference*>::iterator;
206 using DifferenceListConstIterator = QList<Difference*>::const_iterator;
207 
208 } // End of namespace Diff2
209 
210 #endif
211 
212