1 package com
.intellij
.openapi
.editor
.impl
;
3 import com
.intellij
.openapi
.editor
.event
.DocumentEvent
;
4 import com
.intellij
.util
.LocalTimeCounter
;
5 import com
.intellij
.util
.text
.CharArrayCharSequence
;
6 import com
.intellij
.util
.text
.CharArrayUtil
;
7 import com
.intellij
.util
.text
.CharSequenceBackedByArray
;
9 import java
.lang
.ref
.SoftReference
;
14 abstract class CharArray
implements CharSequenceBackedByArray
{
15 private int myCount
= 0;
16 private CharSequence myOriginalSequence
;
17 private char[] myArray
= null;
18 private SoftReference
<String
> myStringRef
= null; // buffers String value - for not to generate it every time
19 private int myBufferSize
;
21 // max chars to hold, bufferSize == 0 means unbounded
22 CharArray(int bufferSize
) {
23 myBufferSize
= bufferSize
;
24 myOriginalSequence
= "";
27 public void setBufferSize(int bufferSize
) {
28 myBufferSize
= bufferSize
;
31 protected abstract DocumentEvent
beforeChangedUpdate(int offset
, CharSequence oldString
, CharSequence newString
, boolean wholeTextReplaced
);
32 protected abstract void afterChangedUpdate(DocumentEvent event
, long newModificationStamp
);
34 public void replaceText(CharSequence chars
) {
35 myOriginalSequence
= chars
;
37 myCount
= chars
.length();
42 public void replace(int startOffset
, int endOffset
, CharSequence toDelete
, CharSequence newString
, long newModificationStamp
,
43 boolean wholeTextReplaced
) {
44 final DocumentEvent event
= beforeChangedUpdate(startOffset
, toDelete
, newString
, wholeTextReplaced
);
45 doReplace(startOffset
, endOffset
, newString
);
46 afterChangedUpdate(event
, newModificationStamp
);
49 private void doReplace(int startOffset
, int endOffset
, CharSequence newString
) {
50 prepareForModification();
52 int newLength
= newString
.length();
53 int oldLength
= endOffset
- startOffset
;
55 CharArrayUtil
.getChars(newString
, myArray
, startOffset
, Math
.min(newLength
, oldLength
));
57 if (newLength
> oldLength
) {
58 doInsert(newString
.subSequence(oldLength
, newLength
), endOffset
);
60 else if (newLength
< oldLength
) {
61 doRemove(startOffset
+ newLength
, startOffset
+ oldLength
);
65 public void remove(int startIndex
, int endIndex
, CharSequence toDelete
) {
66 DocumentEvent event
= beforeChangedUpdate(startIndex
, toDelete
, null, false);
67 doRemove(startIndex
, endIndex
);
68 afterChangedUpdate(event
, LocalTimeCounter
.currentTime());
71 private void doRemove(final int startIndex
, final int endIndex
) {
72 if (startIndex
== endIndex
) {
75 prepareForModification();
77 if (endIndex
< myCount
) {
78 System
.arraycopy(myArray
, endIndex
, myArray
, startIndex
, myCount
- endIndex
);
80 myCount
-= endIndex
- startIndex
;
83 public void insert(CharSequence s
, int startIndex
) {
84 DocumentEvent event
= beforeChangedUpdate(startIndex
, null, s
, false);
85 doInsert(s
, startIndex
);
87 afterChangedUpdate(event
, LocalTimeCounter
.currentTime());
91 private void doInsert(final CharSequence s
, final int startIndex
) {
92 prepareForModification();
94 int insertLength
= s
.length();
95 myArray
= relocateArray(myArray
, myCount
+ insertLength
);
96 if (startIndex
< myCount
) {
97 System
.arraycopy(myArray
, startIndex
, myArray
, startIndex
+ insertLength
, myCount
- startIndex
);
100 CharArrayUtil
.getChars(s
, myArray
,startIndex
);
101 myCount
+= insertLength
;
104 private void prepareForModification() {
105 if (myOriginalSequence
!= null) {
106 myArray
= new char[myOriginalSequence
.length()];
107 CharArrayUtil
.getChars(myOriginalSequence
, myArray
, 0);
108 myOriginalSequence
= null;
113 public CharSequence
getCharArray() {
114 if (myOriginalSequence
!= null) return myOriginalSequence
;
118 public String
toString() {
119 String str
= myStringRef
!= null ? myStringRef
.get() : null;
121 if (myOriginalSequence
!= null) {
122 str
= myOriginalSequence
.toString();
125 str
= new String(myArray
, 0, myCount
);
127 myStringRef
= new SoftReference
<String
>(str
);
132 public final int length() {
136 public final char charAt(int i
) {
137 if (i
< 0 || i
>= myCount
) {
138 throw new IndexOutOfBoundsException("Wrong offset: " + i
);
140 if (myOriginalSequence
!= null) return myOriginalSequence
.charAt(i
);
144 public CharSequence
subSequence(int start
, int end
) {
145 if (start
== 0 && end
== myCount
) return this;
146 if (myOriginalSequence
!= null) {
147 return myOriginalSequence
.subSequence(start
, end
);
149 return new CharArrayCharSequence(myArray
, start
, end
);
152 public char[] getChars() {
153 if (myOriginalSequence
!= null) {
154 if (myArray
== null) {
155 myArray
= CharArrayUtil
.fromSequence(myOriginalSequence
);
161 public void getChars(final char[] dst
, final int dstOffset
) {
162 if (myOriginalSequence
!= null) {
163 CharArrayUtil
.getChars(myOriginalSequence
,dst
, dstOffset
);
166 System
.arraycopy(myArray
, 0, dst
, dstOffset
, length());
170 public CharSequence
substring(int start
, int end
) {
171 if (start
== end
) return "";
172 if (myOriginalSequence
!= null) {
173 return myOriginalSequence
.subSequence(start
, end
);
175 return new String(myArray
, start
, end
- start
);
178 private static char[] relocateArray(char[] array
, int index
) {
179 if (index
< array
.length
) {
183 int newArraySize
= array
.length
;
184 if (newArraySize
== 0) {
187 while (newArraySize
<= index
) {
188 newArraySize
= newArraySize
* 12 / 10 + 1;
190 char[] newArray
= new char[newArraySize
];
191 System
.arraycopy(array
, 0, newArray
, 0, array
.length
);
195 private void trimToSize() {
196 if (myBufferSize
!= 0 && myCount
> myBufferSize
) {
198 remove(0, myCount
- myBufferSize
, getCharArray().subSequence(0, myCount
- myBufferSize
).toString());