You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by br...@apache.org on 2014/04/26 12:39:03 UTC

svn commit: r1590224 - in /commons/proper/lang/trunk/src: changes/changes.xml main/java/org/apache/commons/lang3/text/StrBuilder.java test/java/org/apache/commons/lang3/text/StrBuilderTest.java

Author: britter
Date: Sat Apr 26 10:39:03 2014
New Revision: 1590224

URL: http://svn.apache.org/r1590224
Log:
LANG-993: Add zero copy write method to StrBuilder; LANG-994: Add zero copy read method to StrBuilder. Thanks to Mikhail Mazursky.

Modified:
    commons/proper/lang/trunk/src/changes/changes.xml
    commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/text/StrBuilder.java
    commons/proper/lang/trunk/src/test/java/org/apache/commons/lang3/text/StrBuilderTest.java

Modified: commons/proper/lang/trunk/src/changes/changes.xml
URL: http://svn.apache.org/viewvc/commons/proper/lang/trunk/src/changes/changes.xml?rev=1590224&r1=1590223&r2=1590224&view=diff
==============================================================================
--- commons/proper/lang/trunk/src/changes/changes.xml [utf-8] (original)
+++ commons/proper/lang/trunk/src/changes/changes.xml [utf-8] Sat Apr 26 10:39:03 2014
@@ -22,6 +22,8 @@
   <body>
 
   <release version="3.4" date="tba" description="tba">
+    <action issue="LANG-994" type="add" dev="britter" due-to="Mikhail Mazursky">Add zero copy read method to StrBuilder</action>
+    <action issue="LANG-993" type="add" dev="britter" due-to="Mikhail Mazursky">Add zero copy write method to StrBuilder</action>
     <action issue="LANG-998" type="update" dev="chas">Javadoc is not clear on preferred pattern to instantiate FastDateParser / FastDatePrinter</action>
     <action issue="LANG-996" type="fix" dev="chas">FastDateParser should be case insensitive</action>
     <action issue="LANG-995" type="fix" dev="britter" due-to="Andrey Khobnya">Fix bug with stripping spaces on last line in WordUtils.wrap()</action>

Modified: commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/text/StrBuilder.java
URL: http://svn.apache.org/viewvc/commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/text/StrBuilder.java?rev=1590224&r1=1590223&r2=1590224&view=diff
==============================================================================
--- commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/text/StrBuilder.java (original)
+++ commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/text/StrBuilder.java Sat Apr 26 10:39:03 2014
@@ -16,9 +16,11 @@
  */
 package org.apache.commons.lang3.text;
 
+import java.io.IOException;
 import java.io.Reader;
 import java.io.Serializable;
 import java.io.Writer;
+import java.nio.CharBuffer;
 import java.util.Iterator;
 import java.util.List;
 
@@ -423,6 +425,48 @@ public class StrBuilder implements CharS
 
     //-----------------------------------------------------------------------
     /**
+     * If possible, reads chars from the provided {@link Readable} directly into underlying
+     * character buffer without making extra copies.
+     *
+     * @param readable  object to read from
+     * @return the number of characters read
+     * @throws IOException if an I/O error occurs
+     *
+     * @since 3.4
+     * @see #appendTo(Appendable)
+     */
+    public int readFrom(final Readable readable) throws IOException {
+        final int oldSize = size;
+        if (readable instanceof Reader) {
+            final Reader r = (Reader) readable;
+            ensureCapacity(size + 1);
+            int read;
+            while ((read = r.read(buffer, size, buffer.length - size)) != -1) {
+                size += read;
+                ensureCapacity(size + 1);
+            }
+        } else if (readable instanceof CharBuffer) {
+            final CharBuffer cb = (CharBuffer) readable;
+            final int remaining = cb.remaining();
+            ensureCapacity(size + remaining);
+            cb.get(buffer, size, remaining);
+            size += remaining;
+        } else {
+            while (true) {
+                ensureCapacity(size + 1);
+                final CharBuffer buf = CharBuffer.wrap(buffer, size, buffer.length - size);
+                final int read = readable.read(buf);
+                if (read == -1) {
+                    break;
+                }
+                size += read;
+            }
+        }
+        return size - oldSize;
+    }
+
+    //-----------------------------------------------------------------------
+    /**
      * Appends the new line string to this string builder.
      * <p>
      * The new line string can be altered using {@link #setNewLineText(String)}.
@@ -2610,6 +2654,32 @@ public class StrBuilder implements CharS
         return new StrBuilderWriter();
     }
 
+    /**
+     * Appends current contents of this <code>StrBuilder</code> to the
+     * provided {@link Appendable}.
+     * <p>
+     * This method tries to avoid doing any extra copies of contents.
+     *
+     * @param appendable  the appendable to append data to
+     * @throws IOException  if an I/O error occurs
+     *
+     * @since 3.4
+     * @see #readFrom(Readable)
+     */
+    public void appendTo(final Appendable appendable) throws IOException {
+        if (appendable instanceof Writer) {
+            ((Writer) appendable).write(buffer, 0, size);
+        } else if (appendable instanceof StringBuilder) {
+            ((StringBuilder) appendable).append(buffer, 0, size);
+        } else if (appendable instanceof StringBuffer) {
+            ((StringBuffer) appendable).append(buffer, 0, size);
+        } else if (appendable instanceof CharBuffer) {
+            ((CharBuffer) appendable).put(buffer, 0, size);
+        } else {
+            appendable.append(this);
+        }
+    }
+
     //-----------------------------------------------------------------------
 //    /**
 //     * Gets a String version of the string builder by calling the internal

