Home | History | Annotate | Download | only in nio
      1 /*
      2  *  Licensed to the Apache Software Foundation (ASF) under one or more
      3  *  contributor license agreements.  See the NOTICE file distributed with
      4  *  this work for additional information regarding copyright ownership.
      5  *  The ASF licenses this file to You under the Apache License, Version 2.0
      6  *  (the "License"); you may not use this file except in compliance with
      7  *  the License.  You may obtain a copy of the License at
      8  *
      9  *     http://www.apache.org/licenses/LICENSE-2.0
     10  *
     11  *  Unless required by applicable law or agreed to in writing, software
     12  *  distributed under the License is distributed on an "AS IS" BASIS,
     13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14  *  See the License for the specific language governing permissions and
     15  *  limitations under the License.
     16  */
     17 
     18 package java.nio;
     19 
     20 import java.util.Arrays;
     21 import libcore.io.Memory;
     22 
     23 /**
     24  * A buffer for bytes.
     25  * <p>
     26  * A byte buffer can be created in either one of the following ways:
     27  * <ul>
     28  * <li>{@link #allocate(int) Allocate} a new byte array and create a buffer
     29  * based on it;</li>
     30  * <li>{@link #allocateDirect(int) Allocate} a memory block and create a direct
     31  * buffer based on it;</li>
     32  * <li>{@link #wrap(byte[]) Wrap} an existing byte array to create a new
     33  * buffer.</li>
     34  * </ul>
     35  *
     36  */
     37 public abstract class ByteBuffer extends Buffer implements Comparable<ByteBuffer> {
     38     /**
     39      * The byte order of this buffer, default is {@code BIG_ENDIAN}.
     40      */
     41     ByteOrder order = ByteOrder.BIG_ENDIAN;
     42 
     43     /**
     44      * Creates a byte buffer based on a newly allocated byte array.
     45      *
     46      * @param capacity
     47      *            the capacity of the new buffer
     48      * @return the created byte buffer.
     49      * @throws IllegalArgumentException
     50      *             if {@code capacity < 0}.
     51      */
     52     public static ByteBuffer allocate(int capacity) {
     53         if (capacity < 0) {
     54             throw new IllegalArgumentException("capacity < 0: " + capacity);
     55         }
     56         return new ByteArrayBuffer(new byte[capacity]);
     57     }
     58 
     59     /**
     60      * Creates a direct byte buffer based on a newly allocated memory block.
     61      *
     62      * @param capacity
     63      *            the capacity of the new buffer
     64      * @return the created byte buffer.
     65      * @throws IllegalArgumentException
     66      *             if {@code capacity < 0}.
     67      */
     68     public static ByteBuffer allocateDirect(int capacity) {
     69         if (capacity < 0) {
     70             throw new IllegalArgumentException("capacity < 0: " + capacity);
     71         }
     72         // Ensure alignment by 8.
     73         MemoryBlock memoryBlock = MemoryBlock.allocate(capacity + 7);
     74         long address = memoryBlock.toLong();
     75         long alignedAddress = (address + 7) & ~(long)7;
     76         return new DirectByteBuffer(memoryBlock, capacity, (int)(alignedAddress - address), false, null);
     77     }
     78 
     79     /**
     80      * Creates a new byte buffer by wrapping the given byte array.
     81      * <p>
     82      * Calling this method has the same effect as
     83      * {@code wrap(array, 0, array.length)}.
     84      *
     85      * @param array
     86      *            the byte array which the new buffer will be based on
     87      * @return the created byte buffer.
     88      */
     89     public static ByteBuffer wrap(byte[] array) {
     90         return new ByteArrayBuffer(array);
     91     }
     92 
     93     /**
     94      * Creates a new byte buffer by wrapping the given byte array.
     95      * <p>
     96      * The new buffer's position will be {@code start}, limit will be
     97      * {@code start + byteCount}, capacity will be the length of the array.
     98      *
     99      * @param array
    100      *            the byte array which the new buffer will be based on.
    101      * @param start
    102      *            the start index, must not be negative and not greater than
    103      *            {@code array.length}.
    104      * @param byteCount
    105      *            the length, must not be negative and not greater than
    106      *            {@code array.length - start}.
    107      * @return the created byte buffer.
    108      * @throws IndexOutOfBoundsException
    109      *                if either {@code start} or {@code byteCount} is invalid.
    110      */
    111     public static ByteBuffer wrap(byte[] array, int start, int byteCount) {
    112         Arrays.checkOffsetAndCount(array.length, start, byteCount);
    113         ByteBuffer buf = new ByteArrayBuffer(array);
    114         buf.position = start;
    115         buf.limit = start + byteCount;
    116         return buf;
    117     }
    118 
    119     ByteBuffer(int capacity, long effectiveDirectAddress) {
    120         super(0, capacity, effectiveDirectAddress);
    121     }
    122 
    123     /**
    124      * Returns the byte array which this buffer is based on, if there is one.
    125      *
    126      * @return the byte array which this buffer is based on.
    127      * @throws ReadOnlyBufferException
    128      *                if this buffer is based on a read-only array.
    129      * @throws UnsupportedOperationException
    130      *                if this buffer is not based on an array.
    131      */
    132     @Override public final byte[] array() {
    133         return protectedArray();
    134     }
    135 
    136     /**
    137      * Returns the offset of the byte array which this buffer is based on, if
    138      * there is one.
    139      * <p>
    140      * The offset is the index of the array which corresponds to the zero
    141      * position of the buffer.
    142      *
    143      * @return the offset of the byte array which this buffer is based on.
    144      * @throws ReadOnlyBufferException
    145      *                if this buffer is based on a read-only array.
    146      * @throws UnsupportedOperationException
    147      *                if this buffer is not based on an array.
    148      */
    149     @Override public final int arrayOffset() {
    150         return protectedArrayOffset();
    151     }
    152 
    153     /**
    154      * Returns a char buffer which is based on the remaining content of this
    155      * byte buffer.
    156      * <p>
    157      * The new buffer's position is zero, its limit and capacity is the number
    158      * of remaining bytes divided by two, and its mark is not set. The new
    159      * buffer's read-only property and byte order are the same as this buffer's.
    160      * The new buffer is direct if this byte buffer is direct.
    161      * <p>
    162      * The new buffer shares its content with this buffer, which means either
    163      * buffer's change of content will be visible to the other. The two buffers'
    164      * position, limit and mark are independent.
    165      */
    166     public abstract CharBuffer asCharBuffer();
    167 
    168     /**
    169      * Returns a double buffer which is based on the remaining content of this
    170      * byte buffer.
    171      * <p>
    172      * The new buffer's position is zero, its limit and capacity is the number
    173      * of remaining bytes divided by eight, and its mark is not set. The new
    174      * buffer's read-only property and byte order are the same as this buffer's.
    175      * The new buffer is direct if this byte buffer is direct.
    176      * <p>
    177      * The new buffer shares its content with this buffer, which means either
    178      * buffer's change of content will be visible to the other. The two buffers'
    179      * position, limit and mark are independent.
    180      */
    181     public abstract DoubleBuffer asDoubleBuffer();
    182 
    183     /**
    184      * Returns a float buffer which is based on the remaining content of this
    185      * byte buffer.
    186      * <p>
    187      * The new buffer's position is zero, its limit and capacity is the number
    188      * of remaining bytes divided by four, and its mark is not set. The new
    189      * buffer's read-only property and byte order are the same as this buffer's.
    190      * The new buffer is direct if this byte buffer is direct.
    191      * <p>
    192      * The new buffer shares its content with this buffer, which means either
    193      * buffer's change of content will be visible to the other. The two buffers'
    194      * position, limit and mark are independent.
    195      */
    196     public abstract FloatBuffer asFloatBuffer();
    197 
    198     /**
    199      * Returns a int buffer which is based on the remaining content of this byte
    200      * buffer.
    201      * <p>
    202      * The new buffer's position is zero, its limit and capacity is the number
    203      * of remaining bytes divided by four, and its mark is not set. The new
    204      * buffer's read-only property and byte order are the same as this buffer's.
    205      * The new buffer is direct if this byte buffer is direct.
    206      * <p>
    207      * The new buffer shares its content with this buffer, which means either
    208      * buffer's change of content will be visible to the other. The two buffers'
    209      * position, limit and mark are independent.
    210      */
    211     public abstract IntBuffer asIntBuffer();
    212 
    213     /**
    214      * Returns a long buffer which is based on the remaining content of this
    215      * byte buffer.
    216      * <p>
    217      * The new buffer's position is zero, its limit and capacity is the number
    218      * of remaining bytes divided by eight, and its mark is not set. The new
    219      * buffer's read-only property and byte order are the same as this buffer's.
    220      * The new buffer is direct if this byte buffer is direct.
    221      * <p>
    222      * The new buffer shares its content with this buffer, which means either
    223      * buffer's change of content will be visible to the other. The two buffers'
    224      * position, limit and mark are independent.
    225      */
    226     public abstract LongBuffer asLongBuffer();
    227 
    228     /**
    229      * Returns a read-only buffer that shares its content with this buffer.
    230      * <p>
    231      * The returned buffer is guaranteed to be a new instance, even if this
    232      * buffer is read-only itself. The new buffer's position, limit, capacity
    233      * and mark are the same as this buffer.
    234      * <p>
    235      * The new buffer shares its content with this buffer, which means this
    236      * buffer's change of content will be visible to the new buffer. The two
    237      * buffer's position, limit and mark are independent.
    238      *
    239      * @return a read-only version of this buffer.
    240      */
    241     public abstract ByteBuffer asReadOnlyBuffer();
    242 
    243     /**
    244      * Returns a short buffer which is based on the remaining content of this
    245      * byte buffer.
    246      * <p>
    247      * The new buffer's position is zero, its limit and capacity is the number
    248      * of remaining bytes divided by two, and its mark is not set. The new
    249      * buffer's read-only property and byte order are the same as this buffer's.
    250      * The new buffer is direct if this byte buffer is direct.
    251      * <p>
    252      * The new buffer shares its content with this buffer, which means either
    253      * buffer's change of content will be visible to the other. The two buffers'
    254      * position, limit and mark are independent.
    255      */
    256     public abstract ShortBuffer asShortBuffer();
    257 
    258     /**
    259      * Compacts this byte buffer.
    260      * <p>
    261      * The remaining bytes will be moved to the head of the
    262      * buffer, starting from position zero. Then the position is set to
    263      * {@code remaining()}; the limit is set to capacity; the mark is
    264      * cleared.
    265      *
    266      * @return {@code this}
    267      * @throws ReadOnlyBufferException
    268      *                if no changes may be made to the contents of this buffer.
    269      */
    270     public abstract ByteBuffer compact();
    271 
    272     /**
    273      * Compares the remaining bytes of this buffer to another byte buffer's
    274      * remaining bytes.
    275      *
    276      * @param otherBuffer
    277      *            another byte buffer.
    278      * @return a negative value if this is less than {@code other}; 0 if this
    279      *         equals to {@code other}; a positive value if this is greater
    280      *         than {@code other}.
    281      * @throws ClassCastException
    282      *                if {@code other} is not a byte buffer.
    283      */
    284     @Override public int compareTo(ByteBuffer otherBuffer) {
    285         int compareRemaining = (remaining() < otherBuffer.remaining()) ? remaining()
    286                 : otherBuffer.remaining();
    287         int thisPos = position;
    288         int otherPos = otherBuffer.position;
    289         byte thisByte, otherByte;
    290         while (compareRemaining > 0) {
    291             thisByte = get(thisPos);
    292             otherByte = otherBuffer.get(otherPos);
    293             if (thisByte != otherByte) {
    294                 return thisByte < otherByte ? -1 : 1;
    295             }
    296             thisPos++;
    297             otherPos++;
    298             compareRemaining--;
    299         }
    300         return remaining() - otherBuffer.remaining();
    301     }
    302 
    303     /**
    304      * Returns a duplicated buffer that shares its content with this buffer.
    305      * <p>
    306      * The duplicated buffer's position, limit, capacity and mark are the same
    307      * as this buffer's. The duplicated buffer's read-only property is the same
    308      * as this buffer's.
    309      *
    310      * <p>Note that <i>in contrast to all non-{@code byte} buffers</i>,
    311      * byte order is not preserved in the duplicate, and is instead set to
    312      * big-endian.
    313      *
    314      * <p>The new buffer shares its content with this buffer, which means either
    315      * buffer's change of content will be visible to the other. The two buffers'
    316      * position, limit and mark are independent.
    317      */
    318     public abstract ByteBuffer duplicate();
    319 
    320     /**
    321      * Checks whether this byte buffer is equal to another object.
    322      * <p>
    323      * If {@code other} is not a byte buffer then {@code false} is returned. Two
    324      * byte buffers are equal if and only if their remaining bytes are exactly
    325      * the same. Position, limit, capacity and mark are not considered.
    326      *
    327      * @param other
    328      *            the object to compare with this byte buffer.
    329      * @return {@code true} if this byte buffer is equal to {@code other},
    330      *         {@code false} otherwise.
    331      */
    332     @Override
    333     public boolean equals(Object other) {
    334         if (!(other instanceof ByteBuffer)) {
    335             return false;
    336         }
    337         ByteBuffer otherBuffer = (ByteBuffer) other;
    338 
    339         if (remaining() != otherBuffer.remaining()) {
    340             return false;
    341         }
    342 
    343         int myPosition = position;
    344         int otherPosition = otherBuffer.position;
    345         boolean equalSoFar = true;
    346         while (equalSoFar && (myPosition < limit)) {
    347             equalSoFar = get(myPosition++) == otherBuffer.get(otherPosition++);
    348         }
    349 
    350         return equalSoFar;
    351     }
    352 
    353     /**
    354      * Returns the byte at the current position and increases the position by 1.
    355      *
    356      * @return the byte at the current position.
    357      * @throws BufferUnderflowException
    358      *                if the position is equal or greater than limit.
    359      */
    360     public abstract byte get();
    361 
    362     /**
    363      * Reads bytes from the current position into the specified byte array and
    364      * increases the position by the number of bytes read.
    365      * <p>
    366      * Calling this method has the same effect as
    367      * {@code get(dst, 0, dst.length)}.
    368      *
    369      * @param dst
    370      *            the destination byte array.
    371      * @return {@code this}
    372      * @throws BufferUnderflowException
    373      *                if {@code dst.length} is greater than {@code remaining()}.
    374      */
    375     public ByteBuffer get(byte[] dst) {
    376         return get(dst, 0, dst.length);
    377     }
    378 
    379     /**
    380      * Reads bytes from the current position into the specified byte array,
    381      * starting at the specified offset, and increases the position by the
    382      * number of bytes read.
    383      *
    384      * @param dst
    385      *            the target byte array.
    386      * @param dstOffset
    387      *            the offset of the byte array, must not be negative and
    388      *            not greater than {@code dst.length}.
    389      * @param byteCount
    390      *            the number of bytes to read, must not be negative and not
    391      *            greater than {@code dst.length - dstOffset}
    392      * @return {@code this}
    393      * @throws IndexOutOfBoundsException if {@code dstOffset < 0 ||  byteCount < 0}
    394      * @throws BufferUnderflowException if {@code byteCount > remaining()}
    395      */
    396     public ByteBuffer get(byte[] dst, int dstOffset, int byteCount) {
    397         Arrays.checkOffsetAndCount(dst.length, dstOffset, byteCount);
    398         if (byteCount > remaining()) {
    399             throw new BufferUnderflowException();
    400         }
    401         for (int i = dstOffset; i < dstOffset + byteCount; ++i) {
    402             dst[i] = get();
    403         }
    404         return this;
    405     }
    406 
    407     /**
    408      * Returns the byte at the specified index and does not change the position.
    409      *
    410      * @param index
    411      *            the index, must not be negative and less than limit.
    412      * @return the byte at the specified index.
    413      * @throws IndexOutOfBoundsException
    414      *                if index is invalid.
    415      */
    416     public abstract byte get(int index);
    417 
    418     /**
    419      * Returns the char at the current position and increases the position by 2.
    420      * <p>
    421      * The 2 bytes starting at the current position are composed into a char
    422      * according to the current byte order and returned.
    423      *
    424      * @return the char at the current position.
    425      * @throws BufferUnderflowException
    426      *                if the position is greater than {@code limit - 2}.
    427      */
    428     public abstract char getChar();
    429 
    430     /**
    431      * Returns the char at the specified index.
    432      * <p>
    433      * The 2 bytes starting from the specified index are composed into a char
    434      * according to the current byte order and returned. The position is not
    435      * changed.
    436      *
    437      * @param index
    438      *            the index, must not be negative and equal or less than
    439      *            {@code limit - 2}.
    440      * @return the char at the specified index.
    441      * @throws IndexOutOfBoundsException
    442      *                if {@code index} is invalid.
    443      */
    444     public abstract char getChar(int index);
    445 
    446     /**
    447      * Returns the double at the current position and increases the position by
    448      * 8.
    449      * <p>
    450      * The 8 bytes starting from the current position are composed into a double
    451      * according to the current byte order and returned.
    452      *
    453      * @return the double at the current position.
    454      * @throws BufferUnderflowException
    455      *                if the position is greater than {@code limit - 8}.
    456      */
    457     public abstract double getDouble();
    458 
    459     /**
    460      * Returns the double at the specified index.
    461      * <p>
    462      * The 8 bytes starting at the specified index are composed into a double
    463      * according to the current byte order and returned. The position is not
    464      * changed.
    465      *
    466      * @param index
    467      *            the index, must not be negative and equal or less than
    468      *            {@code limit - 8}.
    469      * @return the double at the specified index.
    470      * @throws IndexOutOfBoundsException
    471      *                if {@code index} is invalid.
    472      */
    473     public abstract double getDouble(int index);
    474 
    475     /**
    476      * Returns the float at the current position and increases the position by
    477      * 4.
    478      * <p>
    479      * The 4 bytes starting at the current position are composed into a float
    480      * according to the current byte order and returned.
    481      *
    482      * @return the float at the current position.
    483      * @throws BufferUnderflowException
    484      *                if the position is greater than {@code limit - 4}.
    485      */
    486     public abstract float getFloat();
    487 
    488     /**
    489      * Returns the float at the specified index.
    490      * <p>
    491      * The 4 bytes starting at the specified index are composed into a float
    492      * according to the current byte order and returned. The position is not
    493      * changed.
    494      *
    495      * @param index
    496      *            the index, must not be negative and equal or less than
    497      *            {@code limit - 4}.
    498      * @return the float at the specified index.
    499      * @throws IndexOutOfBoundsException
    500      *                if {@code index} is invalid.
    501      */
    502     public abstract float getFloat(int index);
    503 
    504     /**
    505      * Returns the int at the current position and increases the position by 4.
    506      * <p>
    507      * The 4 bytes starting at the current position are composed into a int
    508      * according to the current byte order and returned.
    509      *
    510      * @return the int at the current position.
    511      * @throws BufferUnderflowException
    512      *                if the position is greater than {@code limit - 4}.
    513      */
    514     public abstract int getInt();
    515 
    516     /**
    517      * Returns the int at the specified index.
    518      * <p>
    519      * The 4 bytes starting at the specified index are composed into a int
    520      * according to the current byte order and returned. The position is not
    521      * changed.
    522      *
    523      * @param index
    524      *            the index, must not be negative and equal or less than
    525      *            {@code limit - 4}.
    526      * @return the int at the specified index.
    527      * @throws IndexOutOfBoundsException
    528      *                if {@code index} is invalid.
    529      */
    530     public abstract int getInt(int index);
    531 
    532     /**
    533      * Returns the long at the current position and increases the position by 8.
    534      * <p>
    535      * The 8 bytes starting at the current position are composed into a long
    536      * according to the current byte order and returned.
    537      *
    538      * @return the long at the current position.
    539      * @throws BufferUnderflowException
    540      *                if the position is greater than {@code limit - 8}.
    541      */
    542     public abstract long getLong();
    543 
    544     /**
    545      * Returns the long at the specified index.
    546      * <p>
    547      * The 8 bytes starting at the specified index are composed into a long
    548      * according to the current byte order and returned. The position is not
    549      * changed.
    550      *
    551      * @param index
    552      *            the index, must not be negative and equal or less than
    553      *            {@code limit - 8}.
    554      * @return the long at the specified index.
    555      * @throws IndexOutOfBoundsException
    556      *                if {@code index} is invalid.
    557      */
    558     public abstract long getLong(int index);
    559 
    560     /**
    561      * Returns the short at the current position and increases the position by 2.
    562      * <p>
    563      * The 2 bytes starting at the current position are composed into a short
    564      * according to the current byte order and returned.
    565      *
    566      * @return the short at the current position.
    567      * @throws BufferUnderflowException
    568      *                if the position is greater than {@code limit - 2}.
    569      */
    570     public abstract short getShort();
    571 
    572     /**
    573      * Returns the short at the specified index.
    574      * <p>
    575      * The 2 bytes starting at the specified index are composed into a short
    576      * according to the current byte order and returned. The position is not
    577      * changed.
    578      *
    579      * @param index
    580      *            the index, must not be negative and equal or less than
    581      *            {@code limit - 2}.
    582      * @return the short at the specified index.
    583      * @throws IndexOutOfBoundsException
    584      *                if {@code index} is invalid.
    585      */
    586     public abstract short getShort(int index);
    587 
    588     @Override public final boolean hasArray() {
    589         return protectedHasArray();
    590     }
    591 
    592     /**
    593      * Calculates this buffer's hash code from the remaining chars. The
    594      * position, limit, capacity and mark don't affect the hash code.
    595      *
    596      * @return the hash code calculated from the remaining bytes.
    597      */
    598     @Override
    599     public int hashCode() {
    600         int myPosition = position;
    601         int hash = 0;
    602         while (myPosition < limit) {
    603             hash = hash + get(myPosition++);
    604         }
    605         return hash;
    606     }
    607 
    608     /**
    609      * Indicates whether this buffer is direct.
    610      *
    611      * @return {@code true} if this buffer is direct, {@code false} otherwise.
    612      */
    613     @Override public abstract boolean isDirect();
    614 
    615     /**
    616      * Indicates whether this buffer is still accessible.
    617      *
    618      * @return {@code true} if this buffer is accessible, {@code false} if the
    619      *         buffer was made inaccessible (e.g. freed) and should not be used.
    620      * @hide
    621      */
    622     public boolean isAccessible() {
    623         return true;
    624     }
    625 
    626     /**
    627      * Sets buffer accessibility (only supported for direct byte buffers). If
    628      * {@code accessible} is {@code false}, {@link #isAccessible} will return
    629      * false, and any attempt to access the buffer will throw an exception. If
    630      * {@code true}, the buffer will become useable again, unless it has been
    631      * freed.
    632      *
    633      * @hide
    634      */
    635     public void setAccessible(boolean accessible) {
    636         throw new UnsupportedOperationException();
    637     }
    638 
    639     /**
    640      * Returns the byte order used by this buffer when converting bytes from/to
    641      * other primitive types.
    642      * <p>
    643      * The default byte order of byte buffer is always
    644      * {@link ByteOrder#BIG_ENDIAN BIG_ENDIAN}
    645      *
    646      * @return the byte order used by this buffer when converting bytes from/to
    647      *         other primitive types.
    648      */
    649     public final ByteOrder order() {
    650         return order;
    651     }
    652 
    653     /**
    654      * Sets the byte order of this buffer.
    655      *
    656      * @param byteOrder
    657      *            the byte order to set. If {@code null} then the order
    658      *            will be {@link ByteOrder#LITTLE_ENDIAN LITTLE_ENDIAN}.
    659      * @return {@code this}
    660      * @see ByteOrder
    661      */
    662     public final ByteBuffer order(ByteOrder byteOrder) {
    663         if (byteOrder == null) {
    664             byteOrder = ByteOrder.LITTLE_ENDIAN;
    665         }
    666         order = byteOrder;
    667         return this;
    668     }
    669 
    670     /**
    671      * Child class implements this method to realize {@code array()}.
    672      *
    673      * @see #array()
    674      */
    675     abstract byte[] protectedArray();
    676 
    677     /**
    678      * Child class implements this method to realize {@code arrayOffset()}.
    679      *
    680      * @see #arrayOffset()
    681      */
    682     abstract int protectedArrayOffset();
    683 
    684     /**
    685      * Child class implements this method to realize {@code hasArray()}.
    686      *
    687      * @see #hasArray()
    688      */
    689     abstract boolean protectedHasArray();
    690 
    691     /**
    692      * Writes the given byte to the current position and increases the position
    693      * by 1.
    694      *
    695      * @param b
    696      *            the byte to write.
    697      * @return {@code this}
    698      * @throws BufferOverflowException
    699      *                if position is equal or greater than limit.
    700      * @throws ReadOnlyBufferException
    701      *                if no changes may be made to the contents of this buffer.
    702      */
    703     public abstract ByteBuffer put(byte b);
    704 
    705     /**
    706      * Writes bytes in the given byte array to the current position and
    707      * increases the position by the number of bytes written.
    708      * <p>
    709      * Calling this method has the same effect as
    710      * {@code put(src, 0, src.length)}.
    711      *
    712      * @param src
    713      *            the source byte array.
    714      * @return {@code this}
    715      * @throws BufferOverflowException
    716      *                if {@code remaining()} is less than {@code src.length}.
    717      * @throws ReadOnlyBufferException
    718      *                if no changes may be made to the contents of this buffer.
    719      */
    720     public final ByteBuffer put(byte[] src) {
    721         return put(src, 0, src.length);
    722     }
    723 
    724     /**
    725      * Writes bytes in the given byte array, starting from the specified offset,
    726      * to the current position and increases the position by the number of bytes
    727      * written.
    728      *
    729      * @param src
    730      *            the source byte array.
    731      * @param srcOffset
    732      *            the offset of byte array, must not be negative and not greater
    733      *            than {@code src.length}.
    734      * @param byteCount
    735      *            the number of bytes to write, must not be negative and not
    736      *            greater than {@code src.length - srcOffset}.
    737      * @return {@code this}
    738      * @throws BufferOverflowException
    739      *                if {@code remaining()} is less than {@code byteCount}.
    740      * @throws IndexOutOfBoundsException
    741      *                if either {@code srcOffset} or {@code byteCount} is invalid.
    742      * @throws ReadOnlyBufferException
    743      *                if no changes may be made to the contents of this buffer.
    744      */
    745     public ByteBuffer put(byte[] src, int srcOffset, int byteCount) {
    746         Arrays.checkOffsetAndCount(src.length, srcOffset, byteCount);
    747         if (byteCount > remaining()) {
    748             throw new BufferOverflowException();
    749         }
    750         for (int i = srcOffset; i < srcOffset + byteCount; ++i) {
    751             put(src[i]);
    752         }
    753         return this;
    754     }
    755 
    756     /**
    757      * Writes all the remaining bytes of the {@code src} byte buffer to this
    758      * buffer's current position, and increases both buffers' position by the
    759      * number of bytes copied.
    760      *
    761      * @param src
    762      *            the source byte buffer.
    763      * @return {@code this}
    764      * @throws BufferOverflowException
    765      *                if {@code src.remaining()} is greater than this buffer's
    766      *                {@code remaining()}.
    767      * @throws IllegalArgumentException
    768      *                if {@code src} is this buffer.
    769      * @throws ReadOnlyBufferException
    770      *                if no changes may be made to the contents of this buffer.
    771      */
    772     public ByteBuffer put(ByteBuffer src) {
    773         if (!isAccessible()) {
    774             throw new IllegalStateException("buffer is inaccessible");
    775         }
    776         if (isReadOnly()) {
    777             throw new ReadOnlyBufferException();
    778         }
    779         if (src == this) {
    780             throw new IllegalArgumentException("src == this");
    781         }
    782         if (!src.isAccessible()) {
    783             throw new IllegalStateException("src buffer is inaccessible");
    784         }
    785         int srcByteCount = src.remaining();
    786         if (srcByteCount > remaining()) {
    787             throw new BufferOverflowException();
    788         }
    789 
    790         Object srcObject = src.isDirect() ? src : NioUtils.unsafeArray(src);
    791         int srcOffset = src.position();
    792         if (!src.isDirect()) {
    793             srcOffset += NioUtils.unsafeArrayOffset(src);
    794         }
    795 
    796         ByteBuffer dst = this;
    797         Object dstObject = dst.isDirect() ? dst : NioUtils.unsafeArray(dst);
    798         int dstOffset = dst.position();
    799         if (!dst.isDirect()) {
    800             dstOffset += NioUtils.unsafeArrayOffset(dst);
    801         }
    802 
    803         Memory.memmove(dstObject, dstOffset, srcObject, srcOffset, srcByteCount);
    804         src.position(src.limit());
    805         dst.position(dst.position() + srcByteCount);
    806 
    807         return this;
    808     }
    809 
    810     /**
    811      * Write a byte to the specified index of this buffer without changing the
    812      * position.
    813      *
    814      * @param index
    815      *            the index, must not be negative and less than the limit.
    816      * @param b
    817      *            the byte to write.
    818      * @return {@code this}
    819      * @throws IndexOutOfBoundsException
    820      *                if {@code index} is invalid.
    821      * @throws ReadOnlyBufferException
    822      *                if no changes may be made to the contents of this buffer.
    823      */
    824     public abstract ByteBuffer put(int index, byte b);
    825 
    826     /**
    827      * Writes the given char to the current position and increases the position
    828      * by 2.
    829      * <p>
    830      * The char is converted to bytes using the current byte order.
    831      *
    832      * @param value
    833      *            the char to write.
    834      * @return {@code this}
    835      * @throws BufferOverflowException
    836      *                if position is greater than {@code limit - 2}.
    837      * @throws ReadOnlyBufferException
    838      *                if no changes may be made to the contents of this buffer.
    839      */
    840     public abstract ByteBuffer putChar(char value);
    841 
    842     /**
    843      * Writes the given char to the specified index of this buffer.
    844      * <p>
    845      * The char is converted to bytes using the current byte order. The position
    846      * is not changed.
    847      *
    848      * @param index
    849      *            the index, must not be negative and equal or less than
    850      *            {@code limit - 2}.
    851      * @param value
    852      *            the char to write.
    853      * @return {@code this}
    854      * @throws IndexOutOfBoundsException
    855      *                if {@code index} is invalid.
    856      * @throws ReadOnlyBufferException
    857      *                if no changes may be made to the contents of this buffer.
    858      */
    859     public abstract ByteBuffer putChar(int index, char value);
    860 
    861     /**
    862      * Writes the given double to the current position and increases the position
    863      * by 8.
    864      * <p>
    865      * The double is converted to bytes using the current byte order.
    866      *
    867      * @param value
    868      *            the double to write.
    869      * @return {@code this}
    870      * @throws BufferOverflowException
    871      *                if position is greater than {@code limit - 8}.
    872      * @throws ReadOnlyBufferException
    873      *                if no changes may be made to the contents of this buffer.
    874      */
    875     public abstract ByteBuffer putDouble(double value);
    876 
    877     /**
    878      * Writes the given double to the specified index of this buffer.
    879      * <p>
    880      * The double is converted to bytes using the current byte order. The
    881      * position is not changed.
    882      *
    883      * @param index
    884      *            the index, must not be negative and equal or less than
    885      *            {@code limit - 8}.
    886      * @param value
    887      *            the double to write.
    888      * @return {@code this}
    889      * @throws IndexOutOfBoundsException
    890      *                if {@code index} is invalid.
    891      * @throws ReadOnlyBufferException
    892      *                if no changes may be made to the contents of this buffer.
    893      */
    894     public abstract ByteBuffer putDouble(int index, double value);
    895 
    896     /**
    897      * Writes the given float to the current position and increases the position
    898      * by 4.
    899      * <p>
    900      * The float is converted to bytes using the current byte order.
    901      *
    902      * @param value
    903      *            the float to write.
    904      * @return {@code this}
    905      * @throws BufferOverflowException
    906      *                if position is greater than {@code limit - 4}.
    907      * @throws ReadOnlyBufferException
    908      *                if no changes may be made to the contents of this buffer.
    909      */
    910     public abstract ByteBuffer putFloat(float value);
    911 
    912     /**
    913      * Writes the given float to the specified index of this buffer.
    914      * <p>
    915      * The float is converted to bytes using the current byte order. The
    916      * position is not changed.
    917      *
    918      * @param index
    919      *            the index, must not be negative and equal or less than
    920      *            {@code limit - 4}.
    921      * @param value
    922      *            the float to write.
    923      * @return {@code this}
    924      * @throws IndexOutOfBoundsException
    925      *                if {@code index} is invalid.
    926      * @throws ReadOnlyBufferException
    927      *                if no changes may be made to the contents of this buffer.
    928      */
    929     public abstract ByteBuffer putFloat(int index, float value);
    930 
    931     /**
    932      * Writes the given int to the current position and increases the position by
    933      * 4.
    934      * <p>
    935      * The int is converted to bytes using the current byte order.
    936      *
    937      * @param value
    938      *            the int to write.
    939      * @return {@code this}
    940      * @throws BufferOverflowException
    941      *                if position is greater than {@code limit - 4}.
    942      * @throws ReadOnlyBufferException
    943      *                if no changes may be made to the contents of this buffer.
    944      */
    945     public abstract ByteBuffer putInt(int value);
    946 
    947     /**
    948      * Writes the given int to the specified index of this buffer.
    949      * <p>
    950      * The int is converted to bytes using the current byte order. The position
    951      * is not changed.
    952      *
    953      * @param index
    954      *            the index, must not be negative and equal or less than
    955      *            {@code limit - 4}.
    956      * @param value
    957      *            the int to write.
    958      * @return {@code this}
    959      * @throws IndexOutOfBoundsException
    960      *                if {@code index} is invalid.
    961      * @throws ReadOnlyBufferException
    962      *                if no changes may be made to the contents of this buffer.
    963      */
    964     public abstract ByteBuffer putInt(int index, int value);
    965 
    966     /**
    967      * Writes the given long to the current position and increases the position
    968      * by 8.
    969      * <p>
    970      * The long is converted to bytes using the current byte order.
    971      *
    972      * @param value
    973      *            the long to write.
    974      * @return {@code this}
    975      * @throws BufferOverflowException
    976      *                if position is greater than {@code limit - 8}.
    977      * @throws ReadOnlyBufferException
    978      *                if no changes may be made to the contents of this buffer.
    979      */
    980     public abstract ByteBuffer putLong(long value);
    981 
    982     /**
    983      * Writes the given long to the specified index of this buffer.
    984      * <p>
    985      * The long is converted to bytes using the current byte order. The position
    986      * is not changed.
    987      *
    988      * @param index
    989      *            the index, must not be negative and equal or less than
    990      *            {@code limit - 8}.
    991      * @param value
    992      *            the long to write.
    993      * @return {@code this}
    994      * @throws IndexOutOfBoundsException
    995      *                if {@code index} is invalid.
    996      * @throws ReadOnlyBufferException
    997      *                if no changes may be made to the contents of this buffer.
    998      */
    999     public abstract ByteBuffer putLong(int index, long value);
   1000 
   1001     /**
   1002      * Writes the given short to the current position and increases the position
   1003      * by 2.
   1004      * <p>
   1005      * The short is converted to bytes using the current byte order.
   1006      *
   1007      * @param value
   1008      *            the short to write.
   1009      * @return {@code this}
   1010      * @throws BufferOverflowException
   1011      *                if position is greater than {@code limit - 2}.
   1012      * @throws ReadOnlyBufferException
   1013      *                if no changes may be made to the contents of this buffer.
   1014      */
   1015     public abstract ByteBuffer putShort(short value);
   1016 
   1017     /**
   1018      * Writes the given short to the specified index of this buffer.
   1019      * <p>
   1020      * The short is converted to bytes using the current byte order. The
   1021      * position is not changed.
   1022      *
   1023      * @param index
   1024      *            the index, must not be negative and equal or less than
   1025      *            {@code limit - 2}.
   1026      * @param value
   1027      *            the short to write.
   1028      * @return {@code this}
   1029      * @throws IndexOutOfBoundsException
   1030      *                if {@code index} is invalid.
   1031      * @throws ReadOnlyBufferException
   1032      *                if no changes may be made to the contents of this buffer.
   1033      */
   1034     public abstract ByteBuffer putShort(int index, short value);
   1035 
   1036     /**
   1037      * Returns a sliced buffer that shares its content with this buffer.
   1038      * <p>
   1039      * The sliced buffer's capacity will be this buffer's
   1040      * {@code remaining()}, and it's zero position will correspond to
   1041      * this buffer's current position. The new buffer's position will be 0,
   1042      * limit will be its capacity, and its mark is cleared. The new buffer's
   1043      * read-only property and byte order are the same as this buffer's.
   1044      * <p>
   1045      * The new buffer shares its content with this buffer, which means either
   1046      * buffer's change of content will be visible to the other. The two buffers'
   1047      * position, limit and mark are independent.
   1048      */
   1049     public abstract ByteBuffer slice();
   1050 }
   1051