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 }