diff options
author | Eric Blake <ebb9@email.byu.edu> | 2003-03-24 00:50:18 +0000 |
---|---|---|
committer | Tom Tromey <tromey@gcc.gnu.org> | 2003-03-24 00:50:18 +0000 |
commit | ce1bb3bbbaeebbeea5b9e3b41e98efac1a3530ed (patch) | |
tree | 6cae07836eef2ed9d18073a8b7e48580e4196f5f /libjava/java | |
parent | fc3703e35c1769b71d838064d05075b1e106c2a0 (diff) | |
download | gcc-ce1bb3bbbaeebbeea5b9e3b41e98efac1a3530ed.zip gcc-ce1bb3bbbaeebbeea5b9e3b41e98efac1a3530ed.tar.gz gcc-ce1bb3bbbaeebbeea5b9e3b41e98efac1a3530ed.tar.bz2 |
natStringBuffer.cc (regionMatches): New function.
2003-03-23 Eric Blake <ebb9@email.byu.edu>
* java/lang/natStringBuffer.cc (regionMatches): New function.
* java/lang/String.java (count): Now package-private.
* java/lang/StringBuffer.java: Merged with Classpath.
From-SVN: r64770
Diffstat (limited to 'libjava/java')
-rw-r--r-- | libjava/java/lang/String.java | 4 | ||||
-rw-r--r-- | libjava/java/lang/StringBuffer.java | 1177 | ||||
-rw-r--r-- | libjava/java/lang/natStringBuffer.cc | 14 |
3 files changed, 690 insertions, 505 deletions
diff --git a/libjava/java/lang/String.java b/libjava/java/lang/String.java index 2c814e1..17b5dab 100644 --- a/libjava/java/lang/String.java +++ b/libjava/java/lang/String.java @@ -1,4 +1,4 @@ -/* Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation +/* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Free Software Foundation This file is part of libgcj. @@ -26,7 +26,7 @@ public final class String implements Serializable, Comparable, CharSequence { private Object data; private int boffset; // Note this is a byte offset - don't use in Java code! - private int count; + int count; // This is probably not necessary because this class is special cased already // but it will avoid showing up as a discrepancy when comparing SUIDs. diff --git a/libjava/java/lang/StringBuffer.java b/libjava/java/lang/StringBuffer.java index 922d6bb..fac7892 100644 --- a/libjava/java/lang/StringBuffer.java +++ b/libjava/java/lang/StringBuffer.java @@ -1,5 +1,5 @@ /* StringBuffer.java -- Growable strings - Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc. + Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -7,7 +7,7 @@ GNU Classpath is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. - + GNU Classpath is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU @@ -36,276 +36,194 @@ obligated to do so. If you do not wish to do so, delete this exception statement from your version. */ package java.lang; -import java.io.Serializable; -/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3 - * Updated using online JDK 1.2 docs. - * Believed complete and correct to JDK 1.2. - * Merged with Classpath. - */ +import java.io.Serializable; /** * <code>StringBuffer</code> represents a changeable <code>String</code>. * It provides the operations required to modify the - * <code>StringBuffer</code> including insert, replace, delete, append, - * and reverse. - * <P> + * <code>StringBuffer</code>, including insert, replace, delete, append, + * and reverse. It is thread-safe; meaning that all modifications to a buffer + * are in synchronized methods. * - * <code>StringBuffer</code>s are variable-length in nature, so even if + * <p><code>StringBuffer</code>s are variable-length in nature, so even if * you initialize them to a certain size, they can still grow larger than - * that. <EM>Capacity</EM> indicates the number of characters the + * that. <em>Capacity</em> indicates the number of characters the * <code>StringBuffer</code> can have in it before it has to grow (growing * the char array is an expensive operation involving <code>new</code>). - * <P> * - * Incidentally, the String operator "+" actually is turned into a - * <code>StringBuffer</code> operation: - * <BR> - * <code>a + b</code> - * <BR> - * is the same as - * <BR> - * <code>new StringBuffer(a).append(b).toString()</code>. + * <p>Incidentally, compilers often implement the String operator "+" + * by using a <code>StringBuffer</code> operation:<br> + * <code>a + b</code><br> + * is the same as<br> + * <code>new StringBuffer().append(a).append(b).toString()</code>. * - * @implnote Classpath's StringBuffer is capable of sharing memory with - * Strings for efficiency. This will help in two instances: - * first, when a StringBuffer is created from a String but is - * never changed, and second, when a StringBuffer is converted - * to a String and the StringBuffer is not changed after that. + * <p>Classpath's StringBuffer is capable of sharing memory with Strings for + * efficiency. This will help when a StringBuffer is converted to a String + * and the StringBuffer is not changed after that (quite common when performing + * string concatenation). * - * @since JDK1.0 * @author Paul Fisher * @author John Keiser * @author Tom Tromey - * @see java.lang.String + * @author Eric Blake <ebb9@email.byu.edu> + * @see String + * @since 1.0 + * @status updated to 1.4 */ public final class StringBuffer implements Serializable, CharSequence { - /** Append the <code>String</code> value of the argument to this <code>StringBuffer</code>. - * Uses <code>String.valueOf()</code> to convert to - * <code>String</code>. - * @param bool the <code>boolean</code> to convert and append. - * @return this <code>StringBuffer</code>. - * @see java.lang.String#valueOf(boolean) + /** + * Compatible with JDK 1.0+. */ - public StringBuffer append (boolean bool) - { - return append (String.valueOf(bool)); - } + private static final long serialVersionUID = 3388685877147921107L; - /** Append the <code>char</code> to this <code>StringBuffer</code>. - * @param c the <code>char</code> to append. - * @return this <code>StringBuffer</code>. + /** + * Index of next available character (and thus the size of the current + * string contents). Note that this has permissions set this way so that + * String can get the value. + * + * @serial the number of characters in the buffer */ - public synchronized StringBuffer append (char ch) - { - ensureCapacity_unsynchronized (count + 1); - value[count++] = ch; - return this; - } + int count; - /** Append the <code>String</code> value of the argument to this <code>StringBuffer</code>. - * Uses <code>String.valueOf()</code> to convert to - * <code>String</code>. - * @param inum the <code>int</code> to convert and append. - * @return this <code>StringBuffer</code>. - * @see java.lang.String#valueOf(int) + /** + * The buffer. Note that this has permissions set this way so that String + * can get the value. + * + * @serial the buffer */ - public native StringBuffer append (int inum); + char[] value; - /** Append the <code>String</code> value of the argument to this <code>StringBuffer</code>. - * Uses <code>String.valueOf()</code> to convert to - * <code>String</code>. - * @param lnum the <code>long</code> to convert and append. - * @return this <code>StringBuffer</code>. - * @see java.lang.String#valueOf(long) + /** + * True if the buffer is shared with another object (StringBuffer or + * String); this means the buffer must be copied before writing to it again. + * Note that this has permissions set this way so that String can get the + * value. + * + * @serial whether the buffer is shared */ - public StringBuffer append (long lnum) - { - return append (String.valueOf(lnum)); - } + boolean shared; - /** Append the <code>String</code> value of the argument to this <code>StringBuffer</code>. - * Uses <code>String.valueOf()</code> to convert to - * <code>String</code>. - * @param fnum the <code>float</code> to convert and append. - * @return this <code>StringBuffer</code>. - * @see java.lang.String#valueOf(float) + /** + * The default capacity of a buffer. */ - public StringBuffer append (float fnum) - { - return append (String.valueOf(fnum)); - } + private final static int DEFAULT_CAPACITY = 16; - /** Append the <code>String</code> value of the argument to this <code>StringBuffer</code>. - * Uses <code>String.valueOf()</code> to convert to - * <code>String</code>. - * @param dnum the <code>double</code> to convert and append. - * @return this <code>StringBuffer</code>. - * @see java.lang.String#valueOf(double) + /** + * Create a new StringBuffer with default capacity 16. */ - public StringBuffer append (double dnum) + public StringBuffer() { - return append (String.valueOf(dnum)); + this(DEFAULT_CAPACITY); } - /** Append the <code>String</code> value of the argument to this <code>StringBuffer</code>. - * Uses <code>String.valueOf()</code> to convert to - * <code>String</code>. - * @param obj the <code>Object</code> to convert and append. - * @return this <code>StringBuffer</code>. - * @see java.lang.String#valueOf(java.lang.Object) + /** + * Create an empty <code>StringBuffer</code> with the specified initial + * capacity. + * + * @param capacity the initial capacity + * @throws NegativeArraySizeException if capacity is negative */ - public StringBuffer append (Object obj) + public StringBuffer(int capacity) { - return append (String.valueOf(obj)); + value = new char[capacity]; } - /** Append the <code>String</code> to this <code>StringBuffer</code>. - * @param str the <code>String</code> to append. - * @return this <code>StringBuffer</code>. + /** + * Create a new <code>StringBuffer</code> with the characters in the + * specified <code>String</code>. Initial capacity will be the size of the + * String plus 16. + * + * @param str the <code>String</code> to convert + * @throws NullPointerException if str is null */ - public synchronized StringBuffer append (String str) + public StringBuffer(String str) { - if (str == null) - str = "null"; - int len = str.length(); - ensureCapacity_unsynchronized (count + len); - str.getChars(0, len, value, count); - count += len; - return this; + // Unfortunately, because the size is 16 larger, we cannot share. + count = str.count; + value = new char[count + DEFAULT_CAPACITY]; + str.getChars(0, count, value, 0); } - /** Append the <code>char</code> array to this <code>StringBuffer</code>. - * @param data the <code>char[]</code> to append. - * @return this <code>StringBuffer</code>. - * @exception NullPointerException if <code>str</code> is <code>null</code>. + /** + * Get the length of the <code>String</code> this <code>StringBuffer</code> + * would create. Not to be confused with the <em>capacity</em> of the + * <code>StringBuffer</code>. + * + * @return the length of this <code>StringBuffer</code> + * @see #capacity() + * @see #setLength(int) */ - public StringBuffer append (char[] data) + public synchronized int length() { - return append (data, 0, data.length); + return count; } - /** Append the <code>char</code> array to this <code>StringBuffer</code>. - * @param data the <code>char[]</code> to append. - * @param offset the place to start grabbing characters from - * <code>str</code>. - * @param count the number of characters to get from <code>str</code>. - * @return this <code>StringBuffer</code>. - * @exception NullPointerException if <code>str</code> is <code>null</code>. - * @exception IndexOutOfBoundsException if <code>offset</code> or - * <code>offset+len</code> is out of range. - */ - public synchronized StringBuffer append (char[] data, int offset, int count) - { - ensureCapacity_unsynchronized (this.count + count); - System.arraycopy(data, offset, value, this.count, count); - this.count += count; - return this; - } - - /** Get the total number of characters this <code>StringBuffer</code> - * can support before it must be grown. Not to be confused with - * <em>length</em>. - * @return the capacity of this <code>StringBuffer</code> - * @see #length() - * @see #ensureCapacity(int) + /** + * Get the total number of characters this <code>StringBuffer</code> can + * support before it must be grown. Not to be confused with <em>length</em>. + * + * @return the capacity of this <code>StringBuffer</code> + * @see #length() + * @see #ensureCapacity(int) */ - public int capacity () + public synchronized int capacity() { return value.length; } - /** Get the character at the specified index. - * @param index the index of the character to get, starting at 0. - * @return the character at the specified index. - * @exception IndexOutOfBoundsException if the desired character index - * is negative or greater then length() - 1. + /** + * Increase the capacity of this <code>StringBuffer</code>. This will + * ensure that an expensive growing operation will not occur until + * <code>minimumCapacity</code> is reached. The buffer is grown to the + * larger of <code>minimumCapacity</code> and + * <code>capacity() * 2 + 2</code>, if it is not already large enough. + * + * @param minimumCapacity the new capacity + * @see #capacity() */ - public synchronized char charAt (int index) + public synchronized void ensureCapacity(int minimumCapacity) { - if (index >= count) - throw new StringIndexOutOfBoundsException (index); - return value[index]; + ensureCapacity_unsynchronized(minimumCapacity); } - /** Delete characters from this <code>StringBuffer</code>. - * <code>delete(10, 12)</code> will delete 10 and 11, but not 12. - * @param start the first character to delete. - * @param end the index after the last character to delete. - * @return this <code>StringBuffer</code>. - * @exception StringIndexOutOfBoundsException if <code>start</code> - * or <code>end-1</code> are out of bounds, or if - * <code>start > end</code>. + /** + * Set the length of this StringBuffer. If the new length is greater than + * the current length, all the new characters are set to '\0'. If the new + * length is less than the current length, the first <code>newLength</code> + * characters of the old array will be preserved, and the remaining + * characters are truncated. + * + * @param newLength the new length + * @throws IndexOutOfBoundsException if the new length is negative + * (while unspecified, this is a StringIndexOutOfBoundsException) + * @see #length() */ - public synchronized StringBuffer delete (int start, int end) + public synchronized void setLength(int newLength) { - if (start < 0 || start > count || start > end) - throw new StringIndexOutOfBoundsException (start); - if (end > count) - end = count; - // This will unshare if required. - ensureCapacity_unsynchronized (count); - if (count - end != 0) - System.arraycopy (value, end, value, start, count - end); - count -= (end - start); - return this; - } + if (newLength < 0) + throw new StringIndexOutOfBoundsException(newLength); - /** Delete a character from this <code>StringBuffer</code>. - * @param index the index of the character to delete. - * @return this <code>StringBuffer</code>. - * @exception StringIndexOutOfBoundsException if <code>index</code> - * is out of bounds. - */ - public StringBuffer deleteCharAt(int index) - { - return delete (index, index + 1); + ensureCapacity_unsynchronized(newLength); + while (count < newLength) + value[count++] = '\0'; + count = newLength; } - /** Increase the capacity of this <code>StringBuffer</code>. - * This will ensure that an expensive growing operation will not occur - * until <code>minimumCapacity</code> is reached. - * If the capacity is actually already greater than <code>minimumCapacity</code> - * @param minimumCapacity the new capacity. - * @see #capacity() + /** + * Get the character at the specified index. + * + * @param index the index of the character to get, starting at 0 + * @return the character at the specified index + * @throws IndexOutOfBoundsException if index is negative or >= length() + * (while unspecified, this is a StringIndexOutOfBoundsException) */ - public synchronized void ensureCapacity (int minimumCapacity) + public synchronized char charAt(int index) { - if (shared || minimumCapacity > value.length) - { - // We don't want to make a larger vector when `shared' is - // set. If we do, then setLength becomes very inefficient - // when repeatedly reusing a StringBuffer in a loop. - int max = (minimumCapacity > value.length - ? value.length*2+2 - : value.length); - minimumCapacity = (minimumCapacity < max ? max : minimumCapacity); - char[] nb = new char[minimumCapacity]; - System.arraycopy(value, 0, nb, 0, count); - value = nb; - shared = false; - } - } - - // ensureCapacity is used by several synchronized methods in StringBuffer. - // There's no need to synchronize again. - private void ensureCapacity_unsynchronized (int minimumCapacity) - { - if (shared || minimumCapacity > value.length) - { - // We don't want to make a larger vector when `shared' is - // set. If we do, then setLength becomes very inefficient - // when repeatedly reusing a StringBuffer in a loop. - int max = (minimumCapacity > value.length - ? value.length*2+2 - : value.length); - minimumCapacity = (minimumCapacity < max ? max : minimumCapacity); - char[] nb = new char[minimumCapacity]; - System.arraycopy(value, 0, nb, 0, count); - value = nb; - shared = false; - } + if (index < 0 || index >= count) + throw new StringIndexOutOfBoundsException(index); + return value[index]; } /** @@ -332,397 +250,652 @@ public final class StringBuffer implements Serializable, CharSequence System.arraycopy(value, srcOffset, dst, dstOffset, todo); } - /** Insert the <code>String</code> value of the argument into this <code>StringBuffer</code>. - * Uses <code>String.valueOf()</code> to convert to - * <code>String</code>. - * @param offset the place to insert. - * @param bool the <code>boolean</code> to convert and insert. - * @return this <code>StringBuffer</code>. - * @exception IndexOutOfBoundsException if <code>offset</code> is out - * of range for this <code>StringBuffer</code>. - * @see java.lang.String#valueOf(boolean) + /** + * Set the character at the specified index. + * + * @param index the index of the character to set starting at 0 + * @param ch the value to set that character to + * @throws IndexOutOfBoundsException if index is negative or >= length() + * (while unspecified, this is a StringIndexOutOfBoundsException) */ - public StringBuffer insert (int offset, boolean bool) + public synchronized void setCharAt(int index, char ch) { - return insert (offset, bool ? "true" : "false"); + if (index < 0 || index >= count) + throw new StringIndexOutOfBoundsException(index); + // Call ensureCapacity to enforce copy-on-write. + ensureCapacity_unsynchronized(count); + value[index] = ch; } - /** Insert the <code>char</code> argument into this <code>StringBuffer</code>. - * @param offset the place to insert. - * @param ch the <code>char</code> to insert. - * @return this <code>StringBuffer</code>. - * @exception IndexOutOfBoundsException if <code>offset</code> is out - * of range for this <code>StringBuffer</code>. + /** + * Append the <code>String</code> value of the argument to this + * <code>StringBuffer</code>. Uses <code>String.valueOf()</code> to convert + * to <code>String</code>. + * + * @param obj the <code>Object</code> to convert and append + * @return this <code>StringBuffer</code> + * @see String#valueOf(Object) + * @see #append(String) */ - public synchronized StringBuffer insert (int offset, char ch) + public StringBuffer append(Object obj) { - if (offset < 0 || offset > count) - throw new StringIndexOutOfBoundsException (offset); - ensureCapacity_unsynchronized (count+1); - System.arraycopy(value, offset, value, offset+1, count-offset); - value[offset] = ch; - count++; - return this; + return append(obj == null ? "null" : obj.toString()); } - /** Insert the <code>String</code> value of the argument into this <code>StringBuffer</code>. - * Uses <code>String.valueOf()</code> to convert to - * <code>String</code>. - * @param offset the place to insert. - * @param inum the <code>int</code> to convert and insert. - * @return this <code>StringBuffer</code>. - * @exception IndexOutOfBoundsException if <code>offset</code> is out - * of range for this <code>StringBuffer</code>. - * @see java.lang.String#valueOf(int) + /** + * Append the <code>String</code> to this <code>StringBuffer</code>. If + * str is null, the String "null" is appended. + * + * @param str the <code>String</code> to append + * @return this <code>StringBuffer</code> */ - public StringBuffer insert (int offset, int inum) + public synchronized StringBuffer append(String str) { - return insert (offset, String.valueOf(inum)); + if (str == null) + str = "null"; + int len = str.count; + ensureCapacity_unsynchronized(count + len); + str.getChars(0, len, value, count); + count += len; + return this; } - /** Insert the <code>String</code> value of the argument into this <code>StringBuffer</code>. - * Uses <code>String.valueOf()</code> to convert to - * <code>String</code>. - * @param offset the place to insert. - * @param lnum the <code>long</code> to convert and insert. - * @return this <code>StringBuffer</code>. - * @exception IndexOutOfBoundsException if <code>offset</code> is out - * of range for this <code>StringBuffer</code>. - * @see java.lang.String#valueOf(long) + /** + * Append the <code>StringBuffer</code> value of the argument to this + * <code>StringBuffer</code>. This behaves the same as + * <code>append((Object) stringBuffer)</code>, except it is more efficient. + * + * @param stringBuffer the <code>StringBuffer</code> to convert and append + * @return this <code>StringBuffer</code> + * @see #append(Object) + * @since 1.4 */ - public StringBuffer insert (int offset, long lnum) + public synchronized StringBuffer append(StringBuffer stringBuffer) { - return insert (offset, String.valueOf(lnum)); + if (stringBuffer == null) + return append("null"); + synchronized (stringBuffer) + { + int len = stringBuffer.count; + ensureCapacity_unsynchronized(count + len); + System.arraycopy(stringBuffer.value, 0, value, count, len); + count += len; + } + return this; } - /** Insert the <code>String</code> value of the argument into this <code>StringBuffer</code>. - * Uses <code>String.valueOf()</code> to convert to - * <code>String</code>. - * @param offset the place to insert. - * @param fnum the <code>float</code> to convert and insert. - * @return this <code>StringBuffer</code>. - * @exception IndexOutOfBoundsException if <code>offset</code> is out - * of range for this <code>StringBuffer</code>. - * @see java.lang.String#valueOf(float) + /** + * Append the <code>char</code> array to this <code>StringBuffer</code>. + * This is similar (but more efficient) than + * <code>append(new String(data))</code>, except in the case of null. + * + * @param data the <code>char[]</code> to append + * @return this <code>StringBuffer</code> + * @throws NullPointerException if <code>str</code> is <code>null</code> + * @see #append(char[], int, int) */ - public StringBuffer insert (int offset, float fnum) + public StringBuffer append(char[] data) { - return insert (offset, String.valueOf(fnum)); + return append(data, 0, data.length); } - /** Insert the <code>String</code> value of the argument into this <code>StringBuffer</code>. - * Uses <code>String.valueOf()</code> to convert to - * <code>String</code>. - * @param offset the place to insert. - * @param dnum the <code>double</code> to convert and insert. - * @return this <code>StringBuffer</code>. - * @exception IndexOutOfBoundsException if <code>offset</code> is out - * of range for this <code>StringBuffer</code>. - * @see java.lang.String#valueOf(double) + /** + * Append part of the <code>char</code> array to this + * <code>StringBuffer</code>. This is similar (but more efficient) than + * <code>append(new String(data, offset, count))</code>, except in the case + * of null. + * + * @param data the <code>char[]</code> to append + * @param offset the start location in <code>str</code> + * @param count the number of characters to get from <code>str</code> + * @return this <code>StringBuffer</code> + * @throws NullPointerException if <code>str</code> is <code>null</code> + * @throws IndexOutOfBoundsException if offset or count is out of range + * (while unspecified, this is a StringIndexOutOfBoundsException) */ - public StringBuffer insert (int offset, double dnum) + public synchronized StringBuffer append(char[] data, int offset, int count) { - return insert (offset, String.valueOf(dnum)); + ensureCapacity_unsynchronized(this.count + count); + System.arraycopy(data, offset, value, this.count, count); + this.count += count; + return this; } - /** Insert the <code>String</code> value of the argument into this <code>StringBuffer</code>. - * Uses <code>String.valueOf()</code> to convert to - * <code>String</code>. - * @param offset the place to insert. - * @param obj the <code>Object</code> to convert and insert. - * @return this <code>StringBuffer</code>. - * @exception IndexOutOfBoundsException if <code>offset</code> is out - * of range for this <code>StringBuffer</code>. - * @see java.lang.String#valueOf(java.lang.Object) + /** + * Append the <code>String</code> value of the argument to this + * <code>StringBuffer</code>. Uses <code>String.valueOf()</code> to convert + * to <code>String</code>. + * + * @param bool the <code>boolean</code> to convert and append + * @return this <code>StringBuffer</code> + * @see String#valueOf(boolean) */ - public StringBuffer insert (int offset, Object obj) + public StringBuffer append(boolean bool) { - return insert (offset, String.valueOf(obj)); + return append(bool ? "true" : "false"); } - /** Insert the <code>String</code> argument into this <code>StringBuffer</code>. - * @param offset the place to insert. - * @param str the <code>String</code> to insert. - * @return this <code>StringBuffer</code>. - * @exception IndexOutOfBoundsException if <code>offset</code> is out - * of range for this <code>StringBuffer</code>. + /** + * Append the <code>char</code> to this <code>StringBuffer</code>. + * + * @param c the <code>char</code> to append + * @return this <code>StringBuffer</code> */ - public synchronized StringBuffer insert (int offset, String str) + public synchronized StringBuffer append(char ch) { - if (offset < 0 || offset > count) - throw new StringIndexOutOfBoundsException (offset); - // Note that using `null' is from JDK 1.2. - if (str == null) - str = "null"; - int len = str.length(); - ensureCapacity_unsynchronized (count+len); - System.arraycopy(value, offset, value, offset+len, count-offset); - str.getChars(0, len, value, offset); - count += len; + ensureCapacity_unsynchronized(count + 1); + value[count++] = ch; return this; } - /** Insert the <code>char[]</code> argument into this - * <code>StringBuffer</code>. - * @param offset the place to insert. - * @param data the <code>char[]</code> to insert. - * @return this <code>StringBuffer</code>. - * @exception NullPointerException if <code>data</code> is - * <code>null</code>. - * @exception IndexOutOfBoundsException if <code>offset</code> is out - * of range for this <code>StringBuffer</code>. - */ - public StringBuffer insert (int offset, char[] data) - { - // One could check if offset is invalid here instead of making sure that - // data isn't null before dereferencing, but this works just as well. - return insert (offset, data, 0, data == null ? 0 : data.length); - } - - /** Insert the <code>char[]</code> argument into this - * <code>StringBuffer</code>. - * @param offset the place to insert. - * @param str the <code>char[]</code> to insert. - * @param str_offset the index in <code>str</code> to start inserting - * from. - * @param len the number of characters to insert. - * @return this <code>StringBuffer</code>. - * @exception NullPointerException if <code>str</code> is <code>null</code>. - * @exception IndexOutOfBoundsException if <code>offset</code> is out - * of range, for this <code>StringBuffer</code>, or if - * <code>str_offset</code> or <code>str_offset+len</code> - * are out of range for <code>str</code>. - */ - public synchronized StringBuffer insert(int offset, char[] str, - int str_offset, int len) + /** + * Append the <code>String</code> value of the argument to this + * <code>StringBuffer</code>. Uses <code>String.valueOf()</code> to convert + * to <code>String</code>. + * + * @param inum the <code>int</code> to convert and append + * @return this <code>StringBuffer</code> + * @see String#valueOf(int) + */ + // GCJ LOCAL: this is native for efficiency. + public native StringBuffer append (int inum); + + /** + * Append the <code>String</code> value of the argument to this + * <code>StringBuffer</code>. Uses <code>String.valueOf()</code> to convert + * to <code>String</code>. + * + * @param lnum the <code>long</code> to convert and append + * @return this <code>StringBuffer</code> + * @see String#valueOf(long) + */ + public StringBuffer append(long lnum) { - if (offset < 0 || offset > count) - throw new StringIndexOutOfBoundsException (offset); - if (len < 0) - throw new StringIndexOutOfBoundsException (len); - if (str_offset < 0 || str_offset + len > str.length) - throw new StringIndexOutOfBoundsException (str_offset); - ensureCapacity_unsynchronized (count + len); - System.arraycopy(value, offset, value, offset + len, count - offset); - System.arraycopy(str, str_offset, value, offset, len); - count += len; + return append(Long.toString(lnum, 10)); + } + + /** + * Append the <code>String</code> value of the argument to this + * <code>StringBuffer</code>. Uses <code>String.valueOf()</code> to convert + * to <code>String</code>. + * + * @param fnum the <code>float</code> to convert and append + * @return this <code>StringBuffer</code> + * @see String#valueOf(float) + */ + public StringBuffer append(float fnum) + { + return append(Float.toString(fnum)); + } + + /** + * Append the <code>String</code> value of the argument to this + * <code>StringBuffer</code>. Uses <code>String.valueOf()</code> to convert + * to <code>String</code>. + * + * @param dnum the <code>double</code> to convert and append + * @return this <code>StringBuffer</code> + * @see String#valueOf(double) + */ + public StringBuffer append(double dnum) + { + return append(Double.toString(dnum)); + } + + /** + * Delete characters from this <code>StringBuffer</code>. + * <code>delete(10, 12)</code> will delete 10 and 11, but not 12. It is + * harmless for end to be larger than length(). + * + * @param start the first character to delete + * @param end the index after the last character to delete + * @return this <code>StringBuffer</code> + * @throws StringIndexOutOfBoundsException if start or end are out of bounds + * @since 1.2 + */ + public synchronized StringBuffer delete(int start, int end) + { + if (start < 0 || start > count || start > end) + throw new StringIndexOutOfBoundsException(start); + if (end > count) + end = count; + // This will unshare if required. + ensureCapacity_unsynchronized(count); + if (count - end != 0) + System.arraycopy(value, end, value, start, count - end); + count -= end - start; return this; } - /** Get the length of the <code>String</code> this - * <code>StringBuffer</code> would create. Not to be confused with the - * <em>capacity</em> of the <code>StringBuffer</code>. - * @return the length of this <code>StringBuffer</code>. - * @see #capacity() - * @see #setLength(int) + /** + * Delete a character from this <code>StringBuffer</code>. + * + * @param index the index of the character to delete + * @return this <code>StringBuffer</code> + * @throws StringIndexOutOfBoundsException if index is out of bounds + * @since 1.2 */ - public int length () + public StringBuffer deleteCharAt(int index) { - return count; + return delete(index, index + 1); } - /** Replace characters between index <code>start</code> (inclusive) and - * <code>end</code> (exclusive) with <code>str</code>. If <code>end</code> - * is larger than the size of this StringBuffer, all characters after - * <code>start</code> are replaced. - * @param start the beginning index of characters to delete (inclusive). - * @param end the ending index of characters to delete (exclusive). - * @param str the new <code>String</code> to insert. - * @return this <code>StringBuffer</code>. + /** + * Replace characters between index <code>start</code> (inclusive) and + * <code>end</code> (exclusive) with <code>str</code>. If <code>end</code> + * is larger than the size of this StringBuffer, all characters after + * <code>start</code> are replaced. + * + * @param start the beginning index of characters to delete (inclusive) + * @param end the ending index of characters to delete (exclusive) + * @param str the new <code>String</code> to insert + * @return this <code>StringBuffer</code> + * @throws StringIndexOutOfBoundsException if start or end are out of bounds + * @throws NullPointerException if str is null + * @since 1.2 */ - public synchronized StringBuffer replace (int start, int end, String str) + public synchronized StringBuffer replace(int start, int end, String str) { if (start < 0 || start > count || start > end) - throw new StringIndexOutOfBoundsException (start); - - int len = str.length(); + throw new StringIndexOutOfBoundsException(start); + + int len = str.count; // Calculate the difference in 'count' after the replace. - int delta = len - ((end > count ? count : end) - start); - ensureCapacity_unsynchronized (count + delta); - + int delta = len - (end > count ? count : end) + start; + ensureCapacity_unsynchronized(count + delta); + if (delta != 0 && end < count) System.arraycopy(value, end, value, end + delta, count - end); - - str.getChars (0, len, value, start); - count += delta; - return this; + + str.getChars(0, len, value, start); + count += delta; + return this; } - /** Reverse the characters in this StringBuffer. - * @return this <code>StringBuffer</code>. + /** + * Creates a substring of this StringBuffer, starting at a specified index + * and ending at the end of this StringBuffer. + * + * @param beginIndex index to start substring (base 0) + * @return new String which is a substring of this StringBuffer + * @throws StringIndexOutOfBoundsException if beginIndex is out of bounds + * @see #substring(int, int) + * @since 1.2 */ - public synchronized StringBuffer reverse () + public String substring(int beginIndex) { - // Call ensureCapacity to enforce copy-on-write. - ensureCapacity_unsynchronized (count); - for (int i = 0; i < count / 2; ++i) - { - char c = value[i]; - value[i] = value[count - i - 1]; - value[count - i - 1] = c; - } - return this; + return substring(beginIndex, count); } - /** Set the character at the specified index. - * @param index the index of the character to set starting at 0. - * @param ch the value to set that character to. - * @exception IndexOutOfBoundsException if the specified character - * index is not between 0 and length() - 1 (inclusive). + /** + * Creates a substring of this StringBuffer, starting at a specified index + * and ending at one character before a specified index. This is implemented + * the same as <code>substring(beginIndex, endIndex)</code>, to satisfy + * the CharSequence interface. + * + * @param beginIndex index to start at (inclusive, base 0) + * @param endIndex index to end at (exclusive) + * @return new String which is a substring of this StringBuffer + * @throws IndexOutOfBoundsException if beginIndex or endIndex is out of + * bounds + * @see #substring(int, int) + * @since 1.4 */ - public synchronized void setCharAt (int index, char ch) + public CharSequence subSequence(int beginIndex, int endIndex) { - if (index < 0 || index >= count) - throw new StringIndexOutOfBoundsException (index); - // Call ensureCapacity to enforce copy-on-write. - ensureCapacity_unsynchronized (count); - value[index] = ch; + return substring(beginIndex, endIndex); } - /** Set the length of this StringBuffer. - * <P> - * If the new length is greater than the current length, all the new - * characters are set to '\0'. - * <P> - * If the new length is less than the current length, the first - * <code>newLength</code> characters of the old array will be - * @param newLength the new length - * @exception IndexOutOfBoundsException if the new length is - * negative. - * @see #length() + /** + * Creates a substring of this StringBuffer, starting at a specified index + * and ending at one character before a specified index. + * + * @param beginIndex index to start at (inclusive, base 0) + * @param endIndex index to end at (exclusive) + * @return new String which is a substring of this StringBuffer + * @throws StringIndexOutOfBoundsException if beginIndex or endIndex is out + * of bounds + * @since 1.2 */ - public synchronized void setLength (int newLength) + public synchronized String substring(int beginIndex, int endIndex) { - if (newLength < 0) - throw new StringIndexOutOfBoundsException (newLength); + int len = endIndex - beginIndex; + if (beginIndex < 0 || endIndex > count || len < 0) + throw new StringIndexOutOfBoundsException(); + if (len == 0) + return ""; + // Share the char[] unless 3/4 empty. + shared = (len << 2) >= value.length; + // Package constructor avoids an array copy. + return new String(value, beginIndex, len, shared); + } - ensureCapacity_unsynchronized (newLength); - for (int i = count; i < newLength; ++i) - value[i] = '\0'; - count = newLength; + /** + * Insert a subarray of the <code>char[]</code> argument into this + * <code>StringBuffer</code>. + * + * @param offset the place to insert in this buffer + * @param str the <code>char[]</code> to insert + * @param str_offset the index in <code>str</code> to start inserting from + * @param len the number of characters to insert + * @return this <code>StringBuffer</code> + * @throws NullPointerException if <code>str</code> is <code>null</code> + * @throws StringIndexOutOfBoundsException if any index is out of bounds + * @since 1.2 + */ + public synchronized StringBuffer insert(int offset, + char[] str, int str_offset, int len) + { + if (offset < 0 || offset > count || len < 0 + || str_offset < 0 || str_offset + len > str.length) + throw new StringIndexOutOfBoundsException(); + ensureCapacity_unsynchronized(count + len); + System.arraycopy(value, offset, value, offset + len, count - offset); + System.arraycopy(str, str_offset, value, offset, len); + count += len; + return this; } - /** Create a new StringBuffer with default capacity 16. - * @see JLS 20.13.1 + /** + * Insert the <code>String</code> value of the argument into this + * <code>StringBuffer</code>. Uses <code>String.valueOf()</code> to convert + * to <code>String</code>. + * + * @param offset the place to insert in this buffer + * @param obj the <code>Object</code> to convert and insert + * @return this <code>StringBuffer</code> + * @exception StringIndexOutOfBoundsException if offset is out of bounds + * @see String#valueOf(Object) */ - public StringBuffer () + public StringBuffer insert(int offset, Object obj) { - this (DEFAULT_CAPACITY); + return insert(offset, obj == null ? "null" : obj.toString()); } - /** Create an empty <code>StringBuffer</code> with the specified initial capacity. - * @param capacity the initial capacity. + /** + * Insert the <code>String</code> argument into this + * <code>StringBuffer</code>. If str is null, the String "null" is used + * instead. + * + * @param offset the place to insert in this buffer + * @param str the <code>String</code> to insert + * @return this <code>StringBuffer</code> + * @throws StringIndexOutOfBoundsException if offset is out of bounds */ - public StringBuffer (int capacity) + public synchronized StringBuffer insert(int offset, String str) { - count = 0; - value = new char[capacity]; - shared = false; + if (offset < 0 || offset > count) + throw new StringIndexOutOfBoundsException(offset); + if (str == null) + str = "null"; + int len = str.count; + ensureCapacity_unsynchronized(count + len); + System.arraycopy(value, offset, value, offset + len, count - offset); + str.getChars(0, len, value, offset); + count += len; + return this; } - /** Create a new <code>StringBuffer</code> with the characters in the specified <code>String</code>. - * Initial capacity will be the size of the String plus 16. - * @param str the <code>String</code> to make a <code>StringBuffer</code> out of. - * @XXX optimize for sharing. + /** + * Insert the <code>char[]</code> argument into this + * <code>StringBuffer</code>. + * + * @param offset the place to insert in this buffer + * @param data the <code>char[]</code> to insert + * @return this <code>StringBuffer</code> + * @throws NullPointerException if <code>data</code> is <code>null</code> + * @throws StringIndexOutOfBoundsException if offset is out of bounds + * @see #insert(int, char[], int, int) */ - public StringBuffer (String str) + public StringBuffer insert(int offset, char[] data) { - // The documentation is not clear, but experimentation with - // other implementations indicates that StringBuffer(null) - // should throw a NullPointerException. - count = str.length(); - // JLS: The initial capacity of the string buffer is 16 plus the - // length of the argument string. - value = new char[count + DEFAULT_CAPACITY]; - str.getChars(0, count, value, 0); - shared = false; + return insert(offset, data, 0, data.length); } /** - * Creates a substring of this StringBuffer, starting at a specified index - * and ending at the end of this StringBuffer. + * Insert the <code>String</code> value of the argument into this + * <code>StringBuffer</code>. Uses <code>String.valueOf()</code> to convert + * to <code>String</code>. * - * @param beginIndex index to start substring (base 0) - * - * @return new String which is a substring of this StringBuffer + * @param offset the place to insert in this buffer + * @param bool the <code>boolean</code> to convert and insert + * @return this <code>StringBuffer</code> + * @throws StringIndexOutOfBoundsException if offset is out of bounds + * @see String#valueOf(boolean) + */ + public StringBuffer insert(int offset, boolean bool) + { + return insert(offset, bool ? "true" : "false"); + } + + /** + * Insert the <code>char</code> argument into this <code>StringBuffer</code>. * - * @exception StringIndexOutOfBoundsException - * if (beginIndex < 0 || beginIndex > this.length()) + * @param offset the place to insert in this buffer + * @param ch the <code>char</code> to insert + * @return this <code>StringBuffer</code> + * @throws StringIndexOutOfBoundsException if offset is out of bounds */ - public String substring (int beginIndex) + public synchronized StringBuffer insert(int offset, char ch) { - return substring (beginIndex, count); + if (offset < 0 || offset > count) + throw new StringIndexOutOfBoundsException(offset); + ensureCapacity_unsynchronized(count + 1); + System.arraycopy(value, offset, value, offset + 1, count - offset); + value[offset] = ch; + count++; + return this; } /** - * Creates a substring of this StringBuffer, starting at a specified index - * and ending at one character before a specified index. + * Insert the <code>String</code> value of the argument into this + * <code>StringBuffer</code>. Uses <code>String.valueOf()</code> to convert + * to <code>String</code>. * - * @param beginIndex index to start substring (base 0) - * @param endIndex index after the last character to be - * copied into the substring - * - * @return new String which is a substring of this StringBuffer + * @param offset the place to insert in this buffer + * @param inum the <code>int</code> to convert and insert + * @return this <code>StringBuffer</code> + * @throws StringIndexOutOfBoundsException if offset is out of bounds + * @see String#valueOf(int) + */ + public StringBuffer insert(int offset, int inum) + { + return insert(offset, String.valueOf(inum)); + } + + /** + * Insert the <code>String</code> value of the argument into this + * <code>StringBuffer</code>. Uses <code>String.valueOf()</code> to convert + * to <code>String</code>. * - * @exception StringIndexOutOfBoundsException - * if (beginIndex < 0 || endIndex > this.length() || beginIndex > endIndex) + * @param offset the place to insert in this buffer + * @param lnum the <code>long</code> to convert and insert + * @return this <code>StringBuffer</code> + * @throws StringIndexOutOfBoundsException if offset is out of bounds + * @see String#valueOf(long) */ - public synchronized String substring (int beginIndex, int endIndex) + public StringBuffer insert(int offset, long lnum) { - if (beginIndex < 0 || endIndex > count || beginIndex > endIndex) - throw new StringIndexOutOfBoundsException (); - // FIXME: for libgcj it would be possible, and more efficient, to - // enable sharing here. - return new String (value, beginIndex, endIndex - beginIndex); + return insert(offset, Long.toString(lnum, 10)); } /** - * Creates a substring of this StringBuffer, starting at a specified index - * and ending at one character before a specified index. - * <p> - * To implement <code>CharSequence</code>. - * Calls <code>substring(beginIndex, endIndex)</code>. + * Insert the <code>String</code> value of the argument into this + * <code>StringBuffer</code>. Uses <code>String.valueOf()</code> to convert + * to <code>String</code>. * - * @param beginIndex index to start substring (base 0) - * @param endIndex index after the last character to be - * copied into the substring - * - * @return new String which is a substring of this StringBuffer + * @param offset the place to insert in this buffer + * @param fnum the <code>float</code> to convert and insert + * @return this <code>StringBuffer</code> + * @throws StringIndexOutOfBoundsException if offset is out of bounds + * @see String#valueOf(float) + */ + public StringBuffer insert(int offset, float fnum) + { + return insert(offset, Float.toString(fnum)); + } + + /** + * Insert the <code>String</code> value of the argument into this + * <code>StringBuffer</code>. Uses <code>String.valueOf()</code> to convert + * to <code>String</code>. * - * @exception StringIndexOutOfBoundsException - * if (beginIndex < 0 || endIndex > this.length() || beginIndex > endIndex) + * @param offset the place to insert in this buffer + * @param dnum the <code>double</code> to convert and insert + * @return this <code>StringBuffer</code> + * @throws StringIndexOutOfBoundsException if offset is out of bounds + * @see String#valueOf(double) */ - public CharSequence subSequence (int beginIndex, int endIndex) + public StringBuffer insert(int offset, double dnum) { - return substring(beginIndex, endIndex); + return insert(offset, Double.toString(dnum)); } + /** + * Finds the first instance of a substring in this StringBuffer. + * + * @param str String to find + * @return location (base 0) of the String, or -1 if not found + * @throws NullPointerException if str is null + * @see #indexOf(String, int) + * @since 1.4 + */ + public int indexOf(String str) + { + return indexOf(str, 0); + } - /** Convert this <code>StringBuffer</code> to a <code>String</code>. - * @return the characters in this StringBuffer + /** + * Finds the first instance of a String in this StringBuffer, starting at + * a given index. If starting index is less than 0, the search starts at + * the beginning of this String. If the starting index is greater than the + * length of this String, or the substring is not found, -1 is returned. + * + * @param str String to find + * @param fromIndex index to start the search + * @return location (base 0) of the String, or -1 if not found + * @throws NullPointerException if str is null + * @since 1.4 */ - public String toString () + public synchronized int indexOf(String str, int fromIndex) { - // Note: in libgcj this causes the StringBuffer to be shared. In - // Classpath it does not. - return new String (this); + if (fromIndex < 0) + fromIndex = 0; + int limit = count - str.count; + for ( ; fromIndex <= limit; fromIndex++) + if (regionMatches(fromIndex, str)) + return fromIndex; + return -1; } - // Index of next available character. Note that this has - // permissions set this way so that String can get the value. - int count; + /** + * Finds the last instance of a substring in this StringBuffer. + * + * @param str String to find + * @return location (base 0) of the String, or -1 if not found + * @throws NullPointerException if str is null + * @see #lastIndexOf(String, int) + * @since 1.4 + */ + public int lastIndexOf(String str) + { + return lastIndexOf(str, count - str.count); + } - // The buffer. Note that this has permissions set this way so that - // String can get the value. - char[] value; + /** + * Finds the last instance of a String in this StringBuffer, starting at a + * given index. If starting index is greater than the maximum valid index, + * then the search begins at the end of this String. If the starting index + * is less than zero, or the substring is not found, -1 is returned. + * + * @param str String to find + * @param fromIndex index to start the search + * @return location (base 0) of the String, or -1 if not found + * @throws NullPointerException if str is null + * @since 1.4 + */ + public synchronized int lastIndexOf(String str, int fromIndex) + { + fromIndex = Math.min(fromIndex, count - str.count); + for ( ; fromIndex >= 0; fromIndex--) + if (regionMatches(fromIndex, str)) + return fromIndex; + return -1; + } - // True if we need to copy the buffer before writing to it again. - // FIXME: JDK 1.2 doesn't specify this. The new buffer-growing - // semantics make this less useful in that case, too. Note that - // this has permissions set this way so that String can get the - // value. - boolean shared; + /** + * Reverse the characters in this StringBuffer. The same sequence of + * characters exists, but in the reverse index ordering. + * + * @return this <code>StringBuffer</code> + */ + public synchronized StringBuffer reverse() + { + // Call ensureCapacity to enforce copy-on-write. + ensureCapacity_unsynchronized(count); + for (int i = count >> 1, j = count - i; --i >= 0; ++j) + { + char c = value[i]; + value[i] = value[j]; + value[j] = c; + } + return this; + } + + /** + * Convert this <code>StringBuffer</code> to a <code>String</code>. The + * String is composed of the characters currently in this StringBuffer. Note + * that the result is a copy, and that future modifications to this buffer + * do not affect the String. + * + * @return the characters in this StringBuffer + */ + public String toString() + { + // The string will set this.shared = true. + return new String(this); + } + + /** + * An unsynchronized version of ensureCapacity, used internally to avoid + * the cost of a second lock on the same object. This also has the side + * effect of duplicating the array, if it was shared (to form copy-on-write + * semantics). + * + * @param minimumCapacity the minimum capacity + * @see #ensureCapacity(int) + */ + private void ensureCapacity_unsynchronized(int minimumCapacity) + { + if (shared || minimumCapacity > value.length) + { + // We don't want to make a larger vector when `shared' is + // set. If we do, then setLength becomes very inefficient + // when repeatedly reusing a StringBuffer in a loop. + int max = (minimumCapacity > value.length + ? value.length * 2 + 2 + : value.length); + minimumCapacity = (minimumCapacity < max ? max : minimumCapacity); + char[] nb = new char[minimumCapacity]; + System.arraycopy(value, 0, nb, 0, count); + value = nb; + shared = false; + } + } - static final long serialVersionUID = 3388685877147921107L; - private final static int DEFAULT_CAPACITY = 16; // JLS 20.13.1 + /** + * Predicate which determines if a substring of this matches another String + * starting at a specified offset for each String and continuing for a + * specified length. This is more efficient than creating a String to call + * indexOf on. + * + * @param toffset index to start comparison at for this String + * @param other non-null String to compare to region of this + * @return true if regions match, false otherwise + * @see #indexOf(String, int) + * @see #lastIndexOf(String, int) + * @see String#regionMatches(boolean, int, String, int, int) + */ + // GCJ LOCAL: native for gcj. + private native boolean regionMatches(int toffset, String other); } diff --git a/libjava/java/lang/natStringBuffer.cc b/libjava/java/lang/natStringBuffer.cc index bc70f67..8fbb8df 100644 --- a/libjava/java/lang/natStringBuffer.cc +++ b/libjava/java/lang/natStringBuffer.cc @@ -1,6 +1,6 @@ // natStringBuffer.cc - Implementation of java.lang.StringBuffer native methods. -/* Copyright (C) 2001 Free Software Foundation +/* Copyright (C) 2001, 2003 Free Software Foundation This file is part of libgcj. @@ -28,3 +28,15 @@ java::lang::StringBuffer::append (jint num) count = needed; return this; } + +jboolean +java::lang::StringBuffer::regionMatches(jint toffset, jstring other) +{ + jint len = other->count; + jchar *tptr = elements(value) + toffset; + jchar *optr = JvGetStringChars(other); + while (--len >= 0) + if (*tptr++ != *optr++) + return false; + return true; +} |