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;
21import libcore.io.Memory;
22
23/**
24 * A buffer for bytes.
25 * <p>
26 * A byte buffer can be created in either one of the following ways:
27 * <ul>
28 * <li>{@link #allocate(int) Allocate} a new byte array and create a buffer
29 * based on it;</li>
30 * <li>{@link #allocateDirect(int) Allocate} a memory block and create a direct
31 * buffer based on it;</li>
32 * <li>{@link #wrap(byte[]) Wrap} an existing byte array to create a new
33 * buffer.</li>
34 * </ul>
35 *
36 */
37public abstract class ByteBuffer extends Buffer implements Comparable<ByteBuffer> {
38    /**
39     * The byte order of this buffer, default is {@code BIG_ENDIAN}.
40     */
41    ByteOrder order = ByteOrder.BIG_ENDIAN;
42
43    /**
44     * Creates a byte buffer based on a newly allocated byte array.
45     *
46     * @param capacity
47     *            the capacity of the new buffer
48     * @return the created byte buffer.
49     * @throws IllegalArgumentException
50     *             if {@code capacity < 0}.
51     */
52    public static ByteBuffer allocate(int capacity) {
53        if (capacity < 0) {
54            throw new IllegalArgumentException("capacity < 0: " + capacity);
55        }
56        return new ByteArrayBuffer(new byte[capacity]);
57    }
58
59    /**
60     * Creates a direct byte buffer based on a newly allocated memory block.
61     *
62     * @param capacity
63     *            the capacity of the new buffer
64     * @return the created byte buffer.
65     * @throws IllegalArgumentException
66     *             if {@code capacity < 0}.
67     */
68    public static ByteBuffer allocateDirect(int capacity) {
69        if (capacity < 0) {
70            throw new IllegalArgumentException("capacity < 0: " + capacity);
71        }
72        // Ensure alignment by 8.
73        MemoryBlock memoryBlock = MemoryBlock.allocate(capacity + 7);
74        long address = memoryBlock.toLong();
75        long alignedAddress = (address + 7) & ~(long)7;
76        return new DirectByteBuffer(memoryBlock, capacity, (int)(alignedAddress - address), false, null);
77    }
78
79    /**
80     * Creates a new byte buffer by wrapping the given byte array.
81     * <p>
82     * Calling this method has the same effect as
83     * {@code wrap(array, 0, array.length)}.
84     *
85     * @param array
86     *            the byte array which the new buffer will be based on
87     * @return the created byte buffer.
88     */
89    public static ByteBuffer wrap(byte[] array) {
90        return new ByteArrayBuffer(array);
91    }
92
93    /**
94     * Creates a new byte buffer by wrapping the given byte array.
95     * <p>
96     * The new buffer's position will be {@code start}, limit will be
97     * {@code start + byteCount}, capacity will be the length of the array.
98     *
99     * @param array
100     *            the byte array which the new buffer will be based on.
101     * @param start
102     *            the start index, must not be negative and not greater than
103     *            {@code array.length}.
104     * @param byteCount
105     *            the length, must not be negative and not greater than
106     *            {@code array.length - start}.
107     * @return the created byte buffer.
108     * @throws IndexOutOfBoundsException
109     *                if either {@code start} or {@code byteCount} is invalid.
110     */
111    public static ByteBuffer wrap(byte[] array, int start, int byteCount) {
112        Arrays.checkOffsetAndCount(array.length, start, byteCount);
113        ByteBuffer buf = new ByteArrayBuffer(array);
114        buf.position = start;
115        buf.limit = start + byteCount;
116        return buf;
117    }
118
119    ByteBuffer(int capacity, long effectiveDirectAddress) {
120        super(0, capacity, effectiveDirectAddress);
121    }
122
123    /**
124     * Returns the byte array which this buffer is based on, if there is one.
125     *
126     * @return the byte array which this buffer is based on.
127     * @throws ReadOnlyBufferException
128     *                if this buffer is based on a read-only array.
129     * @throws UnsupportedOperationException
130     *                if this buffer is not based on an array.
131     */
132    @Override public final byte[] array() {
133        return protectedArray();
134    }
135
136    /**
137     * Returns the offset of the byte array which this buffer is based on, if
138     * there is one.
139     * <p>
140     * The offset is the index of the array which corresponds to the zero
141     * position of the buffer.
142     *
143     * @return the offset of the byte array which this buffer is based on.
144     * @throws ReadOnlyBufferException
145     *                if this buffer is based on a read-only array.
146     * @throws UnsupportedOperationException
147     *                if this buffer is not based on an array.
148     */
149    @Override public final int arrayOffset() {
150        return protectedArrayOffset();
151    }
152
153    /**
154     * Returns a char buffer which is based on the remaining content of this
155     * byte buffer.
156     * <p>
157     * The new buffer's position is zero, its limit and capacity is the number
158     * of remaining bytes divided by two, and its mark is not set. The new
159     * buffer's read-only property and byte order are the same as this buffer's.
160     * The new buffer is direct if this byte buffer is direct.
161     * <p>
162     * The new buffer shares its content with this buffer, which means either
163     * buffer's change of content will be visible to the other. The two buffers'
164     * position, limit and mark are independent.
165     */
166    public abstract CharBuffer asCharBuffer();
167
168    /**
169     * Returns a double buffer which is based on the remaining content of this
170     * byte buffer.
171     * <p>
172     * The new buffer's position is zero, its limit and capacity is the number
173     * of remaining bytes divided by eight, and its mark is not set. The new
174     * buffer's read-only property and byte order are the same as this buffer's.
175     * The new buffer is direct if this byte buffer is direct.
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 buffers'
179     * position, limit and mark are independent.
180     */
181    public abstract DoubleBuffer asDoubleBuffer();
182
183    /**
184     * Returns a float buffer which is based on the remaining content of this
185     * byte buffer.
186     * <p>
187     * The new buffer's position is zero, its limit and capacity is the number
188     * of remaining bytes divided by four, and its mark is not set. The new
189     * buffer's read-only property and byte order are the same as this buffer's.
190     * The new buffer is direct if this byte buffer is direct.
191     * <p>
192     * The new buffer shares its content with this buffer, which means either
193     * buffer's change of content will be visible to the other. The two buffers'
194     * position, limit and mark are independent.
195     */
196    public abstract FloatBuffer asFloatBuffer();
197
198    /**
199     * Returns a int buffer which is based on the remaining content of this byte
200     * buffer.
201     * <p>
202     * The new buffer's position is zero, its limit and capacity is the number
203     * of remaining bytes divided by four, and its mark is not set. The new
204     * buffer's read-only property and byte order are the same as this buffer's.
205     * The new buffer is direct if this byte buffer is direct.
206     * <p>
207     * The new buffer shares its content with this buffer, which means either
208     * buffer's change of content will be visible to the other. The two buffers'
209     * position, limit and mark are independent.
210     */
211    public abstract IntBuffer asIntBuffer();
212
213    /**
214     * Returns a long buffer which is based on the remaining content of this
215     * byte buffer.
216     * <p>
217     * The new buffer's position is zero, its limit and capacity is the number
218     * of remaining bytes divided by eight, and its mark is not set. The new
219     * buffer's read-only property and byte order are the same as this buffer's.
220     * The new buffer is direct if this byte buffer is direct.
221     * <p>
222     * The new buffer shares its content with this buffer, which means either
223     * buffer's change of content will be visible to the other. The two buffers'
224     * position, limit and mark are independent.
225     */
226    public abstract LongBuffer asLongBuffer();
227
228    /**
229     * Returns a read-only buffer that shares its content with this buffer.
230     * <p>
231     * The returned buffer is guaranteed to be a new instance, even if this
232     * buffer is read-only itself. The new buffer's position, limit, capacity
233     * and mark are the same as this buffer.
234     * <p>
235     * The new buffer shares its content with this buffer, which means this
236     * buffer's change of content will be visible to the new buffer. The two
237     * buffer's position, limit and mark are independent.
238     *
239     * @return a read-only version of this buffer.
240     */
241    public abstract ByteBuffer asReadOnlyBuffer();
242
243    /**
244     * Returns a short buffer which is based on the remaining content of this
245     * byte buffer.
246     * <p>
247     * The new buffer's position is zero, its limit and capacity is the number
248     * of remaining bytes divided by two, and its mark is not set. The new
249     * buffer's read-only property and byte order are the same as this buffer's.
250     * The new buffer is direct if this byte buffer is direct.
251     * <p>
252     * The new buffer shares its content with this buffer, which means either
253     * buffer's change of content will be visible to the other. The two buffers'
254     * position, limit and mark are independent.
255     */
256    public abstract ShortBuffer asShortBuffer();
257
258    /**
259     * Compacts this byte buffer.
260     * <p>
261     * The remaining bytes will be moved to the head of the
262     * buffer, starting from position zero. Then the position is set to
263     * {@code remaining()}; the limit is set to capacity; the mark is
264     * cleared.
265     *
266     * @return {@code this}
267     * @throws ReadOnlyBufferException
268     *                if no changes may be made to the contents of this buffer.
269     */
270    public abstract ByteBuffer compact();
271
272    /**
273     * Compares the remaining bytes of this buffer to another byte buffer's
274     * remaining bytes.
275     *
276     * @param otherBuffer
277     *            another byte buffer.
278     * @return a negative value if this is less than {@code other}; 0 if this
279     *         equals to {@code other}; a positive value if this is greater
280     *         than {@code other}.
281     * @throws ClassCastException
282     *                if {@code other} is not a byte buffer.
283     */
284    @Override public int compareTo(ByteBuffer otherBuffer) {
285        int compareRemaining = (remaining() < otherBuffer.remaining()) ? remaining()
286                : otherBuffer.remaining();
287        int thisPos = position;
288        int otherPos = otherBuffer.position;
289        byte thisByte, otherByte;
290        while (compareRemaining > 0) {
291            thisByte = get(thisPos);
292            otherByte = otherBuffer.get(otherPos);
293            if (thisByte != otherByte) {
294                return thisByte < otherByte ? -1 : 1;
295            }
296            thisPos++;
297            otherPos++;
298            compareRemaining--;
299        }
300        return remaining() - otherBuffer.remaining();
301    }
302
303    /**
304     * Returns a duplicated buffer that shares its content with this buffer.
305     * <p>
306     * The duplicated buffer's position, limit, capacity and mark are the same
307     * as this buffer's. The duplicated buffer's read-only property is the same
308     * as this buffer's.
309     *
310     * <p>Note that <i>in contrast to all non-{@code byte} buffers</i>,
311     * byte order is not preserved in the duplicate, and is instead set to
312     * big-endian.
313     *
314     * <p>The new buffer shares its content with this buffer, which means either
315     * buffer's change of content will be visible to the other. The two buffers'
316     * position, limit and mark are independent.
317     */
318    public abstract ByteBuffer duplicate();
319
320    /**
321     * Checks whether this byte buffer is equal to another object.
322     * <p>
323     * If {@code other} is not a byte buffer then {@code false} is returned. Two
324     * byte buffers are equal if and only if their remaining bytes are exactly
325     * the same. Position, limit, capacity and mark are not considered.
326     *
327     * @param other
328     *            the object to compare with this byte buffer.
329     * @return {@code true} if this byte buffer is equal to {@code other},
330     *         {@code false} otherwise.
331     */
332    @Override
333    public boolean equals(Object other) {
334        if (!(other instanceof ByteBuffer)) {
335            return false;
336        }
337        ByteBuffer otherBuffer = (ByteBuffer) other;
338
339        if (remaining() != otherBuffer.remaining()) {
340            return false;
341        }
342
343        int myPosition = position;
344        int otherPosition = otherBuffer.position;
345        boolean equalSoFar = true;
346        while (equalSoFar && (myPosition < limit)) {
347            equalSoFar = get(myPosition++) == otherBuffer.get(otherPosition++);
348        }
349
350        return equalSoFar;
351    }
352
353    /**
354     * Returns the byte at the current position and increases the position by 1.
355     *
356     * @return the byte at the current position.
357     * @throws BufferUnderflowException
358     *                if the position is equal or greater than limit.
359     */
360    public abstract byte get();
361
362    /**
363     * Reads bytes from the current position into the specified byte array and
364     * increases the position by the number of bytes read.
365     * <p>
366     * Calling this method has the same effect as
367     * {@code get(dst, 0, dst.length)}.
368     *
369     * @param dst
370     *            the destination byte array.
371     * @return {@code this}
372     * @throws BufferUnderflowException
373     *                if {@code dst.length} is greater than {@code remaining()}.
374     */
375    public ByteBuffer get(byte[] dst) {
376        return get(dst, 0, dst.length);
377    }
378
379    /**
380     * Reads bytes from the current position into the specified byte array,
381     * starting at the specified offset, and increases the position by the
382     * number of bytes read.
383     *
384     * @param dst
385     *            the target byte array.
386     * @param dstOffset
387     *            the offset of the byte array, must not be negative and
388     *            not greater than {@code dst.length}.
389     * @param byteCount
390     *            the number of bytes to read, must not be negative and not
391     *            greater than {@code dst.length - dstOffset}
392     * @return {@code this}
393     * @throws IndexOutOfBoundsException if {@code dstOffset < 0 ||  byteCount < 0}
394     * @throws BufferUnderflowException if {@code byteCount > remaining()}
395     */
396    public ByteBuffer get(byte[] dst, int dstOffset, int byteCount) {
397        Arrays.checkOffsetAndCount(dst.length, dstOffset, byteCount);
398        if (byteCount > remaining()) {
399            throw new BufferUnderflowException();
400        }
401        for (int i = dstOffset; i < dstOffset + byteCount; ++i) {
402            dst[i] = get();
403        }
404        return this;
405    }
406
407    /**
408     * Returns the byte at the specified index and does not change the position.
409     *
410     * @param index
411     *            the index, must not be negative and less than limit.
412     * @return the byte at the specified index.
413     * @throws IndexOutOfBoundsException
414     *                if index is invalid.
415     */
416    public abstract byte get(int index);
417
418    /**
419     * Returns the char at the current position and increases the position by 2.
420     * <p>
421     * The 2 bytes starting at the current position are composed into a char
422     * according to the current byte order and returned.
423     *
424     * @return the char at the current position.
425     * @throws BufferUnderflowException
426     *                if the position is greater than {@code limit - 2}.
427     */
428    public abstract char getChar();
429
430    /**
431     * Returns the char at the specified index.
432     * <p>
433     * The 2 bytes starting from the specified index are composed into a char
434     * according to the current byte order and returned. The position is not
435     * changed.
436     *
437     * @param index
438     *            the index, must not be negative and equal or less than
439     *            {@code limit - 2}.
440     * @return the char at the specified index.
441     * @throws IndexOutOfBoundsException
442     *                if {@code index} is invalid.
443     */
444    public abstract char getChar(int index);
445
446    /**
447     * Returns the double at the current position and increases the position by
448     * 8.
449     * <p>
450     * The 8 bytes starting from the current position are composed into a double
451     * according to the current byte order and returned.
452     *
453     * @return the double at the current position.
454     * @throws BufferUnderflowException
455     *                if the position is greater than {@code limit - 8}.
456     */
457    public abstract double getDouble();
458
459    /**
460     * Returns the double at the specified index.
461     * <p>
462     * The 8 bytes starting at the specified index are composed into a double
463     * according to the current byte order and returned. The position is not
464     * changed.
465     *
466     * @param index
467     *            the index, must not be negative and equal or less than
468     *            {@code limit - 8}.
469     * @return the double at the specified index.
470     * @throws IndexOutOfBoundsException
471     *                if {@code index} is invalid.
472     */
473    public abstract double getDouble(int index);
474
475    /**
476     * Returns the float at the current position and increases the position by
477     * 4.
478     * <p>
479     * The 4 bytes starting at the current position are composed into a float
480     * according to the current byte order and returned.
481     *
482     * @return the float at the current position.
483     * @throws BufferUnderflowException
484     *                if the position is greater than {@code limit - 4}.
485     */
486    public abstract float getFloat();
487
488    /**
489     * Returns the float at the specified index.
490     * <p>
491     * The 4 bytes starting at the specified index are composed into a float
492     * according to the current byte order and returned. The position is not
493     * changed.
494     *
495     * @param index
496     *            the index, must not be negative and equal or less than
497     *            {@code limit - 4}.
498     * @return the float at the specified index.
499     * @throws IndexOutOfBoundsException
500     *                if {@code index} is invalid.
501     */
502    public abstract float getFloat(int index);
503
504    /**
505     * Returns the int at the current position and increases the position by 4.
506     * <p>
507     * The 4 bytes starting at the current position are composed into a int
508     * according to the current byte order and returned.
509     *
510     * @return the int at the current position.
511     * @throws BufferUnderflowException
512     *                if the position is greater than {@code limit - 4}.
513     */
514    public abstract int getInt();
515
516    /**
517     * Returns the int at the specified index.
518     * <p>
519     * The 4 bytes starting at the specified index are composed into a int
520     * according to the current byte order and returned. The position is not
521     * changed.
522     *
523     * @param index
524     *            the index, must not be negative and equal or less than
525     *            {@code limit - 4}.
526     * @return the int at the specified index.
527     * @throws IndexOutOfBoundsException
528     *                if {@code index} is invalid.
529     */
530    public abstract int getInt(int index);
531
532    /**
533     * Returns the long at the current position and increases the position by 8.
534     * <p>
535     * The 8 bytes starting at the current position are composed into a long
536     * according to the current byte order and returned.
537     *
538     * @return the long at the current position.
539     * @throws BufferUnderflowException
540     *                if the position is greater than {@code limit - 8}.
541     */
542    public abstract long getLong();
543
544    /**
545     * Returns the long at the specified index.
546     * <p>
547     * The 8 bytes starting at the specified index are composed into a long
548     * according to the current byte order and returned. The position is not
549     * changed.
550     *
551     * @param index
552     *            the index, must not be negative and equal or less than
553     *            {@code limit - 8}.
554     * @return the long at the specified index.
555     * @throws IndexOutOfBoundsException
556     *                if {@code index} is invalid.
557     */
558    public abstract long getLong(int index);
559
560    /**
561     * Returns the short at the current position and increases the position by 2.
562     * <p>
563     * The 2 bytes starting at the current position are composed into a short
564     * according to the current byte order and returned.
565     *
566     * @return the short at the current position.
567     * @throws BufferUnderflowException
568     *                if the position is greater than {@code limit - 2}.
569     */
570    public abstract short getShort();
571
572    /**
573     * Returns the short at the specified index.
574     * <p>
575     * The 2 bytes starting at the specified index are composed into a short
576     * according to the current byte order and returned. The position is not
577     * changed.
578     *
579     * @param index
580     *            the index, must not be negative and equal or less than
581     *            {@code limit - 2}.
582     * @return the short at the specified index.
583     * @throws IndexOutOfBoundsException
584     *                if {@code index} is invalid.
585     */
586    public abstract short getShort(int index);
587
588    @Override public final boolean hasArray() {
589        return protectedHasArray();
590    }
591
592    /**
593     * Calculates this buffer's hash code from the remaining chars. The
594     * position, limit, capacity and mark don't affect the hash code.
595     *
596     * @return the hash code calculated from the remaining bytes.
597     */
598    @Override
599    public int hashCode() {
600        int myPosition = position;
601        int hash = 0;
602        while (myPosition < limit) {
603            hash = hash + get(myPosition++);
604        }
605        return hash;
606    }
607
608    /**
609     * Indicates whether this buffer is direct.
610     *
611     * @return {@code true} if this buffer is direct, {@code false} otherwise.
612     */
613    @Override public abstract boolean isDirect();
614
615    /**
616     * Indicates whether this buffer is still accessible.
617     *
618     * @return {@code true} if this buffer is accessible, {@code false} if the
619     *         buffer was made inaccessible (e.g. freed) and should not be used.
620     * @hide
621     */
622    public boolean isAccessible() {
623        return true;
624    }
625
626    /**
627     * Sets buffer accessibility (only supported for direct byte buffers). If
628     * {@code accessible} is {@code false}, {@link #isAccessible} will return
629     * false, and any attempt to access the buffer will throw an exception. If
630     * {@code true}, the buffer will become useable again, unless it has been
631     * freed.
632     *
633     * @hide
634     */
635    public void setAccessible(boolean accessible) {
636        throw new UnsupportedOperationException();
637    }
638
639    /**
640     * Returns the byte order used by this buffer when converting bytes from/to
641     * other primitive types.
642     * <p>
643     * The default byte order of byte buffer is always
644     * {@link ByteOrder#BIG_ENDIAN BIG_ENDIAN}
645     *
646     * @return the byte order used by this buffer when converting bytes from/to
647     *         other primitive types.
648     */
649    public final ByteOrder order() {
650        return order;
651    }
652
653    /**
654     * Sets the byte order of this buffer.
655     *
656     * @param byteOrder
657     *            the byte order to set. If {@code null} then the order
658     *            will be {@link ByteOrder#LITTLE_ENDIAN LITTLE_ENDIAN}.
659     * @return {@code this}
660     * @see ByteOrder
661     */
662    public final ByteBuffer order(ByteOrder byteOrder) {
663        if (byteOrder == null) {
664            byteOrder = ByteOrder.LITTLE_ENDIAN;
665        }
666        order = byteOrder;
667        return this;
668    }
669
670    /**
671     * Child class implements this method to realize {@code array()}.
672     *
673     * @see #array()
674     */
675    abstract byte[] protectedArray();
676
677    /**
678     * Child class implements this method to realize {@code arrayOffset()}.
679     *
680     * @see #arrayOffset()
681     */
682    abstract int protectedArrayOffset();
683
684    /**
685     * Child class implements this method to realize {@code hasArray()}.
686     *
687     * @see #hasArray()
688     */
689    abstract boolean protectedHasArray();
690
691    /**
692     * Writes the given byte to the current position and increases the position
693     * by 1.
694     *
695     * @param b
696     *            the byte to write.
697     * @return {@code this}
698     * @throws BufferOverflowException
699     *                if position is equal or greater than limit.
700     * @throws ReadOnlyBufferException
701     *                if no changes may be made to the contents of this buffer.
702     */
703    public abstract ByteBuffer put(byte b);
704
705    /**
706     * Writes bytes in the given byte array to the current position and
707     * increases the position by the number of bytes written.
708     * <p>
709     * Calling this method has the same effect as
710     * {@code put(src, 0, src.length)}.
711     *
712     * @param src
713     *            the source byte array.
714     * @return {@code this}
715     * @throws BufferOverflowException
716     *                if {@code remaining()} is less than {@code src.length}.
717     * @throws ReadOnlyBufferException
718     *                if no changes may be made to the contents of this buffer.
719     */
720    public final ByteBuffer put(byte[] src) {
721        return put(src, 0, src.length);
722    }
723
724    /**
725     * Writes bytes in the given byte array, starting from the specified offset,
726     * to the current position and increases the position by the number of bytes
727     * written.
728     *
729     * @param src
730     *            the source byte array.
731     * @param srcOffset
732     *            the offset of byte array, must not be negative and not greater
733     *            than {@code src.length}.
734     * @param byteCount
735     *            the number of bytes to write, must not be negative and not
736     *            greater than {@code src.length - srcOffset}.
737     * @return {@code this}
738     * @throws BufferOverflowException
739     *                if {@code remaining()} is less than {@code byteCount}.
740     * @throws IndexOutOfBoundsException
741     *                if either {@code srcOffset} or {@code byteCount} is invalid.
742     * @throws ReadOnlyBufferException
743     *                if no changes may be made to the contents of this buffer.
744     */
745    public ByteBuffer put(byte[] src, int srcOffset, int byteCount) {
746        Arrays.checkOffsetAndCount(src.length, srcOffset, byteCount);
747        if (byteCount > remaining()) {
748            throw new BufferOverflowException();
749        }
750        for (int i = srcOffset; i < srcOffset + byteCount; ++i) {
751            put(src[i]);
752        }
753        return this;
754    }
755
756    /**
757     * Writes all the remaining bytes of the {@code src} byte buffer to this
758     * buffer's current position, and increases both buffers' position by the
759     * number of bytes copied.
760     *
761     * @param src
762     *            the source byte buffer.
763     * @return {@code this}
764     * @throws BufferOverflowException
765     *                if {@code src.remaining()} is greater than this buffer's
766     *                {@code remaining()}.
767     * @throws IllegalArgumentException
768     *                if {@code src} is this buffer.
769     * @throws ReadOnlyBufferException
770     *                if no changes may be made to the contents of this buffer.
771     */
772    public ByteBuffer put(ByteBuffer src) {
773        if (!isAccessible()) {
774            throw new IllegalStateException("buffer is inaccessible");
775        }
776        if (isReadOnly()) {
777            throw new ReadOnlyBufferException();
778        }
779        if (src == this) {
780            throw new IllegalArgumentException("src == this");
781        }
782        if (!src.isAccessible()) {
783            throw new IllegalStateException("src buffer is inaccessible");
784        }
785        int srcByteCount = src.remaining();
786        if (srcByteCount > remaining()) {
787            throw new BufferOverflowException();
788        }
789
790        Object srcObject = src.isDirect() ? src : NioUtils.unsafeArray(src);
791        int srcOffset = src.position();
792        if (!src.isDirect()) {
793            srcOffset += NioUtils.unsafeArrayOffset(src);
794        }
795
796        ByteBuffer dst = this;
797        Object dstObject = dst.isDirect() ? dst : NioUtils.unsafeArray(dst);
798        int dstOffset = dst.position();
799        if (!dst.isDirect()) {
800            dstOffset += NioUtils.unsafeArrayOffset(dst);
801        }
802
803        Memory.memmove(dstObject, dstOffset, srcObject, srcOffset, srcByteCount);
804        src.position(src.limit());
805        dst.position(dst.position() + srcByteCount);
806
807        return this;
808    }
809
810    /**
811     * Write a byte to the specified index of this buffer without changing the
812     * position.
813     *
814     * @param index
815     *            the index, must not be negative and less than the limit.
816     * @param b
817     *            the byte to write.
818     * @return {@code this}
819     * @throws IndexOutOfBoundsException
820     *                if {@code index} is invalid.
821     * @throws ReadOnlyBufferException
822     *                if no changes may be made to the contents of this buffer.
823     */
824    public abstract ByteBuffer put(int index, byte b);
825
826    /**
827     * Writes the given char to the current position and increases the position
828     * by 2.
829     * <p>
830     * The char is converted to bytes using the current byte order.
831     *
832     * @param value
833     *            the char to write.
834     * @return {@code this}
835     * @throws BufferOverflowException
836     *                if position is greater than {@code limit - 2}.
837     * @throws ReadOnlyBufferException
838     *                if no changes may be made to the contents of this buffer.
839     */
840    public abstract ByteBuffer putChar(char value);
841
842    /**
843     * Writes the given char to the specified index of this buffer.
844     * <p>
845     * The char is converted to bytes using the current byte order. The position
846     * is not changed.
847     *
848     * @param index
849     *            the index, must not be negative and equal or less than
850     *            {@code limit - 2}.
851     * @param value
852     *            the char to write.
853     * @return {@code this}
854     * @throws IndexOutOfBoundsException
855     *                if {@code index} is invalid.
856     * @throws ReadOnlyBufferException
857     *                if no changes may be made to the contents of this buffer.
858     */
859    public abstract ByteBuffer putChar(int index, char value);
860
861    /**
862     * Writes the given double to the current position and increases the position
863     * by 8.
864     * <p>
865     * The double is converted to bytes using the current byte order.
866     *
867     * @param value
868     *            the double to write.
869     * @return {@code this}
870     * @throws BufferOverflowException
871     *                if position is greater than {@code limit - 8}.
872     * @throws ReadOnlyBufferException
873     *                if no changes may be made to the contents of this buffer.
874     */
875    public abstract ByteBuffer putDouble(double value);
876
877    /**
878     * Writes the given double to the specified index of this buffer.
879     * <p>
880     * The double is converted to bytes using the current byte order. The
881     * position is not changed.
882     *
883     * @param index
884     *            the index, must not be negative and equal or less than
885     *            {@code limit - 8}.
886     * @param value
887     *            the double to write.
888     * @return {@code this}
889     * @throws IndexOutOfBoundsException
890     *                if {@code index} is invalid.
891     * @throws ReadOnlyBufferException
892     *                if no changes may be made to the contents of this buffer.
893     */
894    public abstract ByteBuffer putDouble(int index, double value);
895
896    /**
897     * Writes the given float to the current position and increases the position
898     * by 4.
899     * <p>
900     * The float is converted to bytes using the current byte order.
901     *
902     * @param value
903     *            the float to write.
904     * @return {@code this}
905     * @throws BufferOverflowException
906     *                if position is greater than {@code limit - 4}.
907     * @throws ReadOnlyBufferException
908     *                if no changes may be made to the contents of this buffer.
909     */
910    public abstract ByteBuffer putFloat(float value);
911
912    /**
913     * Writes the given float to the specified index of this buffer.
914     * <p>
915     * The float is converted to bytes using the current byte order. The
916     * position is not changed.
917     *
918     * @param index
919     *            the index, must not be negative and equal or less than
920     *            {@code limit - 4}.
921     * @param value
922     *            the float to write.
923     * @return {@code this}
924     * @throws IndexOutOfBoundsException
925     *                if {@code index} is invalid.
926     * @throws ReadOnlyBufferException
927     *                if no changes may be made to the contents of this buffer.
928     */
929    public abstract ByteBuffer putFloat(int index, float value);
930
931    /**
932     * Writes the given int to the current position and increases the position by
933     * 4.
934     * <p>
935     * The int is converted to bytes using the current byte order.
936     *
937     * @param value
938     *            the int to write.
939     * @return {@code this}
940     * @throws BufferOverflowException
941     *                if position is greater than {@code limit - 4}.
942     * @throws ReadOnlyBufferException
943     *                if no changes may be made to the contents of this buffer.
944     */
945    public abstract ByteBuffer putInt(int value);
946
947    /**
948     * Writes the given int to the specified index of this buffer.
949     * <p>
950     * The int is converted to bytes using the current byte order. The position
951     * is not changed.
952     *
953     * @param index
954     *            the index, must not be negative and equal or less than
955     *            {@code limit - 4}.
956     * @param value
957     *            the int to write.
958     * @return {@code this}
959     * @throws IndexOutOfBoundsException
960     *                if {@code index} is invalid.
961     * @throws ReadOnlyBufferException
962     *                if no changes may be made to the contents of this buffer.
963     */
964    public abstract ByteBuffer putInt(int index, int value);
965
966    /**
967     * Writes the given long to the current position and increases the position
968     * by 8.
969     * <p>
970     * The long is converted to bytes using the current byte order.
971     *
972     * @param value
973     *            the long to write.
974     * @return {@code this}
975     * @throws BufferOverflowException
976     *                if position is greater than {@code limit - 8}.
977     * @throws ReadOnlyBufferException
978     *                if no changes may be made to the contents of this buffer.
979     */
980    public abstract ByteBuffer putLong(long value);
981
982    /**
983     * Writes the given long to the specified index of this buffer.
984     * <p>
985     * The long is converted to bytes using the current byte order. The position
986     * is not changed.
987     *
988     * @param index
989     *            the index, must not be negative and equal or less than
990     *            {@code limit - 8}.
991     * @param value
992     *            the long to write.
993     * @return {@code this}
994     * @throws IndexOutOfBoundsException
995     *                if {@code index} is invalid.
996     * @throws ReadOnlyBufferException
997     *                if no changes may be made to the contents of this buffer.
998     */
999    public abstract ByteBuffer putLong(int index, long value);
1000
1001    /**
1002     * Writes the given short to the current position and increases the position
1003     * by 2.
1004     * <p>
1005     * The short is converted to bytes using the current byte order.
1006     *
1007     * @param value
1008     *            the short to write.
1009     * @return {@code this}
1010     * @throws BufferOverflowException
1011     *                if position is greater than {@code limit - 2}.
1012     * @throws ReadOnlyBufferException
1013     *                if no changes may be made to the contents of this buffer.
1014     */
1015    public abstract ByteBuffer putShort(short value);
1016
1017    /**
1018     * Writes the given short to the specified index of this buffer.
1019     * <p>
1020     * The short is converted to bytes using the current byte order. The
1021     * position is not changed.
1022     *
1023     * @param index
1024     *            the index, must not be negative and equal or less than
1025     *            {@code limit - 2}.
1026     * @param value
1027     *            the short to write.
1028     * @return {@code this}
1029     * @throws IndexOutOfBoundsException
1030     *                if {@code index} is invalid.
1031     * @throws ReadOnlyBufferException
1032     *                if no changes may be made to the contents of this buffer.
1033     */
1034    public abstract ByteBuffer putShort(int index, short value);
1035
1036    /**
1037     * Returns a sliced buffer that shares its content with this buffer.
1038     * <p>
1039     * The sliced buffer's capacity will be this buffer's
1040     * {@code remaining()}, and it's zero position will correspond to
1041     * this buffer's current position. The new buffer's position will be 0,
1042     * limit will be its capacity, and its mark is cleared. The new buffer's
1043     * read-only property and byte order are the same as this buffer's.
1044     * <p>
1045     * The new buffer shares its content with this buffer, which means either
1046     * buffer's change of content will be visible to the other. The two buffers'
1047     * position, limit and mark are independent.
1048     */
1049    public abstract ByteBuffer slice();
1050}
1051