1 11 package org.eclipse.jface.text; 12 13 import org.eclipse.core.runtime.Assert; 14 15 16 38 public class GapTextStore implements ITextStore { 39 43 private final int fMinGapSize; 44 48 private final int fMaxGapSize; 49 55 private final float fSizeMultiplier; 56 57 58 private char[] fContent= new char[0]; 59 60 private int fGapStart= 0; 61 62 private int fGapEnd= 0; 63 68 private int fThreshold= 0; 69 70 79 public GapTextStore(int lowWatermark, int highWatermark) { 80 93 this(highWatermark / 2, highWatermark / 2, 0f); 94 } 95 96 102 public GapTextStore() { 103 this(256, 4096, 0.1f); 104 } 105 106 131 public GapTextStore(int minSize, int maxSize, float maxGapFactor) { 132 Assert.isLegal(0f <= maxGapFactor && maxGapFactor <= 1f); 133 Assert.isLegal(0 <= minSize && minSize <= maxSize); 134 fMinGapSize= minSize; 135 fMaxGapSize= maxSize; 136 fSizeMultiplier= 1 / (1 - maxGapFactor / 2); 137 } 138 139 142 public final char get(int offset) { 143 if (offset < fGapStart) 144 return fContent[offset]; 145 146 return fContent[offset + gapSize()]; 147 } 148 149 152 public final String get(int offset, int length) { 153 if (fGapStart <= offset) 154 return new String (fContent, offset + gapSize() , length); 155 156 final int end= offset + length; 157 158 if (end <= fGapStart) 159 return new String (fContent, offset, length); 160 161 StringBuffer buf= new StringBuffer (length); 162 buf.append(fContent, offset, fGapStart - offset); 163 buf.append(fContent, fGapEnd, end - fGapStart); 164 return buf.toString(); 165 } 166 167 170 public final int getLength() { 171 return fContent.length - gapSize(); 172 } 173 174 177 public final void set(String text) { 178 184 replace(0, getLength(), text); 185 } 186 187 190 public final void replace(int offset, int length, String text) { 191 if (text == null) { 192 adjustGap(offset, length, 0); 193 } else { 194 int textLength= text.length(); 195 adjustGap(offset, length, textLength); 196 if (textLength != 0) 197 text.getChars(0, textLength, fContent, offset); 198 } 199 } 200 201 211 private void adjustGap(int offset, int remove, int add) { 212 final int oldGapSize= gapSize(); 213 final int newGapSize= oldGapSize - add + remove; 214 final boolean reuseArray= 0 <= newGapSize && newGapSize <= fThreshold; 215 216 final int newGapStart= offset + add; 217 final int newGapEnd; 218 219 if (reuseArray) 220 newGapEnd= moveGap(offset, remove, oldGapSize, newGapSize, newGapStart); 221 else 222 newGapEnd= reallocate(offset, remove, oldGapSize, newGapSize, newGapStart); 223 224 fGapStart= newGapStart; 225 fGapEnd= newGapEnd; 226 } 227 228 239 private int moveGap(int offset, int remove, int oldGapSize, int newGapSize, int newGapStart) { 240 244 final int newGapEnd= newGapStart + newGapSize; 245 if (offset < fGapStart) { 246 int afterRemove= offset + remove; 247 if (afterRemove < fGapStart) { 248 final int betweenSize= fGapStart - afterRemove; 249 arrayCopy(afterRemove, fContent, newGapEnd, betweenSize); 250 } 251 } else { 253 final int offsetShifted= offset + oldGapSize; 254 final int betweenSize= offsetShifted - fGapEnd; arrayCopy(fGapEnd, fContent, fGapStart, betweenSize); 256 } 257 return newGapEnd; 258 } 259 260 271 private int reallocate(int offset, int remove, final int oldGapSize, int newGapSize, final int newGapStart) { 272 final int newLength= fContent.length - newGapSize; 274 int newArraySize= (int) (newLength * fSizeMultiplier); 276 newGapSize= newArraySize - newLength; 277 278 if (newGapSize < fMinGapSize) { 280 newGapSize= fMinGapSize; 281 newArraySize= newLength + newGapSize; 282 } else if (newGapSize > fMaxGapSize) { 283 newGapSize= fMaxGapSize; 284 newArraySize= newLength + newGapSize; 285 } 286 287 fThreshold= newGapSize * 2; 289 final char[] newContent= allocate(newArraySize); 290 final int newGapEnd= newGapStart + newGapSize; 291 292 299 if (offset < fGapStart) { 300 arrayCopy(0, newContent, 0, offset); 302 int afterRemove= offset + remove; 303 if (afterRemove < fGapStart) { 304 final int betweenSize= fGapStart - afterRemove; 306 arrayCopy(afterRemove, newContent, newGapEnd, betweenSize); 307 final int restSize= fContent.length - fGapEnd; 308 arrayCopy(fGapEnd, newContent, newGapEnd + betweenSize, restSize); 309 } else { 310 afterRemove += oldGapSize; 312 final int restSize= fContent.length - afterRemove; 313 arrayCopy(afterRemove, newContent, newGapEnd, restSize); 314 } 315 } else { 316 arrayCopy(0, newContent, 0, fGapStart); 318 final int offsetShifted= offset + oldGapSize; 319 final int betweenSize= offsetShifted - fGapEnd; 320 arrayCopy(fGapEnd, newContent, fGapStart, betweenSize); 321 final int afterRemove= offsetShifted + remove; 322 final int restSize= fContent.length - afterRemove; 323 arrayCopy(afterRemove, newContent, newGapEnd, restSize); 324 } 325 326 fContent= newContent; 327 return newGapEnd; 328 } 329 330 337 private char[] allocate(int size) { 338 return new char[size]; 339 } 340 341 346 private void arrayCopy(int srcPos, char[] dest, int destPos, int length) { 347 if (length != 0) 348 System.arraycopy(fContent, srcPos, dest, destPos, length); 349 } 350 351 357 private int gapSize() { 358 return fGapEnd - fGapStart; 359 } 360 361 367 protected String getContentAsString() { 368 return new String (fContent); 369 } 370 371 377 protected int getGapStartIndex() { 378 return fGapStart; 379 } 380 381 387 protected int getGapEndIndex() { 388 return fGapEnd; 389 } 390 } 391 | Popular Tags |