Home | History | Annotate | Download | only in nio
      1 /* Licensed to the Apache Software Foundation (ASF) under one or more
      2  * contributor license agreements.  See the NOTICE file distributed with
      3  * this work for additional information regarding copyright ownership.
      4  * The ASF licenses this file to You under the Apache License, Version 2.0
      5  * (the "License"); you may not use this file except in compliance with
      6  * the License.  You may obtain a copy of the License at
      7  *
      8  *     http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package java.nio;
     18 
     19 /**
     20  * A buffer is a list of elements of a specific primitive type.
     21  * <p>
     22  * A buffer can be described by the following properties:
     23  * <ul>
     24  * <li>Capacity: the number of elements a buffer can hold. Capacity may not be
     25  * negative and never changes.</li>
     26  * <li>Position: a cursor of this buffer. Elements are read or written at the
     27  * position if you do not specify an index explicitly. Position may not be
     28  * negative and not greater than the limit.</li>
     29  * <li>Limit: controls the scope of accessible elements. You can only read or
     30  * write elements from index zero to <code>limit - 1</code>. Accessing
     31  * elements out of the scope will cause an exception. Limit may not be negative
     32  * and not greater than capacity.</li>
     33  * <li>Mark: used to remember the current position, so that you can reset the
     34  * position later. Mark may not be negative and no greater than position.</li>
     35  * <li>A buffer can be read-only or read-write. Trying to modify the elements
     36  * of a read-only buffer will cause a <code>ReadOnlyBufferException</code>,
     37  * while changing the position, limit and mark of a read-only buffer is OK.</li>
     38  * <li>A buffer can be direct or indirect. A direct buffer will try its best to
     39  * take advantage of native memory APIs and it may not stay in the Java heap,
     40  * thus it is not affected by garbage collection.</li>
     41  * </ul>
     42  * <p>
     43  * Buffers are not thread-safe. If concurrent access to a buffer instance is
     44  * required, then the callers are responsible to take care of the
     45  * synchronization issues.
     46  */
     47 public abstract class Buffer {
     48 
     49     /**
     50      * <code>UNSET_MARK</code> means the mark has not been set.
     51      */
     52     final static int UNSET_MARK = -1;
     53 
     54     /**
     55      * The capacity of this buffer, which never changes.
     56      */
     57     final int capacity;
     58 
     59     /**
     60      * <code>limit - 1</code> is the last element that can be read or written.
     61      * Limit must be no less than zero and no greater than <code>capacity</code>.
     62      */
     63     int limit;
     64 
     65     /**
     66      * Mark is where position will be set when <code>reset()</code> is called.
     67      * Mark is not set by default. Mark is always no less than zero and no
     68      * greater than <code>position</code>.
     69      */
     70     int mark = UNSET_MARK;
     71 
     72     /**
     73      * The current position of this buffer. Position is always no less than zero
     74      * and no greater than <code>limit</code>.
     75      */
     76     int position = 0;
     77 
     78     // BEGIN android-added
     79     /**
     80      * The log base 2 of the element size of this buffer.  Each typed subclass
     81      * (ByteBuffer, CharBuffer, etc.) is responsible for initializing this
     82      * value.  The value is used by JNI code in frameworks/base/ to avoid the
     83      * need for costly 'instanceof' tests.
     84      */
     85     int _elementSizeShift;
     86 
     87     /**
     88      * For direct buffers, the effective address of the data.  This is set
     89      * on first use.  If the field is zero, this is either not a direct
     90      * buffer or the field has not been initialized, and you need to issue
     91      * the getEffectiveAddress() call and use the result of that.
     92      *
     93      * This is an optimization used by the GetDirectBufferAddress JNI call.
     94      */
     95     int effectiveDirectAddress = 0;
     96     // END android-added
     97 
     98     /**
     99      * Construct a buffer with the specified capacity.
    100      *
    101      * @param capacity
    102      *            The capacity of this buffer
    103      */
    104     Buffer(int capacity) {
    105         super();
    106         if (capacity < 0) {
    107             throw new IllegalArgumentException();
    108         }
    109         this.capacity = this.limit = capacity;
    110     }
    111 
    112     /**
    113      * Returns the array that backs this buffer (optional operation).
    114      * The returned value is the actual array, not a copy, so modifications
    115      * to the array write through to the buffer.
    116      *
    117      * <p>Subclasses should override this method with a covariant return type
    118      * to provide the exact type of the array.
    119      *
    120      * <p>Use {@code hasArray} to ensure this method won't throw.
    121      * (A separate call to {@code isReadOnly} is not necessary.)
    122      *
    123      * @return the array
    124      * @throws ReadOnlyBufferException if the buffer is read-only
    125      *         UnsupportedOperationException if the buffer does not expose an array
    126      * @since 1.6
    127      */
    128     public abstract Object array();
    129 
    130     /**
    131      * Returns the offset into the array returned by {@code array} of the first
    132      * element of the buffer (optional operation). The backing array (if there is one)
    133      * is not necessarily the same size as the buffer, and position 0 in the buffer is
    134      * not necessarily the 0th element in the array. Use
    135      * {@code buffer.array()[offset + buffer.arrayOffset()} to access element {@code offset}
    136      * in {@code buffer}.
    137      *
    138      * <p>Use {@code hasArray} to ensure this method won't throw.
    139      * (A separate call to {@code isReadOnly} is not necessary.)
    140      *
    141      * @return the offset
    142      * @throws ReadOnlyBufferException if the buffer is read-only
    143      *         UnsupportedOperationException if the buffer does not expose an array
    144      * @since 1.6
    145      */
    146     public abstract int arrayOffset();
    147 
    148     /**
    149      * Returns the capacity of this buffer.
    150      *
    151      * @return the number of elements that are contained in this buffer.
    152      */
    153     public final int capacity() {
    154         return capacity;
    155     }
    156 
    157     /**
    158      * Clears this buffer.
    159      * <p>
    160      * While the content of this buffer is not changed, the following internal
    161      * changes take place: the current position is reset back to the start of
    162      * the buffer, the value of the buffer limit is made equal to the capacity
    163      * and mark is cleared.
    164      *
    165      * @return this buffer.
    166      */
    167     public final Buffer clear() {
    168         position = 0;
    169         mark = UNSET_MARK;
    170         limit = capacity;
    171         return this;
    172     }
    173 
    174     /**
    175      * Flips this buffer.
    176      * <p>
    177      * The limit is set to the current position, then the position is set to
    178      * zero, and the mark is cleared.
    179      * <p>
    180      * The content of this buffer is not changed.
    181      *
    182      * @return this buffer.
    183      */
    184     public final Buffer flip() {
    185         limit = position;
    186         position = 0;
    187         mark = UNSET_MARK;
    188         return this;
    189     }
    190 
    191     /**
    192      * Returns true if {@code array} and {@code arrayOffset} won't throw. This method does not
    193      * return true for buffers not backed by arrays because the other methods would throw
    194      * {@code UnsupportedOperationException}, nor does it return true for buffers backed by
    195      * read-only arrays, because the other methods would throw {@code ReadOnlyBufferException}.
    196      * @since 1.6
    197      */
    198     public abstract boolean hasArray();
    199 
    200     /**
    201      * Indicates if there are elements remaining in this buffer, that is if
    202      * {@code position < limit}.
    203      *
    204      * @return {@code true} if there are elements remaining in this buffer,
    205      *         {@code false} otherwise.
    206      */
    207     public final boolean hasRemaining() {
    208         return position < limit;
    209     }
    210 
    211     /**
    212      * Returns true if this is a direct buffer.
    213      * @since 1.6
    214      */
    215     public abstract boolean isDirect();
    216 
    217     /**
    218      * Indicates whether this buffer is read-only.
    219      *
    220      * @return {@code true} if this buffer is read-only, {@code false}
    221      *         otherwise.
    222      */
    223     public abstract boolean isReadOnly();
    224 
    225     /**
    226      * Returns the limit of this buffer.
    227      *
    228      * @return the limit of this buffer.
    229      */
    230     public final int limit() {
    231         return limit;
    232     }
    233 
    234     /**
    235      * Sets the limit of this buffer.
    236      * <p>
    237      * If the current position in the buffer is in excess of
    238      * <code>newLimit</code> then, on returning from this call, it will have
    239      * been adjusted to be equivalent to <code>newLimit</code>. If the mark
    240      * is set and is greater than the new limit, then it is cleared.
    241      *
    242      * @param newLimit
    243      *            the new limit, must not be negative and not greater than
    244      *            capacity.
    245      * @return this buffer.
    246      * @exception IllegalArgumentException
    247      *                if <code>newLimit</code> is invalid.
    248      */
    249     public final Buffer limit(int newLimit) {
    250         if (newLimit < 0 || newLimit > capacity) {
    251             throw new IllegalArgumentException();
    252         }
    253 
    254         limit = newLimit;
    255         if (position > newLimit) {
    256             position = newLimit;
    257         }
    258         if ((mark != UNSET_MARK) && (mark > newLimit)) {
    259             mark = UNSET_MARK;
    260         }
    261         return this;
    262     }
    263 
    264     /**
    265      * Marks the current position, so that the position may return to this point
    266      * later by calling <code>reset()</code>.
    267      *
    268      * @return this buffer.
    269      */
    270     public final Buffer mark() {
    271         mark = position;
    272         return this;
    273     }
    274 
    275     /**
    276      * Returns the position of this buffer.
    277      *
    278      * @return the value of this buffer's current position.
    279      */
    280     public final int position() {
    281         return position;
    282     }
    283 
    284     /**
    285      * Sets the position of this buffer.
    286      * <p>
    287      * If the mark is set and it is greater than the new position, then it is
    288      * cleared.
    289      *
    290      * @param newPosition
    291      *            the new position, must be not negative and not greater than
    292      *            limit.
    293      * @return this buffer.
    294      * @exception IllegalArgumentException
    295      *                if <code>newPosition</code> is invalid.
    296      */
    297     public final Buffer position(int newPosition) {
    298         if (newPosition < 0 || newPosition > limit) {
    299             throw new IllegalArgumentException();
    300         }
    301 
    302         position = newPosition;
    303         if ((mark != UNSET_MARK) && (mark > position)) {
    304             mark = UNSET_MARK;
    305         }
    306         return this;
    307     }
    308 
    309     /**
    310      * Returns the number of remaining elements in this buffer, that is
    311      * {@code limit - position}.
    312      *
    313      * @return the number of remaining elements in this buffer.
    314      */
    315     public final int remaining() {
    316         return limit - position;
    317     }
    318 
    319     /**
    320      * Resets the position of this buffer to the <code>mark</code>.
    321      *
    322      * @return this buffer.
    323      * @exception InvalidMarkException
    324      *                if the mark is not set.
    325      */
    326     public final Buffer reset() {
    327         if (mark == UNSET_MARK) {
    328             throw new InvalidMarkException();
    329         }
    330         position = mark;
    331         return this;
    332     }
    333 
    334     /**
    335      * Rewinds this buffer.
    336      * <p>
    337      * The position is set to zero, and the mark is cleared. The content of this
    338      * buffer is not changed.
    339      *
    340      * @return this buffer.
    341      */
    342     public final Buffer rewind() {
    343         position = 0;
    344         mark = UNSET_MARK;
    345         return this;
    346     }
    347 }
    348