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 
     22 /**
     23  * A buffer of ints.
     24  * <p>
     25  * A int buffer can be created in either of the following ways:
     26  * <ul>
     27  * <li>{@link #allocate(int) Allocate} a new int array and create a buffer
     28  * based on it;</li>
     29  * <li>{@link #wrap(int[]) Wrap} an existing int array to create a new buffer;</li>
     30  * <li>Use {@link java.nio.ByteBuffer#asIntBuffer() ByteBuffer.asIntBuffer} to
     31  * create a int buffer based on a byte buffer.</li>
     32  * </ul>
     33  */
     34 public abstract class IntBuffer extends Buffer implements Comparable<IntBuffer> {
     35 
     36     /**
     37      * Creates an int buffer based on a newly allocated int array.
     38      *
     39      * @param capacity
     40      *            the capacity of the new buffer.
     41      * @return the created int buffer.
     42      * @throws IllegalArgumentException
     43      *             if {@code capacity} is less than zero.
     44      */
     45     public static IntBuffer allocate(int capacity) {
     46         if (capacity < 0) {
     47             throw new IllegalArgumentException("capacity < 0: " + capacity);
     48         }
     49         return new IntArrayBuffer(new int[capacity]);
     50     }
     51 
     52     /**
     53      * Creates a new int buffer by wrapping the given int array.
     54      * <p>
     55      * Calling this method has the same effect as
     56      * {@code wrap(array, 0, array.length)}.
     57      *
     58      * @param array
     59      *            the int array which the new buffer will be based on.
     60      * @return the created int buffer.
     61      */
     62     public static IntBuffer wrap(int[] array) {
     63         return wrap(array, 0, array.length);
     64     }
     65 
     66     /**
     67      * Creates a new int buffer by wrapping the given int array.
     68      * <p>
     69      * The new buffer's position will be {@code start}, limit will be
     70      * {@code start + intCount}, capacity will be the length of the array.
     71      *
     72      * @param array
     73      *            the int array which the new buffer will be based on.
     74      * @param start
     75      *            the start index, must not be negative and not greater than
     76      *            {@code array.length}
     77      * @param intCount
     78      *            the length, must not be negative and not greater than
     79      *            {@code array.length - start}.
     80      * @return the created int buffer.
     81      * @throws IndexOutOfBoundsException
     82      *                if either {@code start} or {@code intCount} is invalid.
     83      */
     84     public static IntBuffer wrap(int[] array, int start, int intCount) {
     85         Arrays.checkOffsetAndCount(array.length, start, intCount);
     86         IntBuffer buf = new IntArrayBuffer(array);
     87         buf.position = start;
     88         buf.limit = start + intCount;
     89         return buf;
     90     }
     91 
     92     IntBuffer(int capacity, long effectiveDirectAddress) {
     93         super(2, capacity, effectiveDirectAddress);
     94     }
     95 
     96     public final int[] array() {
     97         return protectedArray();
     98     }
     99 
    100     public final int arrayOffset() {
    101         return protectedArrayOffset();
    102     }
    103 
    104     /**
    105      * Returns a read-only buffer that shares its content with this buffer.
    106      * <p>
    107      * The returned buffer is guaranteed to be a new instance, even this buffer
    108      * is read-only itself. The new buffer's position, limit, capacity and mark
    109      * are the same as this buffer's.
    110      * <p>
    111      * The new buffer shares its content with this buffer, which means this
    112      * buffer's change of content will be visible to the new buffer. The two
    113      * buffer's position, limit and mark are independent.
    114      *
    115      * @return a read-only version of this buffer.
    116      */
    117     public abstract IntBuffer asReadOnlyBuffer();
    118 
    119     /**
    120      * Compacts this int buffer.
    121      * <p>
    122      * The remaining ints will be moved to the head of the buffer, starting from
    123      * position zero. Then the position is set to {@code remaining()}; the
    124      * limit is set to capacity; the mark is cleared.
    125      *
    126      * @return this buffer.
    127      * @throws ReadOnlyBufferException
    128      *                if no changes may be made to the contents of this buffer.
    129      */
    130     public abstract IntBuffer compact();
    131 
    132     /**
    133      * Compares the remaining ints of this buffer to another int buffer's
    134      * remaining ints.
    135      *
    136      * @param otherBuffer
    137      *            another int buffer.
    138      * @return a negative value if this is less than {@code other}; 0 if this
    139      *         equals to {@code other}; a positive value if this is greater
    140      *         than {@code other}.
    141      * @throws ClassCastException
    142      *                if {@code other} is not an int buffer.
    143      */
    144     public int compareTo(IntBuffer otherBuffer) {
    145         int compareRemaining = (remaining() < otherBuffer.remaining()) ? remaining()
    146                 : otherBuffer.remaining();
    147         int thisPos = position;
    148         int otherPos = otherBuffer.position;
    149         int thisInt, otherInt;
    150         while (compareRemaining > 0) {
    151             thisInt = get(thisPos);
    152             otherInt = otherBuffer.get(otherPos);
    153             if (thisInt != otherInt) {
    154                 return thisInt < otherInt ? -1 : 1;
    155             }
    156             thisPos++;
    157             otherPos++;
    158             compareRemaining--;
    159         }
    160         return remaining() - otherBuffer.remaining();
    161     }
    162 
    163     /**
    164      * Returns a duplicated buffer that shares its content with this buffer.
    165      * <p>
    166      * The duplicated buffer's position, limit, capacity and mark are the same
    167      * as this buffer. The duplicated buffer's read-only property and byte order
    168      * are the same as this buffer's.
    169      * <p>
    170      * The new buffer shares its content with this buffer, which means either
    171      * buffer's change of content will be visible to the other. The two buffers'
    172      * position, limit and mark are independent.
    173      */
    174     public abstract IntBuffer duplicate();
    175 
    176     /**
    177      * Checks whether this int buffer is equal to another object.
    178      * <p>
    179      * If {@code other} is not a int buffer then {@code false} is returned. Two
    180      * int buffers are equal if and only if their remaining ints are exactly the
    181      * same. Position, limit, capacity and mark are not considered.
    182      *
    183      * @param other
    184      *            the object to compare with this int buffer.
    185      * @return {@code true} if this int buffer is equal to {@code other},
    186      *         {@code false} otherwise.
    187      */
    188     @Override
    189     public boolean equals(Object other) {
    190         if (!(other instanceof IntBuffer)) {
    191             return false;
    192         }
    193         IntBuffer otherBuffer = (IntBuffer) other;
    194 
    195         if (remaining() != otherBuffer.remaining()) {
    196             return false;
    197         }
    198 
    199         int myPosition = position;
    200         int otherPosition = otherBuffer.position;
    201         boolean equalSoFar = true;
    202         while (equalSoFar && (myPosition < limit)) {
    203             equalSoFar = get(myPosition++) == otherBuffer.get(otherPosition++);
    204         }
    205 
    206         return equalSoFar;
    207     }
    208 
    209     /**
    210      * Returns the int at the current position and increases the position by 1.
    211      *
    212      * @return the int at the current position.
    213      * @throws BufferUnderflowException
    214      *                if the position is equal or greater than limit.
    215      */
    216     public abstract int get();
    217 
    218     /**
    219      * Reads ints from the current position into the specified int array and
    220      * increases the position by the number of ints read.
    221      * <p>
    222      * Calling this method has the same effect as
    223      * {@code get(dst, 0, dst.length)}.
    224      *
    225      * @param dst
    226      *            the destination int array.
    227      * @return this buffer.
    228      * @throws BufferUnderflowException
    229      *                if {@code dst.length} is greater than {@code remaining()}.
    230      */
    231     public IntBuffer get(int[] dst) {
    232         return get(dst, 0, dst.length);
    233     }
    234 
    235     /**
    236      * Reads ints from the current position into the specified int array,
    237      * starting from the specified offset, and increases the position by the
    238      * number of ints read.
    239      *
    240      * @param dst
    241      *            the target int array.
    242      * @param dstOffset
    243      *            the offset of the int array, must not be negative and not
    244      *            greater than {@code dst.length}.
    245      * @param intCount
    246      *            the number of ints to read, must be no less than zero and not
    247      *            greater than {@code dst.length - dstOffset}.
    248      * @return this buffer.
    249      * @throws IndexOutOfBoundsException
    250      *                if either {@code dstOffset} or {@code intCount} is invalid.
    251      * @throws BufferUnderflowException
    252      *                if {@code intCount} is greater than {@code remaining()}.
    253      */
    254     public IntBuffer get(int[] dst, int dstOffset, int intCount) {
    255         Arrays.checkOffsetAndCount(dst.length, dstOffset, intCount);
    256         if (intCount > remaining()) {
    257             throw new BufferUnderflowException();
    258         }
    259         for (int i = dstOffset; i < dstOffset + intCount; ++i) {
    260             dst[i] = get();
    261         }
    262         return this;
    263     }
    264 
    265     /**
    266      * Returns an int at the specified index; the position is not changed.
    267      *
    268      * @param index
    269      *            the index, must not be negative and less than limit.
    270      * @return an int at the specified index.
    271      * @throws IndexOutOfBoundsException
    272      *                if index is invalid.
    273      */
    274     public abstract int get(int index);
    275 
    276     public final boolean hasArray() {
    277         return protectedHasArray();
    278     }
    279 
    280     /**
    281      * Calculates this buffer's hash code from the remaining chars. The
    282      * position, limit, capacity and mark don't affect the hash code.
    283      *
    284      * @return the hash code calculated from the remaining ints.
    285      */
    286     @Override
    287     public int hashCode() {
    288         int myPosition = position;
    289         int hash = 0;
    290         while (myPosition < limit) {
    291             hash = hash + get(myPosition++);
    292         }
    293         return hash;
    294     }
    295 
    296     /**
    297      * Indicates whether this buffer is direct. A direct buffer will try its
    298      * best to take advantage of native memory APIs and it may not stay in the
    299      * Java heap, so it is not affected by garbage collection.
    300      * <p>
    301      * An int buffer is direct if it is based on a byte buffer and the byte
    302      * buffer is direct.
    303      *
    304      * @return {@code true} if this buffer is direct, {@code false} otherwise.
    305      */
    306     public abstract boolean isDirect();
    307 
    308     /**
    309      * Returns the byte order used by this buffer when converting ints from/to
    310      * bytes.
    311      * <p>
    312      * If this buffer is not based on a byte buffer, then always return the
    313      * platform's native byte order.
    314      *
    315      * @return the byte order used by this buffer when converting ints from/to
    316      *         bytes.
    317      */
    318     public abstract ByteOrder order();
    319 
    320     /**
    321      * Child class implements this method to realize {@code array()}.
    322      *
    323      * @return see {@code array()}
    324      */
    325     abstract int[] protectedArray();
    326 
    327     /**
    328      * Child class implements this method to realize {@code arrayOffset()}.
    329      *
    330      * @return see {@code arrayOffset()}
    331      */
    332     abstract int protectedArrayOffset();
    333 
    334     /**
    335      * Child class implements this method to realize {@code hasArray()}.
    336      *
    337      * @return see {@code hasArray()}
    338      */
    339     abstract boolean protectedHasArray();
    340 
    341     /**
    342      * Writes the given int to the current position and increases the position
    343      * by 1.
    344      *
    345      * @param i
    346      *            the int to write.
    347      * @return this buffer.
    348      * @throws BufferOverflowException
    349      *                if position is equal or greater than limit.
    350      * @throws ReadOnlyBufferException
    351      *                if no changes may be made to the contents of this buffer.
    352      */
    353     public abstract IntBuffer put(int i);
    354 
    355     /**
    356      * Writes ints from the given int array to the current position and
    357      * increases the position by the number of ints written.
    358      * <p>
    359      * Calling this method has the same effect as
    360      * {@code put(src, 0, src.length)}.
    361      *
    362      * @param src
    363      *            the source int array.
    364      * @return this buffer.
    365      * @throws BufferOverflowException
    366      *                if {@code remaining()} is less than {@code src.length}.
    367      * @throws ReadOnlyBufferException
    368      *                if no changes may be made to the contents of this buffer.
    369      */
    370     public final IntBuffer put(int[] src) {
    371         return put(src, 0, src.length);
    372     }
    373 
    374     /**
    375      * Writes ints from the given int array, starting from the specified offset,
    376      * to the current position and increases the position by the number of ints
    377      * written.
    378      *
    379      * @param src
    380      *            the source int array.
    381      * @param srcOffset
    382      *            the offset of int array, must not be negative and not greater
    383      *            than {@code src.length}.
    384      * @param intCount
    385      *            the number of ints to write, must be no less than zero and not
    386      *            greater than {@code src.length - srcOffset}.
    387      * @return this buffer.
    388      * @throws BufferOverflowException
    389      *                if {@code remaining()} is less than {@code intCount}.
    390      * @throws IndexOutOfBoundsException
    391      *                if either {@code srcOffset} or {@code intCount} is invalid.
    392      * @throws ReadOnlyBufferException
    393      *                if no changes may be made to the contents of this buffer.
    394      */
    395     public IntBuffer put(int[] src, int srcOffset, int intCount) {
    396         if (isReadOnly()) {
    397             throw new ReadOnlyBufferException();
    398         }
    399         Arrays.checkOffsetAndCount(src.length, srcOffset, intCount);
    400         if (intCount > remaining()) {
    401             throw new BufferOverflowException();
    402         }
    403         for (int i = srcOffset; i < srcOffset + intCount; ++i) {
    404             put(src[i]);
    405         }
    406         return this;
    407     }
    408 
    409     /**
    410      * Writes all the remaining ints of the {@code src} int buffer to this
    411      * buffer's current position, and increases both buffers' position by the
    412      * number of ints copied.
    413      *
    414      * @param src
    415      *            the source int buffer.
    416      * @return this buffer.
    417      * @throws BufferOverflowException
    418      *                if {@code src.remaining()} is greater than this buffer's
    419      *                {@code remaining()}.
    420      * @throws IllegalArgumentException
    421      *                if {@code src} is this buffer.
    422      * @throws ReadOnlyBufferException
    423      *                if no changes may be made to the contents of this buffer.
    424      */
    425     public IntBuffer put(IntBuffer src) {
    426         if (isReadOnly()) {
    427             throw new ReadOnlyBufferException();
    428         }
    429         if (src == this) {
    430             throw new IllegalArgumentException("src == this");
    431         }
    432         if (src.remaining() > remaining()) {
    433             throw new BufferOverflowException();
    434         }
    435         int[] contents = new int[src.remaining()];
    436         src.get(contents);
    437         put(contents);
    438         return this;
    439     }
    440 
    441     /**
    442      * Write a int to the specified index of this buffer; the position is not
    443      * changed.
    444      *
    445      * @param index
    446      *            the index, must not be negative and less than the limit.
    447      * @param i
    448      *            the int to write.
    449      * @return this buffer.
    450      * @throws IndexOutOfBoundsException
    451      *                if index is invalid.
    452      * @throws ReadOnlyBufferException
    453      *                if no changes may be made to the contents of this buffer.
    454      */
    455     public abstract IntBuffer put(int index, int i);
    456 
    457     /**
    458      * Returns a sliced buffer that shares its content with this buffer.
    459      * <p>
    460      * The sliced buffer's capacity will be this buffer's {@code remaining()},
    461      * and its zero position will correspond to this buffer's current position.
    462      * The new buffer's position will be 0, limit will be its capacity, and its
    463      * mark is cleared. The new buffer's read-only property and byte order are
    464      * same as this buffer's.
    465      * <p>
    466      * The new buffer shares its content with this buffer, which means either
    467      * buffer's change of content will be visible to the other. The two buffers'
    468      * position, limit and mark are independent.
    469      */
    470     public abstract IntBuffer slice();
    471 }
    472