LongBuffer.java revision a1603838fe9e865575c87982e32c6343740e464c
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
18package java.nio;
19
20import 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 */
35public 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();
50        }
51        return new ReadWriteLongArrayBuffer(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     * @exception 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 ReadWriteLongArrayBuffer(array);
89        buf.position = start;
90        buf.limit = start + longCount;
91        return buf;
92    }
93
94    LongBuffer(int capacity) {
95        super(3, capacity, null);
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     * @exception 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     * @exception 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        // BEGIN android-changed
152        long thisLong, otherLong;
153        while (compareRemaining > 0) {
154            thisLong = get(thisPos);
155            otherLong = otherBuffer.get(otherPos);
156            if (thisLong != otherLong) {
157                return thisLong < otherLong ? -1 : 1;
158            }
159            thisPos++;
160            otherPos++;
161            compareRemaining--;
162        }
163        // END android-changed
164        return remaining() - otherBuffer.remaining();
165    }
166
167    /**
168     * Returns a duplicated buffer that shares its content with this buffer.
169     * <p>
170     * The duplicated buffer's position, limit, capacity and mark are the same
171     * as this buffer. The duplicated buffer's read-only property and byte order
172     * are same as this buffer's, too.
173     * <p>
174     * The new buffer shares its content with this buffer, which means either
175     * buffer's change of content will be visible to the other. The two buffer's
176     * position, limit and mark are independent.
177     *
178     * @return a duplicated buffer that shares its content with this buffer.
179     */
180    public abstract LongBuffer duplicate();
181
182    /**
183     * Checks whether this long buffer is equal to another object.
184     * <p>
185     * If {@code other} is not a long buffer then {@code false} is returned. Two
186     * long buffers are equal if and only if their remaining longs are exactly
187     * the same. Position, limit, capacity and mark are not considered.
188     *
189     * @param other
190     *            the object to compare with this long buffer.
191     * @return {@code true} if this long buffer is equal to {@code other},
192     *         {@code false} otherwise.
193     */
194    @Override
195    public boolean equals(Object other) {
196        if (!(other instanceof LongBuffer)) {
197            return false;
198        }
199        LongBuffer otherBuffer = (LongBuffer) other;
200
201        if (remaining() != otherBuffer.remaining()) {
202            return false;
203        }
204
205        int myPosition = position;
206        int otherPosition = otherBuffer.position;
207        boolean equalSoFar = true;
208        while (equalSoFar && (myPosition < limit)) {
209            equalSoFar = get(myPosition++) == otherBuffer.get(otherPosition++);
210        }
211
212        return equalSoFar;
213    }
214
215    /**
216     * Returns the long at the current position and increase the position by 1.
217     *
218     * @return the long at the current position.
219     * @exception BufferUnderflowException
220     *                if the position is equal or greater than limit.
221     */
222    public abstract long get();
223
224    /**
225     * Reads longs from the current position into the specified long array and
226     * increases the position by the number of longs read.
227     * <p>
228     * Calling this method has the same effect as
229     * {@code get(dst, 0, dst.length)}.
230     *
231     * @param dst
232     *            the destination long array.
233     * @return this buffer.
234     * @exception BufferUnderflowException
235     *                if {@code dst.length} is greater than {@code remaining()}.
236     */
237    public LongBuffer get(long[] dst) {
238        return get(dst, 0, dst.length);
239    }
240
241    /**
242     * Reads longs from the current position into the specified long array,
243     * starting from the specified offset, and increase the position by the
244     * number of longs read.
245     *
246     * @param dst
247     *            the target long array.
248     * @param dstOffset
249     *            the offset of the long array, must not be negative and not
250     *            greater than {@code dst.length}.
251     * @param longCount
252     *            the number of longs to read, must be no less than zero and not
253     *            greater than {@code dst.length - dstOffset}.
254     * @return this buffer.
255     * @exception IndexOutOfBoundsException
256     *                if either {@code dstOffset} or {@code longCount} is invalid.
257     * @exception BufferUnderflowException
258     *                if {@code longCount} is greater than {@code remaining()}.
259     */
260    public LongBuffer get(long[] dst, int dstOffset, int longCount) {
261        Arrays.checkOffsetAndCount(dst.length, dstOffset, longCount);
262        if (longCount > remaining()) {
263            throw new BufferUnderflowException();
264        }
265        for (int i = dstOffset; i < dstOffset + longCount; ++i) {
266            dst[i] = get();
267        }
268        return this;
269    }
270
271    /**
272     * Returns the long at the specified index; the position is not changed.
273     *
274     * @param index
275     *            the index, must not be negative and less than limit.
276     * @return the long at the specified index.
277     * @exception IndexOutOfBoundsException
278     *                if index is invalid.
279     */
280    public abstract long get(int index);
281
282    public final boolean hasArray() {
283        return protectedHasArray();
284    }
285
286    /**
287     * Calculates this buffer's hash code from the remaining chars. The
288     * position, limit, capacity and mark don't affect the hash code.
289     *
290     * @return the hash code calculated from the remaining longs.
291     */
292    @Override
293    public int hashCode() {
294        int myPosition = position;
295        int hash = 0;
296        long l;
297        while (myPosition < limit) {
298            l = get(myPosition++);
299            hash = hash + ((int) l) ^ ((int) (l >> 32));
300        }
301        return hash;
302    }
303
304    /**
305     * Indicates whether this buffer is direct. A direct buffer will try its
306     * best to take advantage of native memory APIs and it may not stay in the
307     * Java heap, so it is not affected by garbage collection.
308     * <p>
309     * A long buffer is direct if it is based on a byte buffer and the byte
310     * buffer is direct.
311     *
312     * @return {@code true} if this buffer is direct, {@code false} otherwise.
313     */
314    public abstract boolean isDirect();
315
316    /**
317     * Returns the byte order used by this buffer when converting longs from/to
318     * bytes.
319     * <p>
320     * If this buffer is not based on a byte buffer, then always return the
321     * platform's native byte order.
322     *
323     * @return the byte order used by this buffer when converting longs from/to
324     *         bytes.
325     */
326    public abstract ByteOrder order();
327
328    /**
329     * Child class implements this method to realize {@code array()}.
330     *
331     * @return see {@code array()}
332     */
333    abstract long[] protectedArray();
334
335    /**
336     * Child class implements this method to realize {@code arrayOffset()}.
337     *
338     * @return see {@code arrayOffset()}
339     */
340    abstract int protectedArrayOffset();
341
342    /**
343     * Child class implements this method to realize {@code hasArray()}.
344     *
345     * @return see {@code hasArray()}
346     */
347    abstract boolean protectedHasArray();
348
349    /**
350     * Writes the given long to the current position and increases the position
351     * by 1.
352     *
353     * @param l
354     *            the long to write.
355     * @return this buffer.
356     * @exception BufferOverflowException
357     *                if position is equal or greater than limit.
358     * @exception ReadOnlyBufferException
359     *                if no changes may be made to the contents of this buffer.
360     */
361    public abstract LongBuffer put(long l);
362
363    /**
364     * Writes longs from the given long array to the current position and
365     * increases the position by the number of longs written.
366     * <p>
367     * Calling this method has the same effect as
368     * {@code put(src, 0, src.length)}.
369     *
370     * @param src
371     *            the source long array.
372     * @return this buffer.
373     * @exception BufferOverflowException
374     *                if {@code remaining()} is less than {@code src.length}.
375     * @exception ReadOnlyBufferException
376     *                if no changes may be made to the contents of this buffer.
377     */
378    public final LongBuffer put(long[] src) {
379        return put(src, 0, src.length);
380    }
381
382    /**
383     * Writes longs from the given long array, starting from the specified
384     * offset, to the current position and increases the position by the number
385     * of longs written.
386     *
387     * @param src
388     *            the source long array.
389     * @param srcOffset
390     *            the offset of long array, must not be negative and not greater
391     *            than {@code src.length}.
392     * @param longCount
393     *            the number of longs to write, must be no less than zero and
394     *            not greater than {@code src.length - srcOffset}.
395     * @return this buffer.
396     * @exception BufferOverflowException
397     *                if {@code remaining()} is less than {@code longCount}.
398     * @exception IndexOutOfBoundsException
399     *                if either {@code srcOffset} or {@code longCount} is invalid.
400     * @exception ReadOnlyBufferException
401     *                if no changes may be made to the contents of this buffer.
402     */
403    public LongBuffer put(long[] src, int srcOffset, int longCount) {
404        Arrays.checkOffsetAndCount(src.length, srcOffset, longCount);
405        if (longCount > remaining()) {
406            throw new BufferOverflowException();
407        }
408        for (int i = srcOffset; i < srcOffset + longCount; ++i) {
409            put(src[i]);
410        }
411        return this;
412    }
413
414    /**
415     * Writes all the remaining longs of the {@code src} long buffer to this
416     * buffer's current position, and increases both buffers' position by the
417     * number of longs copied.
418     *
419     * @param src
420     *            the source long buffer.
421     * @return this buffer.
422     * @exception BufferOverflowException
423     *                if {@code src.remaining()} is greater than this buffer's
424     *                {@code remaining()}.
425     * @exception IllegalArgumentException
426     *                if {@code src} is this buffer.
427     * @exception ReadOnlyBufferException
428     *                if no changes may be made to the contents of this buffer.
429     */
430    public LongBuffer put(LongBuffer src) {
431        if (src == this) {
432            throw new IllegalArgumentException();
433        }
434        if (src.remaining() > remaining()) {
435            throw new BufferOverflowException();
436        }
437        long[] contents = new long[src.remaining()];
438        src.get(contents);
439        put(contents);
440        return this;
441    }
442
443    /**
444     * Writes a long to the specified index of this buffer; the position is not
445     * changed.
446     *
447     * @param index
448     *            the index, must not be negative and less than the limit.
449     * @param l
450     *            the long to write.
451     * @return this buffer.
452     * @exception IndexOutOfBoundsException
453     *                if index is invalid.
454     * @exception ReadOnlyBufferException
455     *                if no changes may be made to the contents of this buffer.
456     */
457    public abstract LongBuffer put(int index, long l);
458
459    /**
460     * Returns a sliced buffer that shares its content with this buffer.
461     * <p>
462     * The sliced buffer's capacity will be this buffer's {@code remaining()},
463     * and its zero position will correspond to this buffer's current position.
464     * The new buffer's position will be 0, limit will be its capacity, and its
465     * mark is cleared. The new buffer's read-only property and byte order are
466     * same as this buffer's.
467     * <p>
468     * The new buffer shares its content with this buffer, which means either
469     * buffer's change of content will be visible to the other. The two buffer's
470     * position, limit and mark are independent.
471     *
472     * @return a sliced buffer that shares its content with this buffer.
473     */
474    public abstract LongBuffer slice();
475}
476