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