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