@Override public final char charAt(int i) { if (i < 0 || i >= length()) { throw new IndexOutOfBoundsException("Wrong offset: " + i + "; count:" + length()); } i += myStart; if (myOriginalSequence != null) return myOriginalSequence.charAt(i); final char result; if (hasDeferredChanges()) { TextChangesStorage storage = myDeferredChangesStorage.get(); storage.getLock().lock(); try { result = storage.charAt(myArray, i); } finally { storage.getLock().unlock(); } } else { result = myArray[i]; } if (myDebugDeferredProcessing && isDeferredChangeMode()) { char expected = myDebugArray.charAt(i); if (expected != result) { dumpDebugInfo( String.format( "Incorrect charAt() processing for index %d. Expected: '%c', actual: '%c'", i, expected, result)); } } return result; }
public void setText(@Nullable final DocumentImpl subj, final CharSequence chars) { myOriginalSequence = chars; myArray = null; myCount = chars.length(); myStringRef = null; TextChangesStorage storage = myDeferredChangesStorage.get(); storage.getLock().lock(); try { if (isSubSequence()) { myDeferredChangesStorage.set(new TextChangesStorage()); myStart = 0; myEnd = -1; } else { storage.clear(); } } finally { storage.getLock().unlock(); } if (subj != null) { trimToSize(subj); } if (myDebugDeferredProcessing) { myDebugArray.setText(subj, chars); myDebugDeferredChanges.clear(); } }
private void flushDeferredChanged(@NotNull TextChangesStorage storage) { storage.getLock().lock(); try { doFlushDeferredChanged(); } finally { storage.getLock().unlock(); } }
private void doStoreChange(@NotNull TextChangeImpl change) { TextChangesStorage storage = myDeferredChangesStorage.get(); if (storage.size() >= MAX_DEFERRED_CHANGES_NUMBER) { flushDeferredChanged(storage); } storage.store(change); myDeferredShift += change.getDiff(); if (myDebugDeferredProcessing) { myDebugDeferredChanges.add(change); } }
/** * Stores given change at collection of deferred changes (merging it with others if necessary) and * updates current object state ({@link #length() length} etc). * * @param change new change to store */ private void storeChange(@NotNull TextChangeImpl change) { if (!change.isWithinBounds(length())) { LOG.error( String.format( "Invalid change attempt detected - given change bounds are not within the current char array. Change: %d:%d-%d", change.getText().length(), change.getStart(), change.getEnd()), dumpState()); return; } TextChangesStorage storage = myDeferredChangesStorage.get(); storage.getLock().lock(); try { doStoreChange(change); } finally { storage.getLock().unlock(); } }
public CharSequence substring(final int start, final int end) { if (start == end) return ""; final CharSequence result; if (myOriginalSequence == null) { TextChangesStorage storage = myDeferredChangesStorage.get(); storage.getLock().lock(); try { result = storage.substring(myArray, start + myStart, end + myStart); } finally { storage.getLock().unlock(); } } else { result = myOriginalSequence.subSequence(start, end); } if (myDebugDeferredProcessing && isDeferredChangeMode()) { String expected = myDebugArray.substring(start, end).toString(); checkStrings(String.format("substring(%d, %d)", start, end), expected, result.toString()); } return result; }
private void doFlushDeferredChanged() { TextChangesStorage storage = myDeferredChangesStorage.get(); List<TextChangeImpl> changes = storage.getChanges(); if (changes.isEmpty()) { return; } char[] beforeMerge = null; final boolean inPlace; if (myDebugDeferredProcessing) { beforeMerge = new char[myArray.length]; System.arraycopy(myArray, 0, beforeMerge, 0, myArray.length); } BulkChangesMerger changesMerger = BulkChangesMerger.INSTANCE; if (myArray.length < length()) { myArray = changesMerger.mergeToCharArray(myArray, myCount, changes); inPlace = false; } else { changesMerger.mergeInPlace(myArray, myCount, changes); inPlace = true; } if (myDebugDeferredProcessing) { for (int i = 0, max = length(); i < max; i++) { if (myArray[i] != myDebugArray.myArray[i]) { dumpDebugInfo( String.format( "flushDeferredChanged(). Index %d, expected: '%c', actual '%c'. Text before merge: '%s', merge inplace: %b", i, myDebugArray.myArray[i], myArray[i], Arrays.toString(beforeMerge), inPlace)); break; } } } myCount += myDeferredShift; myDeferredShift = 0; storage.clear(); myDeferredChangeMode = false; }