@@ -13,45 +13,40 @@ import Foundation
1313import FURRExtensions
1414
1515public enum DiffOperation {
16- case Delete
17- case Insert
18- case Equal
16+ case delete
17+ case insert
18+ case equal
1919
2020 func debugDescription( ) -> String {
2121 switch self {
22- case . Delete :
22+ case . delete :
2323 return " delete "
24- case . Equal :
24+ case . equal :
2525 return " equal "
26- case . Insert :
26+ case . insert :
2727 return " insert "
2828 }
2929 }
3030}
3131
32- public class Diff < T: Equatable > : Equatable , CustomDebugStringConvertible {
33- public var operation : DiffOperation
34- public var array : Array < T >
32+ public class Diff < T: Equatable > : Equatable , CustomDebugStringConvertible {
33+ public let operation : DiffOperation
34+ public var array : [ T ]
3535
36- init ( operation inOperation : DiffOperation , array inArray : Array < T > ) {
37- assert ( inArray . count != 0 , " array may not be empty " )
38- self . operation = inOperation
39- self . array = inArray
36+ init ( operation: DiffOperation , array: [ T ] ) {
37+ assert ( array . count != 0 , " array may not be empty " )
38+ self . operation = operation
39+ self . array = array
4040 }
4141
4242 public var debugDescription : String {
43- get {
44- var result : String = self . operation. debugDescription ( )
45- result = result + " " + self . array. debugDescription
46-
47- return result
48- }
43+ var result : String = self . operation. debugDescription ( )
44+ result += " " + self . array. debugDescription
4945
46+ return result
5047 }
5148}
5249
53-
54-
5550public func == < T: Equatable > ( lhs: Diff < T > , rhs: Diff < T > ) -> Bool {
5651 if lhs. operation != rhs. operation {
5752 return false
@@ -60,33 +55,32 @@ public func == <T: Equatable> (lhs: Diff<T>, rhs: Diff<T>) -> Bool {
6055 return lhs. array == rhs. array
6156}
6257
58+ func diff_commonPrefix< T: Equatable > ( arrayA: [ T ] , arrayB: [ T ] ) -> [ T ] {
59+ let smallerCount = ( arrayA. count < arrayB. count) ? arrayA. count : arrayB. count
6360
64- func diff_commonPrefix< T: Equatable > ( arrayA inArrayA: Array < T > , arrayB inArrayB: Array < T > ) -> Array < T > {
65- let smallerCount = ( inArrayA. count < inArrayB. count) ? inArrayA. count : inArrayB. count
66-
67- var common : Array < T > = [ ]
61+ var common : [ T ] = [ ]
6862
6963 for i in 0 ..< smallerCount {
70- if inArrayA [ i] != inArrayB [ i] {
64+ if arrayA [ i] != arrayB [ i] {
7165 break
7266 } else {
73- common. append ( inArrayA [ i] )
67+ common. append ( arrayA [ i] )
7468 }
7569 }
7670
7771 return common
7872}
7973
80- func diff_commonSuffix< T: Equatable > ( arrayA inArrayA : Array < T > , arrayB inArrayB : Array < T > ) -> Array < T > {
81- let smallerCount = ( inArrayA . count < inArrayB . count) ? inArrayA . count : inArrayB . count
74+ func diff_commonSuffix< T: Equatable > ( arrayA: [ T ] , arrayB: [ T ] ) -> [ T ] {
75+ let smallerCount = ( arrayA . count < arrayB . count) ? arrayA . count : arrayB . count
8276
83- var commonReversed : Array < T > = [ ]
77+ var commonReversed : [ T ] = [ ]
8478
8579 for i in 0 ..< smallerCount {
86- if inArrayA [ inArrayA . count - 1 - i] != inArrayB [ inArrayB . count - 1 - i] {
80+ if arrayA [ arrayA . count - 1 - i] != arrayB [ arrayB . count - 1 - i] {
8781 break
8882 } else {
89- commonReversed. append ( inArrayA [ inArrayA . count - 1 - i] )
83+ commonReversed. append ( arrayA [ arrayA . count - 1 - i] )
9084 }
9185 }
9286
@@ -95,35 +89,31 @@ func diff_commonSuffix<T: Equatable>(arrayA inArrayA: Array<T>, arrayB inArrayB:
9589 return common
9690}
9791
98- private func diff_subArrayToIndex< T> ( array inArray: Array < T > , index inIndex: Int ) -> Array < T > {
92+ private func diff_subArrayToIndex< T> ( array inArray: [ T ] , index inIndex: Int ) -> [ T ] {
9993 let result = Array ( inArray [ 0 ..< inIndex] )
10094 return result
10195}
10296
103- private func diff_subArrayFromIndex< T> ( array inArray: Array < T > , index inIndex: Int ) -> Array < T > {
97+ private func diff_subArrayFromIndex< T> ( array inArray: [ T ] , index inIndex: Int ) -> [ T ] {
10498 let result = Array ( inArray [ inIndex..< inArray. endIndex] )
10599 return result
106100}
107101
108- private func diff_appendDiffsAndCompact< T> ( array inArray: Array < Diff < T > > , diffs: Array < Diff < T > > ) -> Array < Diff < T > > {
102+ private func diff_appendDiffsAndCompact< T> ( array inArray: [ Diff < T > ] , diffs: [ Diff < T > ] ) -> [ Diff < T > ] {
109103 var result = inArray
110104 for diff in diffs {
111105 result = diff_appendDiffAndCompact ( array: result, diff: diff)
112106 }
113107 return result
114108}
115109
116- private func diff_appendDiffAndCompact< T> ( array inArray: Array < Diff < T > > , diff: Diff < T > ) -> Array < Diff < T > > {
110+ private func diff_appendDiffAndCompact< T> ( array inArray: [ Diff < T > ] , diff: Diff < T > ) -> [ Diff < T > ] {
117111 guard let lastDiff = inArray. last else {
118112 return [ diff]
119113 }
120114
121115 if diff. operation == lastDiff. operation {
122- #if swift(>=3.0)
123- lastDiff. array. append ( contentsOf: diff. array)
124- #else
125- lastDiff. array. appendContentsOf ( diff. array)
126- #endif
116+ lastDiff. array. append ( contentsOf: diff. array)
127117 return inArray
128118 }
129119
@@ -132,99 +122,121 @@ private func diff_appendDiffAndCompact<T>(array inArray: Array<Diff<T>>, diff: D
132122 return newArray
133123}
134124
135- func diff_removeCommonPrefix< T: Equatable > ( arrayA inArrayA: Array < T > , arrayB inArrayB: Array < T > ) -> ( common: Array < T > , remainingA: Array < T > , remainingB: Array < T > ) {
125+ internal struct DiffCommonAndRemaining < T: Equatable > {
126+ let common : [ T ]
127+ let remainingA : [ T ]
128+ let remainingB : [ T ]
129+ }
130+
131+ func diff_removeCommonPrefix< T: Equatable > ( arrayA inArrayA: [ T ] , arrayB inArrayB: [ T ] ) -> DiffCommonAndRemaining < T > {
136132 let commonPrefix = diff_commonPrefix ( arrayA: inArrayA, arrayB: inArrayB)
137133 let remainingArrayA = diff_subArrayFromIndex ( array: inArrayA, index: commonPrefix. count)
138134 let remainingArrayB = diff_subArrayFromIndex ( array: inArrayB, index: commonPrefix. count)
139- return ( commonPrefix, remainingArrayA, remainingArrayB)
135+ return DiffCommonAndRemaining ( common : commonPrefix, remainingA : remainingArrayA, remainingB : remainingArrayB)
140136}
141137
142- func diff_removeCommonSuffix< T: Equatable > ( arrayA inArrayA: Array < T > , arrayB inArrayB: Array < T > ) -> ( common : Array < T > , remainingA : Array < T > , remainingB : Array < T > ) {
138+ func diff_removeCommonSuffix< T: Equatable > ( arrayA inArrayA: [ T ] , arrayB inArrayB: [ T ] ) -> DiffCommonAndRemaining < T > {
143139 let commonSuffix = diff_commonSuffix ( arrayA: inArrayA, arrayB: inArrayB)
144140 let restOfArrayA = diff_subArrayToIndex ( array: inArrayA, index: inArrayA. count - commonSuffix. count)
145141 let restOfArrayB = diff_subArrayToIndex ( array: inArrayB, index: inArrayB. count - commonSuffix. count)
146- return ( commonSuffix, restOfArrayA, restOfArrayB)
142+ return DiffCommonAndRemaining ( common : commonSuffix, remainingA : restOfArrayA, remainingB : restOfArrayB)
147143}
148144
149- public func diffBetweenArrays< T: Equatable > ( arrayA inArrayA: Array < T > , arrayB inArrayB: Array < T > ) -> Array < Diff < T > > {
145+ public func diffBetweenArrays< T: Equatable > ( arrayA inArrayA: [ T ] , arrayB inArrayB: [ T ] ) -> [ Diff < T > ] {
150146
151147 // Check for equality (speedup).
152148 if inArrayA == inArrayB {
153149 if inArrayA. count != 0 {
154- return [ Diff ( operation: . Equal , array: inArrayA) ]
150+ return [ Diff ( operation: . equal , array: inArrayA) ]
155151 }
156152 return [ ]
157153 }
158154
159- var resultDiffs : Array < Diff < T > > = Array ( )
155+ var resultDiffs : [ Diff < T > ] = [ ]
156+
157+ // e.g.
158+ // A: [111222333]
159+ // B: [111444333]
160160
161161 // Trim off common prefix (speedup).
162- let ( commonPrefix, remainingSuffixArrayA, remainingSuffixArrayB) = diff_removeCommonPrefix ( arrayA: inArrayA, arrayB: inArrayB)
162+ let commonPrefixAndRemaining = diff_removeCommonPrefix ( arrayA: inArrayA, arrayB: inArrayB)
163+
164+ // commonPrefix: [111]
165+ // remainingA: [222333]
166+ // remainingB: [444333]
163167
164168 // Trim off common suffix (speedup).
165- let ( commonSuffix , remainingArrayA , remainingArrayB ) = diff_removeCommonSuffix ( arrayA: remainingSuffixArrayA , arrayB: remainingSuffixArrayB )
169+ let commonSuffixAndRemaining = diff_removeCommonSuffix ( arrayA: commonPrefixAndRemaining . remainingA , arrayB: commonPrefixAndRemaining . remainingB )
166170
167- // add common suffix as equal
168- if commonPrefix. count != 0 {
169- resultDiffs = diff_appendDiffAndCompact ( array: resultDiffs, diff: Diff ( operation: . Equal, array: commonPrefix) )
171+ // commonPrefix: [333]
172+ // remainingA: [222]
173+ // remainingB: [444]
174+
175+ // add common prefix as equal
176+ if commonPrefixAndRemaining. common. count != 0 {
177+ resultDiffs = diff_appendDiffAndCompact ( array: resultDiffs, diff: Diff ( operation: . equal, array: commonPrefixAndRemaining. common) )
170178 }
171179
180+ // [eq: 111]
181+
172182 // diff the remaining part
173- let middlePart = diff_computeDiffsBetweenArrays ( arrayA: remainingArrayA , arrayB: remainingArrayB )
183+ let middlePart = diff_computeDiffsBetweenArrays ( arrayA: commonSuffixAndRemaining . remainingA , arrayB: commonSuffixAndRemaining . remainingB )
174184 resultDiffs = diff_appendDiffsAndCompact ( array: resultDiffs, diffs: middlePart)
175185
186+ // [eq: 111][..: ...][..: ...]
187+
176188 // add the common suffix as equal
177- if commonSuffix . count != 0 {
178- resultDiffs = diff_appendDiffAndCompact ( array: resultDiffs, diff: Diff ( operation: . Equal , array: commonSuffix ) )
189+ if commonSuffixAndRemaining . common . count != 0 {
190+ resultDiffs = diff_appendDiffAndCompact ( array: resultDiffs, diff: Diff ( operation: . equal , array: commonSuffixAndRemaining . common ) )
179191 }
180192
193+ // [eq: 111][..: ...][..: ...][eq: 333]
194+
181195 return resultDiffs
182196}
183197
184-
185- private func diff_computeDiffsBetweenArrays< T: Equatable > ( arrayA inArrayA: Array < T > , arrayB inArrayB: Array < T > ) -> Array < Diff < T > > {
186- if inArrayA. count == 0 && inArrayB. count == 0 {
198+ private func diff_computeDiffsBetweenArrays< T: Equatable > ( arrayA: [ T ] , arrayB: [ T ] ) -> [ Diff < T > ] {
199+ if arrayA. count == 0 && arrayB. count == 0 {
187200 // this case is not covered by the tests so I put a assert here.
188201 // please file a bug if it is hit!
189202 assertionFailure ( " Please file a bug! " )
190203 return [ ]
191204 }
192205
193- if inArrayA . count == 0 {
206+ if arrayA . count == 0 {
194207 // Just add some text (speedup).
195- return [ Diff ( operation: . Insert , array: inArrayB ) ]
208+ return [ Diff ( operation: . insert , array: arrayB ) ]
196209 }
197210
198- if inArrayB . count == 0 {
211+ if arrayB . count == 0 {
199212 // Just delete some text (speedup).
200- return [ Diff ( operation: . Delete , array: inArrayA ) ]
213+ return [ Diff ( operation: . delete , array: arrayA ) ]
201214 }
202215
203- var longArray = inArrayA . count > inArrayB . count ? inArrayA : inArrayB
204- var shortArray = inArrayA . count > inArrayB . count ? inArrayB : inArrayA
216+ var longArray = arrayA . count > arrayB . count ? arrayA : arrayB
217+ var shortArray = arrayA . count > arrayB . count ? arrayB : arrayA
205218
206219 if shortArray. count == 1 && longArray. count == 1 {
207220 // Single character strings.
208221 if shortArray [ 0 ] == longArray [ 0 ] {
209222 // this case is not covered by the tests so I put a assert here.
210223 // please file a bug if it is hit!
211224 assertionFailure ( " Please file a bug! " )
212- return [ Diff ( operation: . Equal , array: shortArray) ]
225+ return [ Diff ( operation: . equal , array: shortArray) ]
213226 }
214227
215- return [
216- Diff ( operation: . Delete, array: inArrayA) ,
217- Diff ( operation: . Insert, array: inArrayB) ,
218- ]
228+ let delete = Diff < T > ( operation: . delete, array: arrayA)
229+ let insert = Diff < T > ( operation: . insert, array: arrayB)
230+ return [ delete, insert]
219231 }
220232
221- return diff_bisectOfArrays ( arrayA: inArrayA , arrayB: inArrayB )
233+ return diff_bisectOfArrays ( arrayA: arrayA , arrayB: arrayB )
222234}
223235
224236// yes this method is way too long. Pull requests welcome!
225237
226238// swiftlint:disable function_body_length
227- func diff_bisectOfArrays< T: Equatable > ( arrayA inArrayA: Array < T > , arrayB inArrayB: Array < T > ) -> Array < Diff < T > > {
239+ func diff_bisectOfArrays< T: Equatable > ( arrayA inArrayA: [ T ] , arrayB inArrayB: [ T ] ) -> [ Diff < T > ] {
228240 let arrayALength = inArrayA. count
229241 let arrayBLength = inArrayB. count
230242 var haveFoundDiffs = false
@@ -238,8 +250,8 @@ func diff_bisectOfArrays<T: Equatable>(arrayA inArrayA: Array<T>, arrayB inArray
238250 vLength = vOffset + 2
239251 }
240252
241- var v1 : Array < Int > = Array ( )
242- var v2 : Array < Int > = Array ( )
253+ var v1 : [ Int ] = [ ]
254+ var v2 : [ Int ] = [ ]
243255
244256 for _ in 0 ..< vLength {
245257 v1. append ( - 1 )
@@ -371,24 +383,16 @@ func diff_bisectOfArrays<T: Equatable>(arrayA inArrayA: Array<T>, arrayB inArray
371383 }
372384
373385 if !haveFoundDiffs {
374- // we have not found a shortest snake so we couldn't cut the problem in half.
386+ // we haven't found a snake at all so we couldn't cut the problem in half.
375387 // This means we have no common element. Just add the diffs straight away.
376- diffs = [ Diff ( operation: . Delete, array: inArrayA) ]
377- #if swift(>=3.0)
378- diffs. append ( contentsOf: [ Diff ( operation: . Insert, array: inArrayB) ] )
379- #else
380- diffs. appendContentsOf ( [ Diff ( operation: . Insert, array: inArrayB) ] )
381- #endif
388+ diffs = [ Diff ( operation: . delete, array: inArrayA) , Diff ( operation: . insert, array: inArrayB) ]
382389 }
383390
384391 return diffs
385392}
386393// swiftlint:enable function_body_length
387394
388- private func diff_bisectSplitOfArrays< T: Equatable > ( arrayA inArrayA: Array < T > ,
389- arrayB inArrayB: Array < T > ,
390- x inX: Int ,
391- y inY: Int ) -> Array < Diff < T > > {
395+ private func diff_bisectSplitOfArrays< T: Equatable > ( arrayA inArrayA: [ T ] , arrayB inArrayB: [ T ] , x inX: Int , y inY: Int ) -> [ Diff < T > ] {
392396 let arrayAa = diff_subArrayToIndex ( array: inArrayA, index: inX)
393397 let arrayBa = diff_subArrayToIndex ( array: inArrayB, index: inY)
394398 let arrayAb = diff_subArrayFromIndex ( array: inArrayA, index: inX)
0 commit comments