1 19 20 package org.netbeans.lib.editor.util; 21 22 33 34 public abstract class FlyOffsetGapList<E> extends GapList<E> { 35 36 private int offsetGapStart; 38 private int offsetGapLength = Integer.MAX_VALUE / 2; 40 public FlyOffsetGapList() { 41 } 42 43 50 protected abstract int elementRawOffset(E elem); 51 52 58 protected abstract void setElementRawOffset(E elem, int rawOffset); 59 60 66 protected abstract boolean isElementFlyweight(E elem); 67 68 78 protected abstract int elementLength(E elem); 79 80 90 protected int startOffset() { 91 return 0; 92 } 93 94 110 protected final int elementOffset(int index) { 111 E elem = get(index); 112 int offset; 113 if (isElementFlyweight(elem)) { 114 offset = 0; 115 while (--index >= 0) { 116 elem = get(index); 117 offset += elementLength(elem); 118 if (!isElementFlyweight(elem)) { 119 offset += raw2RelOffset(elementRawOffset(elem)); 121 break; 122 } 123 } 124 125 } else { offset = raw2RelOffset(elementRawOffset(elem)); 127 } 128 return startOffset() + offset; 129 } 130 131 141 protected final int elementOrEndOffset(int indexOrSize) { 142 E elem; 143 int offset; 144 if (indexOrSize == size() || isElementFlyweight(elem = get(indexOrSize))) { 146 offset = 0; 147 while (--indexOrSize >= 0) { 148 elem = get(indexOrSize); 149 offset += elementLength(elem); 150 if (!isElementFlyweight(elem)) { 151 offset += raw2RelOffset(elementRawOffset(elem)); 153 break; 154 } 155 } 156 157 } else { offset = raw2RelOffset(elementRawOffset(elem)); 159 } 160 return startOffset() + offset; 161 } 162 163 175 public void defaultInsertUpdate(int offset, int length) { 176 assert (length >= 0); 177 if (offset != offsetGapStart()) { 178 moveOffsetGap(offset, findElementIndex(offset)); 179 } 180 updateOffsetGapLength(-length); 181 updateOffsetGapStart(length); 187 } 188 189 202 public void defaultRemoveUpdate(int offset, int length) { 203 assert (length >= 0); 204 int index = findElementIndex(offset); 205 if (offset != offsetGapStart()) { 206 moveOffsetGap(offset, index); 207 } 208 int size = size(); 209 int removeAreaEndRawOffset = offset + offsetGapLength + length; 210 while (index < size) { 214 E elem = get(index++); 215 if (!isElementFlyweight(elem)) { 216 if (elementRawOffset(elem) < removeAreaEndRawOffset) { 217 setElementRawOffset(elem, removeAreaEndRawOffset); 218 } else { break; 220 } 221 } 222 } 223 updateOffsetGapLength(+length); 224 } 225 226 242 protected final void moveOffsetGap(int offset, int index) { 243 if (offset < offsetGapStart) { int bound = size(); 245 for (int i = index; i < bound; i++) { 246 E elem = get(i); 247 if (!isElementFlyweight(elem)) { 248 int rawOffset = elementRawOffset(elem); 249 if (rawOffset < offsetGapStart) { 250 setElementRawOffset(elem, rawOffset + offsetGapLength); 251 } else { 252 break; 253 } 254 } 255 } 256 257 } else { for (int i = index - 1; i >= 0; i--) { 259 E elem = get(i); 260 if (!isElementFlyweight(elem)) { 261 int rawOffset = elementRawOffset(elem); 262 if (rawOffset >= offsetGapStart) { 263 setElementRawOffset(elem, rawOffset - offsetGapLength); 264 } else { 265 break; 266 } 267 } 268 } 269 } 270 offsetGapStart = offset; 271 } 272 273 protected final int offsetGapStart() { 274 return offsetGapStart; 275 } 276 277 287 protected final void updateOffsetGapStart(int offsetDelta) { 288 offsetGapStart += offsetDelta; 289 } 290 291 protected final int offsetGapLength() { 292 return offsetGapLength; 293 } 294 295 305 protected final void updateOffsetGapLength(int offsetGapLengthDelta) { 306 offsetGapLength += offsetGapLengthDelta; 307 assert (offsetGapLength >= 0); } 309 310 322 protected final int findElementIndex(int offset) { 323 int low = 0; 324 int high = size() - 1; 325 326 while (low <= high) { 327 int index = (low + high) / 2; int elemOffset = elementOffset(index); 329 330 if (elemOffset < offset) { 331 low = index + 1; 332 333 } else if (elemOffset > offset) { 334 high = index - 1; 335 336 } else { while (index > 0) { 338 index--; 339 if (elementOffset(index) < offset) { 340 index++; 341 break; 342 } 343 } 344 low = index; 345 break; 346 } 347 } 348 return low; 349 } 350 351 359 protected void updateElementOffsetAdd(E elem) { 360 if (!isElementFlyweight(elem)) { 361 int offset = elementRawOffset(elem); setElementRawOffset(elem, offset2Raw(offset)); 363 } 364 } 365 366 377 protected void updateElementOffsetRemove(E elem) { 378 if (!isElementFlyweight(elem)) { 379 int rawOffset = raw2RelOffset(elementRawOffset(elem)); 380 rawOffset += startOffset(); 381 setElementRawOffset(elem, rawOffset); 382 } 383 } 384 385 391 private int raw2RelOffset(int rawOffset) { 392 return (rawOffset < offsetGapStart) 393 ? rawOffset 394 : rawOffset - offsetGapLength; 395 } 396 397 403 protected final int offset2Raw(int offset) { 404 offset -= startOffset(); 405 if (offset >= offsetGapStart) { 406 offset += offsetGapLength; 407 } 408 return offset; 409 } 410 411 418 protected void consistencyCheck(boolean checkElementLength) { 419 super.consistencyCheck(); 420 421 if (offsetGapLength < 0) { 422 consistencyError("offsetGapLength < 0"); } 424 425 int lastRawOffset = Integer.MIN_VALUE; 426 int lastOffset = Integer.MIN_VALUE; 427 int lastEndOffset = lastOffset; 428 int size = size(); 429 for (int i = 0; i < size; i++) { 430 E elem = get(i); 431 if (!isElementFlyweight(elem)) { 432 int rawOffset = elementRawOffset(elem); 433 int offset = raw2RelOffset(rawOffset); 434 if (rawOffset < lastRawOffset) { 435 consistencyError("Invalid rawOffset=" + rawOffset + " >= lastRawOffset=" + lastRawOffset + " at index=" + i ); 439 } 440 if (offset < lastOffset) { 441 consistencyError("Invalid offset=" + offset + " >= lastOffset=" + lastOffset + " at index=" + i ); 445 } 446 if (checkElementLength) { int length = elementLength(elem); 448 if (i == 0) { 449 lastEndOffset = offset; 450 } 451 if (offset != lastEndOffset) { 452 consistencyError("Offset=" + offset + " differs from lastEndOffset=" + lastEndOffset + " at index=" + i ); 456 } 457 lastEndOffset += length; 458 } 459 lastRawOffset = rawOffset; 460 lastOffset = offset; 461 462 } else { if (checkElementLength) { 464 if (i == 0) { 465 lastEndOffset = 0; 467 } 468 int length = elementLength(elem); 469 lastEndOffset += length; 470 } 471 } 472 } 473 } 474 475 protected String dumpInternals() { 476 return super.dumpInternals() + ", offGap(s=" + offsetGapStart 477 + ", l=" + offsetGapLength + ")"; 478 } 479 480 } 481 | Popular Tags |