/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package java.lang;
import java.io.IOException;
import java.io.InvalidObjectException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import libcore.util.EmptyArray;
/*-[
#import "java/lang/Character.h"
#import "java/lang/Double.h"
#import "java/lang/Float.h"
#import "java/lang/Integer.h"
#import "java/lang/Long.h"
]-*/
/**
* A modifiable {@link CharSequence sequence of characters} for use in creating
* strings. This class is intended as a direct replacement of
* {@link StringBuffer} for non-concurrent use; unlike {@code StringBuffer} this
* class is not synchronized.
*
* <p>For particularly complex string-building needs, consider {@link java.util.Formatter}.
*
* <p>The majority of the modification methods on this class return {@code
* this} so that method calls can be chained together. For example:
* {@code new StringBuilder("a").append("b").append("c").toString()}.
*
* @see CharSequence
* @see Appendable
* @see StringBuffer
* @see String
* @see String#format
* @since 1.5
*/
public final class StringBuilder extends AbstractStringBuilder implements Serializable {
private static final long serialVersionUID = 4383685877147921099L;
/**
* Constructs an instance with an initial capacity of {@code 16}.
*
* @see #capacity()
*/
public StringBuilder() {
}
/**
* Constructs an instance with the specified capacity.
*
* @param capacity
* the initial capacity to use.
* @throws NegativeArraySizeException
* if the specified {@code capacity} is negative.
* @see #capacity()
*/
public StringBuilder(int capacity) {
super(capacity);
}
/**
* Constructs an instance that's initialized with the contents of the
* specified {@code CharSequence}. The capacity of the new builder will be
* the length of the {@code CharSequence} plus 16.
*
* @param seq
* the {@code CharSequence} to copy into the builder.
* @throws NullPointerException
* if {@code seq} is {@code null}.
*/
public StringBuilder(CharSequence seq) {
this(seq.toString());
}
/**
* Constructs an instance that's initialized with the contents of the
* specified {@code String}. The capacity of the new builder will be the
* length of the {@code String} plus 16.
*
* @param str
* the {@code String} to copy into the builder.
* @throws NullPointerException
* if {@code str} is {@code null}.
*/
public StringBuilder(String str) {
super(str.length() + 16);
append(str);
}
/**
* Appends the string representation of the specified {@code boolean} value.
* The {@code boolean} value is converted to a String according to the rule
* defined by {@link String#valueOf(boolean)}.
*
* @param b
* the {@code boolean} value to append.
* @return this builder.
* @see String#valueOf(boolean)
*/
public native StringBuilder append(boolean b) /*-[
JreStringBuilder_appendString(&self->delegate_, b ? @"true" : @"false");
return self;
]-*/;
/**
* Appends the string representation of the specified {@code char} value.
* The {@code char} value is converted to a string according to the rule
* defined by {@link String#valueOf(char)}.
*
* @param c
* the {@code char} value to append.
* @return this builder.
* @see String#valueOf(char)
*/
public native StringBuilder append(char c) /*-[
JreStringBuilder_appendChar(&self->delegate_, c);
return self;
]-*/;
/**
* Appends the string representation of the specified {@code int} value. The
* {@code int} value is converted to a string according to the rule defined
* by {@link String#valueOf(int)}.
*
* @param i
* the {@code int} value to append.
* @return this builder.
* @see String#valueOf(int)
*/
public StringBuilder append(int i) {
IntegralToString.appendInt(this, i);
return this;
}
/**
* Appends the string representation of the specified {@code long} value.
* The {@code long} value is converted to a string according to the rule
* defined by {@link String#valueOf(long)}.
*
* @param l
* the {@code long} value.
* @return this builder.
* @see String#valueOf(long)
*/
public StringBuilder append(long l) {
IntegralToString.appendLong(this, l);
return this;
}
/**
* Appends the string representation of the specified {@code float} value.
* The {@code float} value is converted to a string according to the rule
* defined by {@link String#valueOf(float)}.
*
* @param f
* the {@code float} value to append.
* @return this builder.
* @see String#valueOf(float)
*/
public StringBuilder append(float f) {
RealToString.appendFloat(this, f);
return this;
}
/**
* Appends the string representation of the specified {@code double} value.
* The {@code double} value is converted to a string according to the rule
* defined by {@link String#valueOf(double)}.
*
* @param d
* the {@code double} value to append.
* @return this builder.
* @see String#valueOf(double)
*/
public StringBuilder append(double d) {
RealToString.appendDouble(this, d);
return this;
}
/**
* Appends the string representation of the specified {@code Object}.
* The {@code Object} value is converted to a string according to the rule
* defined by {@link String#valueOf(Object)}.
*
* @param obj
* the {@code Object} to append.
* @return this builder.
* @see String#valueOf(Object)
*/
public native StringBuilder append(Object obj) /*-[
if (obj == nil) {
JreStringBuilder_appendNull(&self->delegate_);
} else {
JreStringBuilder_appendString(&self->delegate_, [obj description]);
}
return self;
]-*/;
/**
* Appends the contents of the specified string. If the string is {@code
* null}, then the string {@code "null"} is appended.
*
* @param str
* the string to append.
* @return this builder.
*/
public native StringBuilder append(String str) /*-[
JreStringBuilder_appendString(&self->delegate_, str);
return self;
]-*/;
/**
* Appends the contents of the specified {@code StringBuffer}. If the
* StringBuffer is {@code null}, then the string {@code "null"} is
* appended.
*
* @param sb
* the {@code StringBuffer} to append.
* @return this builder.
*/
public native StringBuilder append(StringBuffer sb) /*-[
if (sb == nil) {
JreStringBuilder_appendNull(&self->delegate_);
} else {
JreStringBuilder_appendBuffer(
&self->delegate_, sb->delegate_.buffer_, sb->delegate_.count_);
}
return self;
]-*/;
/**
* Appends the string representation of the specified {@code char[]}.
* The {@code char[]} is converted to a string according to the rule
* defined by {@link String#valueOf(char[])}.
*
* @param chars
* the {@code char[]} to append..
* @return this builder.
* @see String#valueOf(char[])
*/
public native StringBuilder append(char[] chars) /*-[
JreStringBuilder_appendCharArray(&self->delegate_, chars);
return self;
]-*/;
/**
* Appends the string representation of the specified subset of the {@code
* char[]}. The {@code char[]} value is converted to a String according to
* the rule defined by {@link String#valueOf(char[],int,int)}.
*
* @param str
* the {@code char[]} to append.
* @param offset
* the inclusive offset index.
* @param len
* the number of characters.
* @return this builder.
* @throws ArrayIndexOutOfBoundsException
* if {@code offset} and {@code len} do not specify a valid
* subsequence.
* @see String#valueOf(char[],int,int)
*/
public native StringBuilder append(char[] str, int offset, int len) /*-[
JreStringBuilder_appendCharArraySubset(&self->delegate_, str, offset, len);
return self;
]-*/;
/**
* Appends the string representation of the specified {@code CharSequence}.
* If the {@code CharSequence} is {@code null}, then the string {@code
* "null"} is appended.
*
* @param csq
* the {@code CharSequence} to append.
* @return this builder.
*/
public native StringBuilder append(CharSequence csq) /*-[
if (csq == nil) {
JreStringBuilder_appendNull(&self->delegate_);
} else {
JreStringBuilder_appendCharSequence(&self->delegate_, csq, 0, [csq length]);
}
return self;
]-*/;
/**
* Appends the string representation of the specified subsequence of the
* {@code CharSequence}. If the {@code CharSequence} is {@code null}, then
* the string {@code "null"} is used to extract the subsequence from.
*
* @param csq
* the {@code CharSequence} to append.
* @param start
* the beginning index.
* @param end
* the ending index.
* @return this builder.
* @throws IndexOutOfBoundsException
* if {@code start} or {@code end} are negative, {@code start}
* is greater than {@code end} or {@code end} is greater than
* the length of {@code csq}.
*/
public native StringBuilder append(CharSequence csq, int start, int end) /*-[
JreStringBuilder_appendCharSequence(&self->delegate_, csq, start, end);
return self;
]-*/;
/**
* Appends the encoded Unicode code point. The code point is converted to a
* {@code char[]} as defined by {@link Character#toChars(int)}.
*
* @param codePoint
* the Unicode code point to encode and append.
* @return this builder.
* @see Character#toChars(int)
*/
public native StringBuilder appendCodePoint(int codePoint) /*-[
JreStringBuilder_appendCharArray(
&self->delegate_, JavaLangCharacter_toCharsWithInt_(codePoint));
return self;
]-*/;
/**
* Deletes a sequence of characters specified by {@code start} and {@code
* end}. Shifts any remaining characters to the left.
*
* @param start
* the inclusive start index.
* @param end
* the exclusive end index.
* @return this builder.
* @throws StringIndexOutOfBoundsException
* if {@code start} is less than zero, greater than the current
* length or greater than {@code end}.
*/
public native StringBuilder delete(int start, int end) /*-[
JreStringBuilder_delete(&self->delegate_, start, end);
return self;
]-*/;
/**
* Deletes the character at the specified index. shifts any remaining
* characters to the left.
*
* @param index
* the index of the character to delete.
* @return this builder.
* @throws StringIndexOutOfBoundsException
* if {@code index} is less than zero or is greater than or
* equal to the current length.
*/
public native StringBuilder deleteCharAt(int index) /*-[
JreStringBuilder_deleteCharAt(&self->delegate_, index);
return self;
]-*/;
/**
* Inserts the string representation of the specified {@code boolean} value
* at the specified {@code offset}. The {@code boolean} value is converted
* to a string according to the rule defined by
* {@link String#valueOf(boolean)}.
*
* @param offset
* the index to insert at.
* @param b
* the {@code boolean} value to insert.
* @return this builder.
* @throws StringIndexOutOfBoundsException
* if {@code offset} is negative or greater than the current
* {@code length}.
* @see String#valueOf(boolean)
*/
public native StringBuilder insert(int offset, boolean b) /*-[
JreStringBuilder_insertString(&self->delegate_, offset, b ? @"true" : @"false");
return self;
]-*/;
/**
* Inserts the string representation of the specified {@code char} value at
* the specified {@code offset}. The {@code char} value is converted to a
* string according to the rule defined by {@link String#valueOf(char)}.
*
* @param offset
* the index to insert at.
* @param c
* the {@code char} value to insert.
* @return this builder.
* @throws IndexOutOfBoundsException
* if {@code offset} is negative or greater than the current
* {@code length()}.
* @see String#valueOf(char)
*/
public native StringBuilder insert(int offset, char c) /*-[
JreStringBuilder_insertChar(&self->delegate_, offset, c);
return self;
]-*/;
/**
* Inserts the string representation of the specified {@code int} value at
* the specified {@code offset}. The {@code int} value is converted to a
* String according to the rule defined by {@link String#valueOf(int)}.
*
* @param offset
* the index to insert at.
* @param i
* the {@code int} value to insert.
* @return this builder.
* @throws StringIndexOutOfBoundsException
* if {@code offset} is negative or greater than the current
* {@code length()}.
* @see String#valueOf(int)
*/
public native StringBuilder insert(int offset, int i) /*-[
JreStringBuilder_insertString(&self->delegate_, offset, JavaLangInteger_toStringWithInt_(i));
return self;
]-*/;
/**
* Inserts the string representation of the specified {@code long} value at
* the specified {@code offset}. The {@code long} value is converted to a
* String according to the rule defined by {@link String#valueOf(long)}.
*
* @param offset
* the index to insert at.
* @param l
* the {@code long} value to insert.
* @return this builder.
* @throws StringIndexOutOfBoundsException
* if {@code offset} is negative or greater than the current
* {code length()}.
* @see String#valueOf(long)
*/
public native StringBuilder insert(int offset, long l) /*-[
JreStringBuilder_insertString(&self->delegate_, offset, JavaLangLong_toStringWithLong_(l));
return self;
]-*/;
/**
* Inserts the string representation of the specified {@code float} value at
* the specified {@code offset}. The {@code float} value is converted to a
* string according to the rule defined by {@link String#valueOf(float)}.
*
* @param offset
* the index to insert at.
* @param f
* the {@code float} value to insert.
* @return this builder.
* @throws StringIndexOutOfBoundsException
* if {@code offset} is negative or greater than the current
* {@code length()}.
* @see String#valueOf(float)
*/
public native StringBuilder insert(int offset, float f) /*-[
JreStringBuilder_insertString(&self->delegate_, offset, JavaLangFloat_toStringWithFloat_(f));
return self;
]-*/;
/**
* Inserts the string representation of the specified {@code double} value
* at the specified {@code offset}. The {@code double} value is converted
* to a String according to the rule defined by
* {@link String#valueOf(double)}.
*
* @param offset
* the index to insert at.
* @param d
* the {@code double} value to insert.
* @return this builder.
* @throws StringIndexOutOfBoundsException
* if {@code offset} is negative or greater than the current
* {@code length()}.
* @see String#valueOf(double)
*/
public native StringBuilder insert(int offset, double d) /*-[
JreStringBuilder_insertString(
&self->delegate_, offset, JavaLangDouble_toStringWithDouble_(d));
return self;
]-*/;
/**
* Inserts the string representation of the specified {@code Object} at the
* specified {@code offset}. The {@code Object} value is converted to a
* String according to the rule defined by {@link String#valueOf(Object)}.
*
* @param offset
* the index to insert at.
* @param obj
* the {@code Object} to insert.
* @return this builder.
* @throws StringIndexOutOfBoundsException
* if {@code offset} is negative or greater than the current
* {@code length()}.
* @see String#valueOf(Object)
*/
public native StringBuilder insert(int offset, Object obj) /*-[
JreStringBuilder_insertString(
&self->delegate_, offset, obj == nil ? @"null" : [obj description]);
return self;
]-*/;
/**
* Inserts the specified string at the specified {@code offset}. If the
* specified string is null, then the String {@code "null"} is inserted.
*
* @param offset
* the index to insert at.
* @param str
* the {@code String} to insert.
* @return this builder.
* @throws StringIndexOutOfBoundsException
* if {@code offset} is negative or greater than the current
* {@code length()}.
*/
public native StringBuilder insert(int offset, String str) /*-[
JreStringBuilder_insertString(&self->delegate_, offset, str);
return self;
]-*/;
/**
* Inserts the string representation of the specified {@code char[]} at the
* specified {@code offset}. The {@code char[]} value is converted to a
* String according to the rule defined by {@link String#valueOf(char[])}.
*
* @param offset
* the index to insert at.
* @param ch
* the {@code char[]} to insert.
* @return this builder.
* @throws StringIndexOutOfBoundsException
* if {@code offset} is negative or greater than the current
* {@code length()}.
* @see String#valueOf(char[])
*/
public native StringBuilder insert(int offset, char[] ch) /*-[
JreStringBuilder_insertCharArray(&self->delegate_, offset, ch);
return self;
]-*/;
/**
* Inserts the string representation of the specified subsequence of the
* {@code char[]} at the specified {@code offset}. The {@code char[]} value
* is converted to a String according to the rule defined by
* {@link String#valueOf(char[],int,int)}.
*
* @param offset
* the index to insert at.
* @param str
* the {@code char[]} to insert.
* @param strOffset
* the inclusive index.
* @param strLen
* the number of characters.
* @return this builder.
* @throws StringIndexOutOfBoundsException
* if {@code offset} is negative or greater than the current
* {@code length()}, or {@code strOffset} and {@code strLen} do
* not specify a valid subsequence.
* @see String#valueOf(char[],int,int)
*/
public native StringBuilder insert(int offset, char[] str, int strOffset,
int strLen) /*-[
JreStringBuilder_insertCharArraySubset(&self->delegate_, offset, str, strOffset, strLen);
return self;
]-*/;
/**
* Inserts the string representation of the specified {@code CharSequence}
* at the specified {@code offset}. The {@code CharSequence} is converted
* to a String as defined by {@link CharSequence#toString()}. If {@code s}
* is {@code null}, then the String {@code "null"} is inserted.
*
* @param offset
* the index to insert at.
* @param s
* the {@code CharSequence} to insert.
* @return this builder.
* @throws IndexOutOfBoundsException
* if {@code offset} is negative or greater than the current
* {@code length()}.
* @see CharSequence#toString()
*/
public native StringBuilder insert(int offset, CharSequence s) /*-[
JreStringBuilder_insertString(&self->delegate_, offset, s == nil ? @"null" : [s description]);
return self;
]-*/;
/**
* Inserts the string representation of the specified subsequence of the
* {@code CharSequence} at the specified {@code offset}. The {@code
* CharSequence} is converted to a String as defined by
* {@link CharSequence#subSequence(int, int)}. If the {@code CharSequence}
* is {@code null}, then the string {@code "null"} is used to determine the
* subsequence.
*
* @param offset
* the index to insert at.
* @param s
* the {@code CharSequence} to insert.
* @param start
* the start of the subsequence of the character sequence.
* @param end
* the end of the subsequence of the character sequence.
* @return this builder.
* @throws IndexOutOfBoundsException
* if {@code offset} is negative or greater than the current
* {@code length()}, or {@code start} and {@code end} do not
* specify a valid subsequence.
* @see CharSequence#subSequence(int, int)
*/
public native StringBuilder insert(int offset, CharSequence s, int start, int end) /*-[
JreStringBuilder_insertCharSequence(&self->delegate_, offset, s, start, end);
return self;
]-*/;
/**
* Replaces the specified subsequence in this builder with the specified
* string.
*
* @param start
* the inclusive begin index.
* @param end
* the exclusive end index.
* @param string
* the replacement string.
* @return this builder.
* @throws StringIndexOutOfBoundsException
* if {@code start} is negative, greater than the current
* {@code length()} or greater than {@code end}.
* @throws NullPointerException
* if {@code str} is {@code null}.
*/
public native StringBuilder replace(int start, int end, String string) /*-[
JreStringBuilder_replace(&self->delegate_, start, end, string);
return self;
]-*/;
/**
* Reverses the order of characters in this builder.
*
* @return this buffer.
*/
public native StringBuilder reverse() /*-[
JreStringBuilder_reverse(&self->delegate_);
return self;
]-*/;
/**
* Returns the contents of this builder.
*
* @return the string representation of the data in this builder.
*/
@Override
public native String toString() /*-[
return JreStringBuilder_toString(&self->delegate_);
]-*/;
@Override
public int length() {
return super.length();
}
@Override
public CharSequence subSequence(int start, int end) {
return super.substring(start, end);
}
/**
* Reads the state of a {@code StringBuilder} from the passed stream and
* restores it to this instance.
*
* @param in
* the stream to read the state from.
* @throws IOException
* if the stream throws it during the read.
* @throws ClassNotFoundException
* if the stream throws it during the read.
*/
private native void readObject(ObjectInputStream in) throws IOException,
ClassNotFoundException /*-[
[((JavaIoObjectInputStream *) nil_chk(inArg)) defaultReadObject];
jint count = [inArg readInt];
IOSCharArray *value = (IOSCharArray *) cast_chk([inArg readObject], [IOSCharArray class]);
[self setWithCharArray:value withInt:count];
]-*/;
/**
* Writes the state of this object to the stream passed.
*
* @param out
* the stream to write the state to.
* @throws IOException
* if the stream throws it during the write.
* @serialData {@code int} - the length of this object. {@code char[]} - the
* buffer from this object, which may be larger than the length
* field.
*/
private void writeObject(ObjectOutputStream out) throws IOException {
out.defaultWriteObject();
out.writeInt(length());
out.writeObject(getValue());
}
}