Mercurial > hg4j
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 } |