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