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