invoca-utils 0.0.3 → 0.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/.rubocop.yml +5 -0
- data/Gemfile +11 -1
- data/Gemfile.lock +2 -2
- data/invoca-utils.gemspec +0 -11
- data/lib/invoca/utils.rb +8 -0
- data/lib/invoca/utils/diff.rb +290 -282
- data/lib/invoca/utils/guaranteed_utf8_string.rb +106 -45
- data/lib/invoca/utils/version.rb +1 -1
- data/test/helpers/constant_overrides.rb +44 -0
- data/test/test_helper.rb +3 -0
- data/test/unit/guaranteed_utf8_string_test.rb +191 -67
- data/test/unit/time_calculations_test.rb +0 -1
- data/test/unit/utils_test.rb +45 -2
- metadata +6 -129
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 14c0f52c191ceaa28ea84e6c14c7dedcee379d12
|
4
|
+
data.tar.gz: ec9d1132db9c4c9ea067e5797e464d4b194d4d0e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d5cea013efd99a4a8a34593bd95fb601135c0abe96aa53e579b8e6b47a8d3d4f8c34cd6d34a8e635067909835500a160a646c6105f8c658a2827698f83de9b40
|
7
|
+
data.tar.gz: 3a9101e2351ef8081b6199109ed97d5f22d50d306e6762519f68742cd624de3773daeabd5d7d7ecfe5c6260357c0e02a91870b87ab695f96b123d74f3b4c7712
|
data/.gitignore
CHANGED
data/.rubocop.yml
ADDED
@@ -0,0 +1,5 @@
|
|
1
|
+
# This rubocop config file inherits from our centralized style-guide repository.
|
2
|
+
# If you are looking to update the ruby style guide, be sure to both update the rubocop config
|
3
|
+
# as well as the README.md
|
4
|
+
# https://github.com/Invoca/style-guide/tree/master/ruby
|
5
|
+
inherit_from: https://raw.githubusercontent.com/Invoca/style-guide/master/ruby/.rubocop.yml
|
data/Gemfile
CHANGED
@@ -1,5 +1,15 @@
|
|
1
1
|
source 'https://rubygems.org'
|
2
2
|
|
3
|
-
# Specify your gem's dependencies in invoca-utils.gemspec
|
4
3
|
gemspec
|
5
4
|
|
5
|
+
group :development do
|
6
|
+
gem 'bundler', '~> 1.6'
|
7
|
+
gem 'rake'
|
8
|
+
gem 'test-unit', '= 1.2.3'
|
9
|
+
gem 'rr', '=1.1.2'
|
10
|
+
gem 'shoulda', '= 3.5.0'
|
11
|
+
gem 'pry'
|
12
|
+
gem 'ruby-prof'
|
13
|
+
gem 'minitest'
|
14
|
+
gem 'tzinfo'
|
15
|
+
end
|
data/Gemfile.lock
CHANGED
data/invoca-utils.gemspec
CHANGED
@@ -1,4 +1,3 @@
|
|
1
|
-
# coding: utf-8
|
2
1
|
lib = File.expand_path('../lib', __FILE__)
|
3
2
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
3
|
require 'invoca/utils/version'
|
@@ -17,14 +16,4 @@ Gem::Specification.new do |spec|
|
|
17
16
|
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
17
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
18
|
spec.require_paths = ["lib"]
|
20
|
-
|
21
|
-
spec.add_development_dependency "bundler", "~> 1.6"
|
22
|
-
spec.add_development_dependency "rake"
|
23
|
-
spec.add_development_dependency "test-unit", "= 1.2.3"
|
24
|
-
spec.add_development_dependency "rr", "=1.1.2"
|
25
|
-
spec.add_development_dependency "shoulda", "= 3.5.0"
|
26
|
-
spec.add_development_dependency "pry"
|
27
|
-
spec.add_development_dependency "ruby-prof"
|
28
|
-
spec.add_development_dependency "minitest"
|
29
|
-
spec.add_development_dependency "tzinfo"
|
30
19
|
end
|
data/lib/invoca/utils.rb
CHANGED
data/lib/invoca/utils/diff.rb
CHANGED
@@ -1,332 +1,340 @@
|
|
1
1
|
# adapted from http://users.cybercity.dk/~dsl8950/ruby/diff-0.3.tar.gz
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
3
|
+
module Invoca
|
4
|
+
module Utils
|
5
|
+
class Diff
|
6
|
+
|
7
|
+
VERSION = 0.3
|
8
|
+
|
9
|
+
def self.lcs(a, b)
|
10
|
+
astart = 0
|
11
|
+
bstart = 0
|
12
|
+
afinish = a.length - 1
|
13
|
+
bfinish = b.length - 1
|
14
|
+
lcs = []
|
15
|
+
|
16
|
+
# First we prune off any common elements at the beginning
|
17
|
+
while (astart <= afinish && bstart <= afinish && a[astart] == b[bstart])
|
18
|
+
lcs[astart] = bstart
|
19
|
+
astart += 1
|
20
|
+
bstart += 1
|
21
|
+
end
|
20
22
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
23
|
+
# now the end
|
24
|
+
while (astart <= afinish && bstart <= bfinish && a[afinish] == b[bfinish])
|
25
|
+
lcs[afinish] = bfinish
|
26
|
+
afinish -= 1
|
27
|
+
bfinish -= 1
|
28
|
+
end
|
27
29
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
30
|
+
bmatches = reverse_hash(b, bstart..bfinish)
|
31
|
+
thresh = []
|
32
|
+
links = []
|
33
|
+
|
34
|
+
(astart..afinish).each { |aindex|
|
35
|
+
aelem = a[aindex]
|
36
|
+
next unless bmatches.has_key? aelem
|
37
|
+
k = nil
|
38
|
+
bmatches[aelem].reverse.each { |bindex|
|
39
|
+
if k && (thresh[k] > bindex) && (thresh[k - 1] < bindex)
|
40
|
+
thresh[k] = bindex
|
41
|
+
else
|
42
|
+
k = replacenextlarger(thresh, bindex, k)
|
43
|
+
end
|
44
|
+
links[k] = [(k == 0) ? nil : links[k - 1], aindex, bindex] if k
|
45
|
+
}
|
46
|
+
}
|
47
|
+
|
48
|
+
if !thresh.empty?
|
49
|
+
link = links[thresh.length - 1]
|
50
|
+
while link
|
51
|
+
lcs[link[1]] = link[2]
|
52
|
+
link = link[0]
|
53
|
+
end
|
41
54
|
end
|
42
|
-
links[k] = [ (k==0) ? nil : links[k-1], aindex, bindex ] if k
|
43
|
-
}
|
44
|
-
}
|
45
|
-
|
46
|
-
if !thresh.empty?
|
47
|
-
link = links[thresh.length-1]
|
48
|
-
while link
|
49
|
-
lcs[link[1]] = link[2]
|
50
|
-
link = link[0]
|
51
|
-
end
|
52
|
-
end
|
53
55
|
|
54
|
-
|
55
|
-
|
56
|
+
return lcs
|
57
|
+
end
|
56
58
|
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
59
|
+
def self.nested_compare(subtractions, additions, index)
|
60
|
+
subtraction = subtractions[index]
|
61
|
+
addition = additions[index]
|
62
|
+
if subtraction.is_a?(Array) && addition.is_a?(Array)
|
63
|
+
return "Nested array diff:\n#{ compare(subtraction, addition) }\n"
|
64
|
+
elsif subtraction.is_a?(Hash) && addition.is_a?(Hash)
|
65
|
+
return "Nested hash diff:\n#{ compare(subtraction, addition) }\n"
|
66
|
+
else
|
67
|
+
""
|
68
|
+
end
|
69
|
+
end
|
68
70
|
|
69
|
-
|
70
|
-
|
71
|
-
|
71
|
+
def self.format(value)
|
72
|
+
value.is_a?(Numeric) || value.is_a?(String) ? value : value.inspect
|
73
|
+
end
|
72
74
|
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
end
|
86
|
-
unless curr_diff && (curr_diff[1].first..curr_diff[1].last) === index
|
87
|
-
result << " #{format arg}\n" unless arg.nil? || options[:short_description]
|
88
|
-
end
|
89
|
-
if curr_diff && curr_diff[1].first == index
|
90
|
-
verb, _a_range, _b_range, del, add = curr_diff
|
91
|
-
result <<
|
92
|
-
case verb
|
93
|
-
when 'd'
|
94
|
-
del.map { |t| "- #{format t}\n"}.join
|
95
|
-
when 'a'
|
96
|
-
add.map { |t| "+ #{format t}\n"}.join +
|
97
|
-
(arg.nil? ? '' : " #{format arg}\n")
|
98
|
-
when 'c'
|
99
|
-
del.map_with_index { |t, del_index| "- #{format t}\n#{nested_compare(del, add, del_index)}" }.join +
|
100
|
-
add.map { |t| "+ #{format t}\n" }.join
|
75
|
+
def self.compare arg1, arg2, options = {}
|
76
|
+
result = ''
|
77
|
+
if arg1 != arg2
|
78
|
+
if arg1.class == arg2.class || (arg1.is_a?(Hash) && arg2.is_a?(Hash)) || (arg1.is_a?(Array) && arg2.is_a?(Array)) # Hash and Array are equivalent when specialized
|
79
|
+
case arg1
|
80
|
+
when Array
|
81
|
+
diff_obj = Diff.new(arg1, arg2)
|
82
|
+
summary = diff_obj.summary
|
83
|
+
curr_diff = nil
|
84
|
+
(arg1 + [nil]).each_with_index do |arg, index|
|
85
|
+
if curr_diff.nil? || index > curr_diff[1].last
|
86
|
+
curr_diff = summary.shift
|
101
87
|
end
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
88
|
+
unless curr_diff && (curr_diff[1].first..curr_diff[1].last) === index
|
89
|
+
result << " #{format arg}\n" unless arg.nil? || options[:short_description]
|
90
|
+
end
|
91
|
+
if curr_diff && curr_diff[1].first == index
|
92
|
+
verb, _a_range, _b_range, del, add = curr_diff
|
93
|
+
result <<
|
94
|
+
case verb
|
95
|
+
when 'd'
|
96
|
+
del.map { |t| "- #{format t}\n" }.join
|
97
|
+
when 'a'
|
98
|
+
add.map { |t| "+ #{format t}\n" }.join +
|
99
|
+
(arg.nil? ? '' : " #{format arg}\n")
|
100
|
+
when 'c'
|
101
|
+
del.map_with_index { |t, del_index| "- #{format t}\n#{nested_compare(del, add, del_index)}" }.join +
|
102
|
+
add.map { |t| "+ #{format t}\n" }.join
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
summary.empty? or raise "Summary left: #{summary.inspect}"
|
107
|
+
when Hash
|
108
|
+
arg1.each do |key, value|
|
109
|
+
if arg2.has_key? key
|
110
|
+
result += "[#{key.inspect}] #{compare value, arg2[key]};\n" if value != arg2[key]
|
111
|
+
else
|
112
|
+
result += "[#{key.inspect}] expected #{value.inspect}, was missing;\n"
|
113
|
+
end
|
114
|
+
end
|
115
|
+
(arg2.keys - arg1.keys).each do |key|
|
116
|
+
result += "[#{key.inspect}] not expected, was #{arg2[key].inspect};\n"
|
117
|
+
end
|
109
118
|
else
|
110
|
-
result
|
119
|
+
result = "expected #{arg1.inspect}, was #{arg2.inspect} "
|
111
120
|
end
|
121
|
+
elsif arg1.class.in?([Float, BigDecimal]) && arg2.class.in?([Float, BigDecimal])
|
122
|
+
result = "expected #{arg1.class}: #{arg1.to_s}, was #{arg2.class}: #{arg2.to_s} "
|
123
|
+
else
|
124
|
+
result = "expected #{arg1.class}:#{arg1.inspect}, was #{arg2.class}:#{arg2.inspect} "
|
112
125
|
end
|
113
|
-
(arg2.keys - arg1.keys).each do |key|
|
114
|
-
result += "[#{key.inspect}] not expected, was #{arg2[key].inspect};\n"
|
115
|
-
end
|
116
|
-
else
|
117
|
-
result = "expected #{arg1.inspect}, was #{arg2.inspect} "
|
118
126
|
end
|
119
|
-
|
120
|
-
result = "expected #{arg1.class}: #{arg1.to_s}, was #{arg2.class}: #{arg2.to_s} "
|
121
|
-
else
|
122
|
-
result = "expected #{arg1.class}:#{arg1.inspect}, was #{arg2.class}:#{arg2.inspect} "
|
127
|
+
result
|
123
128
|
end
|
124
|
-
end
|
125
|
-
result
|
126
|
-
end
|
127
129
|
|
128
130
|
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
131
|
+
def makediff(a, b)
|
132
|
+
lcs = self.class.lcs(a, b)
|
133
|
+
ai = bi = 0
|
134
|
+
while ai < lcs.length
|
135
|
+
if lcs[ai]
|
136
|
+
while bi < lcs[ai]
|
137
|
+
discardb(bi, b[bi])
|
138
|
+
bi += 1
|
139
|
+
end
|
140
|
+
match
|
141
|
+
bi += 1
|
142
|
+
else
|
143
|
+
discarda(ai, a[ai])
|
144
|
+
end
|
145
|
+
ai += 1
|
146
|
+
end
|
147
|
+
while ai < a.length
|
148
|
+
discarda(ai, a[ai])
|
149
|
+
ai += 1
|
150
|
+
end
|
151
|
+
while bi < b.length
|
135
152
|
discardb(bi, b[bi])
|
136
153
|
bi += 1
|
137
154
|
end
|
138
155
|
match
|
139
|
-
bi += 1
|
140
|
-
else
|
141
|
-
discarda(ai, a[ai])
|
142
156
|
end
|
143
|
-
ai += 1
|
144
|
-
end
|
145
|
-
while ai < a.length
|
146
|
-
discarda(ai, a[ai])
|
147
|
-
ai += 1
|
148
|
-
end
|
149
|
-
while bi < b.length
|
150
|
-
discardb(bi, b[bi])
|
151
|
-
bi += 1
|
152
|
-
end
|
153
|
-
match
|
154
|
-
end
|
155
157
|
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
158
|
+
def compact!
|
159
|
+
diffs = []
|
160
|
+
@diffs.each do |diff|
|
161
|
+
puts "compacting #{diff.inspect}"
|
162
|
+
i = 0
|
163
|
+
curdiff = []
|
164
|
+
while i < diff.length
|
165
|
+
action = diff[i][0]
|
166
|
+
s = @difftype.is_a?(String) ? diff[i][2, 1] : [diff[i][2]]
|
167
|
+
offset = diff[i][1]
|
168
|
+
last = offset
|
169
|
+
i += 1
|
170
|
+
while diff[i] && diff[i][0] == action && diff[i][1] == last + 1
|
171
|
+
s << diff[i][2]
|
172
|
+
last = diff[i][1]
|
173
|
+
i += 1
|
174
|
+
end
|
175
|
+
curdiff.push [action, offset, s]
|
176
|
+
end
|
177
|
+
diffs.push curdiff
|
172
178
|
end
|
173
|
-
|
179
|
+
@diffs = diffs
|
180
|
+
self
|
174
181
|
end
|
175
|
-
diffs.push curdiff
|
176
|
-
end
|
177
|
-
@diffs = diffs
|
178
|
-
self
|
179
|
-
end
|
180
182
|
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
183
|
+
def compact
|
184
|
+
result = self.dup
|
185
|
+
result.compact!
|
186
|
+
result
|
187
|
+
end
|
186
188
|
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
189
|
+
def summary
|
190
|
+
result = []
|
191
|
+
b_offset = 0
|
192
|
+
@diffs.each do |block|
|
193
|
+
del = []
|
194
|
+
add = []
|
195
|
+
block.each do |diff|
|
196
|
+
case diff[0]
|
197
|
+
when "-"
|
198
|
+
del << diff[2]
|
199
|
+
when "+"
|
200
|
+
add << diff[2]
|
201
|
+
end
|
202
|
+
end
|
203
|
+
first = block[0][1]
|
204
|
+
verb, a_range, b_range =
|
205
|
+
if del.empty?
|
206
|
+
['a', [first - b_offset, first - b_offset], [first, first + add.size - 1]]
|
207
|
+
elsif add.empty?
|
208
|
+
['d', [first, first + del.size - 1], [first + b_offset, first + b_offset]]
|
209
|
+
else
|
210
|
+
['c', [first, first + del.size - 1], [first + b_offset, first + b_offset + add.size - 1]]
|
211
|
+
end
|
212
|
+
b_offset = b_offset + add.size - del.size
|
213
|
+
result << [verb, a_range, b_range, del, add]
|
199
214
|
end
|
215
|
+
result
|
200
216
|
end
|
201
|
-
first = block[0][1]
|
202
|
-
verb, a_range, b_range =
|
203
|
-
if del.empty?
|
204
|
-
[ 'a', [first-b_offset,first-b_offset], [first, first+add.size-1] ]
|
205
|
-
elsif add.empty?
|
206
|
-
[ 'd', [first, first+del.size-1], [first+b_offset, first+b_offset] ]
|
207
|
-
else
|
208
|
-
[ 'c', [first, first+del.size-1], [first+b_offset, first+b_offset+add.size-1] ]
|
209
|
-
end
|
210
|
-
b_offset = b_offset + add.size - del.size
|
211
|
-
result << [verb, a_range, b_range, del, add]
|
212
|
-
end
|
213
|
-
result
|
214
|
-
end
|
215
217
|
|
216
|
-
|
218
|
+
attr_reader :diffs, :difftype
|
217
219
|
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
def match
|
226
|
-
@diffs << @curdiffs unless @curdiffs.empty?
|
227
|
-
@curdiffs = []
|
228
|
-
end
|
229
|
-
|
230
|
-
def discarda(i, elem)
|
231
|
-
@curdiffs.push ['-', i, elem]
|
232
|
-
end
|
220
|
+
def initialize(a, b)
|
221
|
+
@difftype = a.class
|
222
|
+
@diffs = []
|
223
|
+
@curdiffs = []
|
224
|
+
makediff(a, b)
|
225
|
+
end
|
233
226
|
|
234
|
-
|
235
|
-
|
236
|
-
|
227
|
+
def match
|
228
|
+
@diffs << @curdiffs unless @curdiffs.empty?
|
229
|
+
@curdiffs = []
|
230
|
+
end
|
237
231
|
|
238
|
-
|
239
|
-
|
240
|
-
|
232
|
+
def discarda(i, elem)
|
233
|
+
@curdiffs.push ['-', i, elem]
|
234
|
+
end
|
241
235
|
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
def self.reverse_hash(lhs, range = nil)
|
246
|
-
range ||= (0...lhs.length)
|
247
|
-
revmap = {}
|
248
|
-
range.each { |i|
|
249
|
-
elem = lhs[i]
|
250
|
-
if revmap.has_key? elem
|
251
|
-
revmap[elem].push i
|
252
|
-
else
|
253
|
-
revmap[elem] = [i]
|
236
|
+
def discardb(i, elem)
|
237
|
+
@curdiffs.push ['+', i, elem]
|
254
238
|
end
|
255
|
-
}
|
256
|
-
return revmap
|
257
|
-
end
|
258
239
|
|
259
|
-
|
260
|
-
|
261
|
-
if lhs.empty? || value > lhs[-1]
|
262
|
-
lhs.push value
|
263
|
-
return high
|
264
|
-
end
|
265
|
-
# binary search for replacement point
|
266
|
-
low = 0
|
267
|
-
while low < high
|
268
|
-
index = (high+low)/2
|
269
|
-
found = lhs[index]
|
270
|
-
return nil if value == found
|
271
|
-
if value > found
|
272
|
-
low = index + 1
|
273
|
-
else
|
274
|
-
high = index
|
240
|
+
def inspect
|
241
|
+
@diffs.inspect
|
275
242
|
end
|
276
|
-
end
|
277
243
|
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
244
|
+
# Create a hash that maps elements of the array to arrays of indices
|
245
|
+
# where the elements are found.
|
246
|
+
|
247
|
+
def self.reverse_hash(lhs, range = nil)
|
248
|
+
range ||= (0...lhs.length)
|
249
|
+
revmap = {}
|
250
|
+
range.each { |i|
|
251
|
+
elem = lhs[i]
|
252
|
+
if revmap.has_key? elem
|
253
|
+
revmap[elem].push i
|
254
|
+
else
|
255
|
+
revmap[elem] = [i]
|
256
|
+
end
|
257
|
+
}
|
258
|
+
return revmap
|
259
|
+
end
|
285
260
|
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
bi += 1
|
261
|
+
def self.replacenextlarger(lhs, value, high = nil)
|
262
|
+
high ||= lhs.length
|
263
|
+
if lhs.empty? || value > lhs[-1]
|
264
|
+
lhs.push value
|
265
|
+
return high
|
266
|
+
end
|
267
|
+
# binary search for replacement point
|
268
|
+
low = 0
|
269
|
+
while low < high
|
270
|
+
index = (high + low) / 2
|
271
|
+
found = lhs[index]
|
272
|
+
return nil if value == found
|
273
|
+
if value > found
|
274
|
+
low = index + 1
|
275
|
+
else
|
276
|
+
high = index
|
303
277
|
end
|
278
|
+
end
|
279
|
+
|
280
|
+
lhs[low] = value
|
281
|
+
# $stderr << "replace #{value} : 0/#{low}/#{init_high} (#{steps} steps) (#{init_high-low} off )\n"
|
282
|
+
# $stderr.puts lhs.inspect
|
283
|
+
#gets
|
284
|
+
#p length - low
|
285
|
+
return low
|
286
|
+
end
|
287
|
+
|
288
|
+
def self.patch(lhs, diff)
|
289
|
+
newary = nil
|
290
|
+
if diff.difftype == String
|
291
|
+
newary = diff.difftype.new('')
|
292
|
+
else
|
293
|
+
newary = diff.difftype.new
|
294
|
+
end
|
295
|
+
ai = 0
|
296
|
+
bi = 0
|
297
|
+
diff.diffs.each { |d|
|
298
|
+
d.each { |mod|
|
299
|
+
case mod[0]
|
300
|
+
when '-'
|
301
|
+
while ai < mod[1]
|
302
|
+
newary << lhs[ai]
|
303
|
+
ai += 1
|
304
|
+
bi += 1
|
305
|
+
end
|
306
|
+
ai += 1
|
307
|
+
when '+'
|
308
|
+
while bi < mod[1]
|
309
|
+
newary << lhs[ai]
|
310
|
+
ai += 1
|
311
|
+
bi += 1
|
312
|
+
end
|
313
|
+
newary << mod[2]
|
314
|
+
bi += 1
|
315
|
+
else
|
316
|
+
raise "Unknown diff action"
|
317
|
+
end
|
318
|
+
}
|
319
|
+
}
|
320
|
+
while ai < lhs.length
|
321
|
+
newary << lhs[ai]
|
304
322
|
ai += 1
|
305
|
-
when '+'
|
306
|
-
while bi < mod[1]
|
307
|
-
newary << lhs[ai]
|
308
|
-
ai += 1
|
309
|
-
bi += 1
|
310
|
-
end
|
311
|
-
newary << mod[2]
|
312
323
|
bi += 1
|
313
|
-
else
|
314
|
-
raise "Unknown diff action"
|
315
324
|
end
|
316
|
-
|
317
|
-
|
318
|
-
while ai < lhs.length
|
319
|
-
newary << lhs[ai]
|
320
|
-
ai += 1
|
321
|
-
bi += 1
|
325
|
+
return newary
|
326
|
+
end
|
322
327
|
end
|
323
|
-
return newary
|
324
328
|
end
|
325
329
|
end
|
326
330
|
|
327
|
-
module
|
328
|
-
|
329
|
-
|
331
|
+
module Invoca
|
332
|
+
module Utils
|
333
|
+
module Diffable
|
334
|
+
def diff(b)
|
335
|
+
Diff.new(self, b)
|
336
|
+
end
|
337
|
+
end
|
330
338
|
end
|
331
339
|
end
|
332
340
|
|