Path: blob/master/src/java.base/share/classes/java/lang/AbstractStringBuilder.java
41152 views
/*1* Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package java.lang;2627import jdk.internal.math.FloatingDecimal;2829import java.util.Arrays;30import java.util.Spliterator;31import java.util.stream.IntStream;32import java.util.stream.StreamSupport;33import jdk.internal.util.ArraysSupport;3435import static java.lang.String.COMPACT_STRINGS;36import static java.lang.String.UTF16;37import static java.lang.String.LATIN1;38import static java.lang.String.checkIndex;39import static java.lang.String.checkOffset;4041/**42* A mutable sequence of characters.43* <p>44* Implements a modifiable string. At any point in time it contains some45* particular sequence of characters, but the length and content of the46* sequence can be changed through certain method calls.47*48* <p>Unless otherwise noted, passing a {@code null} argument to a constructor49* or method in this class will cause a {@link NullPointerException} to be50* thrown.51*52* @author Michael McCloskey53* @author Martin Buchholz54* @author Ulf Zibis55* @since 1.556*/57abstract class AbstractStringBuilder implements Appendable, CharSequence {58/**59* The value is used for character storage.60*/61byte[] value;6263/**64* The id of the encoding used to encode the bytes in {@code value}.65*/66byte coder;6768/**69* The count is the number of characters used.70*/71int count;7273private static final byte[] EMPTYVALUE = new byte[0];7475/**76* This no-arg constructor is necessary for serialization of subclasses.77*/78AbstractStringBuilder() {79value = EMPTYVALUE;80}8182/**83* Creates an AbstractStringBuilder of the specified capacity.84*/85AbstractStringBuilder(int capacity) {86if (COMPACT_STRINGS) {87value = new byte[capacity];88coder = LATIN1;89} else {90value = StringUTF16.newBytesFor(capacity);91coder = UTF16;92}93}9495/**96* Constructs an AbstractStringBuilder that contains the same characters97* as the specified {@code String}. The initial capacity of98* the string builder is {@code 16} plus the length of the99* {@code String} argument.100*101* @param str the string to copy.102*/103AbstractStringBuilder(String str) {104int length = str.length();105int capacity = (length < Integer.MAX_VALUE - 16)106? length + 16 : Integer.MAX_VALUE;107final byte initCoder = str.coder();108coder = initCoder;109value = (initCoder == LATIN1)110? new byte[capacity] : StringUTF16.newBytesFor(capacity);111append(str);112}113114/**115* Constructs an AbstractStringBuilder that contains the same characters116* as the specified {@code CharSequence}. The initial capacity of117* the string builder is {@code 16} plus the length of the118* {@code CharSequence} argument.119*120* @param seq the sequence to copy.121*/122AbstractStringBuilder(CharSequence seq) {123int length = seq.length();124if (length < 0) {125throw new NegativeArraySizeException("Negative length: " + length);126}127int capacity = (length < Integer.MAX_VALUE - 16)128? length + 16 : Integer.MAX_VALUE;129130final byte initCoder;131if (COMPACT_STRINGS) {132if (seq instanceof AbstractStringBuilder) {133initCoder = ((AbstractStringBuilder)seq).getCoder();134} else if (seq instanceof String) {135initCoder = ((String)seq).coder();136} else {137initCoder = LATIN1;138}139} else {140initCoder = UTF16;141}142143coder = initCoder;144value = (initCoder == LATIN1)145? new byte[capacity] : StringUTF16.newBytesFor(capacity);146append(seq);147}148149/**150* Compares the objects of two AbstractStringBuilder implementations lexicographically.151*152* @since 11153*/154int compareTo(AbstractStringBuilder another) {155if (this == another) {156return 0;157}158159byte[] val1 = value;160byte[] val2 = another.value;161int count1 = this.count;162int count2 = another.count;163164if (coder == another.coder) {165return isLatin1() ? StringLatin1.compareTo(val1, val2, count1, count2)166: StringUTF16.compareTo(val1, val2, count1, count2);167}168return isLatin1() ? StringLatin1.compareToUTF16(val1, val2, count1, count2)169: StringUTF16.compareToLatin1(val1, val2, count1, count2);170}171172/**173* Returns the length (character count).174*175* @return the length of the sequence of characters currently176* represented by this object177*/178@Override179public int length() {180return count;181}182183/**184* Returns the current capacity. The capacity is the number of characters185* that can be stored (including already written characters), beyond which186* an allocation will occur.187*188* @return the current capacity189*/190public int capacity() {191return value.length >> coder;192}193194/**195* Ensures that the capacity is at least equal to the specified minimum.196* If the current capacity is less than the argument, then a new internal197* array is allocated with greater capacity. The new capacity is the198* larger of:199* <ul>200* <li>The {@code minimumCapacity} argument.201* <li>Twice the old capacity, plus {@code 2}.202* </ul>203* If the {@code minimumCapacity} argument is nonpositive, this204* method takes no action and simply returns.205* Note that subsequent operations on this object can reduce the206* actual capacity below that requested here.207*208* @param minimumCapacity the minimum desired capacity.209*/210public void ensureCapacity(int minimumCapacity) {211if (minimumCapacity > 0) {212ensureCapacityInternal(minimumCapacity);213}214}215216/**217* For positive values of {@code minimumCapacity}, this method218* behaves like {@code ensureCapacity}, however it is never219* synchronized.220* If {@code minimumCapacity} is non positive due to numeric221* overflow, this method throws {@code OutOfMemoryError}.222*/223private void ensureCapacityInternal(int minimumCapacity) {224// overflow-conscious code225int oldCapacity = value.length >> coder;226if (minimumCapacity - oldCapacity > 0) {227value = Arrays.copyOf(value,228newCapacity(minimumCapacity) << coder);229}230}231232/**233* The maximum size of array to allocate (unless necessary).234* Some VMs reserve some header words in an array.235* Attempts to allocate larger arrays may result in236* OutOfMemoryError: Requested array size exceeds VM limit237*/238private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;239240/**241* Returns a capacity at least as large as the given minimum capacity.242* Returns the current capacity increased by the current length + 2 if243* that suffices.244* Will not return a capacity greater than245* {@code (MAX_ARRAY_SIZE >> coder)} unless the given minimum capacity246* is greater than that.247*248* @param minCapacity the desired minimum capacity249* @throws OutOfMemoryError if minCapacity is less than zero or250* greater than (Integer.MAX_VALUE >> coder)251*/252private int newCapacity(int minCapacity) {253int oldLength = value.length;254int newLength = minCapacity << coder;255int growth = newLength - oldLength;256int length = ArraysSupport.newLength(oldLength, growth, oldLength + (2 << coder));257if (length == Integer.MAX_VALUE) {258throw new OutOfMemoryError("Required length exceeds implementation limit");259}260return length >> coder;261}262263/**264* If the coder is "isLatin1", this inflates the internal 8-bit storage265* to 16-bit <hi=0, low> pair storage.266*/267private void inflate() {268if (!isLatin1()) {269return;270}271byte[] buf = StringUTF16.newBytesFor(value.length);272StringLatin1.inflate(value, 0, buf, 0, count);273this.value = buf;274this.coder = UTF16;275}276277/**278* Attempts to reduce storage used for the character sequence.279* If the buffer is larger than necessary to hold its current sequence of280* characters, then it may be resized to become more space efficient.281* Calling this method may, but is not required to, affect the value282* returned by a subsequent call to the {@link #capacity()} method.283*/284public void trimToSize() {285int length = count << coder;286if (length < value.length) {287value = Arrays.copyOf(value, length);288}289}290291/**292* Sets the length of the character sequence.293* The sequence is changed to a new character sequence294* whose length is specified by the argument. For every nonnegative295* index <i>k</i> less than {@code newLength}, the character at296* index <i>k</i> in the new character sequence is the same as the297* character at index <i>k</i> in the old sequence if <i>k</i> is less298* than the length of the old character sequence; otherwise, it is the299* null character {@code '\u005Cu0000'}.300*301* In other words, if the {@code newLength} argument is less than302* the current length, the length is changed to the specified length.303* <p>304* If the {@code newLength} argument is greater than or equal305* to the current length, sufficient null characters306* ({@code '\u005Cu0000'}) are appended so that307* length becomes the {@code newLength} argument.308* <p>309* The {@code newLength} argument must be greater than or equal310* to {@code 0}.311*312* @param newLength the new length313* @throws IndexOutOfBoundsException if the314* {@code newLength} argument is negative.315*/316public void setLength(int newLength) {317if (newLength < 0) {318throw new StringIndexOutOfBoundsException(newLength);319}320ensureCapacityInternal(newLength);321if (count < newLength) {322if (isLatin1()) {323StringLatin1.fillNull(value, count, newLength);324} else {325StringUTF16.fillNull(value, count, newLength);326}327}328count = newLength;329}330331/**332* Returns the {@code char} value in this sequence at the specified index.333* The first {@code char} value is at index {@code 0}, the next at index334* {@code 1}, and so on, as in array indexing.335* <p>336* The index argument must be greater than or equal to337* {@code 0}, and less than the length of this sequence.338*339* <p>If the {@code char} value specified by the index is a340* <a href="Character.html#unicode">surrogate</a>, the surrogate341* value is returned.342*343* @param index the index of the desired {@code char} value.344* @return the {@code char} value at the specified index.345* @throws IndexOutOfBoundsException if {@code index} is346* negative or greater than or equal to {@code length()}.347*/348@Override349public char charAt(int index) {350checkIndex(index, count);351if (isLatin1()) {352return (char)(value[index] & 0xff);353}354return StringUTF16.charAt(value, index);355}356357/**358* Returns the character (Unicode code point) at the specified359* index. The index refers to {@code char} values360* (Unicode code units) and ranges from {@code 0} to361* {@link #length()}{@code - 1}.362*363* <p> If the {@code char} value specified at the given index364* is in the high-surrogate range, the following index is less365* than the length of this sequence, and the366* {@code char} value at the following index is in the367* low-surrogate range, then the supplementary code point368* corresponding to this surrogate pair is returned. Otherwise,369* the {@code char} value at the given index is returned.370*371* @param index the index to the {@code char} values372* @return the code point value of the character at the373* {@code index}374* @throws IndexOutOfBoundsException if the {@code index}375* argument is negative or not less than the length of this376* sequence.377*/378public int codePointAt(int index) {379int count = this.count;380byte[] value = this.value;381checkIndex(index, count);382if (isLatin1()) {383return value[index] & 0xff;384}385return StringUTF16.codePointAtSB(value, index, count);386}387388/**389* Returns the character (Unicode code point) before the specified390* index. The index refers to {@code char} values391* (Unicode code units) and ranges from {@code 1} to {@link392* #length()}.393*394* <p> If the {@code char} value at {@code (index - 1)}395* is in the low-surrogate range, {@code (index - 2)} is not396* negative, and the {@code char} value at {@code (index -397* 2)} is in the high-surrogate range, then the398* supplementary code point value of the surrogate pair is399* returned. If the {@code char} value at {@code index -400* 1} is an unpaired low-surrogate or a high-surrogate, the401* surrogate value is returned.402*403* @param index the index following the code point that should be returned404* @return the Unicode code point value before the given index.405* @throws IndexOutOfBoundsException if the {@code index}406* argument is less than 1 or greater than the length407* of this sequence.408*/409public int codePointBefore(int index) {410int i = index - 1;411if (i < 0 || i >= count) {412throw new StringIndexOutOfBoundsException(index);413}414if (isLatin1()) {415return value[i] & 0xff;416}417return StringUTF16.codePointBeforeSB(value, index);418}419420/**421* Returns the number of Unicode code points in the specified text422* range of this sequence. The text range begins at the specified423* {@code beginIndex} and extends to the {@code char} at424* index {@code endIndex - 1}. Thus the length (in425* {@code char}s) of the text range is426* {@code endIndex-beginIndex}. Unpaired surrogates within427* this sequence count as one code point each.428*429* @param beginIndex the index to the first {@code char} of430* the text range.431* @param endIndex the index after the last {@code char} of432* the text range.433* @return the number of Unicode code points in the specified text434* range435* @throws IndexOutOfBoundsException if the436* {@code beginIndex} is negative, or {@code endIndex}437* is larger than the length of this sequence, or438* {@code beginIndex} is larger than {@code endIndex}.439*/440public int codePointCount(int beginIndex, int endIndex) {441if (beginIndex < 0 || endIndex > count || beginIndex > endIndex) {442throw new IndexOutOfBoundsException();443}444if (isLatin1()) {445return endIndex - beginIndex;446}447return StringUTF16.codePointCountSB(value, beginIndex, endIndex);448}449450/**451* Returns the index within this sequence that is offset from the452* given {@code index} by {@code codePointOffset} code453* points. Unpaired surrogates within the text range given by454* {@code index} and {@code codePointOffset} count as455* one code point each.456*457* @param index the index to be offset458* @param codePointOffset the offset in code points459* @return the index within this sequence460* @throws IndexOutOfBoundsException if {@code index}461* is negative or larger then the length of this sequence,462* or if {@code codePointOffset} is positive and the subsequence463* starting with {@code index} has fewer than464* {@code codePointOffset} code points,465* or if {@code codePointOffset} is negative and the subsequence466* before {@code index} has fewer than the absolute value of467* {@code codePointOffset} code points.468*/469public int offsetByCodePoints(int index, int codePointOffset) {470if (index < 0 || index > count) {471throw new IndexOutOfBoundsException();472}473return Character.offsetByCodePoints(this,474index, codePointOffset);475}476477/**478* Characters are copied from this sequence into the479* destination character array {@code dst}. The first character to480* be copied is at index {@code srcBegin}; the last character to481* be copied is at index {@code srcEnd-1}. The total number of482* characters to be copied is {@code srcEnd-srcBegin}. The483* characters are copied into the subarray of {@code dst} starting484* at index {@code dstBegin} and ending at index:485* <pre>{@code486* dstbegin + (srcEnd-srcBegin) - 1487* }</pre>488*489* @param srcBegin start copying at this offset.490* @param srcEnd stop copying at this offset.491* @param dst the array to copy the data into.492* @param dstBegin offset into {@code dst}.493* @throws IndexOutOfBoundsException if any of the following is true:494* <ul>495* <li>{@code srcBegin} is negative496* <li>{@code dstBegin} is negative497* <li>the {@code srcBegin} argument is greater than498* the {@code srcEnd} argument.499* <li>{@code srcEnd} is greater than500* {@code this.length()}.501* <li>{@code dstBegin+srcEnd-srcBegin} is greater than502* {@code dst.length}503* </ul>504*/505public void getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin)506{507checkRangeSIOOBE(srcBegin, srcEnd, count); // compatible to old version508int n = srcEnd - srcBegin;509checkRange(dstBegin, dstBegin + n, dst.length);510if (isLatin1()) {511StringLatin1.getChars(value, srcBegin, srcEnd, dst, dstBegin);512} else {513StringUTF16.getChars(value, srcBegin, srcEnd, dst, dstBegin);514}515}516517/**518* The character at the specified index is set to {@code ch}. This519* sequence is altered to represent a new character sequence that is520* identical to the old character sequence, except that it contains the521* character {@code ch} at position {@code index}.522* <p>523* The index argument must be greater than or equal to524* {@code 0}, and less than the length of this sequence.525*526* @param index the index of the character to modify.527* @param ch the new character.528* @throws IndexOutOfBoundsException if {@code index} is529* negative or greater than or equal to {@code length()}.530*/531public void setCharAt(int index, char ch) {532checkIndex(index, count);533if (isLatin1() && StringLatin1.canEncode(ch)) {534value[index] = (byte)ch;535} else {536if (isLatin1()) {537inflate();538}539StringUTF16.putCharSB(value, index, ch);540}541}542543/**544* Appends the string representation of the {@code Object} argument.545* <p>546* The overall effect is exactly as if the argument were converted547* to a string by the method {@link String#valueOf(Object)},548* and the characters of that string were then549* {@link #append(String) appended} to this character sequence.550*551* @param obj an {@code Object}.552* @return a reference to this object.553*/554public AbstractStringBuilder append(Object obj) {555return append(String.valueOf(obj));556}557558/**559* Appends the specified string to this character sequence.560* <p>561* The characters of the {@code String} argument are appended, in562* order, increasing the length of this sequence by the length of the563* argument. If {@code str} is {@code null}, then the four564* characters {@code "null"} are appended.565* <p>566* Let <i>n</i> be the length of this character sequence just prior to567* execution of the {@code append} method. Then the character at568* index <i>k</i> in the new character sequence is equal to the character569* at index <i>k</i> in the old character sequence, if <i>k</i> is less570* than <i>n</i>; otherwise, it is equal to the character at index571* <i>k-n</i> in the argument {@code str}.572*573* @param str a string.574* @return a reference to this object.575*/576public AbstractStringBuilder append(String str) {577if (str == null) {578return appendNull();579}580int len = str.length();581ensureCapacityInternal(count + len);582putStringAt(count, str);583count += len;584return this;585}586587/**588* Appends the specified {@code StringBuffer} to this sequence.589*590* @param sb the {@code StringBuffer} to append.591* @return a reference to this object.592*/593public AbstractStringBuilder append(StringBuffer sb) {594return this.append((AbstractStringBuilder)sb);595}596597/**598* @since 1.8599*/600AbstractStringBuilder append(AbstractStringBuilder asb) {601if (asb == null) {602return appendNull();603}604int len = asb.length();605ensureCapacityInternal(count + len);606if (getCoder() != asb.getCoder()) {607inflate();608}609asb.getBytes(value, count, coder);610count += len;611return this;612}613614// Documentation in subclasses because of synchro difference615@Override616public AbstractStringBuilder append(CharSequence s) {617if (s == null) {618return appendNull();619}620if (s instanceof String) {621return this.append((String)s);622}623if (s instanceof AbstractStringBuilder) {624return this.append((AbstractStringBuilder)s);625}626return this.append(s, 0, s.length());627}628629private AbstractStringBuilder appendNull() {630ensureCapacityInternal(count + 4);631int count = this.count;632byte[] val = this.value;633if (isLatin1()) {634val[count++] = 'n';635val[count++] = 'u';636val[count++] = 'l';637val[count++] = 'l';638} else {639count = StringUTF16.putCharsAt(val, count, 'n', 'u', 'l', 'l');640}641this.count = count;642return this;643}644645/**646* Appends a subsequence of the specified {@code CharSequence} to this647* sequence.648* <p>649* Characters of the argument {@code s}, starting at650* index {@code start}, are appended, in order, to the contents of651* this sequence up to the (exclusive) index {@code end}. The length652* of this sequence is increased by the value of {@code end - start}.653* <p>654* Let <i>n</i> be the length of this character sequence just prior to655* execution of the {@code append} method. Then the character at656* index <i>k</i> in this character sequence becomes equal to the657* character at index <i>k</i> in this sequence, if <i>k</i> is less than658* <i>n</i>; otherwise, it is equal to the character at index659* <i>k+start-n</i> in the argument {@code s}.660* <p>661* If {@code s} is {@code null}, then this method appends662* characters as if the s parameter was a sequence containing the four663* characters {@code "null"}.664*665* @param s the sequence to append.666* @param start the starting index of the subsequence to be appended.667* @param end the end index of the subsequence to be appended.668* @return a reference to this object.669* @throws IndexOutOfBoundsException if670* {@code start} is negative, or671* {@code start} is greater than {@code end} or672* {@code end} is greater than {@code s.length()}673*/674@Override675public AbstractStringBuilder append(CharSequence s, int start, int end) {676if (s == null) {677s = "null";678}679checkRange(start, end, s.length());680int len = end - start;681ensureCapacityInternal(count + len);682if (s instanceof String) {683appendChars((String)s, start, end);684} else {685appendChars(s, start, end);686}687return this;688}689690691/**692* Appends the string representation of the {@code char} array693* argument to this sequence.694* <p>695* The characters of the array argument are appended, in order, to696* the contents of this sequence. The length of this sequence697* increases by the length of the argument.698* <p>699* The overall effect is exactly as if the argument were converted700* to a string by the method {@link String#valueOf(char[])},701* and the characters of that string were then702* {@link #append(String) appended} to this character sequence.703*704* @param str the characters to be appended.705* @return a reference to this object.706*/707public AbstractStringBuilder append(char[] str) {708int len = str.length;709ensureCapacityInternal(count + len);710appendChars(str, 0, len);711return this;712}713714/**715* Appends the string representation of a subarray of the716* {@code char} array argument to this sequence.717* <p>718* Characters of the {@code char} array {@code str}, starting at719* index {@code offset}, are appended, in order, to the contents720* of this sequence. The length of this sequence increases721* by the value of {@code len}.722* <p>723* The overall effect is exactly as if the arguments were converted724* to a string by the method {@link String#valueOf(char[],int,int)},725* and the characters of that string were then726* {@link #append(String) appended} to this character sequence.727*728* @param str the characters to be appended.729* @param offset the index of the first {@code char} to append.730* @param len the number of {@code char}s to append.731* @return a reference to this object.732* @throws IndexOutOfBoundsException733* if {@code offset < 0} or {@code len < 0}734* or {@code offset+len > str.length}735*/736public AbstractStringBuilder append(char[] str, int offset, int len) {737int end = offset + len;738checkRange(offset, end, str.length);739ensureCapacityInternal(count + len);740appendChars(str, offset, end);741return this;742}743744/**745* Appends the string representation of the {@code boolean}746* argument to the sequence.747* <p>748* The overall effect is exactly as if the argument were converted749* to a string by the method {@link String#valueOf(boolean)},750* and the characters of that string were then751* {@link #append(String) appended} to this character sequence.752*753* @param b a {@code boolean}.754* @return a reference to this object.755*/756public AbstractStringBuilder append(boolean b) {757ensureCapacityInternal(count + (b ? 4 : 5));758int count = this.count;759byte[] val = this.value;760if (isLatin1()) {761if (b) {762val[count++] = 't';763val[count++] = 'r';764val[count++] = 'u';765val[count++] = 'e';766} else {767val[count++] = 'f';768val[count++] = 'a';769val[count++] = 'l';770val[count++] = 's';771val[count++] = 'e';772}773} else {774if (b) {775count = StringUTF16.putCharsAt(val, count, 't', 'r', 'u', 'e');776} else {777count = StringUTF16.putCharsAt(val, count, 'f', 'a', 'l', 's', 'e');778}779}780this.count = count;781return this;782}783784/**785* Appends the string representation of the {@code char}786* argument to this sequence.787* <p>788* The argument is appended to the contents of this sequence.789* The length of this sequence increases by {@code 1}.790* <p>791* The overall effect is exactly as if the argument were converted792* to a string by the method {@link String#valueOf(char)},793* and the character in that string were then794* {@link #append(String) appended} to this character sequence.795*796* @param c a {@code char}.797* @return a reference to this object.798*/799@Override800public AbstractStringBuilder append(char c) {801ensureCapacityInternal(count + 1);802if (isLatin1() && StringLatin1.canEncode(c)) {803value[count++] = (byte)c;804} else {805if (isLatin1()) {806inflate();807}808StringUTF16.putCharSB(value, count++, c);809}810return this;811}812813/**814* Appends the string representation of the {@code int}815* argument to this sequence.816* <p>817* The overall effect is exactly as if the argument were converted818* to a string by the method {@link String#valueOf(int)},819* and the characters of that string were then820* {@link #append(String) appended} to this character sequence.821*822* @param i an {@code int}.823* @return a reference to this object.824*/825public AbstractStringBuilder append(int i) {826int count = this.count;827int spaceNeeded = count + Integer.stringSize(i);828ensureCapacityInternal(spaceNeeded);829if (isLatin1()) {830Integer.getChars(i, spaceNeeded, value);831} else {832StringUTF16.getChars(i, count, spaceNeeded, value);833}834this.count = spaceNeeded;835return this;836}837838/**839* Appends the string representation of the {@code long}840* argument to this sequence.841* <p>842* The overall effect is exactly as if the argument were converted843* to a string by the method {@link String#valueOf(long)},844* and the characters of that string were then845* {@link #append(String) appended} to this character sequence.846*847* @param l a {@code long}.848* @return a reference to this object.849*/850public AbstractStringBuilder append(long l) {851int count = this.count;852int spaceNeeded = count + Long.stringSize(l);853ensureCapacityInternal(spaceNeeded);854if (isLatin1()) {855Long.getChars(l, spaceNeeded, value);856} else {857StringUTF16.getChars(l, count, spaceNeeded, value);858}859this.count = spaceNeeded;860return this;861}862863/**864* Appends the string representation of the {@code float}865* argument to this sequence.866* <p>867* The overall effect is exactly as if the argument were converted868* to a string by the method {@link String#valueOf(float)},869* and the characters of that string were then870* {@link #append(String) appended} to this character sequence.871*872* @param f a {@code float}.873* @return a reference to this object.874*/875public AbstractStringBuilder append(float f) {876FloatingDecimal.appendTo(f,this);877return this;878}879880/**881* Appends the string representation of the {@code double}882* argument to this sequence.883* <p>884* The overall effect is exactly as if the argument were converted885* to a string by the method {@link String#valueOf(double)},886* and the characters of that string were then887* {@link #append(String) appended} to this character sequence.888*889* @param d a {@code double}.890* @return a reference to this object.891*/892public AbstractStringBuilder append(double d) {893FloatingDecimal.appendTo(d,this);894return this;895}896897/**898* Removes the characters in a substring of this sequence.899* The substring begins at the specified {@code start} and extends to900* the character at index {@code end - 1} or to the end of the901* sequence if no such character exists. If902* {@code start} is equal to {@code end}, no changes are made.903*904* @param start The beginning index, inclusive.905* @param end The ending index, exclusive.906* @return This object.907* @throws StringIndexOutOfBoundsException if {@code start}908* is negative, greater than {@code length()}, or909* greater than {@code end}.910*/911public AbstractStringBuilder delete(int start, int end) {912int count = this.count;913if (end > count) {914end = count;915}916checkRangeSIOOBE(start, end, count);917int len = end - start;918if (len > 0) {919shift(end, -len);920this.count = count - len;921}922return this;923}924925/**926* Appends the string representation of the {@code codePoint}927* argument to this sequence.928*929* <p> The argument is appended to the contents of this sequence.930* The length of this sequence increases by931* {@link Character#charCount(int) Character.charCount(codePoint)}.932*933* <p> The overall effect is exactly as if the argument were934* converted to a {@code char} array by the method935* {@link Character#toChars(int)} and the character in that array936* were then {@link #append(char[]) appended} to this character937* sequence.938*939* @param codePoint a Unicode code point940* @return a reference to this object.941* @throws IllegalArgumentException if the specified942* {@code codePoint} isn't a valid Unicode code point943*/944public AbstractStringBuilder appendCodePoint(int codePoint) {945if (Character.isBmpCodePoint(codePoint)) {946return append((char)codePoint);947}948return append(Character.toChars(codePoint));949}950951/**952* Removes the {@code char} at the specified position in this953* sequence. This sequence is shortened by one {@code char}.954*955* <p>Note: If the character at the given index is a supplementary956* character, this method does not remove the entire character. If957* correct handling of supplementary characters is required,958* determine the number of {@code char}s to remove by calling959* {@code Character.charCount(thisSequence.codePointAt(index))},960* where {@code thisSequence} is this sequence.961*962* @param index Index of {@code char} to remove963* @return This object.964* @throws StringIndexOutOfBoundsException if the {@code index}965* is negative or greater than or equal to966* {@code length()}.967*/968public AbstractStringBuilder deleteCharAt(int index) {969checkIndex(index, count);970shift(index + 1, -1);971count--;972return this;973}974975/**976* Replaces the characters in a substring of this sequence977* with characters in the specified {@code String}. The substring978* begins at the specified {@code start} and extends to the character979* at index {@code end - 1} or to the end of the980* sequence if no such character exists. First the981* characters in the substring are removed and then the specified982* {@code String} is inserted at {@code start}. (This983* sequence will be lengthened to accommodate the984* specified String if necessary.)985*986* @param start The beginning index, inclusive.987* @param end The ending index, exclusive.988* @param str String that will replace previous contents.989* @return This object.990* @throws StringIndexOutOfBoundsException if {@code start}991* is negative, greater than {@code length()}, or992* greater than {@code end}.993*/994public AbstractStringBuilder replace(int start, int end, String str) {995int count = this.count;996if (end > count) {997end = count;998}999checkRangeSIOOBE(start, end, count);1000int len = str.length();1001int newCount = count + len - (end - start);1002ensureCapacityInternal(newCount);1003shift(end, newCount - count);1004this.count = newCount;1005putStringAt(start, str);1006return this;1007}10081009/**1010* Returns a new {@code String} that contains a subsequence of1011* characters currently contained in this character sequence. The1012* substring begins at the specified index and extends to the end of1013* this sequence.1014*1015* @param start The beginning index, inclusive.1016* @return The new string.1017* @throws StringIndexOutOfBoundsException if {@code start} is1018* less than zero, or greater than the length of this object.1019*/1020public String substring(int start) {1021return substring(start, count);1022}10231024/**1025* Returns a new character sequence that is a subsequence of this sequence.1026*1027* <p> An invocation of this method of the form1028*1029* <pre>{@code1030* sb.subSequence(begin, end)}</pre>1031*1032* behaves in exactly the same way as the invocation1033*1034* <pre>{@code1035* sb.substring(begin, end)}</pre>1036*1037* This method is provided so that this class can1038* implement the {@link CharSequence} interface.1039*1040* @param start the start index, inclusive.1041* @param end the end index, exclusive.1042* @return the specified subsequence.1043*1044* @throws IndexOutOfBoundsException1045* if {@code start} or {@code end} are negative,1046* if {@code end} is greater than {@code length()},1047* or if {@code start} is greater than {@code end}1048*/1049@Override1050public CharSequence subSequence(int start, int end) {1051return substring(start, end);1052}10531054/**1055* Returns a new {@code String} that contains a subsequence of1056* characters currently contained in this sequence. The1057* substring begins at the specified {@code start} and1058* extends to the character at index {@code end - 1}.1059*1060* @param start The beginning index, inclusive.1061* @param end The ending index, exclusive.1062* @return The new string.1063* @throws StringIndexOutOfBoundsException if {@code start}1064* or {@code end} are negative or greater than1065* {@code length()}, or {@code start} is1066* greater than {@code end}.1067*/1068public String substring(int start, int end) {1069checkRangeSIOOBE(start, end, count);1070if (isLatin1()) {1071return StringLatin1.newString(value, start, end - start);1072}1073return StringUTF16.newString(value, start, end - start);1074}10751076private void shift(int offset, int n) {1077System.arraycopy(value, offset << coder,1078value, (offset + n) << coder, (count - offset) << coder);1079}10801081/**1082* Inserts the string representation of a subarray of the {@code str}1083* array argument into this sequence. The subarray begins at the1084* specified {@code offset} and extends {@code len} {@code char}s.1085* The characters of the subarray are inserted into this sequence at1086* the position indicated by {@code index}. The length of this1087* sequence increases by {@code len} {@code char}s.1088*1089* @param index position at which to insert subarray.1090* @param str A {@code char} array.1091* @param offset the index of the first {@code char} in subarray to1092* be inserted.1093* @param len the number of {@code char}s in the subarray to1094* be inserted.1095* @return This object1096* @throws StringIndexOutOfBoundsException if {@code index}1097* is negative or greater than {@code length()}, or1098* {@code offset} or {@code len} are negative, or1099* {@code (offset+len)} is greater than1100* {@code str.length}.1101*/1102public AbstractStringBuilder insert(int index, char[] str, int offset,1103int len)1104{1105checkOffset(index, count);1106checkRangeSIOOBE(offset, offset + len, str.length);1107ensureCapacityInternal(count + len);1108shift(index, len);1109count += len;1110putCharsAt(index, str, offset, offset + len);1111return this;1112}11131114/**1115* Inserts the string representation of the {@code Object}1116* argument into this character sequence.1117* <p>1118* The overall effect is exactly as if the second argument were1119* converted to a string by the method {@link String#valueOf(Object)},1120* and the characters of that string were then1121* {@link #insert(int,String) inserted} into this character1122* sequence at the indicated offset.1123* <p>1124* The {@code offset} argument must be greater than or equal to1125* {@code 0}, and less than or equal to the {@linkplain #length() length}1126* of this sequence.1127*1128* @param offset the offset.1129* @param obj an {@code Object}.1130* @return a reference to this object.1131* @throws StringIndexOutOfBoundsException if the offset is invalid.1132*/1133public AbstractStringBuilder insert(int offset, Object obj) {1134return insert(offset, String.valueOf(obj));1135}11361137/**1138* Inserts the string into this character sequence.1139* <p>1140* The characters of the {@code String} argument are inserted, in1141* order, into this sequence at the indicated offset, moving up any1142* characters originally above that position and increasing the length1143* of this sequence by the length of the argument. If1144* {@code str} is {@code null}, then the four characters1145* {@code "null"} are inserted into this sequence.1146* <p>1147* The character at index <i>k</i> in the new character sequence is1148* equal to:1149* <ul>1150* <li>the character at index <i>k</i> in the old character sequence, if1151* <i>k</i> is less than {@code offset}1152* <li>the character at index <i>k</i>{@code -offset} in the1153* argument {@code str}, if <i>k</i> is not less than1154* {@code offset} but is less than {@code offset+str.length()}1155* <li>the character at index <i>k</i>{@code -str.length()} in the1156* old character sequence, if <i>k</i> is not less than1157* {@code offset+str.length()}1158* </ul><p>1159* The {@code offset} argument must be greater than or equal to1160* {@code 0}, and less than or equal to the {@linkplain #length() length}1161* of this sequence.1162*1163* @param offset the offset.1164* @param str a string.1165* @return a reference to this object.1166* @throws StringIndexOutOfBoundsException if the offset is invalid.1167*/1168public AbstractStringBuilder insert(int offset, String str) {1169checkOffset(offset, count);1170if (str == null) {1171str = "null";1172}1173int len = str.length();1174ensureCapacityInternal(count + len);1175shift(offset, len);1176count += len;1177putStringAt(offset, str);1178return this;1179}11801181/**1182* Inserts the string representation of the {@code char} array1183* argument into this sequence.1184* <p>1185* The characters of the array argument are inserted into the1186* contents of this sequence at the position indicated by1187* {@code offset}. The length of this sequence increases by1188* the length of the argument.1189* <p>1190* The overall effect is exactly as if the second argument were1191* converted to a string by the method {@link String#valueOf(char[])},1192* and the characters of that string were then1193* {@link #insert(int,String) inserted} into this character1194* sequence at the indicated offset.1195* <p>1196* The {@code offset} argument must be greater than or equal to1197* {@code 0}, and less than or equal to the {@linkplain #length() length}1198* of this sequence.1199*1200* @param offset the offset.1201* @param str a character array.1202* @return a reference to this object.1203* @throws StringIndexOutOfBoundsException if the offset is invalid.1204*/1205public AbstractStringBuilder insert(int offset, char[] str) {1206checkOffset(offset, count);1207int len = str.length;1208ensureCapacityInternal(count + len);1209shift(offset, len);1210count += len;1211putCharsAt(offset, str, 0, len);1212return this;1213}12141215/**1216* Inserts the specified {@code CharSequence} into this sequence.1217* <p>1218* The characters of the {@code CharSequence} argument are inserted,1219* in order, into this sequence at the indicated offset, moving up1220* any characters originally above that position and increasing the length1221* of this sequence by the length of the argument s.1222* <p>1223* The result of this method is exactly the same as if it were an1224* invocation of this object's1225* {@link #insert(int,CharSequence,int,int) insert}(dstOffset, s, 0, s.length())1226* method.1227*1228* <p>If {@code s} is {@code null}, then the four characters1229* {@code "null"} are inserted into this sequence.1230*1231* @param dstOffset the offset.1232* @param s the sequence to be inserted1233* @return a reference to this object.1234* @throws IndexOutOfBoundsException if the offset is invalid.1235*/1236public AbstractStringBuilder insert(int dstOffset, CharSequence s) {1237if (s == null) {1238s = "null";1239}1240return this.insert(dstOffset, s, 0, s.length());1241}12421243/**1244* Inserts a subsequence of the specified {@code CharSequence} into1245* this sequence.1246* <p>1247* The subsequence of the argument {@code s} specified by1248* {@code start} and {@code end} are inserted,1249* in order, into this sequence at the specified destination offset, moving1250* up any characters originally above that position. The length of this1251* sequence is increased by {@code end - start}.1252* <p>1253* The character at index <i>k</i> in this sequence becomes equal to:1254* <ul>1255* <li>the character at index <i>k</i> in this sequence, if1256* <i>k</i> is less than {@code dstOffset}1257* <li>the character at index <i>k</i>{@code +start-dstOffset} in1258* the argument {@code s}, if <i>k</i> is greater than or equal to1259* {@code dstOffset} but is less than {@code dstOffset+end-start}1260* <li>the character at index <i>k</i>{@code -(end-start)} in this1261* sequence, if <i>k</i> is greater than or equal to1262* {@code dstOffset+end-start}1263* </ul><p>1264* The {@code dstOffset} argument must be greater than or equal to1265* {@code 0}, and less than or equal to the {@linkplain #length() length}1266* of this sequence.1267* <p>The start argument must be nonnegative, and not greater than1268* {@code end}.1269* <p>The end argument must be greater than or equal to1270* {@code start}, and less than or equal to the length of s.1271*1272* <p>If {@code s} is {@code null}, then this method inserts1273* characters as if the s parameter was a sequence containing the four1274* characters {@code "null"}.1275*1276* @param dstOffset the offset in this sequence.1277* @param s the sequence to be inserted.1278* @param start the starting index of the subsequence to be inserted.1279* @param end the end index of the subsequence to be inserted.1280* @return a reference to this object.1281* @throws IndexOutOfBoundsException if {@code dstOffset}1282* is negative or greater than {@code this.length()}, or1283* {@code start} or {@code end} are negative, or1284* {@code start} is greater than {@code end} or1285* {@code end} is greater than {@code s.length()}1286*/1287public AbstractStringBuilder insert(int dstOffset, CharSequence s,1288int start, int end)1289{1290if (s == null) {1291s = "null";1292}1293checkOffset(dstOffset, count);1294checkRange(start, end, s.length());1295int len = end - start;1296ensureCapacityInternal(count + len);1297shift(dstOffset, len);1298count += len;1299if (s instanceof String) {1300putStringAt(dstOffset, (String) s, start, end);1301} else {1302putCharsAt(dstOffset, s, start, end);1303}1304return this;1305}13061307/**1308* Inserts the string representation of the {@code boolean}1309* argument into this sequence.1310* <p>1311* The overall effect is exactly as if the second argument were1312* converted to a string by the method {@link String#valueOf(boolean)},1313* and the characters of that string were then1314* {@link #insert(int,String) inserted} into this character1315* sequence at the indicated offset.1316* <p>1317* The {@code offset} argument must be greater than or equal to1318* {@code 0}, and less than or equal to the {@linkplain #length() length}1319* of this sequence.1320*1321* @param offset the offset.1322* @param b a {@code boolean}.1323* @return a reference to this object.1324* @throws StringIndexOutOfBoundsException if the offset is invalid.1325*/1326public AbstractStringBuilder insert(int offset, boolean b) {1327return insert(offset, String.valueOf(b));1328}13291330/**1331* Inserts the string representation of the {@code char}1332* argument into this sequence.1333* <p>1334* The overall effect is exactly as if the second argument were1335* converted to a string by the method {@link String#valueOf(char)},1336* and the character in that string were then1337* {@link #insert(int,String) inserted} into this character1338* sequence at the indicated offset.1339* <p>1340* The {@code offset} argument must be greater than or equal to1341* {@code 0}, and less than or equal to the {@linkplain #length() length}1342* of this sequence.1343*1344* @param offset the offset.1345* @param c a {@code char}.1346* @return a reference to this object.1347* @throws IndexOutOfBoundsException if the offset is invalid.1348*/1349public AbstractStringBuilder insert(int offset, char c) {1350checkOffset(offset, count);1351ensureCapacityInternal(count + 1);1352shift(offset, 1);1353count += 1;1354if (isLatin1() && StringLatin1.canEncode(c)) {1355value[offset] = (byte)c;1356} else {1357if (isLatin1()) {1358inflate();1359}1360StringUTF16.putCharSB(value, offset, c);1361}1362return this;1363}13641365/**1366* Inserts the string representation of the second {@code int}1367* argument into this sequence.1368* <p>1369* The overall effect is exactly as if the second argument were1370* converted to a string by the method {@link String#valueOf(int)},1371* and the characters of that string were then1372* {@link #insert(int,String) inserted} into this character1373* sequence at the indicated offset.1374* <p>1375* The {@code offset} argument must be greater than or equal to1376* {@code 0}, and less than or equal to the {@linkplain #length() length}1377* of this sequence.1378*1379* @param offset the offset.1380* @param i an {@code int}.1381* @return a reference to this object.1382* @throws StringIndexOutOfBoundsException if the offset is invalid.1383*/1384public AbstractStringBuilder insert(int offset, int i) {1385return insert(offset, String.valueOf(i));1386}13871388/**1389* Inserts the string representation of the {@code long}1390* argument into this sequence.1391* <p>1392* The overall effect is exactly as if the second argument were1393* converted to a string by the method {@link String#valueOf(long)},1394* and the characters of that string were then1395* {@link #insert(int,String) inserted} into this character1396* sequence at the indicated offset.1397* <p>1398* The {@code offset} argument must be greater than or equal to1399* {@code 0}, and less than or equal to the {@linkplain #length() length}1400* of this sequence.1401*1402* @param offset the offset.1403* @param l a {@code long}.1404* @return a reference to this object.1405* @throws StringIndexOutOfBoundsException if the offset is invalid.1406*/1407public AbstractStringBuilder insert(int offset, long l) {1408return insert(offset, String.valueOf(l));1409}14101411/**1412* Inserts the string representation of the {@code float}1413* argument into this sequence.1414* <p>1415* The overall effect is exactly as if the second argument were1416* converted to a string by the method {@link String#valueOf(float)},1417* and the characters of that string were then1418* {@link #insert(int,String) inserted} into this character1419* sequence at the indicated offset.1420* <p>1421* The {@code offset} argument must be greater than or equal to1422* {@code 0}, and less than or equal to the {@linkplain #length() length}1423* of this sequence.1424*1425* @param offset the offset.1426* @param f a {@code float}.1427* @return a reference to this object.1428* @throws StringIndexOutOfBoundsException if the offset is invalid.1429*/1430public AbstractStringBuilder insert(int offset, float f) {1431return insert(offset, String.valueOf(f));1432}14331434/**1435* Inserts the string representation of the {@code double}1436* argument into this sequence.1437* <p>1438* The overall effect is exactly as if the second argument were1439* converted to a string by the method {@link String#valueOf(double)},1440* and the characters of that string were then1441* {@link #insert(int,String) inserted} into this character1442* sequence at the indicated offset.1443* <p>1444* The {@code offset} argument must be greater than or equal to1445* {@code 0}, and less than or equal to the {@linkplain #length() length}1446* of this sequence.1447*1448* @param offset the offset.1449* @param d a {@code double}.1450* @return a reference to this object.1451* @throws StringIndexOutOfBoundsException if the offset is invalid.1452*/1453public AbstractStringBuilder insert(int offset, double d) {1454return insert(offset, String.valueOf(d));1455}14561457/**1458* Returns the index within this string of the first occurrence of the1459* specified substring.1460*1461* <p>The returned index is the smallest value {@code k} for which:1462* <pre>{@code1463* this.toString().startsWith(str, k)1464* }</pre>1465* If no such value of {@code k} exists, then {@code -1} is returned.1466*1467* @param str the substring to search for.1468* @return the index of the first occurrence of the specified substring,1469* or {@code -1} if there is no such occurrence.1470*/1471public int indexOf(String str) {1472return indexOf(str, 0);1473}14741475/**1476* Returns the index within this string of the first occurrence of the1477* specified substring, starting at the specified index.1478*1479* <p>The returned index is the smallest value {@code k} for which:1480* <pre>{@code1481* k >= Math.min(fromIndex, this.length()) &&1482* this.toString().startsWith(str, k)1483* }</pre>1484* If no such value of {@code k} exists, then {@code -1} is returned.1485*1486* @param str the substring to search for.1487* @param fromIndex the index from which to start the search.1488* @return the index of the first occurrence of the specified substring,1489* starting at the specified index,1490* or {@code -1} if there is no such occurrence.1491*/1492public int indexOf(String str, int fromIndex) {1493return String.indexOf(value, coder, count, str, fromIndex);1494}14951496/**1497* Returns the index within this string of the last occurrence of the1498* specified substring. The last occurrence of the empty string "" is1499* considered to occur at the index value {@code this.length()}.1500*1501* <p>The returned index is the largest value {@code k} for which:1502* <pre>{@code1503* this.toString().startsWith(str, k)1504* }</pre>1505* If no such value of {@code k} exists, then {@code -1} is returned.1506*1507* @param str the substring to search for.1508* @return the index of the last occurrence of the specified substring,1509* or {@code -1} if there is no such occurrence.1510*/1511public int lastIndexOf(String str) {1512return lastIndexOf(str, count);1513}15141515/**1516* Returns the index within this string of the last occurrence of the1517* specified substring, searching backward starting at the specified index.1518*1519* <p>The returned index is the largest value {@code k} for which:1520* <pre>{@code1521* k <= Math.min(fromIndex, this.length()) &&1522* this.toString().startsWith(str, k)1523* }</pre>1524* If no such value of {@code k} exists, then {@code -1} is returned.1525*1526* @param str the substring to search for.1527* @param fromIndex the index to start the search from.1528* @return the index of the last occurrence of the specified substring,1529* searching backward from the specified index,1530* or {@code -1} if there is no such occurrence.1531*/1532public int lastIndexOf(String str, int fromIndex) {1533return String.lastIndexOf(value, coder, count, str, fromIndex);1534}15351536/**1537* Causes this character sequence to be replaced by the reverse of1538* the sequence. If there are any surrogate pairs included in the1539* sequence, these are treated as single characters for the1540* reverse operation. Thus, the order of the high-low surrogates1541* is never reversed.1542*1543* Let <i>n</i> be the character length of this character sequence1544* (not the length in {@code char} values) just prior to1545* execution of the {@code reverse} method. Then the1546* character at index <i>k</i> in the new character sequence is1547* equal to the character at index <i>n-k-1</i> in the old1548* character sequence.1549*1550* <p>Note that the reverse operation may result in producing1551* surrogate pairs that were unpaired low-surrogates and1552* high-surrogates before the operation. For example, reversing1553* "\u005CuDC00\u005CuD800" produces "\u005CuD800\u005CuDC00" which is1554* a valid surrogate pair.1555*1556* @return a reference to this object.1557*/1558public AbstractStringBuilder reverse() {1559byte[] val = this.value;1560int count = this.count;1561int n = count - 1;1562if (isLatin1()) {1563for (int j = (n-1) >> 1; j >= 0; j--) {1564int k = n - j;1565byte cj = val[j];1566val[j] = val[k];1567val[k] = cj;1568}1569} else {1570StringUTF16.reverse(val, count);1571}1572return this;1573}15741575/**1576* Returns a string representing the data in this sequence.1577* A new {@code String} object is allocated and initialized to1578* contain the character sequence currently represented by this1579* object. This {@code String} is then returned. Subsequent1580* changes to this sequence do not affect the contents of the1581* {@code String}.1582*1583* @return a string representation of this sequence of characters.1584*/1585@Override1586public abstract String toString();15871588/**1589* {@inheritDoc}1590* @since 91591*/1592@Override1593public IntStream chars() {1594// Reuse String-based spliterator. This requires a supplier to1595// capture the value and count when the terminal operation is executed1596return StreamSupport.intStream(1597() -> {1598// The combined set of field reads are not atomic and thread1599// safe but bounds checks will ensure no unsafe reads from1600// the byte array1601byte[] val = this.value;1602int count = this.count;1603byte coder = this.coder;1604return coder == LATIN11605? new StringLatin1.CharsSpliterator(val, 0, count, 0)1606: new StringUTF16.CharsSpliterator(val, 0, count, 0);1607},1608Spliterator.ORDERED | Spliterator.SIZED | Spliterator.SUBSIZED,1609false);1610}16111612/**1613* {@inheritDoc}1614* @since 91615*/1616@Override1617public IntStream codePoints() {1618// Reuse String-based spliterator. This requires a supplier to1619// capture the value and count when the terminal operation is executed1620return StreamSupport.intStream(1621() -> {1622// The combined set of field reads are not atomic and thread1623// safe but bounds checks will ensure no unsafe reads from1624// the byte array1625byte[] val = this.value;1626int count = this.count;1627byte coder = this.coder;1628return coder == LATIN11629? new StringLatin1.CharsSpliterator(val, 0, count, 0)1630: new StringUTF16.CodePointsSpliterator(val, 0, count, 0);1631},1632Spliterator.ORDERED,1633false);1634}16351636/**1637* Needed by {@code String} for the contentEquals method.1638*/1639final byte[] getValue() {1640return value;1641}16421643/*1644* Invoker guarantees it is in UTF16 (inflate itself for asb), if two1645* coders are different and the dstBegin has enough space1646*1647* @param dstBegin the char index, not offset of byte[]1648* @param coder the coder of dst[]1649*/1650void getBytes(byte[] dst, int dstBegin, byte coder) {1651if (this.coder == coder) {1652System.arraycopy(value, 0, dst, dstBegin << coder, count << coder);1653} else { // this.coder == LATIN && coder == UTF161654StringLatin1.inflate(value, 0, dst, dstBegin, count);1655}1656}16571658/* for readObject() */1659void initBytes(char[] value, int off, int len) {1660if (String.COMPACT_STRINGS) {1661this.value = StringUTF16.compress(value, off, len);1662if (this.value != null) {1663this.coder = LATIN1;1664return;1665}1666}1667this.coder = UTF16;1668this.value = StringUTF16.toBytes(value, off, len);1669}16701671final byte getCoder() {1672return COMPACT_STRINGS ? coder : UTF16;1673}16741675final boolean isLatin1() {1676return COMPACT_STRINGS && coder == LATIN1;1677}16781679private final void putCharsAt(int index, char[] s, int off, int end) {1680if (isLatin1()) {1681byte[] val = this.value;1682for (int i = off, j = index; i < end; i++) {1683char c = s[i];1684if (StringLatin1.canEncode(c)) {1685val[j++] = (byte)c;1686} else {1687inflate();1688StringUTF16.putCharsSB(this.value, j, s, i, end);1689return;1690}1691}1692} else {1693StringUTF16.putCharsSB(this.value, index, s, off, end);1694}1695}16961697private final void putCharsAt(int index, CharSequence s, int off, int end) {1698if (isLatin1()) {1699byte[] val = this.value;1700for (int i = off, j = index; i < end; i++) {1701char c = s.charAt(i);1702if (StringLatin1.canEncode(c)) {1703val[j++] = (byte)c;1704} else {1705inflate();1706StringUTF16.putCharsSB(this.value, j, s, i, end);1707return;1708}1709}1710} else {1711StringUTF16.putCharsSB(this.value, index, s, off, end);1712}1713}17141715private void putStringAt(int index, String str, int off, int end) {1716if (getCoder() != str.coder()) {1717inflate();1718}1719str.getBytes(value, off, index, coder, end - off);1720}17211722private void putStringAt(int index, String str) {1723putStringAt(index, str, 0, str.length());1724}17251726private final void appendChars(char[] s, int off, int end) {1727int count = this.count;1728if (isLatin1()) {1729byte[] val = this.value;1730for (int i = off, j = count; i < end; i++) {1731char c = s[i];1732if (StringLatin1.canEncode(c)) {1733val[j++] = (byte)c;1734} else {1735this.count = count = j;1736inflate();1737StringUTF16.putCharsSB(this.value, j, s, i, end);1738this.count = count + end - i;1739return;1740}1741}1742} else {1743StringUTF16.putCharsSB(this.value, count, s, off, end);1744}1745this.count = count + end - off;1746}17471748private final void appendChars(String s, int off, int end) {1749if (isLatin1()) {1750if (s.isLatin1()) {1751System.arraycopy(s.value(), off, this.value, this.count, end - off);1752} else {1753// We might need to inflate, but do it as late as possible since1754// the range of characters we're copying might all be latin11755byte[] val = this.value;1756for (int i = off, j = count; i < end; i++) {1757char c = s.charAt(i);1758if (StringLatin1.canEncode(c)) {1759val[j++] = (byte) c;1760} else {1761count = j;1762inflate();1763System.arraycopy(s.value(), i << UTF16, this.value, j << UTF16, (end - i) << UTF16);1764count += end - i;1765return;1766}1767}1768}1769} else if (s.isLatin1()) {1770StringUTF16.putCharsSB(this.value, this.count, s, off, end);1771} else { // both UTF161772System.arraycopy(s.value(), off << UTF16, this.value, this.count << UTF16, (end - off) << UTF16);1773}1774count += end - off;1775}17761777private final void appendChars(CharSequence s, int off, int end) {1778if (isLatin1()) {1779byte[] val = this.value;1780for (int i = off, j = count; i < end; i++) {1781char c = s.charAt(i);1782if (StringLatin1.canEncode(c)) {1783val[j++] = (byte)c;1784} else {1785count = j;1786inflate();1787StringUTF16.putCharsSB(this.value, j, s, i, end);1788count += end - i;1789return;1790}1791}1792} else {1793StringUTF16.putCharsSB(this.value, count, s, off, end);1794}1795count += end - off;1796}17971798/* IndexOutOfBoundsException, if out of bounds */1799private static void checkRange(int start, int end, int len) {1800if (start < 0 || start > end || end > len) {1801throw new IndexOutOfBoundsException(1802"start " + start + ", end " + end + ", length " + len);1803}1804}18051806/* StringIndexOutOfBoundsException, if out of bounds */1807private static void checkRangeSIOOBE(int start, int end, int len) {1808if (start < 0 || start > end || end > len) {1809throw new StringIndexOutOfBoundsException(1810"start " + start + ", end " + end + ", length " + len);1811}1812}1813}181418151816