summaryrefslogtreecommitdiff
path: root/gnu
diff options
context:
space:
mode:
authorAndrew John Hughes <gnu_andrew@member.fsf.org>2008-05-11 18:48:49 +0000
committerAndrew John Hughes <gnu_andrew@member.fsf.org>2008-05-11 18:48:49 +0000
commit86880fe522a4d41324facbf2620b36d49e26fb16 (patch)
tree4979d84f95d5cbd6993087191f6096aaac2977cd /gnu
parente06521356049c9e47ebcdf4206a8536737ace90b (diff)
downloadclasspath-86880fe522a4d41324facbf2620b36d49e26fb16.tar.gz
2008-05-11 Andrew John Hughes <gnu_andrew@member.fsf.org>
PR classpath/36147 * gnu/java/lang/CPStringBuilder.java: (allocated): New flag to mark whether or not the array has been allocated to a String object. (ensureCapacity(int)): Removed. (ensureCapacity_unsynchronized(int)): Renamed to ensureCapacity, and creates an array when allocated is true. (allocateArray(int)): Added. (trimToSize()): Use allocateArray method. (toString()): Set allocated to true; (substring(int,int)): Likewise.
Diffstat (limited to 'gnu')
-rw-r--r--gnu/java/lang/CPStringBuilder.java96
1 files changed, 53 insertions, 43 deletions
diff --git a/gnu/java/lang/CPStringBuilder.java b/gnu/java/lang/CPStringBuilder.java
index d46787837..c2ca848f9 100644
--- a/gnu/java/lang/CPStringBuilder.java
+++ b/gnu/java/lang/CPStringBuilder.java
@@ -71,6 +71,19 @@ public final class CPStringBuilder
private char[] value;
/**
+ * A flag to denote whether the string being created has been
+ * allocated to a {@link String} object. On construction,
+ * the character array, {@link #value} is referenced only
+ * by this class. Once {@link #toString()},
+ * {@link #substring(int)} or {@link #substring(int,int)}
+ * are called, the array is also referenced by a {@link String}
+ * object and this flag is set. Subsequent modifications to
+ * this buffer cause a new array to be allocated and the flag
+ * to be reset.
+ */
+ private boolean allocated = false;
+
+ /**
* The default capacity of a buffer.
* This can be configured using gnu.classpath.cpstringbuilder.capacity
*/
@@ -172,21 +185,6 @@ public final class CPStringBuilder
}
/**
- * Increase the capacity of this <code>CPStringBuilder</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 void ensureCapacity(int minimumCapacity)
- {
- ensureCapacity_unsynchronized(minimumCapacity);
- }
-
- /**
* 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>
@@ -205,9 +203,9 @@ public final class CPStringBuilder
int valueLength = value.length;
- /* Always call ensureCapacity_unsynchronized in order to preserve
+ /* Always call ensureCapacity in order to preserve
copy-on-write semantics. */
- ensureCapacity_unsynchronized(newLength);
+ ensureCapacity(newLength);
if (newLength < valueLength)
{
@@ -309,7 +307,7 @@ public final class CPStringBuilder
if (index < 0 || index >= count)
throw new StringIndexOutOfBoundsException(index);
// Call ensureCapacity to enforce copy-on-write.
- ensureCapacity_unsynchronized(count);
+ ensureCapacity(count);
value[index] = ch;
}
@@ -340,7 +338,7 @@ public final class CPStringBuilder
if (str == null)
str = "null";
int len = str.length();
- ensureCapacity_unsynchronized(count + len);
+ ensureCapacity(count + len);
str.getChars(0, len, value, count);
count += len;
return this;
@@ -402,7 +400,7 @@ public final class CPStringBuilder
{
if (offset < 0 || count < 0 || offset > data.length - count)
throw new StringIndexOutOfBoundsException();
- ensureCapacity_unsynchronized(this.count + count);
+ ensureCapacity(this.count + count);
System.arraycopy(data, offset, value, this.count, count);
this.count += count;
return this;
@@ -430,7 +428,7 @@ public final class CPStringBuilder
*/
public CPStringBuilder append(char ch)
{
- ensureCapacity_unsynchronized(count + 1);
+ ensureCapacity(count + 1);
value[count++] = ch;
return this;
}
@@ -465,7 +463,7 @@ public final class CPStringBuilder
return append("null");
if (end - start > 0)
{
- ensureCapacity_unsynchronized(count + end - start);
+ ensureCapacity(count + end - start);
for (; start < end; ++start)
value[count++] = seq.charAt(start);
}
@@ -542,7 +540,7 @@ public final class CPStringBuilder
public CPStringBuilder appendCodePoint(int code)
{
int len = Character.charCount(code);
- ensureCapacity_unsynchronized(count + len);
+ ensureCapacity(count + len);
Character.toChars(code, value, count);
count += len;
return this;
@@ -565,7 +563,7 @@ public final class CPStringBuilder
throw new StringIndexOutOfBoundsException(start);
if (end > count)
end = count;
- ensureCapacity_unsynchronized(count);
+ ensureCapacity(count);
if (count - end != 0)
System.arraycopy(value, end, value, start, count - end);
count -= end - start;
@@ -607,7 +605,7 @@ public final class CPStringBuilder
int len = str.length();
// Calculate the difference in 'count' after the replace.
int delta = len - (end > count ? count : end) + start;
- ensureCapacity_unsynchronized(count + delta);
+ ensureCapacity(count + delta);
if (delta != 0 && end < count)
System.arraycopy(value, end, value, end + delta, count - end);
@@ -635,7 +633,7 @@ public final class CPStringBuilder
if (offset < 0 || offset > count || len < 0
|| str_offset < 0 || str_offset > str.length - len)
throw new StringIndexOutOfBoundsException();
- ensureCapacity_unsynchronized(count + len);
+ ensureCapacity(count + len);
System.arraycopy(value, offset, value, offset + len, count - offset);
System.arraycopy(str, str_offset, value, offset, len);
count += len;
@@ -675,7 +673,7 @@ public final class CPStringBuilder
if (str == null)
str = "null";
int len = str.length();
- ensureCapacity_unsynchronized(count + len);
+ ensureCapacity(count + len);
System.arraycopy(value, offset, value, offset + len, count - offset);
str.getChars(0, len, value, offset);
count += len;
@@ -721,7 +719,7 @@ public final class CPStringBuilder
if (start < 0 || end < 0 || start > end || end > sequence.length())
throw new IndexOutOfBoundsException();
int len = end - start;
- ensureCapacity_unsynchronized(count + len);
+ ensureCapacity(count + len);
System.arraycopy(value, offset, value, offset + len, count - offset);
for (int i = start; i < end; ++i)
value[offset++] = sequence.charAt(i);
@@ -773,7 +771,7 @@ public final class CPStringBuilder
{
if (offset < 0 || offset > count)
throw new StringIndexOutOfBoundsException(offset);
- ensureCapacity_unsynchronized(count + 1);
+ ensureCapacity(count + 1);
System.arraycopy(value, offset, value, offset + 1, count - offset);
value[offset] = ch;
count++;
@@ -928,7 +926,7 @@ public final class CPStringBuilder
public CPStringBuilder reverse()
{
// Call ensureCapacity to enforce copy-on-write.
- ensureCapacity_unsynchronized(count);
+ ensureCapacity(count);
for (int i = count >> 1, j = count - i; --i >= 0; ++j)
{
char c = value[i];
@@ -955,11 +953,7 @@ public final class CPStringBuilder
// If we save more than 200 characters, shrink.
// If we save more than 1/4 of the buffer, shrink.
if (wouldSave > 200 || wouldSave * 4 > value.length)
- {
- char[] newValue = new char[count];
- System.arraycopy(value, 0, newValue, 0, count);
- value = newValue;
- }
+ allocateArray(count);
}
/**
@@ -1040,27 +1034,41 @@ public final class CPStringBuilder
/**
* Increase the capacity of this <code>StringBuilder</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
+ * ensure that an expensive growing operation will not occur until either
+ * <code>minimumCapacity</code> is reached or the array has been allocated.
+ * 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()
*/
- protected void ensureCapacity_unsynchronized(int minimumCapacity)
+ public void ensureCapacity(int minimumCapacity)
{
- if (minimumCapacity > value.length)
+ if (allocated || minimumCapacity > value.length)
{
int max = value.length * 2 + 2;
minimumCapacity = (minimumCapacity < max ? max : minimumCapacity);
- char[] nb = new char[minimumCapacity];
- System.arraycopy(value, 0, nb, 0, count);
- value = nb;
+ allocateArray(minimumCapacity);
}
}
/**
+ * Allocates a new character array. This method is triggered when
+ * a write is attempted after the array has been passed to a
+ * {@link String} object, so that the builder does not modify
+ * the immutable {@link String}.
+ *
+ * @param capacity the size of the new array.
+ */
+ private void allocateArray(int capacity)
+ {
+ char[] nb = new char[capacity];
+ System.arraycopy(value, 0, nb, 0, count);
+ value = nb;
+ allocated = false;
+ }
+
+ /**
* Get the length of the <code>String</code> this <code>StringBuilder</code>
* would create. Not to be confused with the <em>capacity</em> of the
* <code>StringBuilder</code>.
@@ -1123,6 +1131,7 @@ public final class CPStringBuilder
int len = endIndex - beginIndex;
if (len == 0)
return "";
+ allocated = true;
return VMCPStringBuilder.toString(value, beginIndex, len);
}
@@ -1136,6 +1145,7 @@ public final class CPStringBuilder
*/
public String toString()
{
+ allocated = true;
return VMCPStringBuilder.toString(value, 0, count);
}