All Downloads are FREE. Search and download functionalities are using the official Maven repository.

java.nio.Buffer Maven / Gradle / Ivy

There is a newer version: 1.14.0
Show newest version
/* Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package java.nio;

/**
 * A buffer is a list of elements of a specific primitive type.
 * 

* A buffer can be described by the following properties: *

    *
  • Capacity: the number of elements a buffer can hold. Capacity may not be * negative and never changes.
  • *
  • Position: a cursor of this buffer. Elements are read or written at the * position if you do not specify an index explicitly. Position may not be * negative and not greater than the limit.
  • *
  • Limit: controls the scope of accessible elements. You can only read or * write elements from index zero to limit - 1. Accessing * elements out of the scope will cause an exception. Limit may not be negative * and not greater than capacity.
  • *
  • Mark: used to remember the current position, so that you can reset the * position later. Mark may not be negative and no greater than position.
  • *
  • A buffer can be read-only or read-write. Trying to modify the elements * of a read-only buffer will cause a ReadOnlyBufferException, * while changing the position, limit and mark of a read-only buffer is OK.
  • *
  • A buffer can be direct or indirect. A direct buffer will try its best to * take advantage of native memory APIs and it may not stay in the Java heap, * thus it is not affected by garbage collection.
  • *
*

* Buffers are not thread-safe. If concurrent access to a buffer instance is * required, then the callers are responsible to take care of the * synchronization issues. */ public abstract class Buffer { /** * UNSET_MARK means the mark has not been set. */ static final int UNSET_MARK = -1; /** * The capacity of this buffer, which never changes. */ final int capacity; /** * limit - 1 is the last element that can be read or written. * Limit must be no less than zero and no greater than capacity. */ int limit; /** * Mark is where position will be set when reset() is called. * Mark is not set by default. Mark is always no less than zero and no * greater than position. */ int mark = UNSET_MARK; /** * The current position of this buffer. Position is always no less than zero * and no greater than limit. */ int position = 0; /** * The log base 2 of the element size of this buffer. Each typed subclass * (ByteBuffer, CharBuffer, etc.) is responsible for initializing this * value. The value is used by JNI code in frameworks/base/ to avoid the * need for costly 'instanceof' tests. */ final int _elementSizeShift; /** * For direct buffers, the effective address of the data; zero otherwise. * This is set in the constructor. * TODO: make this final at the cost of loads of extra constructors? [how many?] */ long effectiveDirectAddress; /** * For direct buffers, the underlying MemoryBlock; null otherwise. */ final MemoryBlock block; Buffer(int elementSizeShift, int capacity, MemoryBlock block) { this._elementSizeShift = elementSizeShift; if (capacity < 0) { throw new IllegalArgumentException("capacity < 0: " + capacity); } this.capacity = this.limit = capacity; this.block = block; } /** * Returns the array that backs this buffer (optional operation). * The returned value is the actual array, not a copy, so modifications * to the array write through to the buffer. * *

Subclasses should override this method with a covariant return type * to provide the exact type of the array. * *

Use {@code hasArray} to ensure this method won't throw. * (A separate call to {@code isReadOnly} is not necessary.) * * @return the array * @throws ReadOnlyBufferException if the buffer is read-only * UnsupportedOperationException if the buffer does not expose an array * @since 1.6 */ public abstract Object array(); /** * Returns the offset into the array returned by {@code array} of the first * element of the buffer (optional operation). The backing array (if there is one) * is not necessarily the same size as the buffer, and position 0 in the buffer is * not necessarily the 0th element in the array. Use * {@code buffer.array()[offset + buffer.arrayOffset()} to access element {@code offset} * in {@code buffer}. * *

Use {@code hasArray} to ensure this method won't throw. * (A separate call to {@code isReadOnly} is not necessary.) * * @return the offset * @throws ReadOnlyBufferException if the buffer is read-only * UnsupportedOperationException if the buffer does not expose an array * @since 1.6 */ public abstract int arrayOffset(); /** * Returns the capacity of this buffer. * * @return the number of elements that are contained in this buffer. */ public final int capacity() { return capacity; } /** * Used for the scalar get/put operations. */ void checkIndex(int index) { if (index < 0 || index >= limit) { throw new IndexOutOfBoundsException("index=" + index + ", limit=" + limit); } } /** * Used for the ByteBuffer operations that get types larger than a byte. */ void checkIndex(int index, int sizeOfType) { if (index < 0 || index > limit - sizeOfType) { throw new IndexOutOfBoundsException("index=" + index + ", limit=" + limit + ", size of type=" + sizeOfType); } } int checkGetBounds(int bytesPerElement, int length, int offset, int count) { int byteCount = bytesPerElement * count; if ((offset | count) < 0 || offset > length || length - offset < count) { throw new IndexOutOfBoundsException("offset=" + offset + ", count=" + count + ", length=" + length); } if (byteCount > remaining()) { throw new BufferUnderflowException(); } return byteCount; } int checkPutBounds(int bytesPerElement, int length, int offset, int count) { int byteCount = bytesPerElement * count; if ((offset | count) < 0 || offset > length || length - offset < count) { throw new IndexOutOfBoundsException("offset=" + offset + ", count=" + count + ", length=" + length); } if (byteCount > remaining()) { throw new BufferOverflowException(); } if (isReadOnly()) { throw new ReadOnlyBufferException(); } return byteCount; } void checkStartEndRemaining(int start, int end) { if (end < start || start < 0 || end > remaining()) { throw new IndexOutOfBoundsException("start=" + start + ", end=" + end + ", remaining()=" + remaining()); } } /** * Clears this buffer. *

* While the content of this buffer is not changed, the following internal * changes take place: the current position is reset back to the start of * the buffer, the value of the buffer limit is made equal to the capacity * and mark is cleared. * * @return this buffer. */ public final Buffer clear() { position = 0; mark = UNSET_MARK; limit = capacity; return this; } /** * Flips this buffer. *

* The limit is set to the current position, then the position is set to * zero, and the mark is cleared. *

* The content of this buffer is not changed. * * @return this buffer. */ public final Buffer flip() { limit = position; position = 0; mark = UNSET_MARK; return this; } /** * Returns true if {@code array} and {@code arrayOffset} won't throw. This method does not * return true for buffers not backed by arrays because the other methods would throw * {@code UnsupportedOperationException}, nor does it return true for buffers backed by * read-only arrays, because the other methods would throw {@code ReadOnlyBufferException}. * @since 1.6 */ public abstract boolean hasArray(); /** * Indicates if there are elements remaining in this buffer, that is if * {@code position < limit}. * * @return {@code true} if there are elements remaining in this buffer, * {@code false} otherwise. */ public final boolean hasRemaining() { return position < limit; } /** * Returns true if this is a direct buffer. * @since 1.6 */ public abstract boolean isDirect(); /** * Indicates whether this buffer is read-only. * * @return {@code true} if this buffer is read-only, {@code false} * otherwise. */ public abstract boolean isReadOnly(); final void checkWritable() { if (isReadOnly()) { throw new IllegalArgumentException("Read-only buffer"); } } /** * Returns the limit of this buffer. * * @return the limit of this buffer. */ public final int limit() { return limit; } /** * Sets the limit of this buffer. *

* If the current position in the buffer is in excess of * newLimit then, on returning from this call, it will have * been adjusted to be equivalent to newLimit. If the mark * is set and is greater than the new limit, then it is cleared. * * @param newLimit * the new limit, must not be negative and not greater than * capacity. * @return this buffer. * @exception IllegalArgumentException * if newLimit is invalid. */ public final Buffer limit(int newLimit) { if (newLimit < 0 || newLimit > capacity) { throw new IllegalArgumentException("Bad limit (capacity " + capacity + "): " + newLimit); } limit = newLimit; if (position > newLimit) { position = newLimit; } if ((mark != UNSET_MARK) && (mark > newLimit)) { mark = UNSET_MARK; } return this; } /** * Marks the current position, so that the position may return to this point * later by calling reset(). * * @return this buffer. */ public final Buffer mark() { mark = position; return this; } /** * Returns the position of this buffer. * * @return the value of this buffer's current position. */ public final int position() { return position; } /** * Sets the position of this buffer. *

* If the mark is set and it is greater than the new position, then it is * cleared. * * @param newPosition * the new position, must be not negative and not greater than * limit. * @return this buffer. * @exception IllegalArgumentException * if newPosition is invalid. */ public final Buffer position(int newPosition) { positionImpl(newPosition); return this; } void positionImpl(int newPosition) { if (newPosition < 0 || newPosition > limit) { throw new IllegalArgumentException("Bad position (limit " + limit + "): " + newPosition); } position = newPosition; if ((mark != UNSET_MARK) && (mark > position)) { mark = UNSET_MARK; } } /** * Returns the number of remaining elements in this buffer, that is * {@code limit - position}. * * @return the number of remaining elements in this buffer. */ public final int remaining() { return limit - position; } /** * Resets the position of this buffer to the mark. * * @return this buffer. * @exception InvalidMarkException * if the mark is not set. */ public final Buffer reset() { if (mark == UNSET_MARK) { throw new InvalidMarkException("Mark not set"); } position = mark; return this; } /** * Rewinds this buffer. *

* The position is set to zero, and the mark is cleared. The content of this * buffer is not changed. * * @return this buffer. */ public final Buffer rewind() { position = 0; mark = UNSET_MARK; return this; } /** * Returns a string describing this buffer. */ @Override public String toString() { return getClass().getName() + "[position=" + position + ",limit=" + limit + ",capacity=" + capacity + "]"; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy