View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   * http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  
20  package org.apache.commons.csv;
21  
22  /**
23   * A simple StringBuffer replacement that aims to reduce copying as much as possible.
24   * The buffer grows as necessary. This class is not thread safe.
25   *
26   * @author Ortwin Glück
27   */
28  class CharBuffer {
29  
30      private char[] c;
31  
32      /**
33       * Actually used number of characters in the array.
34       * It is also the index at which a new character will be inserted into <code>c</code>.
35       */
36      private int length;
37  
38      /**
39       * Creates a new CharBuffer with an initial capacity of 32 characters.
40       */
41      CharBuffer() {
42          this(32);
43      }
44  
45      /**
46       * Creates a new CharBuffer with an initial capacity
47       * of <code>length</code> characters.
48       */
49      CharBuffer(final int length) {
50          if (length == 0) {
51              throw new IllegalArgumentException("Can't create an empty CharBuffer");
52          }
53          this.c = new char[length];
54      }
55  
56      /**
57       * Empties the buffer. The capacity still remains the same, so no memory is freed.
58       */
59      void clear() {
60          length = 0;
61      }
62  
63      /**
64       * Returns the number of characters in the buffer.
65       *
66       * @return the number of characters
67       */
68      int length() {
69          return length;
70      }
71  
72      /**
73       * Returns the current capacity of the buffer.
74       *
75       * @return the maximum number of characters that can be stored in this buffer without resizing it.
76       */
77      int capacity() {
78          return c.length;
79      }
80  
81  
82      /**
83       * Appends the contents of <code>cb</code> to the end of this CharBuffer.
84       *
85       * @param cb the CharBuffer to append or null
86       */
87      void append(final CharBuffer cb) {
88          if (cb == null) {
89              return;
90          }
91          provideCapacity(length + cb.length);
92          System.arraycopy(cb.c, 0, c, length, cb.length);
93          length += cb.length;
94      }
95  
96      /**
97       * Appends <code>s</code> to the end of this CharBuffer.
98       * This method involves copying the new data once!
99       *
100      * @param s the String to append or null
101      */
102     void append(final String s) {
103         if (s == null) {
104             return;
105         }
106         append(s.toCharArray());
107     }
108 
109     /**
110      * Appends <code>data</code> to the end of this CharBuffer.
111      * This method involves copying the new data once!
112      *
113      * @param data the char[] to append or null
114      */
115     void append(final char[] data) {
116         if (data == null) {
117             return;
118         }
119         provideCapacity(length + data.length);
120         System.arraycopy(data, 0, c, length, data.length);
121         length += data.length;
122     }
123 
124     /**
125      * Appends a single character to the end of this CharBuffer.
126      * This method involves copying the new data once!
127      *
128      * @param data the char to append
129      */
130     void append(final char data) {
131         provideCapacity(length + 1);
132         c[length] = data;
133         length++;
134     }
135 
136     /**
137      * Shrinks the capacity of the buffer to the current length if necessary.
138      * This method involves copying the data once!
139      */
140     void shrink() {
141         if (c.length == length) {
142             return;
143         }
144         char[] newc = new char[length];
145         System.arraycopy(c, 0, newc, 0, length);
146         c = newc;
147     }
148 
149     /**
150      * Removes trailing whitespace.
151      */
152     void trimTrailingWhitespace() {
153         while (length > 0 && Character.isWhitespace(c[length - 1])) {
154             length--;
155         }
156     }
157 
158     /**
159      * Returns the contents of the buffer as a char[]. The returned array may
160      * be the internal array of the buffer, so the caller must take care when
161      * modifying it.
162      * This method allows to avoid copying if the caller knows the exact capacity
163      * before.
164      *
165      * @return
166      */
167     char[] getCharacters() {
168         if (c.length == length) {
169             return c;
170         }
171         char[] chars = new char[length];
172         System.arraycopy(c, 0, chars, 0, length);
173         return chars;
174     }
175 
176     /**
177      * Returns the character at the specified position.
178      */
179     char charAt(int pos) {
180         return c[pos];
181     }
182 
183     /**
184      * Converts the contents of the buffer into a StringBuffer.
185      * This method involves copying the new data once!
186      *
187      * @return the contents of the character buffer as a String
188      */
189     @Override
190     public String toString() {
191         return new String(c, 0, length);
192     }
193 
194     /**
195      * Copies the data into a new array of at least <code>capacity</code> size.
196      *
197      * @param capacity
198      */
199     void provideCapacity(final int capacity) {
200         if (c.length >= capacity) {
201             return;
202         }
203         int newcapacity = ((capacity * 3) >> 1) + 1;
204         char[] newc = new char[newcapacity];
205         System.arraycopy(c, 0, newc, 0, length);
206         c = newc;
207     }
208 }