comparison src/org/tmatesoft/hg/internal/BlameHelper.java @ 674:cce0387c6041

Introduced dedicated IntSliceSeq/IntTuple in place of IntArray with subsequences
author Artem Tikhomirov <tikhomirov.artem@gmail.com>
date Wed, 17 Jul 2013 15:40:51 +0200
parents 5f52074707b2
children 8625cba0a5a8
comparison
equal deleted inserted replaced
673:545b1d4cc11d 674:cce0387c6041
17 package org.tmatesoft.hg.internal; 17 package org.tmatesoft.hg.internal;
18 18
19 import static org.tmatesoft.hg.core.HgIterateDirection.OldToNew; 19 import static org.tmatesoft.hg.core.HgIterateDirection.OldToNew;
20 import static org.tmatesoft.hg.repo.HgRepository.NO_REVISION; 20 import static org.tmatesoft.hg.repo.HgRepository.NO_REVISION;
21 21
22 import java.util.Iterator;
22 import java.util.LinkedList; 23 import java.util.LinkedList;
23 import java.util.ListIterator; 24 import java.util.ListIterator;
24 25
25 import org.tmatesoft.hg.core.HgCallbackTargetException; 26 import org.tmatesoft.hg.core.HgCallbackTargetException;
26 import org.tmatesoft.hg.internal.DiffHelper.LineSequence; 27 import org.tmatesoft.hg.internal.DiffHelper.LineSequence;
217 private final HgBlameInspector insp; 218 private final HgBlameInspector insp;
218 private final int csetOrigin; 219 private final int csetOrigin;
219 private final int csetTarget; 220 private final int csetTarget;
220 private EqualBlocksCollector p2MergeCommon; 221 private EqualBlocksCollector p2MergeCommon;
221 private int csetMergeParent; 222 private int csetMergeParent;
222 private IntVector mergeRanges; 223 private IntSliceSeq mergeRanges;
223 private final AnnotateRev annotatedRevision; 224 private final AnnotateRev annotatedRevision;
224 private HgCallbackTargetException error; 225 private HgCallbackTargetException error;
225 226
226 public BlameBlockInspector(HgDataFile df, int fileRevIndex, HgBlameInspector inspector, int originCset, int targetCset) { 227 public BlameBlockInspector(HgDataFile df, int fileRevIndex, HgBlameInspector inspector, int originCset, int targetCset) {
227 assert inspector != null; 228 assert inspector != null;
233 } 234 }
234 235
235 public void setMergeParent2(EqualBlocksCollector p2Merge, int parentCset2) { 236 public void setMergeParent2(EqualBlocksCollector p2Merge, int parentCset2) {
236 p2MergeCommon = p2Merge; 237 p2MergeCommon = p2Merge;
237 csetMergeParent = parentCset2; 238 csetMergeParent = parentCset2;
238 mergeRanges = new IntVector(3*10, 3*10); 239 mergeRanges = new IntSliceSeq(3, 10, 10);
239 } 240 }
240 241
241 @Override 242 @Override
242 public void begin(LineSequence s1, LineSequence s2) { 243 public void begin(LineSequence s1, LineSequence s2) {
243 super.begin(s1, s2); 244 super.begin(s1, s2);
296 * NOW, lines from p2 are always reported as pure add (since we need their insertion point to be in p2, not in p1) 297 * NOW, lines from p2 are always reported as pure add (since we need their insertion point to be in p2, not in p1)
297 * and we try to consume p1 changes as soon as we see first p1's range 298 * and we try to consume p1 changes as soon as we see first p1's range
298 */ 299 */
299 int s1TotalLines = s1To - s1From, s1ConsumedLines = 0, s1Start = s1From; 300 int s1TotalLines = s1To - s1From, s1ConsumedLines = 0, s1Start = s1From;
300 301
301 for (int i = 0; i < mergeRanges.size(); i += 3) { 302 for (Iterator<IntTuple> it = mergeRanges.iterator(); it.hasNext();) {
302 final int rangeOrigin = mergeRanges.get(i); 303 IntTuple mergeRange = it.next();
303 final int rangeStart = mergeRanges.get(i+1); 304 final int rangeOrigin = mergeRange.at(0);
304 final int rangeLen = mergeRanges.get(i+2); 305 final int rangeStart = mergeRange.at(1);
305 final boolean lastRange = i+3 >= mergeRanges.size(); 306 final int rangeLen = mergeRange.at(2);
307 final boolean lastRange = it.hasNext();
306 final int s1LinesLeft = s1TotalLines - s1ConsumedLines; 308 final int s1LinesLeft = s1TotalLines - s1ConsumedLines;
307 // how many lines we may report as changed (don't use more than in range unless it's the very last range) 309 // how many lines we may report as changed (don't use more than in range unless it's the very last range)
308 final int s1LinesToBorrow = lastRange ? s1LinesLeft : Math.min(s1LinesLeft, rangeLen); 310 final int s1LinesToBorrow = lastRange ? s1LinesLeft : Math.min(s1LinesLeft, rangeLen);
309 if (rangeOrigin != csetMergeParent && s1LinesToBorrow > 0) { 311 if (rangeOrigin != csetMergeParent && s1LinesToBorrow > 0) {
310 ChangeBlockImpl block = getChangeBlock(s1Start, s1LinesToBorrow, rangeStart, rangeLen); 312 ChangeBlockImpl block = getChangeBlock(s1Start, s1LinesToBorrow, rangeStart, rangeLen);
347 try { 349 try {
348 if (p2MergeCommon != null) { 350 if (p2MergeCommon != null) {
349 mergeRanges.clear(); 351 mergeRanges.clear();
350 p2MergeCommon.combineAndMarkRangesWithTarget(s2From, s2To - s2From, csetOrigin, csetMergeParent, mergeRanges); 352 p2MergeCommon.combineAndMarkRangesWithTarget(s2From, s2To - s2From, csetOrigin, csetMergeParent, mergeRanges);
351 int insPoint = s1InsertPoint; // track changes to insertion point 353 int insPoint = s1InsertPoint; // track changes to insertion point
352 for (int i = 0; i < mergeRanges.size(); i += 3) { 354 for (IntTuple mergeRange : mergeRanges) {
353 int rangeOrigin = mergeRanges.get(i); 355 int rangeOrigin = mergeRange.at(0);
354 int rangeStart = mergeRanges.get(i+1); 356 int rangeStart = mergeRange.at(1);
355 int rangeLen = mergeRanges.get(i+2); 357 int rangeLen = mergeRange.at(2);
356 ChangeBlockImpl block = getAddBlock(rangeStart, rangeLen, insPoint); 358 ChangeBlockImpl block = getAddBlock(rangeStart, rangeLen, insPoint);
357 block.setOriginAndTarget(rangeOrigin, csetTarget); 359 block.setOriginAndTarget(rangeOrigin, csetTarget);
358 insp.added(block); 360 insp.added(block);
359 // indicate insPoint moved down number of lines we just reported 361 // indicate insPoint moved down number of lines we just reported
360 insPoint += rangeLen; 362 insPoint += rangeLen;
617 } 619 }
618 } 620 }
619 621
620 622
621 private static class EqualBlocksCollector implements DiffHelper.MatchInspector<LineSequence> { 623 private static class EqualBlocksCollector implements DiffHelper.MatchInspector<LineSequence> {
622 private final RangeSeq matches = new RangeSeq(); 624 private final RangePairSeq matches = new RangePairSeq();
623 625
624 public void begin(LineSequence s1, LineSequence s2) { 626 public void begin(LineSequence s1, LineSequence s2) {
625 } 627 }
626 628
627 public void match(int startSeq1, int startSeq2, int matchLength) { 629 public void match(int startSeq1, int startSeq2, int matchLength) {
656 * intersects [start..start+length) with ranges of target lines, and based on the intersection 658 * intersects [start..start+length) with ranges of target lines, and based on the intersection
657 * breaks initial range into smaller ranges and records them into result, with marker to indicate 659 * breaks initial range into smaller ranges and records them into result, with marker to indicate
658 * whether the range is from initial range (markerSource) or is a result of the intersection with target 660 * whether the range is from initial range (markerSource) or is a result of the intersection with target
659 * (markerTarget) 661 * (markerTarget)
660 */ 662 */
661 public void combineAndMarkRangesWithTarget(int start, int length, int markerSource, int markerTarget, IntVector result) { 663 public void combineAndMarkRangesWithTarget(int start, int length, int markerSource, int markerTarget, IntSliceSeq result) {
664 assert result.sliceSize() == 3;
662 int sourceStart = start, targetStart = start, sourceEnd = start + length; 665 int sourceStart = start, targetStart = start, sourceEnd = start + length;
663 for (int l = sourceStart; l < sourceEnd; l++) { 666 for (int l = sourceStart; l < sourceEnd; l++) {
664 if (matches.includesTargetLine(l)) { 667 if (matches.includesTargetLine(l)) {
665 // l is from target 668 // l is from target
666 if (sourceStart < l) { 669 if (sourceStart < l) {
667 // few lines from source range were not in the target, report them 670 // few lines from source range were not in the target, report them
668 result.add(markerSource); 671 result.add(markerSource, sourceStart, l - sourceStart);
669 result.add(sourceStart);
670 result.add(l - sourceStart);
671 } 672 }
672 // indicate the earliest line from source range to use 673 // indicate the earliest line from source range to use
673 sourceStart = l + 1; 674 sourceStart = l + 1;
674 } else { 675 } else {
675 // l is not in target 676 // l is not in target
676 if (targetStart < l) { 677 if (targetStart < l) {
677 // report lines from target range 678 // report lines from target range
678 result.add(markerTarget); 679 result.add(markerTarget, targetStart, l - targetStart);
679 result.add(targetStart);
680 result.add(l - targetStart);
681 } 680 }
682 // next line *may* be from target 681 // next line *may* be from target
683 targetStart = l + 1; 682 targetStart = l + 1;
684 } 683 }
685 } 684 }
686 // if source range end with line from target, sourceStart would be == sourceEnd, and we need to add range with markerTarget 685 // if source range end with line from target, sourceStart would be == sourceEnd, and we need to add range with markerTarget
687 // if source range doesn't end with target line, targetStart == sourceEnd, while sourceStart < sourceEnd 686 // if source range doesn't end with target line, targetStart == sourceEnd, while sourceStart < sourceEnd
688 if (sourceStart < sourceEnd) { 687 if (sourceStart < sourceEnd) {
689 assert targetStart == sourceEnd; 688 assert targetStart == sourceEnd;
690 // something left from the source range 689 // something left from the source range
691 result.add(markerSource); 690 result.add(markerSource, sourceStart, sourceEnd - sourceStart);
692 result.add(sourceStart);
693 result.add(sourceEnd - sourceStart);
694 } else if (targetStart < sourceEnd) { 691 } else if (targetStart < sourceEnd) {
695 assert sourceStart == sourceEnd; 692 assert sourceStart == sourceEnd;
696 result.add(markerTarget); 693 result.add(markerTarget, targetStart, sourceEnd - targetStart);
697 result.add(targetStart);
698 result.add(sourceEnd - targetStart);
699 } 694 }
700 } 695 }
701 } 696 }
702 697
703 private static class AnnotateRev implements RevisionDescriptor { 698 private static class AnnotateRev implements RevisionDescriptor {
768 bc.intersectWithTarget(7, 10, r); 763 bc.intersectWithTarget(7, 10, r);
769 for (int i = 0; i < r.size(); i+=2) { 764 for (int i = 0; i < r.size(); i+=2) {
770 System.out.printf("[%d..%d) ", r.get(i), r.get(i) + r.get(i+1)); 765 System.out.printf("[%d..%d) ", r.get(i), r.get(i) + r.get(i+1));
771 } 766 }
772 System.out.println(); 767 System.out.println();
773 r.clear(); 768 IntSliceSeq mr = new IntSliceSeq(3);
774 bc.combineAndMarkRangesWithTarget(0, 16, 508, 514, r); 769 bc.combineAndMarkRangesWithTarget(0, 16, 508, 514, mr);
775 for (int i = 0; i < r.size(); i+=3) { 770 for (IntTuple t : mr) {
776 System.out.printf("%d:[%d..%d) ", r.get(i), r.get(i+1), r.get(i+1) + r.get(i+2)); 771 System.out.printf("%d:[%d..%d) ", t.at(0), t.at(1), t.at(1) + t.at(2));
777 } 772 }
778 } 773 }
779 } 774 }