001 /* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 */ 019 package org.apache.commons.csv; 020 021 /** 022 * A simple StringBuffer replacement that aims to 023 * reduce copying as much as possible. The buffer 024 * grows as necessary. 025 * This class is not thread safe. 026 * 027 * @author Ortwin Gl???ck 028 */ 029 public class CharBuffer { 030 031 private char[] c; 032 033 /** 034 * Actually used number of characters in the array. 035 * It is also the index at which 036 * a new character will be inserted into <code>c</code>. 037 */ 038 private int length; 039 040 /** 041 * Creates a new CharBuffer with an initial capacity of 32 characters. 042 */ 043 public CharBuffer() { 044 this(32); 045 } 046 047 /** 048 * Creates a new CharBuffer with an initial capacity 049 * of <code>length</code> characters. 050 */ 051 public CharBuffer(final int length) { 052 if (length == 0) { 053 throw new IllegalArgumentException("Can't create an empty CharBuffer"); 054 } 055 this.c = new char[length]; 056 } 057 058 /** 059 * Empties the buffer. The capacity still remains the same, so no memory is freed. 060 */ 061 public void clear() { 062 length = 0; 063 } 064 065 /** 066 * Returns the number of characters in the buffer. 067 * 068 * @return the number of characters 069 */ 070 public int length() { 071 return length; 072 } 073 074 /** 075 * Returns the current capacity of the buffer. 076 * 077 * @return the maximum number of characters that can be stored in this buffer without 078 * resizing it. 079 */ 080 public int capacity() { 081 return c.length; 082 } 083 084 085 /** 086 * Appends the contents of <code>cb</code> to the end of this CharBuffer. 087 * 088 * @param cb the CharBuffer to append or null 089 */ 090 public void append(final CharBuffer cb) { 091 if (cb == null) { 092 return; 093 } 094 provideCapacity(length + cb.length); 095 System.arraycopy(cb.c, 0, c, length, cb.length); 096 length += cb.length; 097 } 098 099 /** 100 * Appends <code>s</code> to the end of this CharBuffer. 101 * This method involves copying the new data once! 102 * 103 * @param s the String to append or null 104 */ 105 public void append(final String s) { 106 if (s == null) { 107 return; 108 } 109 append(s.toCharArray()); 110 } 111 112 /** 113 * Appends <code>sb</code> to the end of this CharBuffer. 114 * This method involves copying the new data once! 115 * 116 * @param sb the StringBuffer to append or null 117 */ 118 public void append(final StringBuffer sb) { 119 if (sb == null) { 120 return; 121 } 122 provideCapacity(length + sb.length()); 123 sb.getChars(0, sb.length(), c, length); 124 length += sb.length(); 125 } 126 127 /** 128 * Appends <code>data</code> to the end of this CharBuffer. 129 * This method involves copying the new data once! 130 * 131 * @param data the char[] to append or null 132 */ 133 public void append(final char[] data) { 134 if (data == null) { 135 return; 136 } 137 provideCapacity(length + data.length); 138 System.arraycopy(data, 0, c, length, data.length); 139 length += data.length; 140 } 141 142 /** 143 * Appends a single character to the end of this CharBuffer. 144 * This method involves copying the new data once! 145 * 146 * @param data the char to append 147 */ 148 public void append(final char data) { 149 provideCapacity(length + 1); 150 c[length] = data; 151 length++; 152 } 153 154 /** 155 * Shrinks the capacity of the buffer to the current length if necessary. 156 * This method involves copying the data once! 157 */ 158 public void shrink() { 159 if (c.length == length) { 160 return; 161 } 162 char[] newc = new char[length]; 163 System.arraycopy(c, 0, newc, 0, length); 164 c = newc; 165 } 166 167 /** 168 * Removes trailing whitespace. 169 */ 170 public void trimTrailingWhitespace() { 171 while (length > 0 && Character.isWhitespace(c[length - 1])) { 172 length--; 173 } 174 } 175 176 /** 177 * Returns the contents of the buffer as a char[]. The returned array may 178 * be the internal array of the buffer, so the caller must take care when 179 * modifying it. 180 * This method allows to avoid copying if the caller knows the exact capacity 181 * before. 182 * 183 * @return 184 */ 185 public char[] getCharacters() { 186 if (c.length == length) { 187 return c; 188 } 189 char[] chars = new char[length]; 190 System.arraycopy(c, 0, chars, 0, length); 191 return chars; 192 } 193 194 /** 195 * Returns the character at the specified position. 196 */ 197 public char charAt(int pos) { 198 return c[pos]; 199 } 200 201 /** 202 * Converts the contents of the buffer into a StringBuffer. 203 * This method involves copying the new data once! 204 * 205 * @return 206 */ 207 public StringBuffer toStringBuffer() { 208 StringBuffer sb = new StringBuffer(length); 209 sb.append(c, 0, length); 210 return sb; 211 } 212 213 /** 214 * Converts the contents of the buffer into a StringBuffer. 215 * This method involves copying the new data once! 216 * 217 * @return 218 */ 219 public String toString() { 220 return new String(c, 0, length); 221 } 222 223 /** 224 * Copies the data into a new array of at least <code>capacity</code> size. 225 * 226 * @param capacity 227 */ 228 public void provideCapacity(final int capacity) { 229 if (c.length >= capacity) { 230 return; 231 } 232 int newcapacity = ((capacity * 3) >> 1) + 1; 233 char[] newc = new char[newcapacity]; 234 System.arraycopy(c, 0, newc, 0, length); 235 c = newc; 236 } 237 }