60
def _get_longest_match(self, pos, max_pos, locations):
61
"""Get the longest possible match for the current position."""
67
locations = self.get_idx_matches(pos)
69
# No more matches, just return whatever we have, but we know that
70
# this last position is not going to match anything
75
# We are starting a new range
76
copy_ends = [loc + 1 for loc in locations]
78
locations = None # Consumed
80
# We are currently in the middle of a match
81
next_locations = set(copy_ends).intersection(locations)
82
if len(next_locations):
84
copy_ends = [loc + 1 for loc in next_locations]
86
locations = None # Consumed
88
# But we are done with this match, we should be
89
# starting a new one, though. We will pass back
90
# 'locations' so that we don't have to do another
95
return None, pos, locations
96
return (((min(copy_ends) - range_len, range_start, range_len)),
99
def get_matching_blocks(self, lines, soft=False):
100
"""Return the ranges in lines which match self.lines.
102
:param lines: lines to compress
103
:return: A list of (old_start, new_start, length) tuples which reflect
104
a region in self.lines that is present in lines. The last element
105
of the list is always (old_len, new_len, 0) to provide a end point
106
for generating instructions from the matching blocks list.
110
self.set_right_lines(lines)
113
result_append = result.append
116
min_match_bytes = 200
118
block, pos, locations = self._get_longest_match(pos, max_pos,
120
if block is not None:
121
# Check to see if we are matching fewer than 5 characters,
122
# which is turned into a simple 'insert', rather than a copy
123
# If we have more than 5 lines, we definitely have more than 5
125
if block[-1] < min_match_bytes:
126
# This block may be a 'short' block, check
127
old_start, new_start, range_len = block
128
matched_bytes = sum(map(len,
129
lines[new_start:new_start + range_len]))
130
if matched_bytes < min_match_bytes:
132
if block is not None:
134
result_append((len(self.lines), len(lines), 0))
60
137
def _get_matching_lines(self):
61
138
"""Return a dictionary showing matching lines."""
87
164
self._right_lines = lines
90
def _get_longest_match(equivalence_table, pos, max_pos, locations):
91
"""Get the longest possible match for the current position."""
97
locations = equivalence_table.get_idx_matches(pos)
99
# No more matches, just return whatever we have, but we know that
100
# this last position is not going to match anything
104
if copy_ends is None:
105
# We are starting a new range
106
copy_ends = [loc + 1 for loc in locations]
108
locations = None # Consumed
110
# We are currently in the middle of a match
111
next_locations = set(copy_ends).intersection(locations)
112
if len(next_locations):
114
copy_ends = [loc + 1 for loc in next_locations]
116
locations = None # Consumed
118
# But we are done with this match, we should be
119
# starting a new one, though. We will pass back 'locations'
120
# so that we don't have to do another lookup.
123
if copy_ends is None:
124
return None, pos, locations
125
return ((min(copy_ends) - range_len, range_start, range_len)), pos, locations
168
def make_delta(source_bytes, target_bytes):
169
"""Create a delta from source to target."""
170
line_locations = EquivalenceTable([])
128
174
def apply_delta(basis, delta):