Replaced CharBuffer with StringBuilder (CSV-59)

git-svn-id: https://svn.apache.org/repos/asf/commons/proper/csv/trunk@1300659 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Emmanuel Bourg 2012-03-14 17:42:28 +00:00
parent f8294d2d22
commit 3cb5801a98
3 changed files with 10 additions and 351 deletions

View File

@ -235,7 +235,7 @@ class CSVLexer {
/** length of the initial token (content-)buffer */ /** length of the initial token (content-)buffer */
private static final int INITIAL_TOKEN_LENGTH = 50; private static final int INITIAL_TOKEN_LENGTH = 50;
private final CharBuffer wsBuf = new CharBuffer(); private final StringBuilder wsBuf = new StringBuilder();
private final CSVFormat format; private final CSVFormat format;
@ -267,13 +267,13 @@ class CSVLexer {
Type type = INVALID; Type type = INVALID;
/** The content buffer. */ /** The content buffer. */
CharBuffer content = new CharBuffer(INITIAL_TOKEN_LENGTH); StringBuilder content = new StringBuilder(INITIAL_TOKEN_LENGTH);
/** Token ready flag: indicates a valid token with content (ready for the parser). */ /** Token ready flag: indicates a valid token with content (ready for the parser). */
boolean isReady; boolean isReady;
Token reset() { Token reset() {
content.clear(); content.setLength(0);
type = INVALID; type = INVALID;
isReady = false; isReady = false;
return this; return this;
@ -299,7 +299,7 @@ class CSVLexer {
* @throws IOException on stream access error * @throws IOException on stream access error
*/ */
Token nextToken(Token tkn) throws IOException { Token nextToken(Token tkn) throws IOException {
wsBuf.clear(); // reuse wsBuf.setLength(0); // reuse
// get the last read char (required for empty line detection) // get the last read char (required for empty line detection)
int lastChar = in.readAgain(); int lastChar = in.readAgain();
@ -308,7 +308,6 @@ class CSVLexer {
/* note: unfortunately isEndOfLine may consumes a character silently. /* note: unfortunately isEndOfLine may consumes a character silently.
* this has no effect outside of the method. so a simple workaround * this has no effect outside of the method. so a simple workaround
* is to call 'readAgain' on the stream... * is to call 'readAgain' on the stream...
* uh: might using objects instead of base-types (jdk1.5 autoboxing!)
*/ */
int c = in.read(); int c = in.read();
boolean eol = isEndOfLine(c); boolean eol = isEndOfLine(c);
@ -427,12 +426,17 @@ class CSVLexer {
} }
if (format.isTrailingSpacesIgnored()) { if (format.isTrailingSpacesIgnored()) {
tkn.content.trimTrailingWhitespace(); trimTrailingSpaces(tkn.content);
} }
return tkn; return tkn;
} }
private void trimTrailingSpaces(StringBuilder buffer) {
while (buffer.length() > 0 && Character.isWhitespace(buffer.charAt(buffer.length() - 1))) {
buffer.setLength(buffer.length() - 1);
}
}
/** /**
* An encapsulated token lexer * An encapsulated token lexer

View File

@ -1,166 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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
*/
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.
*/
CharBuffer() {
this(32);
}
/**
* Creates a new CharBuffer with an initial capacity
* of <code>length</code> characters.
*/
CharBuffer(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.
*/
void clear() {
length = 0;
}
/**
* Returns the number of characters in the buffer.
*
* @return the number of characters
*/
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.
*/
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
*/
void append(CharBuffer cb) {
if (cb != null) {
ensureCapacity(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
*/
void append(String s) {
if (s != null) {
append(s.toCharArray());
}
}
/**
* 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
*/
void append(char[] data) {
if (data != null) {
ensureCapacity(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
*/
void append(char data) {
ensureCapacity(length + 1);
c[length] = data;
length++;
}
/**
* Removes trailing whitespace.
*/
void trimTrailingWhitespace() {
while (length > 0 && Character.isWhitespace(c[length - 1])) {
length--;
}
}
/**
* Converts the contents of the buffer into a StringBuffer.
* This method involves copying the new data once!
*
* @return the contents of the character buffer as a String
*/
@Override
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
*/
void ensureCapacity(int capacity) {
if (c.length < capacity) {
int newcapacity = ((capacity * 3) >> 1) + 1;
char[] newc = new char[newcapacity];
System.arraycopy(c, 0, newc, 0, length);
c = newc;
}
}
}

View File

@ -1,179 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 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());
}
}
//-- 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.toString().toCharArray();
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.toString().toCharArray();
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((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.ensureCapacity(2);
assertEquals(4, buffer.capacity());
buffer.ensureCapacity(8);
assertTrue(buffer.capacity() >= 8);
}
public void testTrim() throws Exception {
CharBuffer buffer = new CharBuffer();
buffer.append(" ");
buffer.trimTrailingWhitespace();
assertEquals(0, buffer.length());
buffer = new CharBuffer();
buffer.append("Hello World! ");
buffer.trimTrailingWhitespace();
assertEquals("Hello World!", buffer.toString());
}
}