Modified: commons/proper/lang/trunk/src/test/java/org/apache/commons/lang3/text/StrBuilderTest.java
URL: http://svn.apache.org/viewvc/commons/proper/lang/trunk/src/test/java/org/apache/commons/lang3/text/StrBuilderTest.java?rev=1590224&r1=1590223&r2=1590224&view=diff
==============================================================================
--- commons/proper/lang/trunk/src/test/java/org/apache/commons/lang3/text/StrBuilderTest.java (original)
+++ commons/proper/lang/trunk/src/test/java/org/apache/commons/lang3/text/StrBuilderTest.java Sat Apr 26 10:39:03 2014
@@ -19,8 +19,13 @@ package org.apache.commons.lang3.text;
 
 import org.junit.Test;
 import static org.junit.Assert.*;
+
+import java.io.IOException;
 import java.io.Reader;
+import java.io.StringReader;
+import java.io.StringWriter;
 import java.io.Writer;
+import java.nio.CharBuffer;
 import java.util.Arrays;
 
 import org.apache.commons.lang3.ArrayUtils;
@@ -93,6 +98,84 @@ public class StrBuilderTest {
 
     //-----------------------------------------------------------------------
     @Test
+    public void testReadFromReader() throws Exception {
+        String s = "";
+        for (int i = 0; i < 100; ++i) {
+            StrBuilder sb = new StrBuilder();
+            int len = sb.readFrom(new StringReader(s));
+
+            assertEquals(s.length(), len);
+            assertEquals(s, sb.toString());
+
+            s += Integer.toString(i);
+        }
+    }
+
+    @Test
+    public void testReadFromReaderAppendsToEnd() throws Exception {
+        StrBuilder sb = new StrBuilder("Test");
+        sb.readFrom(new StringReader(" 123"));
+        assertEquals("Test 123", sb.toString());
+    }
+
+    @Test
+    public void testReadFromCharBuffer() throws Exception {
+        String s = "";
+        for (int i = 0; i < 100; ++i) {
+            StrBuilder sb = new StrBuilder();
+            int len = sb.readFrom(CharBuffer.wrap(s));
+
+            assertEquals(s.length(), len);
+            assertEquals(s, sb.toString());
+
+            s += Integer.toString(i);
+        }
+    }
+
+    @Test
+    public void testReadFromCharBufferAppendsToEnd() throws Exception {
+        StrBuilder sb = new StrBuilder("Test");
+        sb.readFrom(CharBuffer.wrap(" 123"));
+        assertEquals("Test 123", sb.toString());
+    }
+
+    @Test
+    public void testReadFromReadable() throws Exception {
+        String s = "";
+        for (int i = 0; i < 100; ++i) {
+            StrBuilder sb = new StrBuilder();
+            int len = sb.readFrom(new MockReadable(s));
+
+            assertEquals(s.length(), len);
+            assertEquals(s, sb.toString());
+
+            s += Integer.toString(i);
+        }
+    }
+
+    @Test
+    public void testReadFromReadableAppendsToEnd() throws Exception {
+        StrBuilder sb = new StrBuilder("Test");
+        sb.readFrom(new MockReadable(" 123"));
+        assertEquals("Test 123", sb.toString());
+    }
+
+    private static class MockReadable implements Readable {
+
+        private final CharBuffer src;
+
+        public MockReadable(final String src) {
+            this.src = CharBuffer.wrap(src);
+        }
+
+        @Override
+        public int read(final CharBuffer cb) throws IOException {
+            return src.read(cb);
+        }
+    }
+
+    //-----------------------------------------------------------------------
+    @Test
     public void testGetSetNewLineText() {
         final StrBuilder sb = new StrBuilder();
         assertEquals(null, sb.getNewLineText());
@@ -1855,4 +1938,48 @@ public class StrBuilderTest {
         assertEquals(sb.toString(), sb.build());
     }
 
+    //-----------------------------------------------------------------------
+    @Test
+    public void testAppendToWriter() throws Exception {
+        final StrBuilder sb = new StrBuilder("1234567890");
+        final StringWriter writer = new StringWriter();
+        writer.append("Test ");
+
+        sb.appendTo(writer);
+
+        assertEquals("Test 1234567890", writer.toString());
+    }
+
+    @Test
+    public void testAppendToStringBuilder() throws Exception {
+        final StrBuilder sb = new StrBuilder("1234567890");
+        final StringBuilder builder = new StringBuilder("Test ");
+
+        sb.appendTo(builder);
+
+        assertEquals("Test 1234567890", builder.toString());
+    }
+
+    @Test
+    public void testAppendToStringBuffer() throws Exception {
+        final StrBuilder sb = new StrBuilder("1234567890");
+        final StringBuffer buffer = new StringBuffer("Test ");
+
+        sb.appendTo(buffer);
+
+        assertEquals("Test 1234567890", buffer.toString());
+    }
+
+    @Test
+    public void testAppendToCharBuffer() throws Exception {
+        final StrBuilder sb = new StrBuilder("1234567890");
+        final String text = "Test ";
+        final CharBuffer buffer = CharBuffer.allocate(sb.size() + text.length());
+        buffer.put(text);
+
+        sb.appendTo(buffer);
+
+        buffer.flip();
+        assertEquals("Test 1234567890", buffer.toString());
+    }
 }