View Javadoc
1   /*
2    *  Licensed to the Apache Software Foundation (ASF) under one
3    *  or more contributor license agreements.  See the NOTICE file
4    *  distributed with this work for additional information
5    *  regarding copyright ownership.  The ASF licenses this file
6    *  to you under the Apache License, Version 2.0 (the
7    *  "License"); you may not use this file except in compliance
8    *  with the License.  You may obtain a copy of the License at
9    *
10   *    http://www.apache.org/licenses/LICENSE-2.0
11   *
12   *  Unless required by applicable law or agreed to in writing,
13   *  software distributed under the License is distributed on an
14   *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   *  KIND, either express or implied.  See the License for the
16   *  specific language governing permissions and limitations
17   *  under the License.
18   *
19   */
20  package org.apache.mina.core.buffer;
21  
22  import java.io.EOFException;
23  import java.io.IOException;
24  import java.io.InputStream;
25  import java.io.ObjectInputStream;
26  import java.io.ObjectOutputStream;
27  import java.io.ObjectStreamClass;
28  import java.io.OutputStream;
29  import java.io.Serializable;
30  import java.io.StreamCorruptedException;
31  import java.nio.BufferOverflowException;
32  import java.nio.BufferUnderflowException;
33  import java.nio.ByteBuffer;
34  import java.nio.ByteOrder;
35  import java.nio.CharBuffer;
36  import java.nio.DoubleBuffer;
37  import java.nio.FloatBuffer;
38  import java.nio.IntBuffer;
39  import java.nio.LongBuffer;
40  import java.nio.ShortBuffer;
41  import java.nio.charset.CharacterCodingException;
42  import java.nio.charset.CharsetDecoder;
43  import java.nio.charset.CharsetEncoder;
44  import java.nio.charset.CoderResult;
45  import java.nio.charset.StandardCharsets;
46  import java.util.EnumSet;
47  import java.util.Set;
48  
49  /**
50   * A base implementation of {@link IoBuffer}.  This implementation
51   * assumes that {@link IoBuffer#buf()} always returns a correct NIO
52   * {@link ByteBuffer} instance.  Most implementations could
53   * extend this class and implement their own buffer management mechanism.
54   *
55   * @author <a href="http://mina.apache.org">Apache MINA Project</a>
56   * @see IoBufferAllocator
57   */
58  public abstract class AbstractIoBuffer extends IoBuffer {
59      /** Tells if a buffer has been created from an existing buffer */
60      private final boolean derived;
61  
62      /** A flag set to true if the buffer can extend automatically */
63      private boolean autoExpand;
64  
65      /** A flag set to true if the buffer can shrink automatically */
66      private boolean autoShrink;
67  
68      /** Tells if a buffer can be expanded */
69      private boolean recapacityAllowed = true;
70  
71      /** The minimum number of bytes the IoBuffer can hold */
72      private int minimumCapacity;
73  
74      /** A mask for a byte */
75      private static final long BYTE_MASK = 0xFFL;
76  
77      /** A mask for a short */
78      private static final long SHORT_MASK = 0xFFFFL;
79  
80      /** A mask for an int */
81      private static final long INT_MASK = 0xFFFFFFFFL;
82  
83      /**
84       * We don't have any access to Buffer.markValue(), so we need to track it down,
85       * which will cause small extra overhead.
86       */
87      private int mark = -1;
88  
89      /**
90       * Creates a new parent buffer.
91       * 
92       * @param allocator The allocator to use to create new buffers
93       * @param initialCapacity The initial buffer capacity when created
94       */
95      protected AbstractIoBuffer(IoBufferAllocator allocator, int initialCapacity) {
96          setAllocator(allocator);
97          this.recapacityAllowed = true;
98          this.derived = false;
99          this.minimumCapacity = initialCapacity;
100     }
101 
102     /**
103      * Creates a new derived buffer. A derived buffer uses an existing
104      * buffer properties - the allocator and capacity -.
105      * 
106      * @param parent The buffer we get the properties from
107      */
108     protected AbstractIoBuffer(AbstractIoBuffer parent) {
109         setAllocator(IoBuffer.getAllocator());
110         this.recapacityAllowed = false;
111         this.derived = true;
112         this.minimumCapacity = parent.minimumCapacity;
113     }
114 
115     /**
116      * {@inheritDoc}
117      */
118     @Override
119     public final boolean isDirect() {
120         return buf().isDirect();
121     }
122 
123     /**
124      * {@inheritDoc}
125      */
126     @Override
127     public final boolean isReadOnly() {
128         return buf().isReadOnly();
129     }
130 
131     /**
132      * Sets the underlying NIO buffer instance.
133      * 
134      * @param newBuf The buffer to store within this IoBuffer
135      */
136     protected abstract void buf(ByteBuffer newBuf);
137 
138     /**
139      * {@inheritDoc}
140      */
141     @Override
142     public final int minimumCapacity() {
143         return minimumCapacity;
144     }
145 
146     /**
147      * {@inheritDoc}
148      */
149     @Override
150     public final IoBuffer minimumCapacity(int minimumCapacity) {
151         if (minimumCapacity < 0) {
152             throw new IllegalArgumentException("minimumCapacity: " + minimumCapacity);
153         }
154         this.minimumCapacity = minimumCapacity;
155         return this;
156     }
157 
158     /**
159      * {@inheritDoc}
160      */
161     @Override
162     public final int capacity() {
163         return buf().capacity();
164     }
165 
166     /**
167      * {@inheritDoc}
168      */
169     @Override
170     public final IoBuffer capacity(int newCapacity) {
171         if (!recapacityAllowed) {
172             throw new IllegalStateException("Derived buffers and their parent can't be expanded.");
173         }
174 
175         // Allocate a new buffer and transfer all settings to it.
176         if (newCapacity > capacity()) {
177             // Expand:
178             //// Save the state.
179             int pos = position();
180             int limit = limit();
181             ByteOrder bo = order();
182 
183             //// Reallocate.
184             ByteBuffer oldBuf = buf();
185             ByteBuffer newBuf = getAllocator().allocateNioBuffer(newCapacity, isDirect());
186             oldBuf.clear();
187             newBuf.put(oldBuf);
188             buf(newBuf);
189 
190             //// Restore the state.
191             buf().limit(limit);
192             if (mark >= 0) {
193                 buf().position(mark);
194                 buf().mark();
195             }
196             buf().position(pos);
197             buf().order(bo);
198         }
199 
200         return this;
201     }
202 
203     /**
204      * {@inheritDoc}
205      */
206     @Override
207     public final boolean isAutoExpand() {
208         return autoExpand && recapacityAllowed;
209     }
210 
211     /**
212      * {@inheritDoc}
213      */
214     @Override
215     public final boolean isAutoShrink() {
216         return autoShrink && recapacityAllowed;
217     }
218 
219     /**
220      * {@inheritDoc}
221      */
222     @Override
223     public final boolean isDerived() {
224         return derived;
225     }
226 
227     /**
228      * {@inheritDoc}
229      */
230     @Override
231     public final IoBuffer setAutoExpand(boolean autoExpand) {
232         if (!recapacityAllowed) {
233             throw new IllegalStateException("Derived buffers and their parent can't be expanded.");
234         }
235         this.autoExpand = autoExpand;
236         return this;
237     }
238 
239     /**
240      * {@inheritDoc}
241      */
242     @Override
243     public final IoBuffer setAutoShrink(boolean autoShrink) {
244         if (!recapacityAllowed) {
245             throw new IllegalStateException("Derived buffers and their parent can't be shrinked.");
246         }
247         this.autoShrink = autoShrink;
248         return this;
249     }
250 
251     /**
252      * {@inheritDoc}
253      */
254     @Override
255     public final IoBuffer expand(int expectedRemaining) {
256         return expand(position(), expectedRemaining, false);
257     }
258 
259     private IoBuffer expand(int expectedRemaining, boolean autoExpand) {
260         return expand(position(), expectedRemaining, autoExpand);
261     }
262 
263     /**
264      * {@inheritDoc}
265      */
266     @Override
267     public final IoBuffer expand(int pos, int expectedRemaining) {
268         return expand(pos, expectedRemaining, false);
269     }
270 
271     private IoBuffer expand(int pos, int expectedRemaining, boolean autoExpand) {
272         if (!recapacityAllowed) {
273             throw new IllegalStateException("Derived buffers and their parent can't be expanded.");
274         }
275 
276         int end = pos + expectedRemaining;
277         int newCapacity;
278         
279         if (autoExpand) {
280             newCapacity = IoBuffer.normalizeCapacity(end);
281         } else {
282             newCapacity = end;
283         }
284         if (newCapacity > capacity()) {
285             // The buffer needs expansion.
286             capacity(newCapacity);
287         }
288 
289         if (end > limit()) {
290             // We call limit() directly to prevent StackOverflowError
291             buf().limit(end);
292         }
293         return this;
294     }
295 
296     /**
297      * {@inheritDoc}
298      */
299     @Override
300     public final IoBuffer shrink() {
301 
302         if (!recapacityAllowed) {
303             throw new IllegalStateException("Derived buffers and their parent can't be expanded.");
304         }
305 
306         int position = position();
307         int capacity = capacity();
308         int limit = limit();
309 
310         if (capacity == limit) {
311             return this;
312         }
313 
314         int newCapacity = capacity;
315         int minCapacity = Math.max(minimumCapacity, limit);
316 
317         for (;;) {
318             if (newCapacity >>> 1 < minCapacity) {
319                 break;
320             }
321 
322             newCapacity >>>= 1;
323 
324             if (minCapacity == 0) {
325                 break;
326             }
327         }
328 
329         newCapacity = Math.max(minCapacity, newCapacity);
330 
331         if (newCapacity == capacity) {
332             return this;
333         }
334 
335         // Shrink and compact:
336         //// Save the state.
337         ByteOrder bo = order();
338 
339         //// Reallocate.
340         ByteBuffer oldBuf = buf();
341         ByteBuffer newBuf = getAllocator().allocateNioBuffer(newCapacity, isDirect());
342         oldBuf.position(0);
343         oldBuf.limit(limit);
344         newBuf.put(oldBuf);
345         buf(newBuf);
346 
347         //// Restore the state.
348         buf().position(position);
349         buf().limit(limit);
350         buf().order(bo);
351         mark = -1;
352 
353         return this;
354     }
355 
356     /**
357      * {@inheritDoc}
358      */
359     @Override
360     public final int position() {
361         return buf().position();
362     }
363 
364     /**
365      * {@inheritDoc}
366      */
367     @Override
368     public final IoBuffer position(int newPosition) {
369         autoExpand(newPosition, 0);
370         buf().position(newPosition);
371         
372         if (mark > newPosition) {
373             mark = -1;
374         }
375         
376         return this;
377     }
378 
379     /**
380      * {@inheritDoc}
381      */
382     @Override
383     public final int limit() {
384         return buf().limit();
385     }
386 
387     /**
388      * {@inheritDoc}
389      */
390     @Override
391     public final IoBuffer limit(int newLimit) {
392         autoExpand(newLimit, 0);
393         buf().limit(newLimit);
394         if (mark > newLimit) {
395             mark = -1;
396         }
397         return this;
398     }
399 
400     /**
401      * {@inheritDoc}
402      */
403     @Override
404     public final IoBuffer mark() {
405         ByteBuffer byteBuffer = buf();
406         byteBuffer.mark();
407         mark = byteBuffer.position();
408 
409         return this;
410     }
411 
412     /**
413      * {@inheritDoc}
414      */
415     @Override
416     public final int markValue() {
417         return mark;
418     }
419 
420     /**
421      * {@inheritDoc}
422      */
423     @Override
424     public final IoBuffer reset() {
425         buf().reset();
426         return this;
427     }
428 
429     /**
430      * {@inheritDoc}
431      */
432     @Override
433     public final IoBuffer clear() {
434         buf().clear();
435         mark = -1;
436         return this;
437     }
438 
439     /**
440      * {@inheritDoc}
441      */
442     @Override
443     public final IoBuffer sweep() {
444         clear();
445         return fillAndReset(remaining());
446     }
447 
448     /**
449      * {@inheritDoc}
450      */
451     @Override
452     public final IoBuffer sweep(byte value) {
453         clear();
454         return fillAndReset(value, remaining());
455     }
456 
457     /**
458      * {@inheritDoc}
459      */
460     @Override
461     public final IoBuffer flip() {
462         buf().flip();
463         mark = -1;
464         return this;
465     }
466 
467     /**
468      * {@inheritDoc}
469      */
470     @Override
471     public final IoBuffer rewind() {
472         buf().rewind();
473         mark = -1;
474         return this;
475     }
476 
477     /**
478      * {@inheritDoc}
479      */
480     @Override
481     public final int remaining() {
482         ByteBuffer byteBuffer = buf();
483 
484         return byteBuffer.limit() - byteBuffer.position();
485     }
486 
487     /**
488      * {@inheritDoc}
489      */
490     @Override
491     public final boolean hasRemaining() {
492         ByteBuffer byteBuffer = buf();
493 
494         return byteBuffer.limit() > byteBuffer.position();
495     }
496 
497     /**
498      * {@inheritDoc}
499      */
500     @Override
501     public final byte get() {
502         return buf().get();
503     }
504 
505     /**
506      * {@inheritDoc}
507      */
508     @Override
509     public final short getUnsigned() {
510         return (short) (get() & 0xff);
511     }
512 
513     /**
514      * {@inheritDoc}
515      */
516     @Override
517     public final IoBuffer put(byte b) {
518         autoExpand(1);
519         buf().put(b);
520         return this;
521     }
522 
523     /**
524      * {@inheritDoc}
525      */
526     @Override
527     public IoBuffer putUnsigned(byte value) {
528         autoExpand(1);
529         buf().put((byte) (value & 0xff));
530         return this;
531     }
532 
533     /**
534      * {@inheritDoc}
535      */
536     @Override
537     public IoBuffer putUnsigned(int index, byte value) {
538         autoExpand(index, 1);
539         buf().put(index, (byte) (value & 0xff));
540         return this;
541     }
542 
543     /**
544      * {@inheritDoc}
545      */
546     @Override
547     public IoBuffer putUnsigned(short value) {
548         autoExpand(1);
549         buf().put((byte) (value & 0x00ff));
550         return this;
551     }
552 
553     /**
554      * {@inheritDoc}
555      */
556     @Override
557     public IoBuffer putUnsigned(int index, short value) {
558         autoExpand(index, 1);
559         buf().put(index, (byte) (value & 0x00ff));
560         return this;
561     }
562 
563     /**
564      * {@inheritDoc}
565      */
566     @Override
567     public IoBuffer putUnsigned(int value) {
568         autoExpand(1);
569         buf().put((byte) (value & 0x000000ff));
570         return this;
571     }
572 
573     /**
574      * {@inheritDoc}
575      */
576     @Override
577     public IoBuffer putUnsigned(int index, int value) {
578         autoExpand(index, 1);
579         buf().put(index, (byte) (value & 0x000000ff));
580         return this;
581     }
582 
583     /**
584      * {@inheritDoc}
585      */
586     @Override
587     public IoBuffer putUnsigned(long value) {
588         autoExpand(1);
589         buf().put((byte) (value & 0x00000000000000ffL));
590         return this;
591     }
592 
593     /**
594      * {@inheritDoc}
595      */
596     @Override
597     public IoBuffer putUnsigned(int index, long value) {
598         autoExpand(index, 1);
599         buf().put(index, (byte) (value & 0x00000000000000ffL));
600         return this;
601     }
602 
603     /**
604      * {@inheritDoc}
605      */
606     @Override
607     public final byte get(int index) {
608         return buf().get(index);
609     }
610 
611     /**
612      * {@inheritDoc}
613      */
614     @Override
615     public final short getUnsigned(int index) {
616         return (short) (get(index) & 0xff);
617     }
618 
619     /**
620      * {@inheritDoc}
621      */
622     @Override
623     public final IoBuffer put(int index, byte b) {
624         autoExpand(index, 1);
625         buf().put(index, b);
626         return this;
627     }
628 
629     /**
630      * {@inheritDoc}
631      */
632     @Override
633     public final IoBuffer get(byte[] dst, int offset, int length) {
634         buf().get(dst, offset, length);
635         return this;
636     }
637 
638     /**
639      * {@inheritDoc}
640      */
641     @Override
642     public final IoBuffer put(ByteBuffer src) {
643         autoExpand(src.remaining());
644         buf().put(src);
645         return this;
646     }
647 
648     /**
649      * {@inheritDoc}
650      */
651     @Override
652     public final IoBuffer put(byte[] src, int offset, int length) {
653         autoExpand(length);
654         buf().put(src, offset, length);
655         return this;
656     }
657 
658     /**
659      * {@inheritDoc}
660      */
661     @Override
662     public final IoBuffer compact() {
663         int remaining = remaining();
664         int capacity = capacity();
665 
666         if (capacity == 0) {
667             return this;
668         }
669 
670         if (isAutoShrink() && remaining <= capacity >>> 2 && capacity > minimumCapacity) {
671             int newCapacity = capacity;
672             int minCapacity = Math.max(minimumCapacity, remaining << 1);
673             for (;;) {
674                 if (newCapacity >>> 1 < minCapacity) {
675                     break;
676                 }
677                 newCapacity >>>= 1;
678             }
679 
680             newCapacity = Math.max(minCapacity, newCapacity);
681 
682             if (newCapacity == capacity) {
683                 return this;
684             }
685 
686             // Shrink and compact:
687             //// Save the state.
688             ByteOrder bo = order();
689 
690             //// Sanity check.
691             if (remaining > newCapacity) {
692                 throw new IllegalStateException("The amount of the remaining bytes is greater than "
693                         + "the new capacity.");
694             }
695 
696             //// Reallocate.
697             ByteBuffer oldBuf = buf();
698             ByteBuffer newBuf = getAllocator().allocateNioBuffer(newCapacity, isDirect());
699             newBuf.put(oldBuf);
700             buf(newBuf);
701 
702             //// Restore the state.
703             buf().order(bo);
704         } else {
705             buf().compact();
706         }
707         mark = -1;
708         return this;
709     }
710 
711     /**
712      * {@inheritDoc}
713      */
714     @Override
715     public final ByteOrder order() {
716         return buf().order();
717     }
718 
719     /**
720      * {@inheritDoc}
721      */
722     @Override
723     public final IoBuffer order(ByteOrder bo) {
724         buf().order(bo);
725         return this;
726     }
727 
728     /**
729      * {@inheritDoc}
730      */
731     @Override
732     public final char getChar() {
733         return buf().getChar();
734     }
735 
736     /**
737      * {@inheritDoc}
738      */
739     @Override
740     public final IoBuffer putChar(char value) {
741         autoExpand(2);
742         buf().putChar(value);
743         return this;
744     }
745 
746     /**
747      * {@inheritDoc}
748      */
749     @Override
750     public final char getChar(int index) {
751         return buf().getChar(index);
752     }
753 
754     /**
755      * {@inheritDoc}
756      */
757     @Override
758     public final IoBuffer putChar(int index, char value) {
759         autoExpand(index, 2);
760         buf().putChar(index, value);
761         return this;
762     }
763 
764     /**
765      * {@inheritDoc}
766      */
767     @Override
768     public final CharBuffer asCharBuffer() {
769         return buf().asCharBuffer();
770     }
771 
772     /**
773      * {@inheritDoc}
774      */
775     @Override
776     public final short getShort() {
777         return buf().getShort();
778     }
779 
780     /**
781      * {@inheritDoc}
782      */
783     @Override
784     public final IoBuffer putShort(short value) {
785         autoExpand(2);
786         buf().putShort(value);
787         return this;
788     }
789 
790     /**
791      * {@inheritDoc}
792      */
793     @Override
794     public final short getShort(int index) {
795         return buf().getShort(index);
796     }
797 
798     /**
799      * {@inheritDoc}
800      */
801     @Override
802     public final IoBuffer putShort(int index, short value) {
803         autoExpand(index, 2);
804         buf().putShort(index, value);
805         return this;
806     }
807 
808     /**
809      * {@inheritDoc}
810      */
811     @Override
812     public final ShortBuffer asShortBuffer() {
813         return buf().asShortBuffer();
814     }
815 
816     /**
817      * {@inheritDoc}
818      */
819     @Override
820     public final int getInt() {
821         return buf().getInt();
822     }
823 
824     /**
825      * {@inheritDoc}
826      */
827     @Override
828     public final IoBuffer putInt(int value) {
829         autoExpand(4);
830         buf().putInt(value);
831         return this;
832     }
833 
834     /**
835      * {@inheritDoc}
836      */
837     @Override
838     public final IoBuffer putUnsignedInt(byte value) {
839         autoExpand(4);
840         buf().putInt(value & 0x00ff);
841         return this;
842     }
843 
844     /**
845      * {@inheritDoc}
846      */
847     @Override
848     public final IoBuffer putUnsignedInt(int index, byte value) {
849         autoExpand(index, 4);
850         buf().putInt(index, value & 0x00ff);
851         return this;
852     }
853 
854     /**
855      * {@inheritDoc}
856      */
857     @Override
858     public final IoBuffer putUnsignedInt(short value) {
859         autoExpand(4);
860         buf().putInt(value & 0x0000ffff);
861         return this;
862     }
863 
864     /**
865      * {@inheritDoc}
866      */
867     @Override
868     public final IoBuffer putUnsignedInt(int index, short value) {
869         autoExpand(index, 4);
870         buf().putInt(index, value & 0x0000ffff);
871         return this;
872     }
873 
874     /**
875      * {@inheritDoc}
876      */
877     @Override
878     public final IoBuffer putUnsignedInt(int value) {
879         return putInt(value);
880     }
881 
882     /**
883      * {@inheritDoc}
884      */
885     @Override
886     public final IoBuffer putUnsignedInt(int index, int value) {
887         return putInt(index, value);
888     }
889 
890     /**
891      * {@inheritDoc}
892      */
893     @Override
894     public final IoBuffer putUnsignedInt(long value) {
895         autoExpand(4);
896         buf().putInt((int) (value & 0x00000000ffffffff));
897         return this;
898     }
899 
900     /**
901      * {@inheritDoc}
902      */
903     @Override
904     public final IoBuffer putUnsignedInt(int index, long value) {
905         autoExpand(index, 4);
906         buf().putInt(index, (int) (value & 0x00000000ffffffffL));
907         return this;
908     }
909 
910     /**
911      * {@inheritDoc}
912      */
913     @Override
914     public final IoBuffer putUnsignedShort(byte value) {
915         autoExpand(2);
916         buf().putShort((short) (value & 0x00ff));
917         return this;
918     }
919 
920     /**
921      * {@inheritDoc}
922      */
923     @Override
924     public final IoBuffer putUnsignedShort(int index, byte value) {
925         autoExpand(index, 2);
926         buf().putShort(index, (short) (value & 0x00ff));
927         return this;
928     }
929 
930     /**
931      * {@inheritDoc}
932      */
933     @Override
934     public final IoBuffer putUnsignedShort(short value) {
935         return putShort(value);
936     }
937 
938     /**
939      * {@inheritDoc}
940      */
941     @Override
942     public final IoBuffer putUnsignedShort(int index, short value) {
943         return putShort(index, value);
944     }
945 
946     /**
947      * {@inheritDoc}
948      */
949     @Override
950     public final IoBuffer putUnsignedShort(int value) {
951         autoExpand(2);
952         buf().putShort((short) value);
953         return this;
954     }
955 
956     /**
957      * {@inheritDoc}
958      */
959     @Override
960     public final IoBuffer putUnsignedShort(int index, int value) {
961         autoExpand(index, 2);
962         buf().putShort(index, (short) value);
963         return this;
964     }
965 
966     /**
967      * {@inheritDoc}
968      */
969     @Override
970     public final IoBuffer putUnsignedShort(long value) {
971         autoExpand(2);
972         buf().putShort((short) (value));
973         return this;
974     }
975 
976     /**
977      * {@inheritDoc}
978      */
979     @Override
980     public final IoBuffer putUnsignedShort(int index, long value) {
981         autoExpand(index, 2);
982         buf().putShort(index, (short) (value));
983         return this;
984     }
985 
986     /**
987      * {@inheritDoc}
988      */
989     @Override
990     public final int getInt(int index) {
991         return buf().getInt(index);
992     }
993 
994     /**
995      * {@inheritDoc}
996      */
997     @Override
998     public final IoBuffer putInt(int index, int value) {
999         autoExpand(index, 4);
1000         buf().putInt(index, value);
1001         return this;
1002     }
1003 
1004     /**
1005      * {@inheritDoc}
1006      */
1007     @Override
1008     public final IntBuffer asIntBuffer() {
1009         return buf().asIntBuffer();
1010     }
1011 
1012     /**
1013      * {@inheritDoc}
1014      */
1015     @Override
1016     public final long getLong() {
1017         return buf().getLong();
1018     }
1019 
1020     /**
1021      * {@inheritDoc}
1022      */
1023     @Override
1024     public final IoBuffer putLong(long value) {
1025         autoExpand(8);
1026         buf().putLong(value);
1027         return this;
1028     }
1029 
1030     /**
1031      * {@inheritDoc}
1032      */
1033     @Override
1034     public final long getLong(int index) {
1035         return buf().getLong(index);
1036     }
1037 
1038     /**
1039      * {@inheritDoc}
1040      */
1041     @Override
1042     public final IoBuffer putLong(int index, long value) {
1043         autoExpand(index, 8);
1044         buf().putLong(index, value);
1045         return this;
1046     }
1047 
1048     /**
1049      * {@inheritDoc}
1050      */
1051     @Override
1052     public final LongBuffer asLongBuffer() {
1053         return buf().asLongBuffer();
1054     }
1055 
1056     /**
1057      * {@inheritDoc}
1058      */
1059     @Override
1060     public final float getFloat() {
1061         return buf().getFloat();
1062     }
1063 
1064     /**
1065      * {@inheritDoc}
1066      */
1067     @Override
1068     public final IoBuffer putFloat(float value) {
1069         autoExpand(4);
1070         buf().putFloat(value);
1071         return this;
1072     }
1073 
1074     /**
1075      * {@inheritDoc}
1076      */
1077     @Override
1078     public final float getFloat(int index) {
1079         return buf().getFloat(index);
1080     }
1081 
1082     /**
1083      * {@inheritDoc}
1084      */
1085     @Override
1086     public final IoBuffer putFloat(int index, float value) {
1087         autoExpand(index, 4);
1088         buf().putFloat(index, value);
1089         return this;
1090     }
1091 
1092     /**
1093      * {@inheritDoc}
1094      */
1095     @Override
1096     public final FloatBuffer asFloatBuffer() {
1097         return buf().asFloatBuffer();
1098     }
1099 
1100     /**
1101      * {@inheritDoc}
1102      */
1103     @Override
1104     public final double getDouble() {
1105         return buf().getDouble();
1106     }
1107 
1108     /**
1109      * {@inheritDoc}
1110      */
1111     @Override
1112     public final IoBuffer putDouble(double value) {
1113         autoExpand(8);
1114         buf().putDouble(value);
1115         return this;
1116     }
1117 
1118     /**
1119      * {@inheritDoc}
1120      */
1121     @Override
1122     public final double getDouble(int index) {
1123         return buf().getDouble(index);
1124     }
1125 
1126     /**
1127      * {@inheritDoc}
1128      */
1129     @Override
1130     public final IoBuffer putDouble(int index, double value) {
1131         autoExpand(index, 8);
1132         buf().putDouble(index, value);
1133         return this;
1134     }
1135 
1136     /**
1137      * {@inheritDoc}
1138      */
1139     @Override
1140     public final DoubleBuffer asDoubleBuffer() {
1141         return buf().asDoubleBuffer();
1142     }
1143 
1144     /**
1145      * {@inheritDoc}
1146      */
1147     @Override
1148     public final IoBuffer asReadOnlyBuffer() {
1149         recapacityAllowed = false;
1150         return asReadOnlyBuffer0();
1151     }
1152 
1153     /**
1154      * Implement this method to return the unexpandable read only version of
1155      * this buffer.
1156      * 
1157      * @return the IoBoffer instance
1158      */
1159     protected abstract IoBuffer asReadOnlyBuffer0();
1160 
1161     /**
1162      * {@inheritDoc}
1163      */
1164     @Override
1165     public final IoBuffer duplicate() {
1166         recapacityAllowed = false;
1167         return duplicate0();
1168     }
1169 
1170     /**
1171      * Implement this method to return the unexpandable duplicate of this
1172      * buffer.
1173      * 
1174      * @return the IoBoffer instance
1175      */
1176     protected abstract IoBuffer duplicate0();
1177 
1178     /**
1179      * {@inheritDoc}
1180      */
1181     @Override
1182     public final IoBuffer slice() {
1183         recapacityAllowed = false;
1184         return slice0();
1185     }
1186 
1187     /**
1188      * {@inheritDoc}
1189      */
1190     @Override
1191     public final IoBuffer getSlice(int index, int length) {
1192         if (length < 0) {
1193             throw new IllegalArgumentException("length: " + length);
1194         }
1195 
1196         int pos = position();
1197         int limit = limit();
1198 
1199         if (index > limit) {
1200             throw new IllegalArgumentException("index: " + index);
1201         }
1202 
1203         int endIndex = index + length;
1204 
1205         if (endIndex > limit) {
1206             throw new IndexOutOfBoundsException("index + length (" + endIndex + ") is greater " + "than limit ("
1207                     + limit + ").");
1208         }
1209 
1210         clear();
1211         limit(endIndex);
1212         position(index);
1213 
1214         IoBuffer slice = slice();
1215         limit(limit);
1216         position(pos);
1217 
1218         return slice;
1219     }
1220 
1221     /**
1222      * {@inheritDoc}
1223      */
1224     @Override
1225     public final IoBuffer getSlice(int length) {
1226         if (length < 0) {
1227             throw new IllegalArgumentException("length: " + length);
1228         }
1229         int pos = position();
1230         int limit = limit();
1231         int nextPos = pos + length;
1232         if (limit < nextPos) {
1233             throw new IndexOutOfBoundsException("position + length (" + nextPos + ") is greater " + "than limit ("
1234                     + limit + ").");
1235         }
1236 
1237         limit(pos + length);
1238         IoBuffer slice = slice();
1239         position(nextPos);
1240         limit(limit);
1241         return slice;
1242     }
1243 
1244     /**
1245      * Implement this method to return the unexpandable slice of this
1246      * buffer.
1247      * 
1248      * @return the IoBoffer instance
1249      */
1250     protected abstract IoBuffer slice0();
1251 
1252     /**
1253      * {@inheritDoc}
1254      */
1255     @Override
1256     public int hashCode() {
1257         int h = 1;
1258         int p = position();
1259         for (int i = limit() - 1; i >= p; i--) {
1260             h = 31 * h + get(i);
1261         }
1262         return h;
1263     }
1264 
1265     /**
1266      * {@inheritDoc}
1267      */
1268     @Override
1269     public boolean equals(Object o) {
1270         if (!(o instanceof IoBuffer)) {
1271             return false;
1272         }
1273 
1274         IoBuffer that = (IoBuffer) o;
1275         if (this.remaining() != that.remaining()) {
1276             return false;
1277         }
1278 
1279         int p = this.position();
1280         for (int i = this.limit() - 1, j = that.limit() - 1; i >= p; i--, j--) {
1281             byte v1 = this.get(i);
1282             byte v2 = that.get(j);
1283             if (v1 != v2) {
1284                 return false;
1285             }
1286         }
1287         return true;
1288     }
1289 
1290     /**
1291      * {@inheritDoc}
1292      */
1293     @Override
1294     public int compareTo(IoBuffer that) {
1295         int n = this.position() + Math.min(this.remaining(), that.remaining());
1296         for (int i = this.position(), j = that.position(); i < n; i++, j++) {
1297             byte v1 = this.get(i);
1298             byte v2 = that.get(j);
1299             if (v1 == v2) {
1300                 continue;
1301             }
1302             if (v1 < v2) {
1303                 return -1;
1304             }
1305 
1306             return +1;
1307         }
1308         return this.remaining() - that.remaining();
1309     }
1310 
1311     /**
1312      * {@inheritDoc}
1313      */
1314     @Override
1315     public String toString() {
1316         StringBuilder buf = new StringBuilder();
1317         if (isDirect()) {
1318             buf.append("DirectBuffer");
1319         } else {
1320             buf.append("HeapBuffer");
1321         }
1322         buf.append("[pos=");
1323         buf.append(position());
1324         buf.append(" lim=");
1325         buf.append(limit());
1326         buf.append(" cap=");
1327         buf.append(capacity());
1328         buf.append(": ");
1329         buf.append(getHexDump(16));
1330         buf.append(']');
1331         return buf.toString();
1332     }
1333 
1334     /**
1335      * {@inheritDoc}
1336      */
1337     @Override
1338     public IoBuffer get(byte[] dst) {
1339         return get(dst, 0, dst.length);
1340     }
1341 
1342     /**
1343      * {@inheritDoc}
1344      */
1345     @Override
1346     public IoBuffer put(IoBuffer src) {
1347         return put(src.buf());
1348     }
1349 
1350     /**
1351      * {@inheritDoc}
1352      */
1353     @Override
1354     public IoBuffer put(byte[] src) {
1355         return put(src, 0, src.length);
1356     }
1357 
1358     /**
1359      * {@inheritDoc}
1360      */
1361     @Override
1362     public int getUnsignedShort() {
1363         return getShort() & 0xffff;
1364     }
1365 
1366     /**
1367      * {@inheritDoc}
1368      */
1369     @Override
1370     public int getUnsignedShort(int index) {
1371         return getShort(index) & 0xffff;
1372     }
1373 
1374     /**
1375      * {@inheritDoc}
1376      */
1377     @Override
1378     public long getUnsignedInt() {
1379         return getInt() & 0xffffffffL;
1380     }
1381 
1382     /**
1383      * {@inheritDoc}
1384      */
1385     @Override
1386     public int getMediumInt() {
1387         byte b1 = get();
1388         byte b2 = get();
1389         byte b3 = get();
1390         if (ByteOrder.BIG_ENDIAN.equals(order())) {
1391             return getMediumInt(b1, b2, b3);
1392         }
1393 
1394         return getMediumInt(b3, b2, b1);
1395     }
1396 
1397     /**
1398      * {@inheritDoc}
1399      */
1400     @Override
1401     public int getUnsignedMediumInt() {
1402         int b1 = getUnsigned();
1403         int b2 = getUnsigned();
1404         int b3 = getUnsigned();
1405         if (ByteOrder.BIG_ENDIAN.equals(order())) {
1406             return b1 << 16 | b2 << 8 | b3;
1407         }
1408 
1409         return b3 << 16 | b2 << 8 | b1;
1410     }
1411 
1412     /**
1413      * {@inheritDoc}
1414      */
1415     @Override
1416     public int getMediumInt(int index) {
1417         byte b1 = get(index);
1418         byte b2 = get(index + 1);
1419         byte b3 = get(index + 2);
1420         if (ByteOrder.BIG_ENDIAN.equals(order())) {
1421             return getMediumInt(b1, b2, b3);
1422         }
1423 
1424         return getMediumInt(b3, b2, b1);
1425     }
1426 
1427     /**
1428      * {@inheritDoc}
1429      */
1430     @Override
1431     public int getUnsignedMediumInt(int index) {
1432         int b1 = getUnsigned(index);
1433         int b2 = getUnsigned(index + 1);
1434         int b3 = getUnsigned(index + 2);
1435         
1436         if (ByteOrder.BIG_ENDIAN.equals(order())) {
1437             return b1 << 16 | b2 << 8 | b3;
1438         }
1439 
1440         return b3 << 16 | b2 << 8 | b1;
1441     }
1442 
1443     private int getMediumInt(byte b1, byte b2, byte b3) {
1444         int ret = b1 << 16 & 0xff0000 | b2 << 8 & 0xff00 | b3 & 0xff;
1445         // Check to see if the medium int is negative (high bit in b1 set)
1446         if ((b1 & 0x80) == 0x80) {
1447             // Make the the whole int negative
1448             ret |= 0xff000000;
1449         }
1450         return ret;
1451     }
1452 
1453     /**
1454      * {@inheritDoc}
1455      */
1456     @Override
1457     public IoBuffer putMediumInt(int value) {
1458         byte b1 = (byte) (value >> 16);
1459         byte b2 = (byte) (value >> 8);
1460         byte b3 = (byte) value;
1461 
1462         if (ByteOrder.BIG_ENDIAN.equals(order())) {
1463             put(b1).put(b2).put(b3);
1464         } else {
1465             put(b3).put(b2).put(b1);
1466         }
1467 
1468         return this;
1469     }
1470 
1471     /**
1472      * {@inheritDoc}
1473      */
1474     @Override
1475     public IoBuffer putMediumInt(int index, int value) {
1476         byte b1 = (byte) (value >> 16);
1477         byte b2 = (byte) (value >> 8);
1478         byte b3 = (byte) value;
1479 
1480         if (ByteOrder.BIG_ENDIAN.equals(order())) {
1481             put(index, b1).put(index + 1, b2).put(index + 2, b3);
1482         } else {
1483             put(index, b3).put(index + 1, b2).put(index + 2, b1);
1484         }
1485 
1486         return this;
1487     }
1488 
1489     /**
1490      * {@inheritDoc}
1491      */
1492     @Override
1493     public long getUnsignedInt(int index) {
1494         return getInt(index) & 0xffffffffL;
1495     }
1496 
1497     /**
1498      * {@inheritDoc}
1499      */
1500     @Override
1501     public InputStream asInputStream() {
1502         return new InputStream() {
1503             @Override
1504             public int available() {
1505                 return AbstractIoBuffer.this.remaining();
1506             }
1507 
1508             @Override
1509             public synchronized void mark(int readlimit) {
1510                 AbstractIoBuffer.this.mark();
1511             }
1512 
1513             @Override
1514             public boolean markSupported() {
1515                 return true;
1516             }
1517 
1518             @Override
1519             public int read() {
1520                 if (AbstractIoBuffer.this.hasRemaining()) {
1521                     return AbstractIoBuffer.this.get() & 0xff;
1522                 }
1523 
1524                 return -1;
1525             }
1526 
1527             @Override
1528             public int read(byte[] b, int off, int len) {
1529                 int remaining = AbstractIoBuffer.this.remaining();
1530                 if (remaining > 0) {
1531                     int readBytes = Math.min(remaining, len);
1532                     AbstractIoBuffer.this.get(b, off, readBytes);
1533                     return readBytes;
1534                 }
1535 
1536                 return -1;
1537             }
1538 
1539             @Override
1540             public synchronized void reset() {
1541                 AbstractIoBuffer.this.reset();
1542             }
1543 
1544             @Override
1545             public long skip(long n) {
1546                 int bytes;
1547                 if (n > Integer.MAX_VALUE) {
1548                     bytes = AbstractIoBuffer.this.remaining();
1549                 } else {
1550                     bytes = Math.min(AbstractIoBuffer.this.remaining(), (int) n);
1551                 }
1552                 AbstractIoBuffer.this.skip(bytes);
1553                 return bytes;
1554             }
1555         };
1556     }
1557 
1558     /**
1559      * {@inheritDoc}
1560      */
1561     @Override
1562     public OutputStream asOutputStream() {
1563         return new OutputStream() {
1564             @Override
1565             public void write(byte[] b, int off, int len) {
1566                 AbstractIoBuffer.this.put(b, off, len);
1567             }
1568 
1569             @Override
1570             public void write(int b) {
1571                 AbstractIoBuffer.this.put((byte) b);
1572             }
1573         };
1574     }
1575 
1576     /**
1577      * {@inheritDoc}
1578      */
1579     @Override
1580     public String getHexDump() {
1581         return this.getHexDump(Integer.MAX_VALUE);
1582     }
1583 
1584     /**
1585      * {@inheritDoc}
1586      */
1587     @Override
1588     public String getHexDump(int lengthLimit) {
1589         return IoBufferHexDumper.getHexdump(this, lengthLimit);
1590     }
1591 
1592     /**
1593      * {@inheritDoc}
1594      */
1595     @Override
1596     public String getString(CharsetDecoder decoder) throws CharacterCodingException {
1597         if (!hasRemaining()) {
1598             return "";
1599         }
1600 
1601         boolean utf16 = 
1602                 decoder.charset().equals(StandardCharsets.UTF_16) ||
1603                 decoder.charset().equals(StandardCharsets.UTF_16BE) ||
1604                 decoder.charset().equals(StandardCharsets.UTF_16LE);
1605 
1606         int oldPos = position();
1607         int oldLimit = limit();
1608         int end = -1;
1609         int newPos;
1610 
1611         if (!utf16) {
1612             end = indexOf((byte) 0x00);
1613             if (end < 0) {
1614                 newPos = end = oldLimit;
1615             } else {
1616                 newPos = end + 1;
1617             }
1618         } else {
1619             int i = oldPos;
1620             for (;;) {
1621                 boolean wasZero = get(i) == 0;
1622                 i++;
1623 
1624                 if (i >= oldLimit) {
1625                     break;
1626                 }
1627 
1628                 if (get(i) != 0) {
1629                     i++;
1630                     if (i >= oldLimit) {
1631                         break;
1632                     }
1633 
1634                     continue;
1635                 }
1636 
1637                 if (wasZero) {
1638                     end = i - 1;
1639                     break;
1640                 }
1641             }
1642 
1643             if (end < 0) {
1644                 newPos = end = oldPos + (oldLimit - oldPos & 0xFFFFFFFE);
1645             } else {
1646                 if (end + 2 <= oldLimit) {
1647                     newPos = end + 2;
1648                 } else {
1649                     newPos = end;
1650                 }
1651             }
1652         }
1653 
1654         if (oldPos == end) {
1655             position(newPos);
1656             return "";
1657         }
1658 
1659         limit(end);
1660         decoder.reset();
1661 
1662         int expectedLength = (int) (remaining() * decoder.averageCharsPerByte()) + 1;
1663         CharBuffer out = CharBuffer.allocate(expectedLength);
1664         for (;;) {
1665             CoderResult cr;
1666             if (hasRemaining()) {
1667                 cr = decoder.decode(buf(), out, true);
1668             } else {
1669                 cr = decoder.flush(out);
1670             }
1671 
1672             if (cr.isUnderflow()) {
1673                 break;
1674             }
1675 
1676             if (cr.isOverflow()) {
1677                 CharBuffer o = CharBuffer.allocate(out.capacity() + expectedLength);
1678                 out.flip();
1679                 o.put(out);
1680                 out = o;
1681                 continue;
1682             }
1683 
1684             if (cr.isError()) {
1685                 // Revert the buffer back to the previous state.
1686                 limit(oldLimit);
1687                 position(oldPos);
1688                 cr.throwException();
1689             }
1690         }
1691 
1692         limit(oldLimit);
1693         position(newPos);
1694         return out.flip().toString();
1695     }
1696 
1697     /**
1698      * {@inheritDoc}
1699      */
1700     @Override
1701     public String getString(int fieldSize, CharsetDecoder decoder) throws CharacterCodingException {
1702         checkFieldSize(fieldSize);
1703 
1704         if (fieldSize == 0) {
1705             return "";
1706         }
1707 
1708         if (!hasRemaining()) {
1709             return "";
1710         }
1711 
1712         boolean utf16 = decoder.charset().equals(StandardCharsets.UTF_16) ||
1713                 decoder.charset().equals(StandardCharsets.UTF_16BE) ||
1714                 decoder.charset().equals(StandardCharsets.UTF_16LE);
1715 
1716         if (utf16 && (fieldSize & 1) != 0) {
1717             throw new IllegalArgumentException("fieldSize is not even.");
1718         }
1719 
1720         int oldPos = position();
1721         int oldLimit = limit();
1722         int end = oldPos + fieldSize;
1723 
1724         if (oldLimit < end) {
1725             throw new BufferUnderflowException();
1726         }
1727 
1728         int i;
1729 
1730         if (!utf16) {
1731             for (i = oldPos; i < end; i++) {
1732                 if (get(i) == 0) {
1733                     break;
1734                 }
1735             }
1736 
1737             if (i == end) {
1738                 limit(end);
1739             } else {
1740                 limit(i);
1741             }
1742         } else {
1743             for (i = oldPos; i < end; i += 2) {
1744                 if (get(i) == 0 && get(i + 1) == 0) {
1745                     break;
1746                 }
1747             }
1748 
1749             if (i == end) {
1750                 limit(end);
1751             } else {
1752                 limit(i);
1753             }
1754         }
1755 
1756         if (!hasRemaining()) {
1757             limit(oldLimit);
1758             position(end);
1759             return "";
1760         }
1761         decoder.reset();
1762 
1763         int expectedLength = (int) (remaining() * decoder.averageCharsPerByte()) + 1;
1764         CharBuffer out = CharBuffer.allocate(expectedLength);
1765         for (;;) {
1766             CoderResult cr;
1767             if (hasRemaining()) {
1768                 cr = decoder.decode(buf(), out, true);
1769             } else {
1770                 cr = decoder.flush(out);
1771             }
1772 
1773             if (cr.isUnderflow()) {
1774                 break;
1775             }
1776 
1777             if (cr.isOverflow()) {
1778                 CharBuffer o = CharBuffer.allocate(out.capacity() + expectedLength);
1779                 out.flip();
1780                 o.put(out);
1781                 out = o;
1782                 continue;
1783             }
1784 
1785             if (cr.isError()) {
1786                 // Revert the buffer back to the previous state.
1787                 limit(oldLimit);
1788                 position(oldPos);
1789                 cr.throwException();
1790             }
1791         }
1792 
1793         limit(oldLimit);
1794         position(end);
1795         return out.flip().toString();
1796     }
1797 
1798     /**
1799      * {@inheritDoc}
1800      */
1801     @Override
1802     public IoBuffer putString(CharSequence val, CharsetEncoder encoder) throws CharacterCodingException {
1803         if (val.length() == 0) {
1804             return this;
1805         }
1806 
1807         CharBuffer in = CharBuffer.wrap(val);
1808         encoder.reset();
1809 
1810         int expandedState = 0;
1811 
1812         for (;;) {
1813             CoderResult cr;
1814             if (in.hasRemaining()) {
1815                 cr = encoder.encode(in, buf(), true);
1816             } else {
1817                 cr = encoder.flush(buf());
1818             }
1819 
1820             if (cr.isUnderflow()) {
1821                 break;
1822             }
1823             if (cr.isOverflow()) {
1824                 if (isAutoExpand()) {
1825                     switch (expandedState) {
1826                     case 0:
1827                         autoExpand((int) Math.ceil(in.remaining() * encoder.averageBytesPerChar()));
1828                         expandedState++;
1829                         break;
1830                     case 1:
1831                         autoExpand((int) Math.ceil(in.remaining() * encoder.maxBytesPerChar()));
1832                         expandedState++;
1833                         break;
1834                     default:
1835                         throw new RuntimeException("Expanded by "
1836                                 + (int) Math.ceil(in.remaining() * encoder.maxBytesPerChar())
1837                                 + " but that wasn't enough for '" + val + "'");
1838                     }
1839                     continue;
1840                 }
1841             } else {
1842                 expandedState = 0;
1843             }
1844             cr.throwException();
1845         }
1846         return this;
1847     }
1848 
1849     /**
1850      * {@inheritDoc}
1851      */
1852     @Override
1853     public IoBuffer putString(CharSequence val, int fieldSize, CharsetEncoder encoder) throws CharacterCodingException {
1854         checkFieldSize(fieldSize);
1855 
1856         if (fieldSize == 0) {
1857             return this;
1858         }
1859 
1860         autoExpand(fieldSize);
1861 
1862         boolean utf16 = encoder.charset().equals(StandardCharsets.UTF_16) ||
1863                 encoder.charset().equals(StandardCharsets.UTF_16BE) ||
1864                 encoder.charset().equals(StandardCharsets.UTF_16LE);
1865 
1866 
1867         if (utf16 && (fieldSize & 1) != 0) {
1868             throw new IllegalArgumentException("fieldSize is not even.");
1869         }
1870 
1871         int oldLimit = limit();
1872         int end = position() + fieldSize;
1873 
1874         if (oldLimit < end) {
1875             throw new BufferOverflowException();
1876         }
1877 
1878         if (val.length() == 0) {
1879             if (!utf16) {
1880                 put((byte) 0x00);
1881             } else {
1882                 put((byte) 0x00);
1883                 put((byte) 0x00);
1884             }
1885             position(end);
1886             return this;
1887         }
1888 
1889         CharBuffer in = CharBuffer.wrap(val);
1890         limit(end);
1891         encoder.reset();
1892 
1893         for (;;) {
1894             CoderResult cr;
1895             if (in.hasRemaining()) {
1896                 cr = encoder.encode(in, buf(), true);
1897             } else {
1898                 cr = encoder.flush(buf());
1899             }
1900 
1901             if (cr.isUnderflow() || cr.isOverflow()) {
1902                 break;
1903             }
1904             cr.throwException();
1905         }
1906 
1907         limit(oldLimit);
1908 
1909         if (position() < end) {
1910             if (!utf16) {
1911                 put((byte) 0x00);
1912             } else {
1913                 put((byte) 0x00);
1914                 put((byte) 0x00);
1915             }
1916         }
1917 
1918         position(end);
1919         return this;
1920     }
1921 
1922     /**
1923      * {@inheritDoc}
1924      */
1925     @Override
1926     public String getPrefixedString(CharsetDecoder decoder) throws CharacterCodingException {
1927         return getPrefixedString(2, decoder);
1928     }
1929 
1930     /**
1931      * Reads a string which has a length field before the actual
1932      * encoded string, using the specified <code>decoder</code> and returns it.
1933      *
1934      * @param prefixLength the length of the length field (1, 2, or 4)
1935      * @param decoder the decoder to use for decoding the string
1936      * @return the prefixed string
1937      * @throws CharacterCodingException when decoding fails
1938      * @throws BufferUnderflowException when there is not enough data available
1939      */
1940     @Override
1941     public String getPrefixedString(int prefixLength, CharsetDecoder decoder) throws CharacterCodingException {
1942         if (!prefixedDataAvailable(prefixLength)) {
1943             throw new BufferUnderflowException();
1944         }
1945 
1946         int fieldSize = 0;
1947 
1948         switch (prefixLength) {
1949         case 1:
1950             fieldSize = getUnsigned();
1951             break;
1952         case 2:
1953             fieldSize = getUnsignedShort();
1954             break;
1955         case 4:
1956             fieldSize = getInt();
1957             break;
1958         }
1959 
1960         if (fieldSize == 0) {
1961             return "";
1962         }
1963 
1964         boolean utf16 = decoder.charset().equals(StandardCharsets.UTF_16) ||
1965                 decoder.charset().equals(StandardCharsets.UTF_16BE) ||
1966                 decoder.charset().equals(StandardCharsets.UTF_16LE);
1967 
1968 
1969         if (utf16 && (fieldSize & 1) != 0) {
1970             throw new BufferDataException("fieldSize is not even for a UTF-16 string.");
1971         }
1972 
1973         int oldLimit = limit();
1974         int end = position() + fieldSize;
1975 
1976         if (oldLimit < end) {
1977             throw new BufferUnderflowException();
1978         }
1979 
1980         limit(end);
1981         decoder.reset();
1982 
1983         int expectedLength = (int) (remaining() * decoder.averageCharsPerByte()) + 1;
1984         CharBuffer out = CharBuffer.allocate(expectedLength);
1985         for (;;) {
1986             CoderResult cr;
1987             if (hasRemaining()) {
1988                 cr = decoder.decode(buf(), out, true);
1989             } else {
1990                 cr = decoder.flush(out);
1991             }
1992 
1993             if (cr.isUnderflow()) {
1994                 break;
1995             }
1996 
1997             if (cr.isOverflow()) {
1998                 CharBuffer o = CharBuffer.allocate(out.capacity() + expectedLength);
1999                 out.flip();
2000                 o.put(out);
2001                 out = o;
2002                 continue;
2003             }
2004 
2005             cr.throwException();
2006         }
2007 
2008         limit(oldLimit);
2009         position(end);
2010         return out.flip().toString();
2011     }
2012 
2013     /**
2014      * {@inheritDoc}
2015      */
2016     @Override
2017     public IoBuffer putPrefixedString(CharSequence in, CharsetEncoder encoder) throws CharacterCodingException {
2018         return putPrefixedString(in, 2, 0, encoder);
2019     }
2020 
2021     /**
2022      * {@inheritDoc}
2023      */
2024     @Override
2025     public IoBuffer putPrefixedString(CharSequence in, int prefixLength, CharsetEncoder encoder)
2026             throws CharacterCodingException {
2027         return putPrefixedString(in, prefixLength, 0, encoder);
2028     }
2029 
2030     /**
2031      * {@inheritDoc}
2032      */
2033     @Override
2034     public IoBuffer putPrefixedString(CharSequence in, int prefixLength, int padding, CharsetEncoder encoder)
2035             throws CharacterCodingException {
2036         return putPrefixedString(in, prefixLength, padding, (byte) 0, encoder);
2037     }
2038 
2039     /**
2040      * {@inheritDoc}
2041      */
2042     @Override
2043     public IoBuffer putPrefixedString(CharSequence val, int prefixLength, int padding, byte padValue,
2044             CharsetEncoder encoder) throws CharacterCodingException {
2045         int maxLength;
2046         switch (prefixLength) {
2047         case 1:
2048             maxLength = 255;
2049             break;
2050         case 2:
2051             maxLength = 65535;
2052             break;
2053         case 4:
2054             maxLength = Integer.MAX_VALUE;
2055             break;
2056         default:
2057             throw new IllegalArgumentException("prefixLength: " + prefixLength);
2058         }
2059 
2060         if (val.length() > maxLength) {
2061             throw new IllegalArgumentException("The specified string is too long.");
2062         }
2063         if (val.length() == 0) {
2064             switch (prefixLength) {
2065             case 1:
2066                 put((byte) 0);
2067                 break;
2068             case 2:
2069                 putShort((short) 0);
2070                 break;
2071             case 4:
2072                 putInt(0);
2073                 break;
2074             }
2075             return this;
2076         }
2077 
2078         int padMask;
2079         switch (padding) {
2080         case 0:
2081         case 1:
2082             padMask = 0;
2083             break;
2084         case 2:
2085             padMask = 1;
2086             break;
2087         case 4:
2088             padMask = 3;
2089             break;
2090         default:
2091             throw new IllegalArgumentException("padding: " + padding);
2092         }
2093 
2094         CharBuffer in = CharBuffer.wrap(val);
2095         skip(prefixLength); // make a room for the length field
2096         int oldPos = position();
2097         encoder.reset();
2098 
2099         int expandedState = 0;
2100 
2101         for (;;) {
2102             CoderResult cr;
2103             if (in.hasRemaining()) {
2104                 cr = encoder.encode(in, buf(), true);
2105             } else {
2106                 cr = encoder.flush(buf());
2107             }
2108 
2109             if (position() - oldPos > maxLength) {
2110                 throw new IllegalArgumentException("The specified string is too long.");
2111             }
2112 
2113             if (cr.isUnderflow()) {
2114                 break;
2115             }
2116             if (cr.isOverflow()) {
2117                 if (isAutoExpand()) {
2118                     switch (expandedState) {
2119                     case 0:
2120                         autoExpand((int) Math.ceil(in.remaining() * encoder.averageBytesPerChar()));
2121                         expandedState++;
2122                         break;
2123                     case 1:
2124                         autoExpand((int) Math.ceil(in.remaining() * encoder.maxBytesPerChar()));
2125                         expandedState++;
2126                         break;
2127                     default:
2128                         throw new RuntimeException("Expanded by "
2129                                 + (int) Math.ceil(in.remaining() * encoder.maxBytesPerChar())
2130                                 + " but that wasn't enough for '" + val + "'");
2131                     }
2132                     continue;
2133                 }
2134             } else {
2135                 expandedState = 0;
2136             }
2137             cr.throwException();
2138         }
2139 
2140         // Write the length field
2141         fill(padValue, padding - (position() - oldPos & padMask));
2142         int length = position() - oldPos;
2143         switch (prefixLength) {
2144         case 1:
2145             put(oldPos - 1, (byte) length);
2146             break;
2147         case 2:
2148             putShort(oldPos - 2, (short) length);
2149             break;
2150         case 4:
2151             putInt(oldPos - 4, length);
2152             break;
2153         }
2154         return this;
2155     }
2156 
2157     /**
2158      * {@inheritDoc}
2159      */
2160     @Override
2161     public Object getObject() throws ClassNotFoundException {
2162         return getObject(Thread.currentThread().getContextClassLoader());
2163     }
2164 
2165     /**
2166      * {@inheritDoc}
2167      */
2168     @Override
2169     public Object getObject(final ClassLoader classLoader) throws ClassNotFoundException {
2170         if (!prefixedDataAvailable(4)) {
2171             throw new BufferUnderflowException();
2172         }
2173 
2174         int length = getInt();
2175         if (length <= 4) {
2176             throw new BufferDataException("Object length should be greater than 4: " + length);
2177         }
2178 
2179         int oldLimit = limit();
2180         limit(position() + length);
2181         
2182         try (ObjectInputStream in = new ObjectInputStream(asInputStream()) {
2183                 @Override
2184                 protected ObjectStreamClass readClassDescriptor() throws IOException, ClassNotFoundException {
2185                     int type = read();
2186                     if (type < 0) {
2187                         throw new EOFException();
2188                     }
2189                     switch (type) {
2190                     case 0: // NON-Serializable class or Primitive types
2191                         return super.readClassDescriptor();
2192                     case 1: // Serializable class
2193                         String className = readUTF();
2194                         Class<?> clazz = Class.forName(className, true, classLoader);
2195                         return ObjectStreamClass.lookup(clazz);
2196                     default:
2197                         throw new StreamCorruptedException("Unexpected class descriptor type: " + type);
2198                     }
2199                 }
2200 
2201                 @Override
2202                 protected Class<?> resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException {
2203                     Class<?> clazz = desc.forClass();
2204                     
2205                     if (clazz == null) {
2206                         String name = desc.getName();
2207                         try {
2208                             return Class.forName(name, false, classLoader);
2209                         } catch (ClassNotFoundException ex) {
2210                             return super.resolveClass(desc);
2211                         }
2212                     } else {
2213                         return clazz;
2214                     }
2215                 }
2216             }) {
2217             return in.readObject();
2218         } catch (IOException e) {
2219             throw new BufferDataException(e);
2220         } finally {
2221             limit(oldLimit);
2222         }
2223     }
2224 
2225     /**
2226      * {@inheritDoc}
2227      */
2228     @Override
2229     public IoBuffer putObject(Object o) {
2230         int oldPos = position();
2231         skip(4); // Make a room for the length field.
2232         
2233         try (ObjectOutputStream out = new ObjectOutputStream(asOutputStream()) {
2234                 @Override
2235                 protected void writeClassDescriptor(ObjectStreamClass desc) throws IOException {
2236                     Class<?> clazz = desc.forClass();
2237                     
2238                     if (clazz.isArray() || clazz.isPrimitive() || !Serializable.class.isAssignableFrom(clazz)) {
2239                         write(0);
2240                         super.writeClassDescriptor(desc); 
2241                     } else {
2242                         // Serializable class
2243                         write(1);
2244                         writeUTF(desc.getName());                            
2245                     }
2246                 }
2247             }) {
2248             out.writeObject(o);
2249             out.flush();
2250         } catch (IOException e) {
2251             throw new BufferDataException(e);
2252         }
2253 
2254         // Fill the length field
2255         int newPos = position();
2256         position(oldPos);
2257         putInt(newPos - oldPos - 4);
2258         position(newPos);
2259         return this;
2260     }
2261 
2262     /**
2263      * {@inheritDoc}
2264      */
2265     @Override
2266     public boolean prefixedDataAvailable(int prefixLength) {
2267         return prefixedDataAvailable(prefixLength, Integer.MAX_VALUE);
2268     }
2269 
2270     /**
2271      * {@inheritDoc}
2272      */
2273     @Override
2274     public boolean prefixedDataAvailable(int prefixLength, int maxDataLength) {
2275         if (remaining() < prefixLength) {
2276             return false;
2277         }
2278 
2279         int dataLength;
2280         switch (prefixLength) {
2281         case 1:
2282             dataLength = getUnsigned(position());
2283             break;
2284         case 2:
2285             dataLength = getUnsignedShort(position());
2286             break;
2287         case 4:
2288             dataLength = getInt(position());
2289             break;
2290         default:
2291             throw new IllegalArgumentException("prefixLength: " + prefixLength);
2292         }
2293 
2294         if (dataLength < 0 || dataLength > maxDataLength) {
2295             throw new BufferDataException("dataLength: " + dataLength);
2296         }
2297 
2298         return remaining() - prefixLength >= dataLength;
2299     }
2300 
2301     /**
2302      * {@inheritDoc}
2303      */
2304     @Override
2305     public int indexOf(byte b) {
2306         if (hasArray()) {
2307             int arrayOffset = arrayOffset();
2308             int beginPos = arrayOffset + position();
2309             int limit = arrayOffset + limit();
2310             byte[] array = array();
2311 
2312             for (int i = beginPos; i < limit; i++) {
2313                 if (array[i] == b) {
2314                     return i - arrayOffset;
2315                 }
2316             }
2317         } else {
2318             int beginPos = position();
2319             int limit = limit();
2320 
2321             for (int i = beginPos; i < limit; i++) {
2322                 if (get(i) == b) {
2323                     return i;
2324                 }
2325             }
2326         }
2327 
2328         return -1;
2329     }
2330 
2331     /**
2332      * {@inheritDoc}
2333      */
2334     @Override
2335     public IoBuffer skip(int size) {
2336         autoExpand(size);
2337         return position(position() + size);
2338     }
2339 
2340     /**
2341      * {@inheritDoc}
2342      */
2343     @Override
2344     public IoBuffer fill(byte value, int size) {
2345         autoExpand(size);
2346         int q = size >>> 3;
2347             int r = size & 7;
2348 
2349             if (q > 0) {
2350                 int intValue = value & 0x000000FF | ( value << 8 ) & 0x0000FF00 | ( value << 16 ) & 0x00FF0000 | value << 24;
2351                 long longValue = intValue & 0x00000000FFFFFFFFL | (long)intValue << 32;
2352 
2353                 for (int i = q; i > 0; i--) {
2354                     putLong(longValue);
2355                 }
2356             }
2357 
2358             q = r >>> 2;
2359                 r = r & 3;
2360 
2361                 if (q > 0) {
2362                     int intValue = value & 0x000000FF | ( value << 8 ) & 0x0000FF00 | ( value << 16 ) & 0x00FF0000 | value << 24;
2363                     putInt(intValue);
2364                 }
2365 
2366                 q = r >> 1;
2367                     r = r & 1;
2368 
2369                     if (q > 0) {
2370                         short shortValue = (short) (value & 0x000FF | value << 8);
2371                         putShort(shortValue);
2372                     }
2373 
2374                     if (r > 0) {
2375                         put(value);
2376                     }
2377 
2378                     return this;
2379     }
2380 
2381     /**
2382      * {@inheritDoc}
2383      */
2384     @Override
2385     public IoBuffer fillAndReset(byte value, int size) {
2386         autoExpand(size);
2387         int pos = position();
2388         try {
2389             fill(value, size);
2390         } finally {
2391             position(pos);
2392         }
2393         return this;
2394     }
2395 
2396     /**
2397      * {@inheritDoc}
2398      */
2399     @Override
2400     public IoBuffer fill(int size) {
2401         autoExpand(size);
2402         int q = size >>> 3;
2403                     int r = size & 7;
2404 
2405                     for (int i = q; i > 0; i--) {
2406                         putLong(0L);
2407                     }
2408 
2409                     q = r >>> 2;
2410                 r = r & 3;
2411 
2412                 if (q > 0) {
2413                     putInt(0);
2414                 }
2415 
2416                 q = r >> 1;
2417             r = r & 1;
2418 
2419             if (q > 0) {
2420                 putShort((short) 0);
2421             }
2422 
2423             if (r > 0) {
2424                 put((byte) 0);
2425             }
2426 
2427             return this;
2428     }
2429 
2430     /**
2431      * {@inheritDoc}
2432      */
2433     @Override
2434     public IoBuffer fillAndReset(int size) {
2435         autoExpand(size);
2436         int pos = position();
2437         try {
2438             fill(size);
2439         } finally {
2440             position(pos);
2441         }
2442 
2443         return this;
2444     }
2445 
2446     /**
2447      * {@inheritDoc}
2448      */
2449     @Override
2450     public <E extends Enum<E>> E getEnum(Class<E> enumClass) {
2451         return toEnum(enumClass, getUnsigned());
2452     }
2453 
2454     /**
2455      * {@inheritDoc}
2456      */
2457     @Override
2458     public <E extends Enum<E>> E getEnum(int index, Class<E> enumClass) {
2459         return toEnum(enumClass, getUnsigned(index));
2460     }
2461 
2462     /**
2463      * {@inheritDoc}
2464      */
2465     @Override
2466     public <E extends Enum<E>> E getEnumShort(Class<E> enumClass) {
2467         return toEnum(enumClass, getUnsignedShort());
2468     }
2469 
2470     /**
2471      * {@inheritDoc}
2472      */
2473     @Override
2474     public <E extends Enum<E>> E getEnumShort(int index, Class<E> enumClass) {
2475         return toEnum(enumClass, getUnsignedShort(index));
2476     }
2477 
2478     /**
2479      * {@inheritDoc}
2480      */
2481     @Override
2482     public <E extends Enum<E>> E getEnumInt(Class<E> enumClass) {
2483         return toEnum(enumClass, getInt());
2484     }
2485 
2486     /**
2487      * {@inheritDoc}
2488      */
2489     @Override
2490     public <E extends Enum<E>> E getEnumInt(int index, Class<E> enumClass) {
2491         return toEnum(enumClass, getInt(index));
2492     }
2493 
2494     /**
2495      * {@inheritDoc}
2496      */
2497     @Override
2498     public IoBuffer putEnum(Enum<?> e) {
2499         if (e.ordinal() > BYTE_MASK) {
2500             throw new IllegalArgumentException(enumConversionErrorMessage(e, "byte"));
2501         }
2502         return put((byte) e.ordinal());
2503     }
2504 
2505     /**
2506      * {@inheritDoc}
2507      */
2508     @Override
2509     public IoBuffer putEnum(int index, Enum<?> e) {
2510         if (e.ordinal() > BYTE_MASK) {
2511             throw new IllegalArgumentException(enumConversionErrorMessage(e, "byte"));
2512         }
2513         return put(index, (byte) e.ordinal());
2514     }
2515 
2516     /**
2517      * {@inheritDoc}
2518      */
2519     @Override
2520     public IoBuffer putEnumShort(Enum<?> e) {
2521         if (e.ordinal() > SHORT_MASK) {
2522             throw new IllegalArgumentException(enumConversionErrorMessage(e, "short"));
2523         }
2524         return putShort((short) e.ordinal());
2525     }
2526 
2527     /**
2528      * {@inheritDoc}
2529      */
2530     @Override
2531     public IoBuffer putEnumShort(int index, Enum<?> e) {
2532         if (e.ordinal() > SHORT_MASK) {
2533             throw new IllegalArgumentException(enumConversionErrorMessage(e, "short"));
2534         }
2535         return putShort(index, (short) e.ordinal());
2536     }
2537 
2538     /**
2539      * {@inheritDoc}
2540      */
2541     @Override
2542     public IoBuffer putEnumInt(Enum<?> e) {
2543         return putInt(e.ordinal());
2544     }
2545 
2546     /**
2547      * {@inheritDoc}
2548      */
2549     @Override
2550     public IoBuffer putEnumInt(int index, Enum<?> e) {
2551         return putInt(index, e.ordinal());
2552     }
2553 
2554     private <E> E toEnum(Class<E> enumClass, int i) {
2555         E[] enumConstants = enumClass.getEnumConstants();
2556         if (i > enumConstants.length) {
2557             throw new IndexOutOfBoundsException(String.format(
2558                     "%d is too large of an ordinal to convert to the enum %s", i, enumClass.getName()));
2559         }
2560         return enumConstants[i];
2561     }
2562 
2563     private String enumConversionErrorMessage(Enum<?> e, String type) {
2564         return String.format("%s.%s has an ordinal value too large for a %s", e.getClass().getName(), e.name(), type);
2565     }
2566 
2567     /**
2568      * {@inheritDoc}
2569      */
2570     @Override
2571     public <E extends Enum<E>> Set<E> getEnumSet(Class<E> enumClass) {
2572         return toEnumSet(enumClass, get() & BYTE_MASK);
2573     }
2574 
2575     /**
2576      * {@inheritDoc}
2577      */
2578     @Override
2579     public <E extends Enum<E>> Set<E> getEnumSet(int index, Class<E> enumClass) {
2580         return toEnumSet(enumClass, get(index) & BYTE_MASK);
2581     }
2582 
2583     /**
2584      * {@inheritDoc}
2585      */
2586     @Override
2587     public <E extends Enum<E>> Set<E> getEnumSetShort(Class<E> enumClass) {
2588         return toEnumSet(enumClass, getShort() & SHORT_MASK);
2589     }
2590 
2591     /**
2592      * {@inheritDoc}
2593      */
2594     @Override
2595     public <E extends Enum<E>> Set<E> getEnumSetShort(int index, Class<E> enumClass) {
2596         return toEnumSet(enumClass, getShort(index) & SHORT_MASK);
2597     }
2598 
2599     /**
2600      * {@inheritDoc}
2601      */
2602     @Override
2603     public <E extends Enum<E>> Set<E> getEnumSetInt(Class<E> enumClass) {
2604         return toEnumSet(enumClass, getInt() & INT_MASK);
2605     }
2606 
2607     /**
2608      * {@inheritDoc}
2609      */
2610     @Override
2611     public <E extends Enum<E>> Set<E> getEnumSetInt(int index, Class<E> enumClass) {
2612         return toEnumSet(enumClass, getInt(index) & INT_MASK);
2613     }
2614 
2615     /**
2616      * {@inheritDoc}
2617      */
2618     @Override
2619     public <E extends Enum<E>> Set<E> getEnumSetLong(Class<E> enumClass) {
2620         return toEnumSet(enumClass, getLong());
2621     }
2622 
2623     /**
2624      * {@inheritDoc}
2625      */
2626     @Override
2627     public <E extends Enum<E>> Set<E> getEnumSetLong(int index, Class<E> enumClass) {
2628         return toEnumSet(enumClass, getLong(index));
2629     }
2630 
2631     private <E extends Enum<E>> EnumSet<E> toEnumSet(Class<E> clazz, long vector) {
2632         EnumSet<E> set = EnumSet.noneOf(clazz);
2633         long mask = 1;
2634         for (E e : clazz.getEnumConstants()) {
2635             if ((mask & vector) == mask) {
2636                 set.add(e);
2637             }
2638             mask <<= 1;
2639         }
2640         return set;
2641     }
2642 
2643     /**
2644      * {@inheritDoc}
2645      */
2646     @Override
2647     public <E extends Enum<E>> IoBuffer putEnumSet(Set<E> set) {
2648         long vector = toLong(set);
2649         if ((vector & ~BYTE_MASK) != 0) {
2650             throw new IllegalArgumentException("The enum set is too large to fit in a byte: " + set);
2651         }
2652         return put((byte) vector);
2653     }
2654 
2655     /**
2656      * {@inheritDoc}
2657      */
2658     @Override
2659     public <E extends Enum<E>> IoBuffer putEnumSet(int index, Set<E> set) {
2660         long vector = toLong(set);
2661         if ((vector & ~BYTE_MASK) != 0) {
2662             throw new IllegalArgumentException("The enum set is too large to fit in a byte: " + set);
2663         }
2664         return put(index, (byte) vector);
2665     }
2666 
2667     /**
2668      * {@inheritDoc}
2669      */
2670     @Override
2671     public <E extends Enum<E>> IoBuffer putEnumSetShort(Set<E> set) {
2672         long vector = toLong(set);
2673         if ((vector & ~SHORT_MASK) != 0) {
2674             throw new IllegalArgumentException("The enum set is too large to fit in a short: " + set);
2675         }
2676         return putShort((short) vector);
2677     }
2678 
2679     /**
2680      * {@inheritDoc}
2681      */
2682     @Override
2683     public <E extends Enum<E>> IoBuffer putEnumSetShort(int index, Set<E> set) {
2684         long vector = toLong(set);
2685         if ((vector & ~SHORT_MASK) != 0) {
2686             throw new IllegalArgumentException("The enum set is too large to fit in a short: " + set);
2687         }
2688         return putShort(index, (short) vector);
2689     }
2690 
2691     /**
2692      * {@inheritDoc}
2693      */
2694     @Override
2695     public <E extends Enum<E>> IoBuffer putEnumSetInt(Set<E> set) {
2696         long vector = toLong(set);
2697         if ((vector & ~INT_MASK) != 0) {
2698             throw new IllegalArgumentException("The enum set is too large to fit in an int: " + set);
2699         }
2700         return putInt((int) vector);
2701     }
2702 
2703     /**
2704      * {@inheritDoc}
2705      */
2706     @Override
2707     public <E extends Enum<E>> IoBuffer putEnumSetInt(int index, Set<E> set) {
2708         long vector = toLong(set);
2709         if ((vector & ~INT_MASK) != 0) {
2710             throw new IllegalArgumentException("The enum set is too large to fit in an int: " + set);
2711         }
2712         return putInt(index, (int) vector);
2713     }
2714 
2715     /**
2716      * {@inheritDoc}
2717      */
2718     @Override
2719     public <E extends Enum<E>> IoBuffer putEnumSetLong(Set<E> set) {
2720         return putLong(toLong(set));
2721     }
2722 
2723     /**
2724      * {@inheritDoc}
2725      */
2726     @Override
2727     public <E extends Enum<E>> IoBuffer putEnumSetLong(int index, Set<E> set) {
2728         return putLong(index, toLong(set));
2729     }
2730 
2731     private <E extends Enum<E>> long toLong(Set<E> set) {
2732         long vector = 0;
2733         for (E e : set) {
2734             if (e.ordinal() >= Long.SIZE) {
2735                 throw new IllegalArgumentException("The enum set is too large to fit in a bit vector: " + set);
2736             }
2737             vector |= 1L << e.ordinal();
2738         }
2739         return vector;
2740     }
2741 
2742     /**
2743      * This method forwards the call to {@link #expand(int)} only when
2744      * <tt>autoExpand</tt> property is <tt>true</tt>.
2745      */
2746     private IoBuffer autoExpand(int expectedRemaining) {
2747         if (isAutoExpand()) {
2748             expand(expectedRemaining, true);
2749         }
2750         return this;
2751     }
2752 
2753     /**
2754      * This method forwards the call to {@link #expand(int)} only when
2755      * <tt>autoExpand</tt> property is <tt>true</tt>.
2756      */
2757     private IoBuffer autoExpand(int pos, int expectedRemaining) {
2758         if (isAutoExpand()) {
2759             expand(pos, expectedRemaining, true);
2760         }
2761         return this;
2762     }
2763 
2764     private static void checkFieldSize(int fieldSize) {
2765         if (fieldSize < 0) {
2766             throw new IllegalArgumentException("fieldSize cannot be negative: " + fieldSize);
2767         }
2768     }
2769 }