comparison src/org/tmatesoft/hg/internal/PatchGenerator.java @ 542:a71a05ec11bc

Towards annotate/blame support: general outline of the functionality
author Artem Tikhomirov <tikhomirov.artem@gmail.com>
date Thu, 14 Feb 2013 16:36:13 +0100
parents 946b13196252
children 1e95f48d9886
comparison
equal deleted inserted replaced
541:946b13196252 542:a71a05ec11bc
156 156
157 public void end() { 157 public void end() {
158 } 158 }
159 } 159 }
160 160
161 static class DeltaDumpInspector implements MatchInspector { 161 static class DeltaInspector implements MatchInspector {
162 protected int changeStartS1, changeStartS2; 162 protected int changeStartS1, changeStartS2;
163 protected ChunkSequence seq1, seq2; 163 protected ChunkSequence seq1, seq2;
164 164
165 165
166 public void begin(ChunkSequence s1, ChunkSequence s2) { 166 public void begin(ChunkSequence s1, ChunkSequence s2) {
168 seq2 = s2; 168 seq2 = s2;
169 changeStartS1 = changeStartS2 = 0; 169 changeStartS1 = changeStartS2 = 0;
170 } 170 }
171 171
172 public void match(int startSeq1, int startSeq2, int matchLength) { 172 public void match(int startSeq1, int startSeq2, int matchLength) {
173 reportDeltaElement(startSeq1, startSeq2); 173 reportDeltaElement(startSeq1, startSeq2, matchLength);
174 changeStartS1 = startSeq1 + matchLength; 174 changeStartS1 = startSeq1 + matchLength;
175 changeStartS2 = startSeq2 + matchLength; 175 changeStartS2 = startSeq2 + matchLength;
176 } 176 }
177 177
178 public void end() { 178 public void end() {
179 if (changeStartS1 < seq1.chunkCount() || changeStartS2 < seq2.chunkCount()) { 179 if (changeStartS1 < seq1.chunkCount() || changeStartS2 < seq2.chunkCount()) {
180 reportDeltaElement(seq1.chunkCount(), seq2.chunkCount()); 180 reportDeltaElement(seq1.chunkCount(), seq2.chunkCount(), 0);
181 } 181 }
182 } 182 }
183 183
184 protected void reportDeltaElement(int matchStartSeq1, int matchStartSeq2) { 184 protected void reportDeltaElement(int matchStartSeq1, int matchStartSeq2, int matchLength) {
185 if (changeStartS1 < matchStartSeq1) { 185 if (changeStartS1 < matchStartSeq1) {
186 if (changeStartS2 < matchStartSeq2) { 186 if (changeStartS2 < matchStartSeq2) {
187 System.out.printf("changed [%d..%d) with [%d..%d)\n", changeStartS1, matchStartSeq1, changeStartS2, matchStartSeq2); 187 changed(changeStartS1, matchStartSeq1, changeStartS2, matchStartSeq2);
188 } else { 188 } else {
189 assert changeStartS2 == matchStartSeq2; 189 assert changeStartS2 == matchStartSeq2;
190 System.out.printf("deleted [%d..%d)\n", changeStartS1, matchStartSeq1); 190 deleted(changeStartS1, matchStartSeq1);
191 } 191 }
192 } else { 192 } else {
193 assert changeStartS1 == matchStartSeq1; 193 assert changeStartS1 == matchStartSeq1;
194 if(changeStartS2 < matchStartSeq2) { 194 if(changeStartS2 < matchStartSeq2) {
195 System.out.printf("added [%d..%d)\n", changeStartS2, matchStartSeq2); 195 added(matchStartSeq1, changeStartS2, matchStartSeq2);
196 } else { 196 } else {
197 assert changeStartS2 == matchStartSeq2; 197 assert changeStartS2 == matchStartSeq2;
198 System.out.printf("adjustent equal blocks %d, %d and %d,%d\n", changeStartS1, matchStartSeq1, changeStartS2, matchStartSeq2); 198 System.out.printf("adjustent equal blocks %d, %d and %d,%d\n", changeStartS1, matchStartSeq1, changeStartS2, matchStartSeq2);
199 } 199 }
200 } 200 }
201 } 201 if (matchLength > 0) {
202 } 202 unchanged(matchStartSeq1, matchStartSeq2, matchLength);
203 203 }
204 static class PatchFillInspector extends DeltaDumpInspector { 204 }
205
206 /**
207 * [s1From..s1To) replaced with [s2From..s2To)
208 */
209 protected void changed(int s1From, int s1To, int s2From, int s2To) {
210 // NO-OP
211 }
212
213 protected void deleted(int s1From, int s1To) {
214 // NO-OP
215 }
216
217 protected void added(int s1InsertPoint, int s2From, int s2To) {
218 // NO-OP
219 }
220
221 protected void unchanged(int s1From, int s2From, int length) {
222 // NO-OP
223 }
224 }
225
226 static class DeltaDumpInspector extends DeltaInspector {
227
228 @Override
229 protected void changed(int s1From, int s1To, int s2From, int s2To) {
230 System.out.printf("changed [%d..%d) with [%d..%d)\n", s1From, s1To, s2From, s2To);
231 }
232
233 @Override
234 protected void deleted(int s1From, int s1To) {
235 System.out.printf("deleted [%d..%d)\n", s1From, s1To);
236 }
237
238 @Override
239 protected void added(int s1InsertPoint, int s2From, int s2To) {
240 System.out.printf("added [%d..%d) at %d\n", s2From, s2To, s1InsertPoint);
241 }
242
243 }
244
245 static class PatchFillInspector extends DeltaInspector {
205 private final Patch deltaCollector; 246 private final Patch deltaCollector;
206 247
207 PatchFillInspector(Patch p) { 248 PatchFillInspector(Patch p) {
208 assert p != null; 249 assert p != null;
209 deltaCollector = p; 250 deltaCollector = p;
210 } 251 }
211 252
212 @Override 253 @Override
213 protected void reportDeltaElement(int matchStartSeq1, int matchStartSeq2) { 254 protected void changed(int s1From, int s1To, int s2From, int s2To) {
214 if (changeStartS1 < matchStartSeq1) { 255 int from = seq1.chunk(s1From).getOffset();
215 int from = seq1.chunk(changeStartS1).getOffset(); 256 int to = seq1.chunk(s1To).getOffset();
216 int to = seq1.chunk(matchStartSeq1).getOffset(); 257 byte[] data = seq2.data(s2From, s2To);
217 byte[] data = seq2.data(changeStartS2, matchStartSeq2); 258 deltaCollector.add(from, to, data);
218 deltaCollector.add(from, to, data); 259 }
219 } else { 260
220 assert changeStartS1 == matchStartSeq1; 261 @Override
221 int insPoint = seq1.chunk(changeStartS1).getOffset(); 262 protected void deleted(int s1From, int s1To) {
222 byte[] data = seq2.data(changeStartS2, matchStartSeq2); 263 int from = seq1.chunk(s1From).getOffset();
223 deltaCollector.add(insPoint, insPoint, data); 264 int to = seq1.chunk(s1To).getOffset();
224 } 265 deltaCollector.add(from, to, new byte[0]);
266 }
267
268 @Override
269 protected void added(int s1InsertPoint, int s2From, int s2To) {
270 int insPoint = seq1.chunk(s1InsertPoint).getOffset();
271 byte[] data = seq2.data(s2From, s2To);
272 deltaCollector.add(insPoint, insPoint, data);
225 } 273 }
226 } 274 }
227 275
228 276
229 277
255 init(prev, content); 303 init(prev, content);
256 findMatchingBlocks(new PatchFillInspector(rv)); 304 findMatchingBlocks(new PatchFillInspector(rv));
257 return rv; 305 return rv;
258 } 306 }
259 307
260 private static class ChunkSequence { 308 /*
309 * TODO shall be parameterized (template?) and refacctored to facilitate matching non lines only
310 * (sequence diff algorithm above doesn't care about sequence nature)
311 */
312 static final class ChunkSequence {
261 313
262 private final byte[] input; 314 private final byte[] input;
263 private ArrayList<ByteChain> lines; 315 private ArrayList<ByteChain> lines;
264 316
265 public ChunkSequence(byte[] data) { 317 public ChunkSequence(byte[] data) {