Mercurial > jhg
comparison src/org/tmatesoft/hg/internal/PatchGenerator.java @ 545:15b406c7cd9d
First round of annotate file is functional
| author | Artem Tikhomirov <tikhomirov.artem@gmail.com> |
|---|---|
| date | Fri, 15 Feb 2013 22:15:13 +0100 |
| parents | 7f5998a9619d |
| children | 83afa680555d |
comparison
equal
deleted
inserted
replaced
| 544:7f5998a9619d | 545:15b406c7cd9d |
|---|---|
| 144 void match(int startSeq1, int startSeq2, int matchLength); | 144 void match(int startSeq1, int startSeq2, int matchLength); |
| 145 void end(); | 145 void end(); |
| 146 } | 146 } |
| 147 | 147 |
| 148 static class MatchDumpInspector<T extends ChunkSequence<?>> implements MatchInspector<T> { | 148 static class MatchDumpInspector<T extends ChunkSequence<?>> implements MatchInspector<T> { |
| 149 private int matchCount; | |
| 150 | |
| 149 public void begin(T s1, T s2) { | 151 public void begin(T s1, T s2) { |
| 152 matchCount = 0; | |
| 150 } | 153 } |
| 151 | 154 |
| 152 public void match(int startSeq1, int startSeq2, int matchLength) { | 155 public void match(int startSeq1, int startSeq2, int matchLength) { |
| 153 System.out.printf("match: from line #%d and line #%d of length %d\n", startSeq1, startSeq2, matchLength); | 156 matchCount++; |
| 157 System.out.printf("match #%d: from line #%d and line #%d of length %d\n", matchCount, startSeq1, startSeq2, matchLength); | |
| 154 } | 158 } |
| 155 | 159 |
| 156 public void end() { | 160 public void end() { |
| 161 if (matchCount == 0) { | |
| 162 System.out.println("NO MATCHES FOUND!"); | |
| 163 } | |
| 157 } | 164 } |
| 158 } | 165 } |
| 159 | 166 |
| 160 static class DeltaInspector<T extends ChunkSequence<?>> implements MatchInspector<T> { | 167 static class DeltaInspector<T extends ChunkSequence<?>> implements MatchInspector<T> { |
| 161 protected int changeStartS1, changeStartS2; | 168 protected int changeStartS1, changeStartS2; |
| 172 changeStartS1 = startSeq1 + matchLength; | 179 changeStartS1 = startSeq1 + matchLength; |
| 173 changeStartS2 = startSeq2 + matchLength; | 180 changeStartS2 = startSeq2 + matchLength; |
| 174 } | 181 } |
| 175 | 182 |
| 176 public void end() { | 183 public void end() { |
| 177 if (changeStartS1 < seq1.chunkCount() || changeStartS2 < seq2.chunkCount()) { | 184 if (changeStartS1 < seq1.chunkCount()-1 || changeStartS2 < seq2.chunkCount()-1) { |
| 178 reportDeltaElement(seq1.chunkCount(), seq2.chunkCount(), 0); | 185 reportDeltaElement(seq1.chunkCount()-1, seq2.chunkCount()-1, 0); |
| 179 } | 186 } |
| 180 } | 187 } |
| 181 | 188 |
| 182 protected void reportDeltaElement(int matchStartSeq1, int matchStartSeq2, int matchLength) { | 189 protected void reportDeltaElement(int matchStartSeq1, int matchStartSeq2, int matchLength) { |
| 183 if (changeStartS1 < matchStartSeq1) { | 190 if (changeStartS1 < matchStartSeq1) { |
| 188 deleted(matchStartSeq2, changeStartS1, matchStartSeq1); | 195 deleted(matchStartSeq2, changeStartS1, matchStartSeq1); |
| 189 } | 196 } |
| 190 } else { | 197 } else { |
| 191 assert changeStartS1 == matchStartSeq1; | 198 assert changeStartS1 == matchStartSeq1; |
| 192 if(changeStartS2 < matchStartSeq2) { | 199 if(changeStartS2 < matchStartSeq2) { |
| 193 added(matchStartSeq1, changeStartS2, matchStartSeq2); | 200 added(changeStartS1, changeStartS2, matchStartSeq2); |
| 194 } else { | 201 } else { |
| 195 assert changeStartS2 == matchStartSeq2; | 202 assert changeStartS2 == matchStartSeq2; |
| 196 System.out.printf("adjustent equal blocks %d, %d and %d,%d\n", changeStartS1, matchStartSeq1, changeStartS2, matchStartSeq2); | 203 System.out.printf("adjustent equal blocks %d, %d and %d,%d\n", changeStartS1, matchStartSeq1, changeStartS2, matchStartSeq2); |
| 197 } | 204 } |
| 198 } | 205 } |
| 235 | 242 |
| 236 @Override | 243 @Override |
| 237 protected void added(int s1InsertPoint, int s2From, int s2To) { | 244 protected void added(int s1InsertPoint, int s2From, int s2To) { |
| 238 System.out.printf("added [%d..%d) at %d\n", s2From, s2To, s1InsertPoint); | 245 System.out.printf("added [%d..%d) at %d\n", s2From, s2To, s1InsertPoint); |
| 239 } | 246 } |
| 240 | 247 |
| 248 @Override | |
| 249 protected void unchanged(int s1From, int s2From, int length) { | |
| 250 System.out.printf("same [%d..%d) and [%d..%d)\n", s1From, s1From + length, s2From, s2From + length); | |
| 251 } | |
| 241 } | 252 } |
| 242 | 253 |
| 243 public static void main(String[] args) throws Exception { | 254 public static void main(String[] args) throws Exception { |
| 244 PatchGenerator<LineSequence> pg1 = new PatchGenerator<LineSequence>(); | 255 PatchGenerator<LineSequence> pg1 = new PatchGenerator<LineSequence>(); |
| 245 pg1.init(LineSequence.newlines("hello".getBytes()), LineSequence.newlines("hello\nworld".getBytes())); | 256 // pg1.init(LineSequence.newlines("hello\nabc".getBytes()), LineSequence.newlines("hello\nworld".getBytes())); |
| 257 // pg1.init(LineSequence.newlines("".getBytes()), LineSequence.newlines("hello\nworld".getBytes())); | |
| 258 pg1.init(LineSequence.newlines("hello\nworld".getBytes()), LineSequence.newlines("".getBytes())); | |
| 246 pg1.findMatchingBlocks(new MatchDumpInspector<LineSequence>()); | 259 pg1.findMatchingBlocks(new MatchDumpInspector<LineSequence>()); |
| 247 pg1.findMatchingBlocks(new DeltaDumpInspector<LineSequence>()); | 260 pg1.findMatchingBlocks(new DeltaDumpInspector<LineSequence>()); |
| 248 if (Boolean.FALSE.booleanValue()) { | 261 if (Boolean.FALSE.booleanValue()) { |
| 249 return; | 262 return; |
| 250 } | 263 } |
| 291 | 304 |
| 292 public static LineSequence newlines(byte[] array) { | 305 public static LineSequence newlines(byte[] array) { |
| 293 return new LineSequence(array).splitByNewlines(); | 306 return new LineSequence(array).splitByNewlines(); |
| 294 } | 307 } |
| 295 | 308 |
| 309 // sequence ends with fake, empty line chunk | |
| 296 public LineSequence splitByNewlines() { | 310 public LineSequence splitByNewlines() { |
| 297 lines = new ArrayList<ByteChain>(); | 311 lines = new ArrayList<ByteChain>(); |
| 298 int lastStart = 0; | 312 int lastStart = 0; |
| 299 for (int i = 0; i < input.length; i++) { | 313 for (int i = 0; i < input.length; i++) { |
| 300 if (input[i] == '\n') { | 314 if (input[i] == '\n') { |
| 310 } | 324 } |
| 311 if (lastStart < input.length) { | 325 if (lastStart < input.length) { |
| 312 lines.add(new ByteChain(lastStart, input.length)); | 326 lines.add(new ByteChain(lastStart, input.length)); |
| 313 } | 327 } |
| 314 // empty chunk to keep offset of input end | 328 // empty chunk to keep offset of input end |
| 315 lines.add(new ByteChain(input.length, input.length)); | 329 lines.add(new ByteChain(input.length)); |
| 316 return this; | 330 return this; |
| 317 } | 331 } |
| 318 | 332 |
| 319 public ByteChain chunk(int index) { | 333 public ByteChain chunk(int index) { |
| 320 return lines.get(index); | 334 return lines.get(index); |
| 336 | 350 |
| 337 | 351 |
| 338 final class ByteChain implements Chunk { | 352 final class ByteChain implements Chunk { |
| 339 private final int start, end; | 353 private final int start, end; |
| 340 private final int hash; | 354 private final int hash; |
| 355 | |
| 356 /** | |
| 357 * construct a chunk with a sole purpose to keep | |
| 358 * offset of the data end | |
| 359 */ | |
| 360 ByteChain(int offset) { | |
| 361 start = end = offset; | |
| 362 // ensure this chunk doesn't match trailing chunk of another sequence | |
| 363 hash = System.identityHashCode(this); | |
| 364 } | |
| 341 | 365 |
| 342 ByteChain(int s, int e) { | 366 ByteChain(int s, int e) { |
| 343 start = s; | 367 start = s; |
| 344 end = e; | 368 end = e; |
| 345 hash = calcHash(input, s, e); | 369 hash = calcHash(input, s, e); |
