148 |
} |
} |
149 |
|
|
150 |
/** |
/** |
151 |
|
* Create a new <code>StringBuffer</code> with the characters from the |
152 |
|
* specified <code>CharSequence</code>. Initial capacity will be the |
153 |
|
* size of the CharSequence plus 16. |
154 |
|
* |
155 |
|
* @param sequence the <code>String</code> to convert |
156 |
|
* @throws NullPointerException if str is null |
157 |
|
* |
158 |
|
* @since 1.5 |
159 |
|
*/ |
160 |
|
public StringBuffer(CharSequence sequence) |
161 |
|
{ |
162 |
|
count = Math.max(0, sequence.length()); |
163 |
|
value = new char[count + DEFAULT_CAPACITY]; |
164 |
|
for (int i = 0; i < count; ++i) |
165 |
|
value[i] = sequence.charAt(i); |
166 |
|
} |
167 |
|
|
168 |
|
/** |
169 |
* Get the length of the <code>String</code> this <code>StringBuffer</code> |
* Get the length of the <code>String</code> this <code>StringBuffer</code> |
170 |
* would create. Not to be confused with the <em>capacity</em> of the |
* would create. Not to be confused with the <em>capacity</em> of the |
171 |
* <code>StringBuffer</code>. |
* <code>StringBuffer</code>. |
262 |
} |
} |
263 |
|
|
264 |
/** |
/** |
265 |
|
* Get the code point at the specified index. This is like #charAt(int), |
266 |
|
* but if the character is the start of a surrogate pair, and the |
267 |
|
* following character completes the pair, then the corresponding |
268 |
|
* supplementary code point is returned. |
269 |
|
* @param index the index of the codepoint to get, starting at 0 |
270 |
|
* @return the codepoint at the specified index |
271 |
|
* @throws IndexOutOfBoundsException if index is negative or >= length() |
272 |
|
* (while unspecified, this is a StringIndexOutOfBoundsException) |
273 |
|
* @since 1.5 |
274 |
|
*/ |
275 |
|
public synchronized int codePointAt(int index) |
276 |
|
{ |
277 |
|
if (index < 0 || index >= count) |
278 |
|
throw new StringIndexOutOfBoundsException(index); |
279 |
|
char base = value[index]; |
280 |
|
if (base < Character.MIN_HIGH_SURROGATE |
281 |
|
|| base > Character.MAX_HIGH_SURROGATE |
282 |
|
|| index == count |
283 |
|
|| value[index + 1] < Character.MIN_LOW_SURROGATE |
284 |
|
|| value[index + 1] > Character.MAX_LOW_SURROGATE) |
285 |
|
return base; |
286 |
|
return (((base - Character.MIN_HIGH_SURROGATE) << 10) |
287 |
|
+ (value[index + 1] - Character.MIN_LOW_SURROGATE)); |
288 |
|
} |
289 |
|
|
290 |
|
/** |
291 |
|
* Get the code point before the specified index. This is like |
292 |
|
* #codePointAt(int), but checks the characters at <code>index-1</code> and |
293 |
|
* <code>index-2</code> to see if they form a supplementary code point. |
294 |
|
* @param index the index just past the codepoint to get, starting at 0 |
295 |
|
* @return the codepoint at the specified index |
296 |
|
* @throws IndexOutOfBoundsException if index is negative or >= length() |
297 |
|
* (while unspecified, this is a StringIndexOutOfBoundsException) |
298 |
|
* @since 1.5 |
299 |
|
*/ |
300 |
|
public synchronized int codePointBefore(int index) |
301 |
|
{ |
302 |
|
--index; |
303 |
|
if (index < 0 || index >= count) |
304 |
|
throw new StringIndexOutOfBoundsException(index); |
305 |
|
char base = value[index]; |
306 |
|
if (base < Character.MIN_LOW_SURROGATE |
307 |
|
|| base > Character.MAX_LOW_SURROGATE |
308 |
|
|| index == 0 |
309 |
|
|| value[index - 1] < Character.MIN_HIGH_SURROGATE |
310 |
|
|| value[index - 1] > Character.MAX_HIGH_SURROGATE) |
311 |
|
return base; |
312 |
|
return (((value[index - 1] - Character.MIN_HIGH_SURROGATE) << 10) |
313 |
|
+ (base - Character.MIN_LOW_SURROGATE)); |
314 |
|
} |
315 |
|
|
316 |
|
/** |
317 |
* Get the specified array of characters. <code>srcOffset - srcEnd</code> |
* Get the specified array of characters. <code>srcOffset - srcEnd</code> |
318 |
* characters will be copied into the array you pass in. |
* characters will be copied into the array you pass in. |
319 |
* |
* |
411 |
} |
} |
412 |
|
|
413 |
/** |
/** |
414 |
|
* Append the <code>CharSequence</code> value of the argument to this |
415 |
|
* <code>StringBuffer</code>. |
416 |
|
* |
417 |
|
* @param sequence the <code>CharSequence</code> to append |
418 |
|
* @return this <code>StringBuffer</code> |
419 |
|
* @see #append(Object) |
420 |
|
* @since 1.5 |
421 |
|
*/ |
422 |
|
public synchronized StringBuffer append(CharSequence sequence) |
423 |
|
{ |
424 |
|
if (sequence == null) |
425 |
|
sequence = "null"; |
426 |
|
return append(sequence, 0, sequence.length()); |
427 |
|
} |
428 |
|
|
429 |
|
/** |
430 |
|
* Append the specified subsequence of the <code>CharSequence</code> |
431 |
|
* argument to this <code>StringBuffer</code>. |
432 |
|
* |
433 |
|
* @param sequence the <code>CharSequence</code> to append |
434 |
|
* @param start the starting index |
435 |
|
* @param end one past the ending index |
436 |
|
* @return this <code>StringBuffer</code> |
437 |
|
* @see #append(Object) |
438 |
|
* @since 1.5 |
439 |
|
*/ |
440 |
|
public synchronized StringBuffer append(CharSequence sequence, |
441 |
|
int start, int end) |
442 |
|
{ |
443 |
|
if (sequence == null) |
444 |
|
sequence = "null"; |
445 |
|
if (start < 0 || end < 0 || start > end || end > sequence.length()) |
446 |
|
throw new IndexOutOfBoundsException(); |
447 |
|
ensureCapacity_unsynchronized(this.count + end - start); |
448 |
|
for (int i = start; i < end; ++i) |
449 |
|
value[count++] = sequence.charAt(i); |
450 |
|
return this; |
451 |
|
} |
452 |
|
|
453 |
|
/** |
454 |
* Append the <code>char</code> array to this <code>StringBuffer</code>. |
* Append the <code>char</code> array to this <code>StringBuffer</code>. |
455 |
* This is similar (but more efficient) than |
* This is similar (but more efficient) than |
456 |
* <code>append(new String(data))</code>, except in the case of null. |
* <code>append(new String(data))</code>, except in the case of null. |
517 |
} |
} |
518 |
|
|
519 |
/** |
/** |
520 |
|
* Append the code point to this <code>StringBuffer</code>. |
521 |
|
* This is like #append(char), but will append two characters |
522 |
|
* if a supplementary code point is given. |
523 |
|
* |
524 |
|
* @param code the code point to append |
525 |
|
* @return this <code>StringBuffer</code> |
526 |
|
* @see Character#toChars(int, char[], int) |
527 |
|
*/ |
528 |
|
public synchronized StringBuffer appendCodePoint(int code) |
529 |
|
{ |
530 |
|
int len = Character.charCount(code); |
531 |
|
ensureCapacity_unsynchronized(count + len); |
532 |
|
Character.toChars(code, value, count); |
533 |
|
count += len; |
534 |
|
return this; |
535 |
|
} |
536 |
|
|
537 |
|
/** |
538 |
* Append the <code>String</code> value of the argument to this |
* Append the <code>String</code> value of the argument to this |
539 |
* <code>StringBuffer</code>. Uses <code>String.valueOf()</code> to convert |
* <code>StringBuffer</code>. Uses <code>String.valueOf()</code> to convert |
540 |
* to <code>String</code>. |
* to <code>String</code>. |
788 |
} |
} |
789 |
|
|
790 |
/** |
/** |
791 |
|
* Insert the <code>CharSequence</code> argument into this |
792 |
|
* <code>StringBuffer</code>. If the sequence is null, the String |
793 |
|
* "null" is used instead. |
794 |
|
* |
795 |
|
* @param offset the place to insert in this buffer |
796 |
|
* @param sequence the <code>CharSequence</code> to insert |
797 |
|
* @return this <code>StringBuffer</code> |
798 |
|
* @throws IndexOutOfBoundsException if offset is out of bounds |
799 |
|
* @since 1.5 |
800 |
|
*/ |
801 |
|
public synchronized StringBuffer insert(int offset, CharSequence sequence) |
802 |
|
{ |
803 |
|
if (sequence == null) |
804 |
|
sequence = "null"; |
805 |
|
return insert(offset, sequence, 0, sequence.length()); |
806 |
|
} |
807 |
|
|
808 |
|
/** |
809 |
|
* Insert a subsequence of the <code>CharSequence</code> argument into this |
810 |
|
* <code>StringBuffer</code>. If the sequence is null, the String |
811 |
|
* "null" is used instead. |
812 |
|
* |
813 |
|
* @param offset the place to insert in this buffer |
814 |
|
* @param sequence the <code>CharSequence</code> to insert |
815 |
|
* @param start the starting index of the subsequence |
816 |
|
* @param end one past the ending index of the subsequence |
817 |
|
* @return this <code>StringBuffer</code> |
818 |
|
* @throws IndexOutOfBoundsException if offset, start, |
819 |
|
* or end are out of bounds |
820 |
|
* @since 1.5 |
821 |
|
*/ |
822 |
|
public synchronized StringBuffer insert(int offset, CharSequence sequence, |
823 |
|
int start, int end) |
824 |
|
{ |
825 |
|
if (sequence == null) |
826 |
|
sequence = "null"; |
827 |
|
if (start < 0 || end < 0 || start > end || end > sequence.length()) |
828 |
|
throw new IndexOutOfBoundsException(); |
829 |
|
int len = end - start; |
830 |
|
ensureCapacity_unsynchronized(count + len); |
831 |
|
VMSystem.arraycopy(value, offset, value, offset + len, count - offset); |
832 |
|
for (int i = start; i < end; ++i) |
833 |
|
value[offset++] = sequence.charAt(i); |
834 |
|
count += len; |
835 |
|
return this; |
836 |
|
} |
837 |
|
|
838 |
|
/** |
839 |
* Insert the <code>char[]</code> argument into this |
* Insert the <code>char[]</code> argument into this |
840 |
* <code>StringBuffer</code>. |
* <code>StringBuffer</code>. |
841 |
* |
* |
1056 |
} |
} |
1057 |
|
|
1058 |
/** |
/** |
1059 |
|
* This may reduce the amount of memory used by the StringBuffer, |
1060 |
|
* by resizing the internal array to remove unused space. However, |
1061 |
|
* this method is not required to resize, so this behavior cannot |
1062 |
|
* be relied upon. |
1063 |
|
* @since 1.5 |
1064 |
|
*/ |
1065 |
|
public synchronized void trimToSize() |
1066 |
|
{ |
1067 |
|
int wouldSave = value.length - count; |
1068 |
|
// Some random heuristics: if we save less than 20 characters, who |
1069 |
|
// cares. |
1070 |
|
if (wouldSave < 20) |
1071 |
|
return; |
1072 |
|
// If we save more than 200 characters, shrink. |
1073 |
|
// If we save more than 1/4 of the buffer, shrink. |
1074 |
|
if (wouldSave > 200 || wouldSave * 4 > value.length) |
1075 |
|
{ |
1076 |
|
char[] newValue = new char[count]; |
1077 |
|
VMSystem.arraycopy(value, 0, newValue, 0, count); |
1078 |
|
value = newValue; |
1079 |
|
} |
1080 |
|
} |
1081 |
|
|
1082 |
|
/** |
1083 |
|
* Return the number of code points between two indices in the |
1084 |
|
* <code>StringBuffer</code>. An unpaired surrogate counts as a |
1085 |
|
* code point for this purpose. Characters outside the indicated |
1086 |
|
* range are not examined, even if the range ends in the middle of a |
1087 |
|
* surrogate pair. |
1088 |
|
* |
1089 |
|
* @param start the starting index |
1090 |
|
* @param end one past the ending index |
1091 |
|
* @return the number of code points |
1092 |
|
* @since 1.5 |
1093 |
|
*/ |
1094 |
|
public synchronized int codePointCount(int start, int end) |
1095 |
|
{ |
1096 |
|
int count = 0; |
1097 |
|
while (start < end) |
1098 |
|
{ |
1099 |
|
char base = value[start]; |
1100 |
|
if (base < Character.MIN_HIGH_SURROGATE |
1101 |
|
|| base > Character.MAX_HIGH_SURROGATE |
1102 |
|
|| start == end |
1103 |
|
|| start == count |
1104 |
|
|| value[start + 1] < Character.MIN_LOW_SURROGATE |
1105 |
|
|| value[start + 1] > Character.MAX_LOW_SURROGATE) |
1106 |
|
{ |
1107 |
|
// Nothing. |
1108 |
|
} |
1109 |
|
else |
1110 |
|
{ |
1111 |
|
// Surrogate pair. |
1112 |
|
++start; |
1113 |
|
} |
1114 |
|
++start; |
1115 |
|
++count; |
1116 |
|
} |
1117 |
|
return count; |
1118 |
|
} |
1119 |
|
|
1120 |
|
/** |
1121 |
|
* Starting at the given index, this counts forward by the indicated |
1122 |
|
* number of code points, and then returns the resulting index. An |
1123 |
|
* unpaired surrogate counts as a single code point for this |
1124 |
|
* purpose. |
1125 |
|
* |
1126 |
|
* @param start the starting index |
1127 |
|
* @param codePoints the number of code points |
1128 |
|
* @return the resulting index |
1129 |
|
* @since 1.5 |
1130 |
|
*/ |
1131 |
|
public synchronized int offsetByCodePoints(int start, int codePoints) |
1132 |
|
{ |
1133 |
|
while (codePoints > 0) |
1134 |
|
{ |
1135 |
|
char base = value[start]; |
1136 |
|
if (base < Character.MIN_HIGH_SURROGATE |
1137 |
|
|| base > Character.MAX_HIGH_SURROGATE |
1138 |
|
|| start == count |
1139 |
|
|| value[start + 1] < Character.MIN_LOW_SURROGATE |
1140 |
|
|| value[start + 1] > Character.MAX_LOW_SURROGATE) |
1141 |
|
{ |
1142 |
|
// Nothing. |
1143 |
|
} |
1144 |
|
else |
1145 |
|
{ |
1146 |
|
// Surrogate pair. |
1147 |
|
++start; |
1148 |
|
} |
1149 |
|
++start; |
1150 |
|
--codePoints; |
1151 |
|
} |
1152 |
|
return start; |
1153 |
|
} |
1154 |
|
|
1155 |
|
/** |
1156 |
* An unsynchronized version of ensureCapacity, used internally to avoid |
* An unsynchronized version of ensureCapacity, used internally to avoid |
1157 |
* the cost of a second lock on the same object. This also has the side |
* the cost of a second lock on the same object. This also has the side |
1158 |
* effect of duplicating the array, if it was shared (to form copy-on-write |
* effect of duplicating the array, if it was shared (to form copy-on-write |