michael@0: /*
michael@0: * ====================================================================
michael@0: * Licensed to the Apache Software Foundation (ASF) under one
michael@0: * or more contributor license agreements. See the NOTICE file
michael@0: * distributed with this work for additional information
michael@0: * regarding copyright ownership. The ASF licenses this file
michael@0: * to you under the Apache License, Version 2.0 (the
michael@0: * "License"); you may not use this file except in compliance
michael@0: * with the License. You may obtain a copy of the License at
michael@0: *
michael@0: * http://www.apache.org/licenses/LICENSE-2.0
michael@0: *
michael@0: * Unless required by applicable law or agreed to in writing,
michael@0: * software distributed under the License is distributed on an
michael@0: * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
michael@0: * KIND, either express or implied. See the License for the
michael@0: * specific language governing permissions and limitations
michael@0: * under the License.
michael@0: * ====================================================================
michael@0: *
michael@0: * This software consists of voluntary contributions made by many
michael@0: * individuals on behalf of the Apache Software Foundation. For more
michael@0: * information on the Apache Software Foundation, please see
michael@0: * len
chars to this buffer from the given source
michael@0: * array starting at index off
. The capacity of the buffer
michael@0: * is increased, if necessary, to accommodate all len
chars.
michael@0: *
michael@0: * @param b the chars to be appended.
michael@0: * @param off the index of the first char to append.
michael@0: * @param len the number of chars to append.
michael@0: * @throws IndexOutOfBoundsException if off
is out of
michael@0: * range, len
is negative, or
michael@0: * off
+ len
is out of range.
michael@0: */
michael@0: public void append(final char[] b, int off, int len) {
michael@0: if (b == null) {
michael@0: return;
michael@0: }
michael@0: if ((off < 0) || (off > b.length) || (len < 0) ||
michael@0: ((off + len) < 0) || ((off + len) > b.length)) {
michael@0: throw new IndexOutOfBoundsException("off: "+off+" len: "+len+" b.length: "+b.length);
michael@0: }
michael@0: if (len == 0) {
michael@0: return;
michael@0: }
michael@0: int newlen = this.len + len;
michael@0: if (newlen > this.buffer.length) {
michael@0: expand(newlen);
michael@0: }
michael@0: System.arraycopy(b, off, this.buffer, this.len, len);
michael@0: this.len = newlen;
michael@0: }
michael@0:
michael@0: /**
michael@0: * Appends chars of the given string to this buffer. The capacity of the
michael@0: * buffer is increased, if necessary, to accommodate all chars.
michael@0: *
michael@0: * @param str the string.
michael@0: */
michael@0: public void append(String str) {
michael@0: if (str == null) {
michael@0: str = "null";
michael@0: }
michael@0: int strlen = str.length();
michael@0: int newlen = this.len + strlen;
michael@0: if (newlen > this.buffer.length) {
michael@0: expand(newlen);
michael@0: }
michael@0: str.getChars(0, strlen, this.buffer, this.len);
michael@0: this.len = newlen;
michael@0: }
michael@0:
michael@0: /**
michael@0: * Appends len
chars to this buffer from the given source
michael@0: * buffer starting at index off
. The capacity of the
michael@0: * destination buffer is increased, if necessary, to accommodate all
michael@0: * len
chars.
michael@0: *
michael@0: * @param b the source buffer to be appended.
michael@0: * @param off the index of the first char to append.
michael@0: * @param len the number of chars to append.
michael@0: * @throws IndexOutOfBoundsException if off
is out of
michael@0: * range, len
is negative, or
michael@0: * off
+ len
is out of range.
michael@0: */
michael@0: public void append(final CharArrayBuffer b, int off, int len) {
michael@0: if (b == null) {
michael@0: return;
michael@0: }
michael@0: append(b.buffer, off, len);
michael@0: }
michael@0:
michael@0: /**
michael@0: * Appends all chars to this buffer from the given source buffer starting
michael@0: * at index 0
. The capacity of the destination buffer is
michael@0: * increased, if necessary, to accommodate all {@link #length()} chars.
michael@0: *
michael@0: * @param b the source buffer to be appended.
michael@0: */
michael@0: public void append(final CharArrayBuffer b) {
michael@0: if (b == null) {
michael@0: return;
michael@0: }
michael@0: append(b.buffer,0, b.len);
michael@0: }
michael@0:
michael@0: /**
michael@0: * Appends ch
char to this buffer. The capacity of the buffer
michael@0: * is increased, if necessary, to accommodate the additional char.
michael@0: *
michael@0: * @param ch the char to be appended.
michael@0: */
michael@0: public void append(char ch) {
michael@0: int newlen = this.len + 1;
michael@0: if (newlen > this.buffer.length) {
michael@0: expand(newlen);
michael@0: }
michael@0: this.buffer[this.len] = ch;
michael@0: this.len = newlen;
michael@0: }
michael@0:
michael@0: /**
michael@0: * Appends len
bytes to this buffer from the given source
michael@0: * array starting at index off
. The capacity of the buffer
michael@0: * is increased, if necessary, to accommodate all len
bytes.
michael@0: *
michael@0: * The bytes are converted to chars using simple cast.
michael@0: *
michael@0: * @param b the bytes to be appended.
michael@0: * @param off the index of the first byte to append.
michael@0: * @param len the number of bytes to append.
michael@0: * @throws IndexOutOfBoundsException if off
is out of
michael@0: * range, len
is negative, or
michael@0: * off
+ len
is out of range.
michael@0: */
michael@0: public void append(final byte[] b, int off, int len) {
michael@0: if (b == null) {
michael@0: return;
michael@0: }
michael@0: if ((off < 0) || (off > b.length) || (len < 0) ||
michael@0: ((off + len) < 0) || ((off + len) > b.length)) {
michael@0: throw new IndexOutOfBoundsException("off: "+off+" len: "+len+" b.length: "+b.length);
michael@0: }
michael@0: if (len == 0) {
michael@0: return;
michael@0: }
michael@0: int oldlen = this.len;
michael@0: int newlen = oldlen + len;
michael@0: if (newlen > this.buffer.length) {
michael@0: expand(newlen);
michael@0: }
michael@0: for (int i1 = off, i2 = oldlen; i2 < newlen; i1++, i2++) {
michael@0: this.buffer[i2] = (char) (b[i1] & 0xff);
michael@0: }
michael@0: this.len = newlen;
michael@0: }
michael@0:
michael@0: /**
michael@0: * Appends len
bytes to this buffer from the given source
michael@0: * array starting at index off
. The capacity of the buffer
michael@0: * is increased, if necessary, to accommodate all len
bytes.
michael@0: *
michael@0: * The bytes are converted to chars using simple cast.
michael@0: *
michael@0: * @param b the bytes to be appended.
michael@0: * @param off the index of the first byte to append.
michael@0: * @param len the number of bytes to append.
michael@0: * @throws IndexOutOfBoundsException if off
is out of
michael@0: * range, len
is negative, or
michael@0: * off
+ len
is out of range.
michael@0: */
michael@0: public void append(final ByteArrayBuffer b, int off, int len) {
michael@0: if (b == null) {
michael@0: return;
michael@0: }
michael@0: append(b.buffer(), off, len);
michael@0: }
michael@0:
michael@0: /**
michael@0: * Appends chars of the textual representation of the given object to this
michael@0: * buffer. The capacity of the buffer is increased, if necessary, to
michael@0: * accommodate all chars.
michael@0: *
michael@0: * @param obj the object.
michael@0: */
michael@0: public void append(final Object obj) {
michael@0: append(String.valueOf(obj));
michael@0: }
michael@0:
michael@0: /**
michael@0: * Clears content of the buffer. The underlying char array is not resized.
michael@0: */
michael@0: public void clear() {
michael@0: this.len = 0;
michael@0: }
michael@0:
michael@0: /**
michael@0: * Converts the content of this buffer to an array of chars.
michael@0: *
michael@0: * @return char array
michael@0: */
michael@0: public char[] toCharArray() {
michael@0: char[] b = new char[this.len];
michael@0: if (this.len > 0) {
michael@0: System.arraycopy(this.buffer, 0, b, 0, this.len);
michael@0: }
michael@0: return b;
michael@0: }
michael@0:
michael@0: /**
michael@0: * Returns the char
value in this buffer at the specified
michael@0: * index. The index argument must be greater than or equal to
michael@0: * 0
, and less than the length of this buffer.
michael@0: *
michael@0: * @param i the index of the desired char value.
michael@0: * @return the char value at the specified index.
michael@0: * @throws IndexOutOfBoundsException if index
is
michael@0: * negative or greater than or equal to {@link #length()}.
michael@0: */
michael@0: public char charAt(int i) {
michael@0: return this.buffer[i];
michael@0: }
michael@0:
michael@0: /**
michael@0: * Returns reference to the underlying char array.
michael@0: *
michael@0: * @return the char array.
michael@0: */
michael@0: public char[] buffer() {
michael@0: return this.buffer;
michael@0: }
michael@0:
michael@0: /**
michael@0: * Returns the current capacity. The capacity is the amount of storage
michael@0: * available for newly appended chars, beyond which an allocation will
michael@0: * occur.
michael@0: *
michael@0: * @return the current capacity
michael@0: */
michael@0: public int capacity() {
michael@0: return this.buffer.length;
michael@0: }
michael@0:
michael@0: /**
michael@0: * Returns the length of the buffer (char count).
michael@0: *
michael@0: * @return the length of the buffer
michael@0: */
michael@0: public int length() {
michael@0: return this.len;
michael@0: }
michael@0:
michael@0: /**
michael@0: * Ensures that the capacity is at least equal to the specified minimum.
michael@0: * If the current capacity is less than the argument, then a new internal
michael@0: * array is allocated with greater capacity. If the required
michael@0: * argument is non-positive, this method takes no action.
michael@0: *
michael@0: * @param required the minimum required capacity.
michael@0: */
michael@0: public void ensureCapacity(int required) {
michael@0: if (required <= 0) {
michael@0: return;
michael@0: }
michael@0: int available = this.buffer.length - this.len;
michael@0: if (required > available) {
michael@0: expand(this.len + required);
michael@0: }
michael@0: }
michael@0:
michael@0: /**
michael@0: * Sets the length of the buffer. The new length value is expected to be
michael@0: * less than the current capacity and greater than or equal to
michael@0: * 0
.
michael@0: *
michael@0: * @param len the new length
michael@0: * @throws IndexOutOfBoundsException if the
michael@0: * len
argument is greater than the current
michael@0: * capacity of the buffer or less than 0
.
michael@0: */
michael@0: public void setLength(int len) {
michael@0: if (len < 0 || len > this.buffer.length) {
michael@0: throw new IndexOutOfBoundsException("len: "+len+" < 0 or > buffer len: "+this.buffer.length);
michael@0: }
michael@0: this.len = len;
michael@0: }
michael@0:
michael@0: /**
michael@0: * Returns true
if this buffer is empty, that is, its
michael@0: * {@link #length()} is equal to 0
.
michael@0: * @return true
if this buffer is empty, false
michael@0: * otherwise.
michael@0: */
michael@0: public boolean isEmpty() {
michael@0: return this.len == 0;
michael@0: }
michael@0:
michael@0: /**
michael@0: * Returns true
if this buffer is full, that is, its
michael@0: * {@link #length()} is equal to its {@link #capacity()}.
michael@0: * @return true
if this buffer is full, false
michael@0: * otherwise.
michael@0: */
michael@0: public boolean isFull() {
michael@0: return this.len == this.buffer.length;
michael@0: }
michael@0:
michael@0: /**
michael@0: * Returns the index within this buffer of the first occurrence of the
michael@0: * specified character, starting the search at the specified
michael@0: * beginIndex
and finishing at endIndex
.
michael@0: * If no such character occurs in this buffer within the specified bounds,
michael@0: * -1
is returned.
michael@0: *
michael@0: * There is no restriction on the value of beginIndex
and
michael@0: * endIndex
. If beginIndex
is negative,
michael@0: * it has the same effect as if it were zero. If endIndex
is
michael@0: * greater than {@link #length()}, it has the same effect as if it were
michael@0: * {@link #length()}. If the beginIndex
is greater than
michael@0: * the endIndex
, -1
is returned.
michael@0: *
michael@0: * @param ch the char to search for.
michael@0: * @param beginIndex the index to start the search from.
michael@0: * @param endIndex the index to finish the search at.
michael@0: * @return the index of the first occurrence of the character in the buffer
michael@0: * within the given bounds, or -1
if the character does
michael@0: * not occur.
michael@0: */
michael@0: public int indexOf(int ch, int beginIndex, int endIndex) {
michael@0: if (beginIndex < 0) {
michael@0: beginIndex = 0;
michael@0: }
michael@0: if (endIndex > this.len) {
michael@0: endIndex = this.len;
michael@0: }
michael@0: if (beginIndex > endIndex) {
michael@0: return -1;
michael@0: }
michael@0: for (int i = beginIndex; i < endIndex; i++) {
michael@0: if (this.buffer[i] == ch) {
michael@0: return i;
michael@0: }
michael@0: }
michael@0: return -1;
michael@0: }
michael@0:
michael@0: /**
michael@0: * Returns the index within this buffer of the first occurrence of the
michael@0: * specified character, starting the search at 0
and finishing
michael@0: * at {@link #length()}. If no such character occurs in this buffer within
michael@0: * those bounds, -1
is returned.
michael@0: *
michael@0: * @param ch the char to search for.
michael@0: * @return the index of the first occurrence of the character in the
michael@0: * buffer, or -1
if the character does not occur.
michael@0: */
michael@0: public int indexOf(int ch) {
michael@0: return indexOf(ch, 0, this.len);
michael@0: }
michael@0:
michael@0: /**
michael@0: * Returns a substring of this buffer. The substring begins at the specified
michael@0: * beginIndex
and extends to the character at index
michael@0: * endIndex - 1
.
michael@0: *
michael@0: * @param beginIndex the beginning index, inclusive.
michael@0: * @param endIndex the ending index, exclusive.
michael@0: * @return the specified substring.
michael@0: * @exception StringIndexOutOfBoundsException if the
michael@0: * beginIndex
is negative, or
michael@0: * endIndex
is larger than the length of this
michael@0: * buffer, or beginIndex
is larger than
michael@0: * endIndex
.
michael@0: */
michael@0: public String substring(int beginIndex, int endIndex) {
michael@0: return new String(this.buffer, beginIndex, endIndex - beginIndex);
michael@0: }
michael@0:
michael@0: /**
michael@0: * Returns a substring of this buffer with leading and trailing whitespace
michael@0: * omitted. The substring begins with the first non-whitespace character
michael@0: * from beginIndex
and extends to the last
michael@0: * non-whitespace character with the index lesser than
michael@0: * endIndex
.
michael@0: *
michael@0: * @param beginIndex the beginning index, inclusive.
michael@0: * @param endIndex the ending index, exclusive.
michael@0: * @return the specified substring.
michael@0: * @exception IndexOutOfBoundsException if the
michael@0: * beginIndex
is negative, or
michael@0: * endIndex
is larger than the length of this
michael@0: * buffer, or beginIndex
is larger than
michael@0: * endIndex
.
michael@0: */
michael@0: public String substringTrimmed(int beginIndex, int endIndex) {
michael@0: if (beginIndex < 0) {
michael@0: throw new IndexOutOfBoundsException("Negative beginIndex: "+beginIndex);
michael@0: }
michael@0: if (endIndex > this.len) {
michael@0: throw new IndexOutOfBoundsException("endIndex: "+endIndex+" > length: "+this.len);
michael@0: }
michael@0: if (beginIndex > endIndex) {
michael@0: throw new IndexOutOfBoundsException("beginIndex: "+beginIndex+" > endIndex: "+endIndex);
michael@0: }
michael@0: while (beginIndex < endIndex && HTTP.isWhitespace(this.buffer[beginIndex])) {
michael@0: beginIndex++;
michael@0: }
michael@0: while (endIndex > beginIndex && HTTP.isWhitespace(this.buffer[endIndex - 1])) {
michael@0: endIndex--;
michael@0: }
michael@0: return new String(this.buffer, beginIndex, endIndex - beginIndex);
michael@0: }
michael@0:
michael@0: public String toString() {
michael@0: return new String(this.buffer, 0, this.len);
michael@0: }
michael@0:
michael@0: }