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