##// END OF EJS Templates
remove trailing white-spaces from lib/diff.rb....
Toshi MARUYAMA -
r6349:aa35ef4be8b3
parent child
Show More
@@ -1,282 +1,282
1 1 module RedmineDiff
2 2 class Diff
3 3
4 4 VERSION = 0.3
5 5
6 6 def Diff.lcs(a, b)
7 7 astart = 0
8 8 bstart = 0
9 9 afinish = a.length-1
10 10 bfinish = b.length-1
11 11 mvector = []
12
12
13 13 # First we prune off any common elements at the beginning
14 14 while (astart <= afinish && bstart <= afinish && a[astart] == b[bstart])
15 15 mvector[astart] = bstart
16 16 astart += 1
17 17 bstart += 1
18 18 end
19
19
20 20 # now the end
21 21 while (astart <= afinish && bstart <= bfinish && a[afinish] == b[bfinish])
22 22 mvector[afinish] = bfinish
23 23 afinish -= 1
24 24 bfinish -= 1
25 25 end
26 26
27 27 bmatches = b.reverse_hash(bstart..bfinish)
28 28 thresh = []
29 29 links = []
30
30
31 31 (astart..afinish).each { |aindex|
32 32 aelem = a[aindex]
33 33 next unless bmatches.has_key? aelem
34 34 k = nil
35 35 bmatches[aelem].reverse.each { |bindex|
36 36 if k && (thresh[k] > bindex) && (thresh[k-1] < bindex)
37 37 thresh[k] = bindex
38 38 else
39 39 k = thresh.replacenextlarger(bindex, k)
40 40 end
41 41 links[k] = [ (k==0) ? nil : links[k-1], aindex, bindex ] if k
42 42 }
43 43 }
44 44
45 45 if !thresh.empty?
46 46 link = links[thresh.length-1]
47 47 while link
48 48 mvector[link[1]] = link[2]
49 49 link = link[0]
50 50 end
51 51 end
52 52
53 53 return mvector
54 54 end
55 55
56 56 def makediff(a, b)
57 57 mvector = Diff.lcs(a, b)
58 58 ai = bi = 0
59 59 while ai < mvector.length
60 60 bline = mvector[ai]
61 61 if bline
62 62 while bi < bline
63 63 discardb(bi, b[bi])
64 64 bi += 1
65 65 end
66 66 match(ai, bi)
67 67 bi += 1
68 68 else
69 69 discarda(ai, a[ai])
70 70 end
71 71 ai += 1
72 72 end
73 73 while ai < a.length
74 74 discarda(ai, a[ai])
75 75 ai += 1
76 76 end
77 77 while bi < b.length
78 78 discardb(bi, b[bi])
79 79 bi += 1
80 80 end
81 81 match(ai, bi)
82 82 1
83 83 end
84 84
85 85 def compactdiffs
86 86 diffs = []
87 87 @diffs.each { |df|
88 88 i = 0
89 89 curdiff = []
90 90 while i < df.length
91 91 whot = df[i][0]
92 92 s = @isstring ? df[i][2].chr : [df[i][2]]
93 93 p = df[i][1]
94 94 last = df[i][1]
95 95 i += 1
96 96 while df[i] && df[i][0] == whot && df[i][1] == last+1
97 97 s << df[i][2]
98 98 last = df[i][1]
99 99 i += 1
100 100 end
101 101 curdiff.push [whot, p, s]
102 102 end
103 103 diffs.push curdiff
104 104 }
105 105 return diffs
106 106 end
107 107
108 108 attr_reader :diffs, :difftype
109 109
110 110 def initialize(diffs_or_a, b = nil, isstring = nil)
111 111 if b.nil?
112 112 @diffs = diffs_or_a
113 113 @isstring = isstring
114 114 else
115 115 @diffs = []
116 116 @curdiffs = []
117 117 makediff(diffs_or_a, b)
118 118 @difftype = diffs_or_a.class
119 119 end
120 120 end
121
121
122 122 def match(ai, bi)
123 123 @diffs.push @curdiffs unless @curdiffs.empty?
124 124 @curdiffs = []
125 125 end
126 126
127 127 def discarda(i, elem)
128 128 @curdiffs.push ['-', i, elem]
129 129 end
130 130
131 131 def discardb(i, elem)
132 132 @curdiffs.push ['+', i, elem]
133 133 end
134 134
135 135 def compact
136 136 return Diff.new(compactdiffs)
137 137 end
138 138
139 139 def compact!
140 140 @diffs = compactdiffs
141 141 end
142 142
143 143 def inspect
144 144 @diffs.inspect
145 145 end
146 146
147 147 end
148 148 end
149 149
150 150 module Diffable
151 151 def diff(b)
152 152 RedmineDiff::Diff.new(self, b)
153 153 end
154 154
155 155 # Create a hash that maps elements of the array to arrays of indices
156 156 # where the elements are found.
157 157
158 158 def reverse_hash(range = (0...self.length))
159 159 revmap = {}
160 160 range.each { |i|
161 161 elem = self[i]
162 162 if revmap.has_key? elem
163 163 revmap[elem].push i
164 164 else
165 165 revmap[elem] = [i]
166 166 end
167 167 }
168 168 return revmap
169 169 end
170 170
171 171 def replacenextlarger(value, high = nil)
172 172 high ||= self.length
173 173 if self.empty? || value > self[-1]
174 174 push value
175 175 return high
176 176 end
177 177 # binary search for replacement point
178 178 low = 0
179 179 while low < high
180 180 index = (high+low)/2
181 181 found = self[index]
182 182 return nil if value == found
183 183 if value > found
184 184 low = index + 1
185 185 else
186 186 high = index
187 187 end
188 188 end
189 189
190 190 self[low] = value
191 191 # $stderr << "replace #{value} : 0/#{low}/#{init_high} (#{steps} steps) (#{init_high-low} off )\n"
192 192 # $stderr.puts self.inspect
193 193 #gets
194 194 #p length - low
195 195 return low
196 196 end
197 197
198 198 def patch(diff)
199 199 newary = nil
200 200 if diff.difftype == String
201 201 newary = diff.difftype.new('')
202 202 else
203 203 newary = diff.difftype.new
204 204 end
205 205 ai = 0
206 206 bi = 0
207 207 diff.diffs.each { |d|
208 208 d.each { |mod|
209 209 case mod[0]
210 210 when '-'
211 211 while ai < mod[1]
212 212 newary << self[ai]
213 213 ai += 1
214 214 bi += 1
215 215 end
216 216 ai += 1
217 217 when '+'
218 218 while bi < mod[1]
219 219 newary << self[ai]
220 220 ai += 1
221 221 bi += 1
222 222 end
223 223 newary << mod[2]
224 224 bi += 1
225 225 else
226 226 raise "Unknown diff action"
227 227 end
228 228 }
229 229 }
230 230 while ai < self.length
231 231 newary << self[ai]
232 232 ai += 1
233 233 bi += 1
234 234 end
235 235 return newary
236 236 end
237 237 end
238 238
239 239 class Array
240 240 include Diffable
241 241 end
242 242
243 243 class String
244 244 include Diffable
245 245 end
246 246
247 247 =begin
248 248 = Diff
249 249 (({diff.rb})) - computes the differences between two arrays or
250 250 strings. Copyright (C) 2001 Lars Christensen
251 251
252 252 == Synopsis
253 253
254 254 diff = Diff.new(a, b)
255 255 b = a.patch(diff)
256 256
257 257 == Class Diff
258 258 === Class Methods
259 259 --- Diff.new(a, b)
260 260 --- a.diff(b)
261 261 Creates a Diff object which represent the differences between
262 262 ((|a|)) and ((|b|)). ((|a|)) and ((|b|)) can be either be arrays
263 263 of any objects, strings, or object of any class that include
264 264 module ((|Diffable|))
265 265
266 266 == Module Diffable
267 267 The module ((|Diffable|)) is intended to be included in any class for
268 268 which differences are to be computed. Diffable is included into String
269 269 and Array when (({diff.rb})) is (({require}))'d.
270 270
271 271 Classes including Diffable should implement (({[]})) to get element at
272 272 integer indices, (({<<})) to append elements to the object and
273 273 (({ClassName#new})) should accept 0 arguments to create a new empty
274 274 object.
275 275
276 276 === Instance Methods
277 277 --- Diffable#patch(diff)
278 278 Applies the differences from ((|diff|)) to the object ((|obj|))
279 279 and return the result. ((|obj|)) is not changed. ((|obj|)) and
280 280 can be either an array or a string, but must match the object
281 281 from which the ((|diff|)) was created.
282 282 =end
General Comments 0
You need to be logged in to leave comments. Login now