comparison src/org/tmatesoft/hg/repo/HgBlameFacility.java @ 558:154718ae23ed

Annotate: refactor/reuse range handling code
author Artem Tikhomirov <tikhomirov.artem@gmail.com>
date Mon, 25 Feb 2013 18:41:44 +0100
parents b9e5ac26dd83
children d3c71498919c
comparison
equal deleted inserted replaced
557:b9e5ac26dd83 558:154718ae23ed
31 import org.tmatesoft.hg.internal.Experimental; 31 import org.tmatesoft.hg.internal.Experimental;
32 import org.tmatesoft.hg.internal.IntMap; 32 import org.tmatesoft.hg.internal.IntMap;
33 import org.tmatesoft.hg.internal.IntVector; 33 import org.tmatesoft.hg.internal.IntVector;
34 import org.tmatesoft.hg.internal.DiffHelper.LineSequence; 34 import org.tmatesoft.hg.internal.DiffHelper.LineSequence;
35 import org.tmatesoft.hg.internal.DiffHelper.LineSequence.ByteChain; 35 import org.tmatesoft.hg.internal.DiffHelper.LineSequence.ByteChain;
36 import org.tmatesoft.hg.internal.RangeSeq;
36 import org.tmatesoft.hg.repo.HgBlameFacility.RevisionDescriptor.Recipient; 37 import org.tmatesoft.hg.repo.HgBlameFacility.RevisionDescriptor.Recipient;
37 import org.tmatesoft.hg.util.Adaptable; 38 import org.tmatesoft.hg.util.Adaptable;
38 import org.tmatesoft.hg.util.CancelledException; 39 import org.tmatesoft.hg.util.CancelledException;
39 import org.tmatesoft.hg.util.Pair; 40 import org.tmatesoft.hg.util.Pair;
40 41
738 return contentBlock.seq.data(from, from + length); 739 return contentBlock.seq.data(from, from + length);
739 } 740 }
740 } 741 }
741 742
742 743
743 static class EqualBlocksCollector implements DiffHelper.MatchInspector<LineSequence> { 744 private static class EqualBlocksCollector implements DiffHelper.MatchInspector<LineSequence> {
744 // FIXME replace with RangeSeq 745 private final RangeSeq matches = new RangeSeq();
745 private final IntVector matches = new IntVector(10*3, 2*3);
746 746
747 public void begin(LineSequence s1, LineSequence s2) { 747 public void begin(LineSequence s1, LineSequence s2) {
748 } 748 }
749 749
750 public void match(int startSeq1, int startSeq2, int matchLength) { 750 public void match(int startSeq1, int startSeq2, int matchLength) {
751 matches.add(startSeq1); 751 matches.add(startSeq1, startSeq2, matchLength);
752 matches.add(startSeq2);
753 matches.add(matchLength);
754 } 752 }
755 753
756 public void end() { 754 public void end() {
757 } 755 }
758 756
759 // true when specified line in origin is equal to a line in target 757 public int reverseMapLine(int ln) {
760 public boolean includesOriginLine(int ln) { 758 return matches.reverseMapLine(ln);
761 return includes(ln, 0); 759 }
762 } 760
763
764 // true when specified line in target is equal to a line in origin
765 public boolean includesTargetLine(int ln) {
766 return includes(ln, 1);
767 }
768
769 public void intersectWithTarget(int start, int length, IntVector result) { 761 public void intersectWithTarget(int start, int length, IntVector result) {
770 int s = start; 762 int s = start;
771 for (int l = start, x = start + length; l < x; l++) { 763 for (int l = start, x = start + length; l < x; l++) {
772 if (!includesTargetLine(l)) { 764 if (!matches.includesTargetLine(l)) {
773 if (l - s > 0) { 765 if (l - s > 0) {
774 result.add(s); 766 result.add(s);
775 result.add(l - s); 767 result.add(l - s);
776 } 768 }
777 s = l+1; 769 s = l+1;
781 result.add(s); 773 result.add(s);
782 result.add((start + length) - s); 774 result.add((start + length) - s);
783 } 775 }
784 } 776 }
785 777
786 /**
787 * find out line index in origin that matches specifid target line
788 */
789 public int reverseMapLine(int targetLine) {
790 for (int i = 0; i < matches.size(); i +=3) {
791 int os = matches.get(i);
792 int ts = matches.get(i + 1);
793 int l = matches.get(i + 2);
794 if (ts > targetLine) {
795 return -1;
796 }
797 if (ts + l > targetLine) {
798 return os + (targetLine - ts);
799 }
800 }
801 return -1;
802 }
803
804
805 /* 778 /*
806 * intersects [start..start+length) with ranges of target lines, and based on the intersection 779 * intersects [start..start+length) with ranges of target lines, and based on the intersection
807 * breaks initial range into smaller ranges and records them into result, with marker to indicate 780 * breaks initial range into smaller ranges and records them into result, with marker to indicate
808 * whether the range is from initial range (markerSource) or is a result of the intersection with target 781 * whether the range is from initial range (markerSource) or is a result of the intersection with target
809 * (markerTarget) 782 * (markerTarget)
810 */ 783 */
811 public void combineAndMarkRangesWithTarget(int start, int length, int markerSource, int markerTarget, IntVector result) { 784 public void combineAndMarkRangesWithTarget(int start, int length, int markerSource, int markerTarget, IntVector result) {
812 int sourceStart = start, targetStart = start, sourceEnd = start + length; 785 int sourceStart = start, targetStart = start, sourceEnd = start + length;
813 for (int l = sourceStart; l < sourceEnd; l++) { 786 for (int l = sourceStart; l < sourceEnd; l++) {
814 if (includesTargetLine(l)) { 787 if (matches.includesTargetLine(l)) {
815 // l is from target 788 // l is from target
816 if (sourceStart < l) { 789 if (sourceStart < l) {
817 // few lines from source range were not in the target, report them 790 // few lines from source range were not in the target, report them
818 result.add(markerSource); 791 result.add(markerSource);
819 result.add(sourceStart); 792 result.add(sourceStart);
846 result.add(markerTarget); 819 result.add(markerTarget);
847 result.add(targetStart); 820 result.add(targetStart);
848 result.add(sourceEnd - targetStart); 821 result.add(sourceEnd - targetStart);
849 } 822 }
850 } 823 }
851
852 private boolean includes(int ln, int o) {
853 for (int i = 2; i < matches.size(); o += 3, i+=3) {
854 int rangeStart = matches.get(o);
855 if (rangeStart > ln) {
856 return false;
857 }
858 int rangeLen = matches.get(i);
859 if (rangeStart + rangeLen > ln) {
860 return true;
861 }
862 }
863 return false;
864 }
865 } 824 }
866 825
867 private static class AnnotateRev implements RevisionDescriptor { 826 private static class AnnotateRev implements RevisionDescriptor {
868 public ContentBlock origin, target; 827 public ContentBlock origin, target;
869 public int originCset, targetCset, mergeCset, fileRevIndex; 828 public int originCset, targetCset, mergeCset, fileRevIndex;
921 EqualBlocksCollector bc = new EqualBlocksCollector(); 880 EqualBlocksCollector bc = new EqualBlocksCollector();
922 bc.match(-1, 5, 3); 881 bc.match(-1, 5, 3);
923 bc.match(-1, 10, 2); 882 bc.match(-1, 10, 2);
924 bc.match(-1, 15, 3); 883 bc.match(-1, 15, 3);
925 bc.match(-1, 20, 3); 884 bc.match(-1, 20, 3);
926 assert !bc.includesTargetLine(4);
927 assert bc.includesTargetLine(7);
928 assert !bc.includesTargetLine(8);
929 assert bc.includesTargetLine(10);
930 assert !bc.includesTargetLine(12);
931 IntVector r = new IntVector(); 885 IntVector r = new IntVector();
932 bc.intersectWithTarget(7, 10, r); 886 bc.intersectWithTarget(7, 10, r);
933 for (int i = 0; i < r.size(); i+=2) { 887 for (int i = 0; i < r.size(); i+=2) {
934 System.out.printf("[%d..%d) ", r.get(i), r.get(i) + r.get(i+1)); 888 System.out.printf("[%d..%d) ", r.get(i), r.get(i) + r.get(i+1));
935 } 889 }