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