1 19 20 package org.netbeans.lib.editor.view; 21 22 34 35 class GapObjectArray { 36 37 private static final Object [] EMPTY_ARRAY = new Object [0]; 38 39 43 private Object [] array; 44 45 46 private int gapStart; 47 48 49 private int gapLength; 50 51 public GapObjectArray() { 52 this.array = EMPTY_ARRAY; 53 } 54 55 64 public GapObjectArray(Object [] array, int length) { 65 this.array = array; 66 this.gapStart = length; 67 this.gapLength = array.length - length; 68 } 69 70 73 public int getItemCount() { 74 return array.length - gapLength; 75 } 76 77 83 public Object getItem(int index) { 84 return array[(index < gapStart) ? index : (index + gapLength)]; 85 } 86 87 public void copyItems(int srcStartIndex, int srcEndIndex, 88 Object [] dest, int destIndex) { 89 90 rangeCheck(srcStartIndex, srcEndIndex - srcStartIndex); 91 92 if (srcEndIndex < gapStart) { System.arraycopy(array, srcStartIndex, 94 dest, destIndex, srcEndIndex - srcStartIndex); 95 96 } else { if (srcStartIndex >= gapStart) { System.arraycopy(array, srcStartIndex + gapLength, dest, destIndex, 99 srcEndIndex - srcStartIndex); 100 101 } else { int beforeGap = gapStart - srcStartIndex; 103 System.arraycopy(array, srcStartIndex, dest, destIndex, beforeGap); 104 System.arraycopy(array, gapStart + gapLength, dest, destIndex + beforeGap, 105 srcEndIndex - srcStartIndex - beforeGap); 106 } 107 } 108 } 109 110 public final int getGapStart() { return gapStart; 112 } 113 114 public void replace(int index, int removeCount, Object [] newItems) { 115 remove(index, removeCount); 116 insertAll(index, newItems); 117 } 118 119 public void insertItem(int index, Object item) { 120 indexCheck(index); 121 122 if (gapLength == 0) { 123 enlargeGap(1); 124 } 125 if (index != gapStart) { 126 moveGap(index); 127 } 128 array[gapStart++] = item; 129 gapLength--; 130 } 131 132 public void insertAll(int index, Object [] items) { 133 insertAll(index, items, 0, items.length); 134 } 135 136 public void insertAll(int index, Object [] items, int off, int len) { 137 indexCheck(index); 138 139 if (items.length == 0) { 140 return; 141 } 142 143 int extraLength = len - gapLength; 144 if (extraLength > 0) { 145 enlargeGap(extraLength); 146 } 147 if (index != gapStart) { 148 moveGap(index); 149 } 150 System.arraycopy(items, off, array, gapStart, len); 151 gapStart += len; 152 gapLength -= len; 153 } 154 155 public void ensureCapacity(int minCapacity) { 156 if (minCapacity < 0) { 157 throw new IllegalArgumentException ("minCapacity=" + minCapacity + " < 0"); } 159 160 int capacity = array.length; 161 if (capacity == 0) { setCapacity(minCapacity); 163 } else if (minCapacity > capacity) { enlargeGap(minCapacity - capacity); 165 } 166 } 167 168 public void remove(int index, int count) { 169 remove(index, count, null); 170 } 171 172 public void remove(int index, int count, RemoveUpdater removeUpdater) { 173 rangeCheck(index, count); 174 175 if (count == 0) { 176 return; 177 } 178 179 if (index >= gapStart) { if (index > gapStart) { 181 moveGap(index); 182 } 183 184 index += gapLength; for (int endIndex = index + count; index < endIndex; index++) { 187 if (removeUpdater != null) { 188 removeUpdater.removeUpdate(array[index]); 189 } 190 array[index] = null; 191 } 192 193 } else { int endIndex = index + count; 195 if (endIndex <= gapStart) { 196 if (endIndex < gapStart) { 197 moveGap(endIndex); 198 } 199 gapStart = index; 200 201 } else { for (int clearIndex = index; clearIndex < gapStart; clearIndex++) { 204 if (removeUpdater != null) { 205 removeUpdater.removeUpdate(array[clearIndex]); 206 } 207 array[clearIndex] = null; 208 } 209 210 index = gapStart + gapLength; gapStart = endIndex - count; endIndex += gapLength; 213 214 } 215 216 while (index < endIndex) { 218 if (removeUpdater != null) { 219 removeUpdater.removeUpdate(array[index]); 220 } 221 array[index++] = null; 222 } 223 224 } 225 226 gapLength += count; 227 } 228 229 protected void unoptimizedRemove(int index, int count, RemoveUpdater removeUpdater) { 230 rangeCheck(index, count); 231 232 int endIndex = index + count; 233 if (gapStart != endIndex) { 234 moveGap(endIndex); 235 } 236 237 for (int i = endIndex - 1; i >= index; i--) { 239 if (removeUpdater != null) { 240 removeUpdater.removeUpdate(array[i]); 241 } 242 array[i] = null; 243 } 244 245 gapStart = index; 246 } 247 248 public void compact() { 249 setCapacity(getItemCount()); 250 } 251 252 protected void movedAboveGapUpdate(Object [] array, int index, int count) { 253 } 254 255 protected void movedBelowGapUpdate(Object [] array, int index, int count) { 256 } 257 258 private void moveGap(int index) { 259 if (index <= gapStart) { int moveSize = gapStart - index; 261 System.arraycopy(array, index, array, 262 gapStart + gapLength - moveSize, moveSize); 263 clearEmpty(index, Math.min(moveSize, gapLength)); 264 gapStart = index; 265 movedAboveGapUpdate(array, gapStart + gapLength, moveSize); 266 267 } else { int gapEnd = gapStart + gapLength; 269 int moveSize = index - gapStart; 270 System.arraycopy(array, gapEnd, array, gapStart, moveSize); 271 if (index < gapEnd) { 272 clearEmpty(gapEnd, moveSize); 273 } else { 274 clearEmpty(index, gapLength); 275 } 276 movedBelowGapUpdate(array, gapStart, moveSize); 277 gapStart += moveSize; 278 } 279 } 280 281 private void clearEmpty(int index, int length) { 282 while (--length >= 0) { 283 array[index++] = null; } 285 } 286 287 private void enlargeGap(int extraLength) { 288 int newLength = Math.max(4, 289 Math.max(array.length * 2, array.length + extraLength)); 290 setCapacity(newLength); 291 } 292 293 private void setCapacity(int newCapacity) { 294 int gapEnd = gapStart + gapLength; 295 int afterGapLength = (array.length - gapEnd); 296 int newGapEnd = newCapacity - afterGapLength; 297 Object [] newArray = new Object [newCapacity]; 298 if (newCapacity < gapStart + afterGapLength) { throw new IllegalArgumentException ("newCapacity=" + newCapacity + " < itemCount=" + (gapStart + afterGapLength)); } 302 303 System.arraycopy(array, 0, newArray, 0, gapStart); 304 System.arraycopy(array, gapEnd, newArray, newGapEnd, afterGapLength); 305 array = newArray; 306 gapLength = newGapEnd - gapStart; 307 } 308 309 private void rangeCheck(int index, int count) { 310 if (index < 0 || count < 0 || index + count > getItemCount()) { 311 throw new IndexOutOfBoundsException ("index=" + index + ", count=" + count + ", getItemCount()=" + getItemCount()); } 314 } 315 316 private void indexCheck(int index) { 317 if (index > getItemCount()) { 318 throw new IndexOutOfBoundsException ("index=" + index + ", getItemCount()=" + getItemCount()); } 321 } 322 323 326 void check() { 327 if (gapStart < 0 || gapLength < 0 328 || gapStart + gapLength > array.length 329 ) { 330 throw new IllegalStateException (); 331 } 332 333 for (int i = gapStart + gapLength - 1; i >= gapStart; i--) { 335 if (array[i] != null) { 336 throw new IllegalStateException (); 337 } 338 } 339 } 340 341 public String toStringDetail() { 342 return "gapStart=" + gapStart + ", gapLength=" + gapLength + ", array.length=" + array.length; } 345 346 350 public interface RemoveUpdater { 351 352 356 public void removeUpdate(Object removedItem); 357 358 } 359 360 } 361 | Popular Tags |