53 * @author Ulf Zibis
54 * @since 1.5
55 */
56 abstract class AbstractStringBuilder implements Appendable, CharSequence {
57 /**
58 * The value is used for character storage.
59 */
60 byte[] value;
61
62 /**
63 * The id of the encoding used to encode the bytes in {@code value}.
64 */
65 byte coder;
66
67 /**
68 * The count is the number of characters used.
69 */
70 int count;
71
72 /**
73 * This no-arg constructor is necessary for serialization of subclasses.
74 */
75 AbstractStringBuilder() {
76 }
77
78 /**
79 * Creates an AbstractStringBuilder of the specified capacity.
80 */
81 AbstractStringBuilder(int capacity) {
82 if (COMPACT_STRINGS) {
83 value = new byte[capacity];
84 coder = LATIN1;
85 } else {
86 value = StringUTF16.newBytesFor(capacity);
87 coder = UTF16;
88 }
89 }
90
91 /**
92 * Returns the length (character count).
93 *
94 * @return the length of the sequence of characters currently
95 * represented by this object
96 */
97 @Override
98 public int length() {
99 return count;
100 }
101
102 /**
103 * Returns the current capacity. The capacity is the amount of storage
104 * available for newly inserted characters, beyond which an allocation
105 * will occur.
106 *
107 * @return the current capacity
108 */
109 public int capacity() {
110 return value.length >> coder;
149 * size check or synchronization.
150 */
151 private void expandCapacity(int minimumCapacity) {
152 int newCapacity = (value.length >> coder) * 2 + 2;
153 if (newCapacity - minimumCapacity < 0) {
154 newCapacity = minimumCapacity;
155 }
156 if (newCapacity < 0) {
157 if (minimumCapacity < 0) {// overflow
158 throw new OutOfMemoryError();
159 }
160 newCapacity = Integer.MAX_VALUE;
161 }
162 if (coder != LATIN1 && newCapacity > StringUTF16.MAX_LENGTH) {
163 if (minimumCapacity >= StringUTF16.MAX_LENGTH) {
164 throw new OutOfMemoryError();
165 }
166 newCapacity = StringUTF16.MAX_LENGTH;
167 }
168 this.value = Arrays.copyOf(value, newCapacity << coder);
169 }
170
171 /**
172 * If the coder is "isLatin1", this inflates the internal 8-bit storage
173 * to 16-bit <hi=0, low> pair storage.
174 */
175 private void inflate() {
176 if (!isLatin1()) {
177 return;
178 }
179 byte[] buf = StringUTF16.newBytesFor(value.length);
180 StringLatin1.inflateSB(value, buf, 0, count);
181 this.value = buf;
182 this.coder = UTF16;
183 }
184
185 /**
186 * Attempts to reduce storage used for the character sequence.
187 * If the buffer is larger than necessary to hold its current sequence of
188 * characters, then it may be resized to become more space efficient.
189 * Calling this method may, but is not required to, affect the value
190 * returned by a subsequent call to the {@link #capacity()} method.
191 */
192 public void trimToSize() {
193 int length = count << coder;
194 if (length < value.length) {
195 value = Arrays.copyOf(value, length);
196 }
197 }
198
199 /**
200 * Sets the length of the character sequence.
201 * The sequence is changed to a new character sequence
202 * whose length is specified by the argument. For every nonnegative
208 *
209 * In other words, if the {@code newLength} argument is less than
210 * the current length, the length is changed to the specified length.
211 * <p>
212 * If the {@code newLength} argument is greater than or equal
213 * to the current length, sufficient null characters
214 * ({@code '\u005Cu0000'}) are appended so that
215 * length becomes the {@code newLength} argument.
216 * <p>
217 * The {@code newLength} argument must be greater than or equal
218 * to {@code 0}.
219 *
220 * @param newLength the new length
221 * @throws IndexOutOfBoundsException if the
222 * {@code newLength} argument is negative.
223 */
224 public void setLength(int newLength) {
225 if (newLength < 0) {
226 throw new StringIndexOutOfBoundsException(newLength);
227 }
228 ensureCapacityInternal(newLength);
229 if (count < newLength) {
230 if (isLatin1()) {
231 StringLatin1.fillNull(value, count, newLength);
232 } else {
233 StringUTF16.fillNull(value, count, newLength);
234 }
235 }
236 count = newLength;
237 }
238
239 /**
240 * Returns the {@code char} value in this sequence at the specified index.
241 * The first {@code char} value is at index {@code 0}, the next at index
242 * {@code 1}, and so on, as in array indexing.
243 * <p>
244 * The index argument must be greater than or equal to
245 * {@code 0}, and less than the length of this sequence.
246 *
247 * <p>If the {@code char} value specified by the index is a
248 * <a href="Character.html#unicode">surrogate</a>, the surrogate
249 * value is returned.
250 *
251 * @param index the index of the desired {@code char} value.
252 * @return the {@code char} value at the specified index.
253 * @throws IndexOutOfBoundsException if {@code index} is
254 * negative or greater than or equal to {@code length()}.
420 }
421 }
422
423 /**
424 * The character at the specified index is set to {@code ch}. This
425 * sequence is altered to represent a new character sequence that is
426 * identical to the old character sequence, except that it contains the
427 * character {@code ch} at position {@code index}.
428 * <p>
429 * The index argument must be greater than or equal to
430 * {@code 0}, and less than the length of this sequence.
431 *
432 * @param index the index of the character to modify.
433 * @param ch the new character.
434 * @throws IndexOutOfBoundsException if {@code index} is
435 * negative or greater than or equal to {@code length()}.
436 */
437 public void setCharAt(int index, char ch) {
438 checkIndex(index, count);
439 if (isLatin1() && StringLatin1.canEncode(ch)) {
440 value[index] = (byte)ch;
441 } else {
442 if (isLatin1()) {
443 inflate();
444 }
445 StringUTF16.putCharSB(value, index, ch);
446 }
447 }
448
449 /**
450 * Appends the string representation of the {@code Object} argument.
451 * <p>
452 * The overall effect is exactly as if the argument were converted
453 * to a string by the method {@link String#valueOf(Object)},
454 * and the characters of that string were then
455 * {@link #append(String) appended} to this character sequence.
456 *
457 * @param obj an {@code Object}.
458 * @return a reference to this object.
459 */
460 public AbstractStringBuilder append(Object obj) {
461 return append(String.valueOf(obj));
462 }
463
809 * Removes the characters in a substring of this sequence.
810 * The substring begins at the specified {@code start} and extends to
811 * the character at index {@code end - 1} or to the end of the
812 * sequence if no such character exists. If
813 * {@code start} is equal to {@code end}, no changes are made.
814 *
815 * @param start The beginning index, inclusive.
816 * @param end The ending index, exclusive.
817 * @return This object.
818 * @throws StringIndexOutOfBoundsException if {@code start}
819 * is negative, greater than {@code length()}, or
820 * greater than {@code end}.
821 */
822 public AbstractStringBuilder delete(int start, int end) {
823 if (end > count) {
824 end = count;
825 }
826 checkRangeSIOOBE(start, end, count);
827 int len = end - start;
828 if (len > 0) {
829 shift(end, -len);
830 count -= len;
831 }
832 return this;
833 }
834
835 /**
836 * Appends the string representation of the {@code codePoint}
837 * argument to this sequence.
838 *
839 * <p> The argument is appended to the contents of this sequence.
840 * The length of this sequence increases by
841 * {@link Character#charCount(int) Character.charCount(codePoint)}.
842 *
843 * <p> The overall effect is exactly as if the argument were
844 * converted to a {@code char} array by the method
845 * {@link Character#toChars(int)} and the character in that array
846 * were then {@link #append(char[]) appended} to this character
847 * sequence.
848 *
860
861 /**
862 * Removes the {@code char} at the specified position in this
863 * sequence. This sequence is shortened by one {@code char}.
864 *
865 * <p>Note: If the character at the given index is a supplementary
866 * character, this method does not remove the entire character. If
867 * correct handling of supplementary characters is required,
868 * determine the number of {@code char}s to remove by calling
869 * {@code Character.charCount(thisSequence.codePointAt(index))},
870 * where {@code thisSequence} is this sequence.
871 *
872 * @param index Index of {@code char} to remove
873 * @return This object.
874 * @throws StringIndexOutOfBoundsException if the {@code index}
875 * is negative or greater than or equal to
876 * {@code length()}.
877 */
878 public AbstractStringBuilder deleteCharAt(int index) {
879 checkIndex(index, count);
880 shift(index + 1, -1);
881 count--;
882 return this;
883 }
884
885 /**
886 * Replaces the characters in a substring of this sequence
887 * with characters in the specified {@code String}. The substring
888 * begins at the specified {@code start} and extends to the character
889 * at index {@code end - 1} or to the end of the
890 * sequence if no such character exists. First the
891 * characters in the substring are removed and then the specified
892 * {@code String} is inserted at {@code start}. (This
893 * sequence will be lengthened to accommodate the
894 * specified String if necessary.)
895 *
896 * @param start The beginning index, inclusive.
897 * @param end The ending index, exclusive.
898 * @param str String that will replace previous contents.
899 * @return This object.
900 * @throws StringIndexOutOfBoundsException if {@code start}
901 * is negative, greater than {@code length()}, or
902 * greater than {@code end}.
903 */
904 public AbstractStringBuilder replace(int start, int end, String str) {
905 if (end > count) {
906 end = count;
907 }
908 checkRangeSIOOBE(start, end, count);
909 int len = str.length();
910 int newCount = count + len - (end - start);
911 ensureCapacityInternal(newCount);
912 shift(end, newCount - count);
913 count = newCount;
914 putStringAt(start, str);
915 return this;
916 }
917
918 /**
919 * Returns a new {@code String} that contains a subsequence of
920 * characters currently contained in this character sequence. The
921 * substring begins at the specified index and extends to the end of
922 * this sequence.
923 *
924 * @param start The beginning index, inclusive.
925 * @return The new string.
926 * @throws StringIndexOutOfBoundsException if {@code start} is
927 * less than zero, or greater than the length of this object.
928 */
929 public String substring(int start) {
930 return substring(start, count);
931 }
1448 * sequence, these are treated as single characters for the
1449 * reverse operation. Thus, the order of the high-low surrogates
1450 * is never reversed.
1451 *
1452 * Let <i>n</i> be the character length of this character sequence
1453 * (not the length in {@code char} values) just prior to
1454 * execution of the {@code reverse} method. Then the
1455 * character at index <i>k</i> in the new character sequence is
1456 * equal to the character at index <i>n-k-1</i> in the old
1457 * character sequence.
1458 *
1459 * <p>Note that the reverse operation may result in producing
1460 * surrogate pairs that were unpaired low-surrogates and
1461 * high-surrogates before the operation. For example, reversing
1462 * "\u005CuDC00\u005CuD800" produces "\u005CuD800\u005CuDC00" which is
1463 * a valid surrogate pair.
1464 *
1465 * @return a reference to this object.
1466 */
1467 public AbstractStringBuilder reverse() {
1468 byte[] val = this.value;
1469 int count = this.count;
1470 int coder = this.coder;
1471 int n = count - 1;
1472 if (COMPACT_STRINGS && coder == LATIN1) {
1473 for (int j = (n-1) >> 1; j >= 0; j--) {
1474 int k = n - j;
1475 byte cj = val[j];
1476 val[j] = val[k];
1477 val[k] = cj;
1478 }
1479 } else {
1480 checkOffset(count, val.length >> 1);
1481 boolean hasSurrogates = false;
1482 for (int j = (n-1) >> 1; j >= 0; j--) {
1483 int k = n - j;
1484 char cj = StringUTF16.getChar(val, j);
1485 char ck = StringUTF16.getChar(val, k);
1486 StringUTF16.putChar(val, j, ck);
1487 StringUTF16.putChar(val, k, cj);
1488 if (Character.isSurrogate(cj) ||
1558 false);
1559 }
1560
1561 /**
1562 * Needed by {@code String} for the contentEquals method.
1563 */
1564 final byte[] getValue() {
1565 return value;
1566 }
1567
1568 /*
1569 * Invoker guarantees it is in UTF16 (inflate itself for asb), if two
1570 * coders are different and the dstBegin has enough space
1571 *
1572 * @param dstBegin the char index, not offset of byte[]
1573 * @param coder the coder of dst[]
1574 */
1575 void getBytes(byte dst[], int dstBegin, byte coder) {
1576 if (this.coder == coder) {
1577 System.arraycopy(value, 0, dst, dstBegin << coder, count << coder);
1578 } else { // this.coder == LATIN && coder == UTF16
1579 StringLatin1.inflateSB(value, dst, dstBegin, count);
1580 }
1581 }
1582
1583 /* for readObject() */
1584 void initBytes(char[] value, int off, int len) {
1585 if (String.COMPACT_STRINGS) {
1586 this.value = StringUTF16.compress(value, off, len);
1587 if (this.value != null) {
1588 this.coder = LATIN1;
1589 return;
1590 }
1591 }
1592 this.coder = UTF16;
1593 this.value = StringUTF16.toBytes(value, off, len);
1594 }
1595
1596 final byte getCoder() {
1597 return COMPACT_STRINGS ? coder : UTF16;
1598 }
|
53 * @author Ulf Zibis
54 * @since 1.5
55 */
56 abstract class AbstractStringBuilder implements Appendable, CharSequence {
57 /**
58 * The value is used for character storage.
59 */
60 byte[] value;
61
62 /**
63 * The id of the encoding used to encode the bytes in {@code value}.
64 */
65 byte coder;
66
67 /**
68 * The count is the number of characters used.
69 */
70 int count;
71
72 /**
73 * Whether value array is shared with a String.
74 */
75 transient boolean shared;
76
77 /**
78 * This no-arg constructor is necessary for serialization of subclasses.
79 */
80 AbstractStringBuilder() {
81 }
82
83 /**
84 * Creates an AbstractStringBuilder of the specified capacity.
85 */
86 AbstractStringBuilder(int capacity) {
87 if (COMPACT_STRINGS) {
88 value = new byte[capacity];
89 coder = LATIN1;
90 } else {
91 value = StringUTF16.newBytesFor(capacity);
92 coder = UTF16;
93 }
94 }
95
96 byte[] unshareValue() {
97 if (shared) {
98 // assert (count << coder) == value.length
99 value = Arrays.copyOf(value, value.length);
100 shared = false;
101 }
102 return value;
103 }
104
105 /**
106 * Returns the length (character count).
107 *
108 * @return the length of the sequence of characters currently
109 * represented by this object
110 */
111 @Override
112 public int length() {
113 return count;
114 }
115
116 /**
117 * Returns the current capacity. The capacity is the amount of storage
118 * available for newly inserted characters, beyond which an allocation
119 * will occur.
120 *
121 * @return the current capacity
122 */
123 public int capacity() {
124 return value.length >> coder;
163 * size check or synchronization.
164 */
165 private void expandCapacity(int minimumCapacity) {
166 int newCapacity = (value.length >> coder) * 2 + 2;
167 if (newCapacity - minimumCapacity < 0) {
168 newCapacity = minimumCapacity;
169 }
170 if (newCapacity < 0) {
171 if (minimumCapacity < 0) {// overflow
172 throw new OutOfMemoryError();
173 }
174 newCapacity = Integer.MAX_VALUE;
175 }
176 if (coder != LATIN1 && newCapacity > StringUTF16.MAX_LENGTH) {
177 if (minimumCapacity >= StringUTF16.MAX_LENGTH) {
178 throw new OutOfMemoryError();
179 }
180 newCapacity = StringUTF16.MAX_LENGTH;
181 }
182 this.value = Arrays.copyOf(value, newCapacity << coder);
183 this.shared = false;
184 }
185
186 /**
187 * If the coder is "isLatin1", this inflates the internal 8-bit storage
188 * to 16-bit <hi=0, low> pair storage.
189 */
190 private void inflate() {
191 if (!isLatin1()) {
192 return;
193 }
194 byte[] buf = StringUTF16.newBytesFor(value.length);
195 StringLatin1.inflateSB(value, buf, 0, count);
196 this.value = buf;
197 this.coder = UTF16;
198 this.shared = false;
199 }
200
201 /**
202 * Attempts to reduce storage used for the character sequence.
203 * If the buffer is larger than necessary to hold its current sequence of
204 * characters, then it may be resized to become more space efficient.
205 * Calling this method may, but is not required to, affect the value
206 * returned by a subsequent call to the {@link #capacity()} method.
207 */
208 public void trimToSize() {
209 int length = count << coder;
210 if (length < value.length) {
211 value = Arrays.copyOf(value, length);
212 }
213 }
214
215 /**
216 * Sets the length of the character sequence.
217 * The sequence is changed to a new character sequence
218 * whose length is specified by the argument. For every nonnegative
224 *
225 * In other words, if the {@code newLength} argument is less than
226 * the current length, the length is changed to the specified length.
227 * <p>
228 * If the {@code newLength} argument is greater than or equal
229 * to the current length, sufficient null characters
230 * ({@code '\u005Cu0000'}) are appended so that
231 * length becomes the {@code newLength} argument.
232 * <p>
233 * The {@code newLength} argument must be greater than or equal
234 * to {@code 0}.
235 *
236 * @param newLength the new length
237 * @throws IndexOutOfBoundsException if the
238 * {@code newLength} argument is negative.
239 */
240 public void setLength(int newLength) {
241 if (newLength < 0) {
242 throw new StringIndexOutOfBoundsException(newLength);
243 }
244 if (count < newLength) {
245 ensureCapacityInternal(newLength);
246 if (isLatin1()) {
247 StringLatin1.fillNull(value, count, newLength);
248 } else {
249 StringUTF16.fillNull(value, count, newLength);
250 }
251 } else if (newLength < count) {
252 unshareValue();
253 }
254 count = newLength;
255 }
256
257 /**
258 * Returns the {@code char} value in this sequence at the specified index.
259 * The first {@code char} value is at index {@code 0}, the next at index
260 * {@code 1}, and so on, as in array indexing.
261 * <p>
262 * The index argument must be greater than or equal to
263 * {@code 0}, and less than the length of this sequence.
264 *
265 * <p>If the {@code char} value specified by the index is a
266 * <a href="Character.html#unicode">surrogate</a>, the surrogate
267 * value is returned.
268 *
269 * @param index the index of the desired {@code char} value.
270 * @return the {@code char} value at the specified index.
271 * @throws IndexOutOfBoundsException if {@code index} is
272 * negative or greater than or equal to {@code length()}.
438 }
439 }
440
441 /**
442 * The character at the specified index is set to {@code ch}. This
443 * sequence is altered to represent a new character sequence that is
444 * identical to the old character sequence, except that it contains the
445 * character {@code ch} at position {@code index}.
446 * <p>
447 * The index argument must be greater than or equal to
448 * {@code 0}, and less than the length of this sequence.
449 *
450 * @param index the index of the character to modify.
451 * @param ch the new character.
452 * @throws IndexOutOfBoundsException if {@code index} is
453 * negative or greater than or equal to {@code length()}.
454 */
455 public void setCharAt(int index, char ch) {
456 checkIndex(index, count);
457 if (isLatin1() && StringLatin1.canEncode(ch)) {
458 final byte[] value = unshareValue();
459 value[index] = (byte)ch;
460 } else {
461 if (isLatin1()) {
462 inflate();
463 } else {
464 unshareValue();
465 }
466 StringUTF16.putCharSB(value, index, ch);
467 }
468 }
469
470 /**
471 * Appends the string representation of the {@code Object} argument.
472 * <p>
473 * The overall effect is exactly as if the argument were converted
474 * to a string by the method {@link String#valueOf(Object)},
475 * and the characters of that string were then
476 * {@link #append(String) appended} to this character sequence.
477 *
478 * @param obj an {@code Object}.
479 * @return a reference to this object.
480 */
481 public AbstractStringBuilder append(Object obj) {
482 return append(String.valueOf(obj));
483 }
484
830 * Removes the characters in a substring of this sequence.
831 * The substring begins at the specified {@code start} and extends to
832 * the character at index {@code end - 1} or to the end of the
833 * sequence if no such character exists. If
834 * {@code start} is equal to {@code end}, no changes are made.
835 *
836 * @param start The beginning index, inclusive.
837 * @param end The ending index, exclusive.
838 * @return This object.
839 * @throws StringIndexOutOfBoundsException if {@code start}
840 * is negative, greater than {@code length()}, or
841 * greater than {@code end}.
842 */
843 public AbstractStringBuilder delete(int start, int end) {
844 if (end > count) {
845 end = count;
846 }
847 checkRangeSIOOBE(start, end, count);
848 int len = end - start;
849 if (len > 0) {
850 unshareValue();
851 shift(end, -len);
852 count -= len;
853 }
854 return this;
855 }
856
857 /**
858 * Appends the string representation of the {@code codePoint}
859 * argument to this sequence.
860 *
861 * <p> The argument is appended to the contents of this sequence.
862 * The length of this sequence increases by
863 * {@link Character#charCount(int) Character.charCount(codePoint)}.
864 *
865 * <p> The overall effect is exactly as if the argument were
866 * converted to a {@code char} array by the method
867 * {@link Character#toChars(int)} and the character in that array
868 * were then {@link #append(char[]) appended} to this character
869 * sequence.
870 *
882
883 /**
884 * Removes the {@code char} at the specified position in this
885 * sequence. This sequence is shortened by one {@code char}.
886 *
887 * <p>Note: If the character at the given index is a supplementary
888 * character, this method does not remove the entire character. If
889 * correct handling of supplementary characters is required,
890 * determine the number of {@code char}s to remove by calling
891 * {@code Character.charCount(thisSequence.codePointAt(index))},
892 * where {@code thisSequence} is this sequence.
893 *
894 * @param index Index of {@code char} to remove
895 * @return This object.
896 * @throws StringIndexOutOfBoundsException if the {@code index}
897 * is negative or greater than or equal to
898 * {@code length()}.
899 */
900 public AbstractStringBuilder deleteCharAt(int index) {
901 checkIndex(index, count);
902 unshareValue();
903 shift(index + 1, -1);
904 count--;
905 return this;
906 }
907
908 /**
909 * Replaces the characters in a substring of this sequence
910 * with characters in the specified {@code String}. The substring
911 * begins at the specified {@code start} and extends to the character
912 * at index {@code end - 1} or to the end of the
913 * sequence if no such character exists. First the
914 * characters in the substring are removed and then the specified
915 * {@code String} is inserted at {@code start}. (This
916 * sequence will be lengthened to accommodate the
917 * specified String if necessary.)
918 *
919 * @param start The beginning index, inclusive.
920 * @param end The ending index, exclusive.
921 * @param str String that will replace previous contents.
922 * @return This object.
923 * @throws StringIndexOutOfBoundsException if {@code start}
924 * is negative, greater than {@code length()}, or
925 * greater than {@code end}.
926 */
927 public AbstractStringBuilder replace(int start, int end, String str) {
928 if (end > count) {
929 end = count;
930 }
931 checkRangeSIOOBE(start, end, count);
932 int len = str.length();
933 int newCount = count + len - (end - start);
934 ensureCapacityInternal(newCount);
935 unshareValue();
936 shift(end, newCount - count);
937 count = newCount;
938 putStringAt(start, str);
939 return this;
940 }
941
942 /**
943 * Returns a new {@code String} that contains a subsequence of
944 * characters currently contained in this character sequence. The
945 * substring begins at the specified index and extends to the end of
946 * this sequence.
947 *
948 * @param start The beginning index, inclusive.
949 * @return The new string.
950 * @throws StringIndexOutOfBoundsException if {@code start} is
951 * less than zero, or greater than the length of this object.
952 */
953 public String substring(int start) {
954 return substring(start, count);
955 }
1472 * sequence, these are treated as single characters for the
1473 * reverse operation. Thus, the order of the high-low surrogates
1474 * is never reversed.
1475 *
1476 * Let <i>n</i> be the character length of this character sequence
1477 * (not the length in {@code char} values) just prior to
1478 * execution of the {@code reverse} method. Then the
1479 * character at index <i>k</i> in the new character sequence is
1480 * equal to the character at index <i>n-k-1</i> in the old
1481 * character sequence.
1482 *
1483 * <p>Note that the reverse operation may result in producing
1484 * surrogate pairs that were unpaired low-surrogates and
1485 * high-surrogates before the operation. For example, reversing
1486 * "\u005CuDC00\u005CuD800" produces "\u005CuD800\u005CuDC00" which is
1487 * a valid surrogate pair.
1488 *
1489 * @return a reference to this object.
1490 */
1491 public AbstractStringBuilder reverse() {
1492 byte[] val = unshareValue();
1493 int count = this.count;
1494 int coder = this.coder;
1495 int n = count - 1;
1496 if (COMPACT_STRINGS && coder == LATIN1) {
1497 for (int j = (n-1) >> 1; j >= 0; j--) {
1498 int k = n - j;
1499 byte cj = val[j];
1500 val[j] = val[k];
1501 val[k] = cj;
1502 }
1503 } else {
1504 checkOffset(count, val.length >> 1);
1505 boolean hasSurrogates = false;
1506 for (int j = (n-1) >> 1; j >= 0; j--) {
1507 int k = n - j;
1508 char cj = StringUTF16.getChar(val, j);
1509 char ck = StringUTF16.getChar(val, k);
1510 StringUTF16.putChar(val, j, ck);
1511 StringUTF16.putChar(val, k, cj);
1512 if (Character.isSurrogate(cj) ||
1582 false);
1583 }
1584
1585 /**
1586 * Needed by {@code String} for the contentEquals method.
1587 */
1588 final byte[] getValue() {
1589 return value;
1590 }
1591
1592 /*
1593 * Invoker guarantees it is in UTF16 (inflate itself for asb), if two
1594 * coders are different and the dstBegin has enough space
1595 *
1596 * @param dstBegin the char index, not offset of byte[]
1597 * @param coder the coder of dst[]
1598 */
1599 void getBytes(byte dst[], int dstBegin, byte coder) {
1600 if (this.coder == coder) {
1601 System.arraycopy(value, 0, dst, dstBegin << coder, count << coder);
1602 } else { // this.coder == LATIN1 && coder == UTF16
1603 StringLatin1.inflateSB(value, dst, dstBegin, count);
1604 }
1605 }
1606
1607 /* for readObject() */
1608 void initBytes(char[] value, int off, int len) {
1609 if (String.COMPACT_STRINGS) {
1610 this.value = StringUTF16.compress(value, off, len);
1611 if (this.value != null) {
1612 this.coder = LATIN1;
1613 return;
1614 }
1615 }
1616 this.coder = UTF16;
1617 this.value = StringUTF16.toBytes(value, off, len);
1618 }
1619
1620 final byte getCoder() {
1621 return COMPACT_STRINGS ? coder : UTF16;
1622 }
|