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
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: * @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
if 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 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 b
byte to this buffer. The capacity of the buffer
michael@0: * is increased, if necessary, to accommodate the additional byte.
michael@0: *
michael@0: * @param b the byte to be appended.
michael@0: */
michael@0: public void append(int b) {
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] = (byte)b;
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: * 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: * The chars are converted to bytes using simple cast.
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 bytes to append.
michael@0: * @throws IndexOutOfBoundsException if off
if 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 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] = (byte) b[i1];
michael@0: }
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: * char array buffer starting at index off
. The capacity
michael@0: * of the buffer is increased if necessary to accommodate all
michael@0: * len
chars.
michael@0: *
michael@0: * The chars are converted to bytes using simple cast.
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 bytes to append.
michael@0: * @throws IndexOutOfBoundsException if off
if 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: * Clears content of the buffer. The underlying byte 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 bytes.
michael@0: *
michael@0: * @return byte array
michael@0: */
michael@0: public byte[] toByteArray() {
michael@0: byte[] b = new byte[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 byte
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 byte value.
michael@0: * @return the byte 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 int byteAt(int i) {
michael@0: return this.buffer[i];
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 bytes, beyond which an allocation
michael@0: * will 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 (byte 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: * @since 4.1
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: * Returns reference to the underlying byte array.
michael@0: *
michael@0: * @return the byte array.
michael@0: */
michael@0: public byte[] buffer() {
michael@0: return this.buffer;
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 byte, starting the search at the specified
michael@0: * beginIndex
and finishing at endIndex
.
michael@0: * If no such byte 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 b the byte 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 byte in the buffer
michael@0: * within the given bounds, or -1
if the byte does
michael@0: * not occur.
michael@0: *
michael@0: * @since 4.1
michael@0: */
michael@0: public int indexOf(byte b, 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] == b) {
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 byte, starting the search at 0
and finishing
michael@0: * at {@link #length()}. If no such byte occurs in this buffer within
michael@0: * those bounds, -1
is returned.
michael@0: *
michael@0: * @param b the byte to search for.
michael@0: * @return the index of the first occurrence of the byte in the
michael@0: * buffer, or -1
if the byte does not occur.
michael@0: *
michael@0: * @since 4.1
michael@0: */
michael@0: public int indexOf(byte b) {
michael@0: return indexOf(b, 0, this.len);
michael@0: }
michael@0: }