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]

Reply via email to