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