diff options
Diffstat (limited to 'lib/redmine/string_array_diff/diffable.rb')
-rw-r--r-- | lib/redmine/string_array_diff/diffable.rb | 131 |
1 files changed, 131 insertions, 0 deletions
diff --git a/lib/redmine/string_array_diff/diffable.rb b/lib/redmine/string_array_diff/diffable.rb new file mode 100644 index 000000000..e09afc3db --- /dev/null +++ b/lib/redmine/string_array_diff/diffable.rb @@ -0,0 +1,131 @@ +# frozen_string_literal: true + +=begin + = Diff + (({diff.rb})) - computes the differences between two arrays or + strings. Copyright (C) 2001 Lars Christensen + + == Synopsis + + diff = Diff.new(a, b) + b = a.patch(diff) + + == Class Diff + === Class Methods + --- Diff.new(a, b) + --- a.diff(b) + Creates a Diff object which represent the differences between + ((|a|)) and ((|b|)). ((|a|)) and ((|b|)) can be either be arrays + of any objects, strings, or object of any class that include + module ((|Diffable|)) + + == Module Diffable + The module ((|Diffable|)) is intended to be included in any class for + which differences are to be computed. Diffable is included into String + and Array when (({diff.rb})) is (({require}))'d. + + Classes including Diffable should implement (({[]})) to get element at + integer indices, (({<<})) to append elements to the object and + (({ClassName#new})) should accept 0 arguments to create a new empty + object. + + === Instance Methods + --- Diffable#patch(diff) + Applies the differences from ((|diff|)) to the object ((|obj|)) + and return the result. ((|obj|)) is not changed. ((|obj|)) and + can be either an array or a string, but must match the object + from which the ((|diff|)) was created. +=end + +module Redmine + module StringArrayDiff + module Diffable + def diff(b) + Redmine::StringArrayDiff::Diff.new(self, b) + end + + # Create a hash that maps elements of the array to arrays of indices + # where the elements are found. + + def reverse_hash(range = (0...self.length)) + revmap = {} + range.each { |i| + elem = self[i] + if revmap.has_key? elem + revmap[elem].push i + else + revmap[elem] = [i] + end + } + return revmap + end + + def replacenextlarger(value, high = nil) + high ||= self.length + if self.empty? || value > self[-1] + push value + return high + end + # binary search for replacement point + low = 0 + while low < high + index = (high+low)/2 + found = self[index] + return nil if value == found + if value > found + low = index + 1 + else + high = index + end + end + + self[low] = value + # $stderr << "replace #{value} : 0/#{low}/#{init_high} (#{steps} steps) (#{init_high-low} off )\n" + # $stderr.puts self.inspect + # gets + # p length - low + return low + end + + def patch(diff) + newary = nil + if diff.difftype == String + newary = diff.difftype.new('') + else + newary = diff.difftype.new + end + ai = 0 + bi = 0 + diff.diffs.each { |d| + d.each { |mod| + case mod[0] + when '-' + while ai < mod[1] + newary << self[ai] + ai += 1 + bi += 1 + end + ai += 1 + when '+' + while bi < mod[1] + newary << self[ai] + ai += 1 + bi += 1 + end + newary << mod[2] + bi += 1 + else + raise "Unknown diff action" + end + } + } + while ai < self.length + newary << self[ai] + ai += 1 + bi += 1 + end + return newary + end + end + end +end |