| In: |
libraries/diff/diff.rb
|
| Parent: | Object |
# File libraries/diff/diff.rb, line 38
38: def initialize(a=[''], b=[''], isjunk=nil, byline=false)
39: a = (!byline and a.kind_of? String) ? a.split(//) : a
40: b = (!byline and b.kind_of? String) ? b.split(//) : b
41: @isjunk = isjunk || proc {}
42: set_seqs a, b
43: end
# File libraries/diff/diff.rb, line 100
100: def find_longest_match(alo, ahi, blo, bhi)
101: besti, bestj, bestsize = alo, blo, 0
102:
103: j2len = {}
104:
105: (alo..ahi).step do |i|
106: newj2len = {}
107: (@b2j[@a[i]] || []).each do |j|
108: if j < blo
109: next
110: end
111: if j >= bhi
112: break
113: end
114:
115: k = newj2len[j] = (j2len[j - 1] || 0) + 1
116: if k > bestsize
117: besti, bestj, bestsize = i - k + 1, j - k + 1, k
118: end
119: end
120: j2len = newj2len
121: end
122:
123: while besti > alo and bestj > blo and
124: not @isbjunk.call(@b[bestj-1]) and
125: @a[besti-1] == @b[bestj-1]
126: besti, bestj, bestsize = besti-1, bestj-1, bestsize+1
127: end
128:
129: while besti+bestsize < ahi and bestj+bestsize < bhi and
130: not @isbjunk.call(@b[bestj+bestsize]) and
131: @a[besti+bestsize] == @b[bestj+bestsize]
132: bestsize += 1
133: end
134:
135: while besti > alo and bestj > blo and
136: @isbjunk.call(@b[bestj-1]) and
137: @a[besti-1] == @b[bestj-1]
138: besti, bestj, bestsize = besti-1, bestj-1, bestsize+1
139: end
140:
141: while besti+bestsize < ahi and bestj+bestsize < bhi and
142: @isbjunk.call(@b[bestj+bestsize]) and
143: @a[besti+bestsize] == @b[bestj+bestsize]
144: bestsize += 1
145: end
146:
147: [besti, bestj, bestsize]
148: end
XXX: untested
# File libraries/diff/diff.rb, line 200
200: def get_grouped_opcodes(n=3)
201: codes = get_opcodes
202: if codes[0][0] == :equal
203: tag, i1, i2, j1, j2 = codes[0]
204: codes[0] = tag, [i1, i2 - n].max, i2, [j1, j2-n].max, j2
205: end
206:
207: if codes[-1][0] == :equal
208: tag, i1, i2, j1, j2 = codes[-1]
209: codes[-1] = tag, i1, min(i2, i1+n), j1, min(j2, j1+n)
210: end
211: nn = n + n
212: group = []
213: codes.each do |tag, i1, i2, j1, j2|
214: if tag == :equal and i2-i1 > nn
215: group.push [tag, i1, [i2, i1 + n].min, j1, [j2, j1 + n].min]
216: yield group
217: group = []
218: i1, j1 = [i1, i2-n].max, [j1, j2-n].max
219: group.push [tag, i1, i2, j1 ,j2]
220: end
221: end
222: if group and group.length != 1 and group[0][0] == :equal
223: yield group
224: end
225: end
# File libraries/diff/diff.rb, line 150
150: def get_matching_blocks
151: return @matching_blocks unless @matching_blocks.nil? or
152: @matching_blocks.empty?
153:
154: @matching_blocks = []
155: la, lb = @a.length, @b.length
156: match_block_helper(0, la, 0, lb, @matching_blocks)
157: @matching_blocks.push [la, lb, 0]
158: end
# File libraries/diff/diff.rb, line 173
173: def get_opcodes
174: unless @opcodes.nil? or @opcodes.empty?
175: return @opcodes
176: end
177:
178: i = j = 0
179: @opcodes = answer = []
180: get_matching_blocks.each do |ai, bj, size|
181: tag = if i < ai and j < bj
182: :replace
183: elsif i < ai
184: :delete
185: elsif j < bj
186: :insert
187: end
188:
189: answer.push [tag, i, ai, j, bj] if tag
190:
191: i, j = ai + size, bj + size
192:
193: answer.push [:equal, ai, i, bj, j] unless size.zero?
194:
195: end
196: return answer
197: end
# File libraries/diff/diff.rb, line 234
234: def quick_ratio
235: if @fullbcount.nil? or @fullbcount.empty?
236: @fullbcount = {}
237: @b.each do |elt|
238: @fullbcount[elt] = (@fullbcount[elt] || 0) + 1
239: end
240: end
241:
242: avail = {}
243: matches = 0
244: @a.each do |elt|
245: if avail.has_key? elt
246: numb = avail[elt]
247: else
248: numb = @fullbcount[elt] || 0
249: end
250: avail[elt] = numb - 1
251: if numb > 0
252: matches += 1
253: end
254: end
255: Diff.calculate_ratio matches, @a.length + @b.length
256: end
# File libraries/diff/diff.rb, line 227
227: def ratio
228: matches = get_matching_blocks.reduce(0) do |sum, triple|
229: sum + triple[-1]
230: end
231: Diff.calculate_ratio(matches, @a.length + @b.length)
232: end
# File libraries/diff/diff.rb, line 258
258: def real_quick_ratio
259: la, lb = @a.length, @b.length
260: Diff.calculate_ratio([la, lb].min, la + lb)
261: end
# File libraries/diff/diff.rb, line 50
50: def set_seq_a(a)
51: @a = a
52: @matching_blocks = @opcodes = nil
53: end
# File libraries/diff/diff.rb, line 55
55: def set_seq_b(b)
56: @b = b
57: @matching_blocks = @opcodes = nil
58: chain_b
59: end