Author: oglueck
Date: Thu Aug 10 02:02:13 2006
New Revision: 430324
URL: http://svn.apache.org/viewvc?rev=430324&view=rev
Log:
This patch reduces the amount of intermediate garbage significantly.
PR: SANDBOX-166
Contributed by: Ortwin Glück
Reviewed by: Henri Yandell
Added:
jakarta/commons/sandbox/csv/trunk/src/java/org/apache/commons/csv/CharBuffer.java
jakarta/commons/sandbox/csv/trunk/src/test/org/apache/commons/csv/CharBufferTest.java
Added:
jakarta/commons/sandbox/csv/trunk/src/java/org/apache/commons/csv/CharBuffer.java
URL:
http://svn.apache.org/viewvc/jakarta/commons/sandbox/csv/trunk/src/java/org/apache/commons/csv/CharBuffer.java?rev=430324&view=auto
==============================================================================
---
jakarta/commons/sandbox/csv/trunk/src/java/org/apache/commons/csv/CharBuffer.java
(added)
+++
jakarta/commons/sandbox/csv/trunk/src/java/org/apache/commons/csv/CharBuffer.java
Thu Aug 10 02:02:13 2006
@@ -0,0 +1,188 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ *
+ * Licensed 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 org.apache.commons.csv;
+
+/**
+ * A simple StringBuffer replacement that aims to
+ * reduce copying as much as possible. The buffer
+ * grows as necessary.
+ * This class is not thread safe.
+ *
+ * @author Ortwin Glück
+ */
+public class CharBuffer {
+ private char[] c;
+ /**
+ * Actually used number of characters in the array.
+ * It is also the index at which
+ * a new character will be inserted into <code>c</code>.
+ */
+ private int length;
+
+ /**
+ * Creates a new CharBuffer with an initial capacity of 32 characters.
+ */
+ public CharBuffer() {
+ this(32);
+ }
+
+ /**
+ * Creates a new CharBuffer with an initial capacity
+ * of <code>length</code> characters.
+ */
+ public CharBuffer(final int length) {
+ if (length == 0) throw new IllegalArgumentException("Can't create an
empty CharBuffer");
+ this.c = new char[length];
+ }
+
+ /**
+ * Empties the buffer. The capacity still remains the same, so no memory
is freed.
+ */
+ public void clear() {
+ length = 0;
+ }
+
+ /**
+ * Returns the number of characters in the buffer.
+ * @return the number of characters
+ */
+ public int length() {
+ return length;
+ }
+
+ /**
+ * Returns the current capacity of the buffer.
+ * @return the maximum number of characters that can be stored in this
buffer without
+ * resizing it.
+ */
+ public int capacity() {
+ return c.length;
+ }
+
+ /**
+ * Appends the contents of <code>cb</code> to the end of this CharBuffer.
+ * @param cb the CharBuffer to append or null
+ */
+ public void append(final CharBuffer cb) {
+ if (cb == null) return;
+ provideCapacity(length + cb.length);
+ System.arraycopy(cb.c, 0, c, length, cb.length);
+ length += cb.length;
+ }
+
+ /**
+ * Appends <code>s</code> to the end of this CharBuffer.
+ * This method involves copying the new data once!
+ * @param s the String to append or null
+ */
+ public void append(final String s) {
+ if (s == null) return;
+ append(s.toCharArray());
+ }
+
+ /**
+ * Appends <code>sb</code> to the end of this CharBuffer.
+ * This method involves copying the new data once!
+ * @param sb the StringBuffer to append or null
+ */
+ public void append(final StringBuffer sb) {
+ if (sb == null) return;
+ provideCapacity(length + sb.length());
+ sb.getChars(0, sb.length(), c, length);
+ length += sb.length();
+ }
+
+ /**
+ * Appends <code>data</code> to the end of this CharBuffer.
+ * This method involves copying the new data once!
+ * @param data the char[] to append or null
+ */
+ public void append(final char[] data) {
+ if (data == null) return;
+ provideCapacity(length + data.length);
+ System.arraycopy(data, 0, c, length, data.length);
+ length += data.length;
+ }
+
+ /**
+ * Appends a single character to the end of this CharBuffer.
+ * This method involves copying the new data once!
+ * @param data the char to append
+ */
+ public void append(final char data) {
+ provideCapacity(length + 1);
+ c[length] = data;
+ length++;
+ }
+
+ /**
+ * Shrinks the capacity of the buffer to the current length if necessary.
+ * This method involves copying the data once!
+ */
+ public void shrink() {
+ if (c.length == length) return;
+ char[] newc = new char[length];
+ System.arraycopy(c, 0, newc, 0, length);
+ c = newc;
+ }
+
+ /**
+ * Returns the contents of the buffer as a char[]. The returned array may
+ * be the internal array of the buffer, so the caller must take care when
+ * modifying it.
+ * This method allows to avoid copying if the caller knows the exact
capacity
+ * before.
+ * @return
+ */
+ public char[] getCharacters() {
+ if (c.length == length) return c;
+ char[] chars = new char[length];
+ System.arraycopy(c, 0, chars, 0, length);
+ return chars;
+ }
+
+ /**
+ * Converts the contents of the buffer into a StringBuffer.
+ * This method involves copying the new data once!
+ * @return
+ */
+ public StringBuffer toStringBuffer() {
+ StringBuffer sb = new StringBuffer(length);
+ sb.append(c, 0, length);
+ return sb;
+ }
+
+ /**
+ * Converts the contents of the buffer into a StringBuffer.
+ * This method involves copying the new data once!
+ * @return
+ */
+ public String toString() {
+ return new String(c, 0, length);
+ }
+
+ /**
+ * Copies the data into a new array of at least <code>capacity</code> size.
+ * @param capacity
+ */
+ public void provideCapacity(final int capacity) {
+ if (c.length >= capacity) return;
+ int newcapacity = capacity;
+ char[] newc = new char[newcapacity];
+ System.arraycopy(c, 0, newc, 0, length);
+ c = newc;
+ }
+}
Added:
jakarta/commons/sandbox/csv/trunk/src/test/org/apache/commons/csv/CharBufferTest.java
URL:
http://svn.apache.org/viewvc/jakarta/commons/sandbox/csv/trunk/src/test/org/apache/commons/csv/CharBufferTest.java?rev=430324&view=auto
==============================================================================
---
jakarta/commons/sandbox/csv/trunk/src/test/org/apache/commons/csv/CharBufferTest.java
(added)
+++
jakarta/commons/sandbox/csv/trunk/src/test/org/apache/commons/csv/CharBufferTest.java
Thu Aug 10 02:02:13 2006
@@ -0,0 +1,193 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ *
+ * Licensed 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 org.apache.commons.csv;
+
+import junit.framework.TestCase;
+
+/**
+ *
+ * @author Ortwin Glück
+ */
+public class CharBufferTest extends TestCase {
+ public void testCreate() {
+ CharBuffer cb = new CharBuffer();
+ assertEquals(0, cb.length());
+ try {
+ cb = new CharBuffer(0);
+ fail("Should not be possible");
+ } catch(IllegalArgumentException e) {
+ // expected
+ }
+
+ cb = new CharBuffer(128);
+ assertEquals(0, cb.length());
+ }
+
+ public void testAppendChar() {
+ CharBuffer cb = new CharBuffer(1);
+ String expected = "";
+ for (char c = 'a'; c < 'z'; c++) {
+ cb.append(c);
+ expected += c;
+ assertEquals(expected, cb.toString());
+ assertEquals(expected.length(), cb.length());
+ }
+ }
+
+ public void testAppendCharArray() {
+ CharBuffer cb = new CharBuffer(1);
+ char[] abcd = "abcd".toCharArray();
+ String expected = "";
+ for (int i=0; i<10; i++) {
+ cb.append(abcd);
+ expected += "abcd";
+ assertEquals(expected, cb.toString());
+ assertEquals(4*(i+1), cb.length());
+ }
+ }
+
+ public void testAppendString() {
+ CharBuffer cb = new CharBuffer(1);
+ String abcd = "abcd";
+ String expected = "";
+ for (int i=0; i<10; i++) {
+ cb.append(abcd);
+ expected += abcd;
+ assertEquals(expected, cb.toString());
+ assertEquals(4*(i+1), cb.length());
+ }
+ }
+
+ public void testAppendStringBuffer() {
+ CharBuffer cb = new CharBuffer(1);
+ StringBuffer abcd = new StringBuffer("abcd");
+ String expected = "";
+ for (int i=0; i<10; i++) {
+ cb.append(abcd);
+ expected += "abcd";
+ assertEquals(expected, cb.toString());
+ assertEquals(4*(i+1), cb.length());
+ }
+ }
+
+ public void testAppendCharBuffer() {
+ CharBuffer cb = new CharBuffer(1);
+ CharBuffer abcd = new CharBuffer(17);
+ abcd.append("abcd");
+ String expected = "";
+ for (int i=0; i<10; i++) {
+ cb.append(abcd);
+ expected += "abcd";
+ assertEquals(expected, cb.toString());
+ assertEquals(4*(i+1), cb.length());
+ }
+ }
+
+ public void testShrink() {
+ String data = "123456789012345678901234567890";
+
+ CharBuffer cb = new CharBuffer(data.length() + 100);
+ assertEquals(data.length() + 100, cb.capacity());
+ cb.append(data);
+ assertEquals(data.length() + 100, cb.capacity());
+ assertEquals(data.length(), cb.length());
+ cb.shrink();
+ assertEquals(data.length(), cb.capacity());
+ assertEquals(data.length(), cb.length());
+ assertEquals(data, cb.toString());
+ }
+
+ //-- the following test cases have been adapted from the HttpComponents
project
+ //-- written by Oleg Kalnichevski
+
+ public void testSimpleAppend() throws Exception {
+ CharBuffer buffer = new CharBuffer(16);
+ assertEquals(16, buffer.capacity());
+ assertEquals(0, buffer.length());
+ char[] b1 = buffer.getCharacters();
+ assertNotNull(b1);
+ assertEquals(0, b1.length);
+ assertEquals(0, buffer.length());
+
+ char[] tmp = new char[] { '1', '2', '3', '4'};
+ buffer.append(tmp);
+ assertEquals(16, buffer.capacity());
+ assertEquals(4, buffer.length());
+
+ char[] b2 = buffer.getCharacters();
+ assertNotNull(b2);
+ assertEquals(4, b2.length);
+ for (int i = 0; i < tmp.length; i++) {
+ assertEquals(tmp[i], b2[i]);
+ }
+ assertEquals("1234", buffer.toString());
+
+ buffer.clear();
+ assertEquals(16, buffer.capacity());
+ assertEquals(0, buffer.length());
+ }
+
+ public void testAppendString2() throws Exception {
+ CharBuffer buffer = new CharBuffer(8);
+ buffer.append("stuff");
+ buffer.append(" and more stuff");
+ assertEquals("stuff and more stuff", buffer.toString());
+ }
+
+ public void testAppendNull() throws Exception {
+ CharBuffer buffer = new CharBuffer(8);
+
+ buffer.append((StringBuffer)null);
+ assertEquals("", buffer.toString());
+
+ buffer.append((String)null);
+ assertEquals("", buffer.toString());
+
+ buffer.append((CharBuffer)null);
+ assertEquals("", buffer.toString());
+
+ buffer.append((char[])null);
+ assertEquals("", buffer.toString());
+ }
+
+ public void testAppendCharArrayBuffer() throws Exception {
+ CharBuffer buffer1 = new CharBuffer(8);
+ buffer1.append(" and more stuff");
+ CharBuffer buffer2 = new CharBuffer(8);
+ buffer2.append("stuff");
+ buffer2.append(buffer1);
+ assertEquals("stuff and more stuff", buffer2.toString());
+ }
+
+ public void testAppendSingleChar() throws Exception {
+ CharBuffer buffer = new CharBuffer(4);
+ buffer.append('1');
+ buffer.append('2');
+ buffer.append('3');
+ buffer.append('4');
+ buffer.append('5');
+ buffer.append('6');
+ assertEquals("123456", buffer.toString());
+ }
+
+ public void testProvideCapacity() throws Exception {
+ CharBuffer buffer = new CharBuffer(4);
+ buffer.provideCapacity(2);
+ assertEquals(4, buffer.capacity());
+ buffer.provideCapacity(8);
+ assertTrue(buffer.capacity() >= 8);
+ }
+}
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]