comparison src/org/tmatesoft/hg/internal/FileAnnotation.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 52263817b998
comparison
equal deleted inserted replaced
557:b9e5ac26dd83 558:154718ae23ed
14 * the terms of a license other than GNU General Public License 14 * the terms of a license other than GNU General Public License
15 * contact TMate Software at support@hg4j.com 15 * contact TMate Software at support@hg4j.com
16 */ 16 */
17 package org.tmatesoft.hg.internal; 17 package org.tmatesoft.hg.internal;
18 18
19 import java.util.Formatter;
20 19
21 import org.tmatesoft.hg.core.HgIterateDirection; 20 import org.tmatesoft.hg.core.HgIterateDirection;
22 import org.tmatesoft.hg.repo.HgBlameFacility; 21 import org.tmatesoft.hg.repo.HgBlameFacility;
23 import org.tmatesoft.hg.repo.HgInvalidStateException; 22 import org.tmatesoft.hg.repo.HgInvalidStateException;
24 import org.tmatesoft.hg.repo.HgBlameFacility.AddBlock; 23 import org.tmatesoft.hg.repo.HgBlameFacility.AddBlock;
158 157
159 public int totalLines() { 158 public int totalLines() {
160 return FileAnnotation.this.knownLines.length; 159 return FileAnnotation.this.knownLines.length;
161 } 160 }
162 } 161 }
163
164 private static class RangeSeq {
165 // XXX smth like IntSliceVector to access triples (or slices of any size, in fact)
166 // with easy indexing, e.g. #get(sliceIndex, indexWithinSlice)
167 // and vect.get(7,2) instead of vect.get(7*SIZEOF_SLICE+2)
168 private final IntVector ranges = new IntVector(3*10, 3*5);
169 private int count;
170
171 public void add(int start1, int start2, int length) {
172 if (count > 0) {
173 int lastIndex = 3 * (count-1);
174 int lastS1 = ranges.get(lastIndex);
175 int lastS2 = ranges.get(lastIndex + 1);
176 int lastLen = ranges.get(lastIndex + 2);
177 if (start1 == lastS1 + lastLen && start2 == lastS2 + lastLen) {
178 // new range continues the previous one - just increase the length
179 ranges.set(lastIndex + 2, lastLen + length);
180 return;
181 }
182 }
183 ranges.add(start1, start2, length);
184 count++;
185 }
186
187 public void clear() {
188 ranges.clear();
189 count = 0;
190 }
191
192 public int size() {
193 return count;
194 }
195
196 public int mapLineIndex(int ln) {
197 for (int i = 0; i < ranges.size(); i += 3) {
198 int s1 = ranges.get(i);
199 if (s1 > ln) {
200 return -1;
201 }
202 int l = ranges.get(i+2);
203 if (s1 + l > ln) {
204 int s2 = ranges.get(i + 1);
205 return s2 + (ln - s1);
206 }
207 }
208 return -1;
209 }
210
211 public RangeSeq intersect(RangeSeq target) {
212 RangeSeq v = new RangeSeq();
213 for (int i = 0; i < ranges.size(); i += 3) {
214 int originLine = ranges.get(i);
215 int targetLine = ranges.get(i + 1);
216 int length = ranges.get(i + 2);
217 int startTargetLine = -1, startOriginLine = -1, c = 0;
218 for (int j = 0; j < length; j++) {
219 int lnInFinal = target.mapLineIndex(targetLine + j);
220 if (lnInFinal == -1 || (startTargetLine != -1 && lnInFinal != startTargetLine + c)) {
221 // the line is not among "same" in ultimate origin
222 // or belongs to another/next "same" chunk
223 if (startOriginLine == -1) {
224 continue;
225 }
226 v.add(startOriginLine, startTargetLine, c);
227 c = 0;
228 startOriginLine = startTargetLine = -1;
229 // fall-through to check if it's not complete miss but a next chunk
230 }
231 if (lnInFinal != -1) {
232 if (startOriginLine == -1) {
233 startOriginLine = originLine + j;
234 startTargetLine = lnInFinal;
235 c = 1;
236 } else {
237 // lnInFinal != startTargetLine + s is covered above
238 assert lnInFinal == startTargetLine + c;
239 c++;
240 }
241 }
242 }
243 if (startOriginLine != -1) {
244 assert c > 0;
245 v.add(startOriginLine, startTargetLine, c);
246 }
247 }
248 return v;
249 }
250
251 @SuppressWarnings("unused")
252 public CharSequence dump() {
253 StringBuilder sb = new StringBuilder();
254 Formatter f = new Formatter(sb);
255 for (int i = 0; i < ranges.size(); i += 3) {
256 int s1 = ranges.get(i);
257 int s2 = ranges.get(i + 1);
258 int len = ranges.get(i + 2);
259 f.format("[%d..%d) == [%d..%d); ", s1, s1 + len, s2, s2 + len);
260 }
261 return sb;
262 }
263
264 @Override
265 public String toString() {
266 return String.format("RangeSeq[%d]:%s", count, dump());
267 }
268 }
269 } 162 }