Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
1 /*
2 * ====================================================================
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 * ====================================================================
20 *
21 * This software consists of voluntary contributions made by many
22 * individuals on behalf of the Apache Software Foundation. For more
23 * information on the Apache Software Foundation, please see
24 * <http://www.apache.org/>.
25 *
26 */
28 package ch.boye.httpclientandroidlib.util;
30 import java.io.Serializable;
32 import ch.boye.httpclientandroidlib.protocol.HTTP;
34 /**
35 * A resizable char array.
36 *
37 * @since 4.0
38 */
39 public final class CharArrayBuffer implements Serializable {
41 private static final long serialVersionUID = -6208952725094867135L;
43 private char[] buffer;
44 private int len;
46 /**
47 * Creates an instance of {@link CharArrayBuffer} with the given initial
48 * capacity.
49 *
50 * @param capacity the capacity
51 */
52 public CharArrayBuffer(int capacity) {
53 super();
54 if (capacity < 0) {
55 throw new IllegalArgumentException("Buffer capacity may not be negative");
56 }
57 this.buffer = new char[capacity];
58 }
60 private void expand(int newlen) {
61 char newbuffer[] = new char[Math.max(this.buffer.length << 1, newlen)];
62 System.arraycopy(this.buffer, 0, newbuffer, 0, this.len);
63 this.buffer = newbuffer;
64 }
66 /**
67 * Appends <code>len</code> chars to this buffer from the given source
68 * array starting at index <code>off</code>. The capacity of the buffer
69 * is increased, if necessary, to accommodate all <code>len</code> chars.
70 *
71 * @param b the chars to be appended.
72 * @param off the index of the first char to append.
73 * @param len the number of chars to append.
74 * @throws IndexOutOfBoundsException if <code>off</code> is out of
75 * range, <code>len</code> is negative, or
76 * <code>off</code> + <code>len</code> is out of range.
77 */
78 public void append(final char[] b, int off, int len) {
79 if (b == null) {
80 return;
81 }
82 if ((off < 0) || (off > b.length) || (len < 0) ||
83 ((off + len) < 0) || ((off + len) > b.length)) {
84 throw new IndexOutOfBoundsException("off: "+off+" len: "+len+" b.length: "+b.length);
85 }
86 if (len == 0) {
87 return;
88 }
89 int newlen = this.len + len;
90 if (newlen > this.buffer.length) {
91 expand(newlen);
92 }
93 System.arraycopy(b, off, this.buffer, this.len, len);
94 this.len = newlen;
95 }
97 /**
98 * Appends chars of the given string to this buffer. The capacity of the
99 * buffer is increased, if necessary, to accommodate all chars.
100 *
101 * @param str the string.
102 */
103 public void append(String str) {
104 if (str == null) {
105 str = "null";
106 }
107 int strlen = str.length();
108 int newlen = this.len + strlen;
109 if (newlen > this.buffer.length) {
110 expand(newlen);
111 }
112 str.getChars(0, strlen, this.buffer, this.len);
113 this.len = newlen;
114 }
116 /**
117 * Appends <code>len</code> chars to this buffer from the given source
118 * buffer starting at index <code>off</code>. The capacity of the
119 * destination buffer is increased, if necessary, to accommodate all
120 * <code>len</code> chars.
121 *
122 * @param b the source buffer to be appended.
123 * @param off the index of the first char to append.
124 * @param len the number of chars to append.
125 * @throws IndexOutOfBoundsException if <code>off</code> is out of
126 * range, <code>len</code> is negative, or
127 * <code>off</code> + <code>len</code> is out of range.
128 */
129 public void append(final CharArrayBuffer b, int off, int len) {
130 if (b == null) {
131 return;
132 }
133 append(b.buffer, off, len);
134 }
136 /**
137 * Appends all chars to this buffer from the given source buffer starting
138 * at index <code>0</code>. The capacity of the destination buffer is
139 * increased, if necessary, to accommodate all {@link #length()} chars.
140 *
141 * @param b the source buffer to be appended.
142 */
143 public void append(final CharArrayBuffer b) {
144 if (b == null) {
145 return;
146 }
147 append(b.buffer,0, b.len);
148 }
150 /**
151 * Appends <code>ch</code> char to this buffer. The capacity of the buffer
152 * is increased, if necessary, to accommodate the additional char.
153 *
154 * @param ch the char to be appended.
155 */
156 public void append(char ch) {
157 int newlen = this.len + 1;
158 if (newlen > this.buffer.length) {
159 expand(newlen);
160 }
161 this.buffer[this.len] = ch;
162 this.len = newlen;
163 }
165 /**
166 * Appends <code>len</code> bytes to this buffer from the given source
167 * array starting at index <code>off</code>. The capacity of the buffer
168 * is increased, if necessary, to accommodate all <code>len</code> bytes.
169 * <p>
170 * The bytes are converted to chars using simple cast.
171 *
172 * @param b the bytes to be appended.
173 * @param off the index of the first byte to append.
174 * @param len the number of bytes to append.
175 * @throws IndexOutOfBoundsException if <code>off</code> is out of
176 * range, <code>len</code> is negative, or
177 * <code>off</code> + <code>len</code> is out of range.
178 */
179 public void append(final byte[] b, int off, int len) {
180 if (b == null) {
181 return;
182 }
183 if ((off < 0) || (off > b.length) || (len < 0) ||
184 ((off + len) < 0) || ((off + len) > b.length)) {
185 throw new IndexOutOfBoundsException("off: "+off+" len: "+len+" b.length: "+b.length);
186 }
187 if (len == 0) {
188 return;
189 }
190 int oldlen = this.len;
191 int newlen = oldlen + len;
192 if (newlen > this.buffer.length) {
193 expand(newlen);
194 }
195 for (int i1 = off, i2 = oldlen; i2 < newlen; i1++, i2++) {
196 this.buffer[i2] = (char) (b[i1] & 0xff);
197 }
198 this.len = newlen;
199 }
201 /**
202 * Appends <code>len</code> bytes to this buffer from the given source
203 * array starting at index <code>off</code>. The capacity of the buffer
204 * is increased, if necessary, to accommodate all <code>len</code> bytes.
205 * <p>
206 * The bytes are converted to chars using simple cast.
207 *
208 * @param b the bytes to be appended.
209 * @param off the index of the first byte to append.
210 * @param len the number of bytes to append.
211 * @throws IndexOutOfBoundsException if <code>off</code> is out of
212 * range, <code>len</code> is negative, or
213 * <code>off</code> + <code>len</code> is out of range.
214 */
215 public void append(final ByteArrayBuffer b, int off, int len) {
216 if (b == null) {
217 return;
218 }
219 append(b.buffer(), off, len);
220 }
222 /**
223 * Appends chars of the textual representation of the given object to this
224 * buffer. The capacity of the buffer is increased, if necessary, to
225 * accommodate all chars.
226 *
227 * @param obj the object.
228 */
229 public void append(final Object obj) {
230 append(String.valueOf(obj));
231 }
233 /**
234 * Clears content of the buffer. The underlying char array is not resized.
235 */
236 public void clear() {
237 this.len = 0;
238 }
240 /**
241 * Converts the content of this buffer to an array of chars.
242 *
243 * @return char array
244 */
245 public char[] toCharArray() {
246 char[] b = new char[this.len];
247 if (this.len > 0) {
248 System.arraycopy(this.buffer, 0, b, 0, this.len);
249 }
250 return b;
251 }
253 /**
254 * Returns the <code>char</code> value in this buffer at the specified
255 * index. The index argument must be greater than or equal to
256 * <code>0</code>, and less than the length of this buffer.
257 *
258 * @param i the index of the desired char value.
259 * @return the char value at the specified index.
260 * @throws IndexOutOfBoundsException if <code>index</code> is
261 * negative or greater than or equal to {@link #length()}.
262 */
263 public char charAt(int i) {
264 return this.buffer[i];
265 }
267 /**
268 * Returns reference to the underlying char array.
269 *
270 * @return the char array.
271 */
272 public char[] buffer() {
273 return this.buffer;
274 }
276 /**
277 * Returns the current capacity. The capacity is the amount of storage
278 * available for newly appended chars, beyond which an allocation will
279 * occur.
280 *
281 * @return the current capacity
282 */
283 public int capacity() {
284 return this.buffer.length;
285 }
287 /**
288 * Returns the length of the buffer (char count).
289 *
290 * @return the length of the buffer
291 */
292 public int length() {
293 return this.len;
294 }
296 /**
297 * Ensures that the capacity is at least equal to the specified minimum.
298 * If the current capacity is less than the argument, then a new internal
299 * array is allocated with greater capacity. If the <code>required</code>
300 * argument is non-positive, this method takes no action.
301 *
302 * @param required the minimum required capacity.
303 */
304 public void ensureCapacity(int required) {
305 if (required <= 0) {
306 return;
307 }
308 int available = this.buffer.length - this.len;
309 if (required > available) {
310 expand(this.len + required);
311 }
312 }
314 /**
315 * Sets the length of the buffer. The new length value is expected to be
316 * less than the current capacity and greater than or equal to
317 * <code>0</code>.
318 *
319 * @param len the new length
320 * @throws IndexOutOfBoundsException if the
321 * <code>len</code> argument is greater than the current
322 * capacity of the buffer or less than <code>0</code>.
323 */
324 public void setLength(int len) {
325 if (len < 0 || len > this.buffer.length) {
326 throw new IndexOutOfBoundsException("len: "+len+" < 0 or > buffer len: "+this.buffer.length);
327 }
328 this.len = len;
329 }
331 /**
332 * Returns <code>true</code> if this buffer is empty, that is, its
333 * {@link #length()} is equal to <code>0</code>.
334 * @return <code>true</code> if this buffer is empty, <code>false</code>
335 * otherwise.
336 */
337 public boolean isEmpty() {
338 return this.len == 0;
339 }
341 /**
342 * Returns <code>true</code> if this buffer is full, that is, its
343 * {@link #length()} is equal to its {@link #capacity()}.
344 * @return <code>true</code> if this buffer is full, <code>false</code>
345 * otherwise.
346 */
347 public boolean isFull() {
348 return this.len == this.buffer.length;
349 }
351 /**
352 * Returns the index within this buffer of the first occurrence of the
353 * specified character, starting the search at the specified
354 * <code>beginIndex</code> and finishing at <code>endIndex</code>.
355 * If no such character occurs in this buffer within the specified bounds,
356 * <code>-1</code> is returned.
357 * <p>
358 * There is no restriction on the value of <code>beginIndex</code> and
359 * <code>endIndex</code>. If <code>beginIndex</code> is negative,
360 * it has the same effect as if it were zero. If <code>endIndex</code> is
361 * greater than {@link #length()}, it has the same effect as if it were
362 * {@link #length()}. If the <code>beginIndex</code> is greater than
363 * the <code>endIndex</code>, <code>-1</code> is returned.
364 *
365 * @param ch the char to search for.
366 * @param beginIndex the index to start the search from.
367 * @param endIndex the index to finish the search at.
368 * @return the index of the first occurrence of the character in the buffer
369 * within the given bounds, or <code>-1</code> if the character does
370 * not occur.
371 */
372 public int indexOf(int ch, int beginIndex, int endIndex) {
373 if (beginIndex < 0) {
374 beginIndex = 0;
375 }
376 if (endIndex > this.len) {
377 endIndex = this.len;
378 }
379 if (beginIndex > endIndex) {
380 return -1;
381 }
382 for (int i = beginIndex; i < endIndex; i++) {
383 if (this.buffer[i] == ch) {
384 return i;
385 }
386 }
387 return -1;
388 }
390 /**
391 * Returns the index within this buffer of the first occurrence of the
392 * specified character, starting the search at <code>0</code> and finishing
393 * at {@link #length()}. If no such character occurs in this buffer within
394 * those bounds, <code>-1</code> is returned.
395 *
396 * @param ch the char to search for.
397 * @return the index of the first occurrence of the character in the
398 * buffer, or <code>-1</code> if the character does not occur.
399 */
400 public int indexOf(int ch) {
401 return indexOf(ch, 0, this.len);
402 }
404 /**
405 * Returns a substring of this buffer. The substring begins at the specified
406 * <code>beginIndex</code> and extends to the character at index
407 * <code>endIndex - 1</code>.
408 *
409 * @param beginIndex the beginning index, inclusive.
410 * @param endIndex the ending index, exclusive.
411 * @return the specified substring.
412 * @exception StringIndexOutOfBoundsException if the
413 * <code>beginIndex</code> is negative, or
414 * <code>endIndex</code> is larger than the length of this
415 * buffer, or <code>beginIndex</code> is larger than
416 * <code>endIndex</code>.
417 */
418 public String substring(int beginIndex, int endIndex) {
419 return new String(this.buffer, beginIndex, endIndex - beginIndex);
420 }
422 /**
423 * Returns a substring of this buffer with leading and trailing whitespace
424 * omitted. The substring begins with the first non-whitespace character
425 * from <code>beginIndex</code> and extends to the last
426 * non-whitespace character with the index lesser than
427 * <code>endIndex</code>.
428 *
429 * @param beginIndex the beginning index, inclusive.
430 * @param endIndex the ending index, exclusive.
431 * @return the specified substring.
432 * @exception IndexOutOfBoundsException if the
433 * <code>beginIndex</code> is negative, or
434 * <code>endIndex</code> is larger than the length of this
435 * buffer, or <code>beginIndex</code> is larger than
436 * <code>endIndex</code>.
437 */
438 public String substringTrimmed(int beginIndex, int endIndex) {
439 if (beginIndex < 0) {
440 throw new IndexOutOfBoundsException("Negative beginIndex: "+beginIndex);
441 }
442 if (endIndex > this.len) {
443 throw new IndexOutOfBoundsException("endIndex: "+endIndex+" > length: "+this.len);
444 }
445 if (beginIndex > endIndex) {
446 throw new IndexOutOfBoundsException("beginIndex: "+beginIndex+" > endIndex: "+endIndex);
447 }
448 while (beginIndex < endIndex && HTTP.isWhitespace(this.buffer[beginIndex])) {
449 beginIndex++;
450 }
451 while (endIndex > beginIndex && HTTP.isWhitespace(this.buffer[endIndex - 1])) {
452 endIndex--;
453 }
454 return new String(this.buffer, beginIndex, endIndex - beginIndex);
455 }
457 public String toString() {
458 return new String(this.buffer, 0, this.len);
459 }
461 }