1 19 20 package org.netbeans.editor; 21 22 34 35 public class GapObjectArray implements ObjectArray, ObjectArray.CopyItems { 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 public int getItemCount() { 71 return array.length - gapLength; 72 } 73 74 public Object getItem(int index) { 75 return array[(index < gapStart) ? index : (index + gapLength)]; 76 } 77 78 public void copyItems(int srcStartIndex, int srcEndIndex, 79 Object [] dest, int destIndex) { 80 81 rangeCheck(srcStartIndex, srcEndIndex - srcStartIndex); 82 83 if (srcEndIndex < gapStart) { System.arraycopy(array, srcStartIndex, 85 dest, destIndex, srcEndIndex - srcStartIndex); 86 87 } else { if (srcStartIndex >= gapStart) { System.arraycopy(array, srcStartIndex + gapLength, dest, destIndex, 90 srcEndIndex - srcStartIndex); 91 92 } else { int beforeGap = gapStart - srcStartIndex; 94 System.arraycopy(array, srcStartIndex, dest, destIndex, beforeGap); 95 System.arraycopy(array, gapStart + gapLength, dest, destIndex + beforeGap, 96 srcEndIndex - srcStartIndex - beforeGap); 97 } 98 } 99 } 100 101 public void replace(int index, int removeCount, Object [] newItems) { 102 remove(index, removeCount); 103 insertAll(index, newItems); 104 } 105 106 public void insertItem(int index, Object item) { 107 indexCheck(index); 108 109 if (gapLength == 0) { 110 enlargeGap(1); 111 } 112 if (index != gapStart) { 113 moveGap(index); 114 } 115 array[gapStart++] = item; 116 gapLength--; 117 } 118 119 public void insertAll(int index, Object [] items) { 120 insertAll(index, items, 0, items.length); 121 } 122 123 public void insertAll(int index, Object [] items, int off, int len) { 124 indexCheck(index); 125 126 if (items.length == 0) { 127 return; 128 } 129 130 int extraLength = len - gapLength; 131 if (extraLength > 0) { 132 enlargeGap(extraLength); 133 } 134 if (index != gapStart) { 135 moveGap(index); 136 } 137 System.arraycopy(items, off, array, gapStart, len); 138 gapStart += len; 139 gapLength -= len; 140 } 141 142 public void remove(int index, int count) { 143 remove(index, count, null); 144 } 145 146 public void remove(int index, int count, RemoveUpdater removeUpdater) { 147 rangeCheck(index, count); 148 149 if (count == 0) { 150 return; 151 } 152 153 if (index >= gapStart) { if (index > gapStart) { 155 moveGap(index); 156 } 157 158 index += gapLength; for (int endIndex = index + count; index < endIndex; index++) { 161 if (removeUpdater != null) { 162 removeUpdater.removeUpdate(array[index]); 163 } 164 array[index] = null; 165 } 166 167 } else { int endIndex = index + count; 169 if (endIndex <= gapStart) { 170 if (endIndex < gapStart) { 171 moveGap(endIndex); 172 } 173 gapStart = index; 174 175 } else { for (int clearIndex = index; clearIndex < gapStart; clearIndex++) { 178 if (removeUpdater != null) { 179 removeUpdater.removeUpdate(array[clearIndex]); 180 } 181 array[clearIndex] = null; 182 } 183 184 index = gapStart + gapLength; gapStart = endIndex - count; endIndex += gapLength; 187 188 } 189 190 while (index < endIndex) { 192 if (removeUpdater != null) { 193 removeUpdater.removeUpdate(array[index]); 194 } 195 array[index++] = null; 196 } 197 198 } 199 200 gapLength += count; 201 } 202 203 protected void unoptimizedRemove(int index, int count, RemoveUpdater removeUpdater) { 204 rangeCheck(index, count); 205 206 int endIndex = index + count; 207 if (gapStart != endIndex) { 208 moveGap(endIndex); 209 } 210 211 for (int i = endIndex - 1; i >= index; i--) { 213 if (removeUpdater != null) { 214 removeUpdater.removeUpdate(array[i]); 215 } 216 array[i] = null; 217 } 218 219 gapStart = index; 220 } 221 222 public void compact() { 223 if (gapLength > 0) { 224 int newLength = array.length - gapLength; 225 Object [] newArray = new Object [newLength]; 226 int gapEnd = gapStart + gapLength; 227 System.arraycopy(array, 0, newArray, 0, gapStart); 228 System.arraycopy(array, gapEnd, newArray, gapStart, 229 array.length - gapEnd); 230 array = newArray; 231 gapStart = array.length; 232 gapLength = 0; 233 } 234 } 235 236 protected void movedAboveGapUpdate(Object [] array, int index, int count) { 237 } 238 239 protected void movedBelowGapUpdate(Object [] array, int index, int count) { 240 } 241 242 private void moveGap(int index) { 243 if (index <= gapStart) { int moveSize = gapStart - index; 245 System.arraycopy(array, index, array, 246 gapStart + gapLength - moveSize, moveSize); 247 clearEmpty(index, Math.min(moveSize, gapLength)); 248 gapStart = index; 249 movedAboveGapUpdate(array, gapStart + gapLength, moveSize); 250 251 } else { int gapEnd = gapStart + gapLength; 253 int moveSize = index - gapStart; 254 System.arraycopy(array, gapEnd, array, gapStart, moveSize); 255 if (index < gapEnd) { 256 clearEmpty(gapEnd, moveSize); 257 } else { 258 clearEmpty(index, gapLength); 259 } 260 movedBelowGapUpdate(array, gapStart, moveSize); 261 gapStart += moveSize; 262 } 263 } 264 265 private void clearEmpty(int index, int length) { 266 while (--length >= 0) { 267 array[index++] = null; } 269 } 270 271 private void enlargeGap(int extraLength) { 272 int newLength = Math.max(4, 273 Math.max(array.length * 2, array.length + extraLength)); 274 275 int gapEnd = gapStart + gapLength; 276 int afterGapLength = (array.length - gapEnd); 277 int newGapEnd = newLength - afterGapLength; 278 Object [] newArray = new Object [newLength]; 279 System.arraycopy(array, 0, newArray, 0, gapStart); 280 System.arraycopy(array, gapEnd, newArray, newGapEnd, afterGapLength); 281 array = newArray; 282 gapLength = newGapEnd - gapStart; 283 } 284 285 private void rangeCheck(int index, int count) { 286 if (index < 0 || count < 0 || index + count > getItemCount()) { 287 throw new IndexOutOfBoundsException ("index=" + index + ", count=" + count + ", getItemCount()=" + getItemCount()); } 290 } 291 292 private void indexCheck(int index) { 293 if (index > getItemCount()) { 294 throw new IndexOutOfBoundsException ("index=" + index + ", getItemCount()=" + getItemCount()); } 297 } 298 299 302 void check() { 303 if (gapStart < 0 || gapLength < 0 304 || gapStart + gapLength > array.length 305 ) { 306 throw new IllegalStateException (); 307 } 308 309 for (int i = gapStart + gapLength - 1; i >= gapStart; i--) { 311 if (array[i] != null) { 312 throw new IllegalStateException (); 313 } 314 } 315 } 316 317 public String toStringDetail() { 318 return "gapStart=" + gapStart + ", gapLength=" + gapLength + ", array.length=" + array.length; } 321 322 323 public interface RemoveUpdater { 324 325 public void removeUpdate(Object removedItem); 326 327 } 328 329 } 330 | Popular Tags |