All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.craft.atom.util.buffer.AbstractAdaptiveByteBuffer Maven / Gradle / Ivy

There is a newer version: 3.1.2
Show newest version
/*
 *  Licensed to the Apache Software Foundation (ASF) under one
 *  or more contributor license agreements.  See the NOTICE file
 *  distributed with this work for additional information
 *  regarding copyright ownership.  The ASF licenses this file
 *  to you under the Apache License, Version 2.0 (the
 *  "License"); you may not use this file except in compliance
 *  with the License.  You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing,
 *  software distributed under the License is distributed on an
 *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 *  KIND, either express or implied.  See the License for the
 *  specific language governing permissions and limitations
 *  under the License.
 *
 */
package io.craft.atom.util.buffer;

import java.io.EOFException;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.ObjectStreamClass;
import java.io.OutputStream;
import java.io.Serializable;
import java.io.StreamCorruptedException;
import java.nio.BufferOverflowException;
import java.nio.BufferUnderflowException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.CharBuffer;
import java.nio.DoubleBuffer;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import java.nio.LongBuffer;
import java.nio.ShortBuffer;
import java.nio.charset.CharacterCodingException;
import java.nio.charset.CharsetDecoder;
import java.nio.charset.CharsetEncoder;
import java.nio.charset.CoderResult;
import java.util.EnumSet;
import java.util.Set;

/**
 * A base implementation of {@link AdaptiveByteBuffer}.  This implementation
 * assumes that {@link AdaptiveByteBuffer#buf()} always returns a correct NIO
 * {@link ByteBuffer} instance.  Most implementations could
 * extend this class and implement their own buffer management mechanism.
 *
 * @author Apache MINA Project
 * @author mindwind
 * @version 1.0, 2013/10/09
 * @see BufferAllocator
 */
public abstract class AbstractAdaptiveByteBuffer extends AdaptiveByteBuffer {
	
	
    private static final long BYTE_MASK  = 0xFFL      ;
    private static final long SHORT_MASK = 0xFFFFL    ;
    private static final long INT_MASK   = 0xFFFFFFFFL;
    
	
    /** 
     * 
     * derived          : Tells if a buffer has been created from an existing buffer
     * autoExpand       : A flag set to true if the buffer can extend automatically
     * autoShrink       : A flag set to true if the buffer can shrink automatically
     * recapacityAllowed: Tells if a buffer can be expanded
     * minimumCapacity  : The minimum number of bytes the IoBuffer can hold
     * mark             : We don't have any access to Buffer.markValue(), so we need to track it down, which will cause small extra overhead.
     * 
*/ private final boolean derived ; private boolean autoExpand ; private boolean autoShrink ; private boolean recapacityAllowed = true; private int minimumCapacity ; private int mark = -1 ; // ~ ------------------------------------------------------------------------------------------------------------- /** * Creates a new parent buffer. * * @param allocator The allocator to use to create new buffers * @param initialCapacity The initial buffer capacity when created */ protected AbstractAdaptiveByteBuffer(BufferAllocator allocator, int initialCapacity) { setAllocator(allocator); this.recapacityAllowed = true; this.derived = false; this.minimumCapacity = initialCapacity; } /** * Creates a new derived buffer. A derived buffer uses an existing * buffer properties - the allocator and capacity -. * * @param parent The buffer we get the properties from */ protected AbstractAdaptiveByteBuffer(AbstractAdaptiveByteBuffer parent) { setAllocator(AbstractAdaptiveByteBuffer.getAllocator()); this.recapacityAllowed = false; this.derived = true; this.minimumCapacity = parent.minimumCapacity; } /** * {@inheritDoc} */ @Override public final boolean isDirect() { return buf().isDirect(); } /** * {@inheritDoc} */ @Override public final boolean isReadOnly() { return buf().isReadOnly(); } /** * Sets the underlying NIO buffer instance. * * @param newBuf The buffer to store within this IoBuffer */ protected abstract void buf(ByteBuffer newBuf); /** * {@inheritDoc} */ @Override public final int minimumCapacity() { return minimumCapacity; } /** * {@inheritDoc} */ @Override public final AdaptiveByteBuffer minimumCapacity(int minimumCapacity) { if (minimumCapacity < 0) { throw new IllegalArgumentException("minimumCapacity: " + minimumCapacity); } this.minimumCapacity = minimumCapacity; return this; } /** * {@inheritDoc} */ @Override public final int capacity() { return buf().capacity(); } /** * {@inheritDoc} */ @Override public final AdaptiveByteBuffer capacity(int newCapacity) { if (!recapacityAllowed) { throw new IllegalStateException("Derived buffers and their parent can't be expanded."); } // Allocate a new buffer and transfer all settings to it. if (newCapacity > capacity()) { // Expand: //// Save the state. int pos = position(); int limit = limit(); ByteOrder bo = order(); //// Reallocate. ByteBuffer oldBuf = buf(); ByteBuffer newBuf = getAllocator().allocateNioBuffer(newCapacity, isDirect()); oldBuf.clear(); newBuf.put(oldBuf); buf(newBuf); //// Restore the state. buf().limit(limit); if (mark >= 0) { buf().position(mark); buf().mark(); } buf().position(pos); buf().order(bo); } return this; } /** * {@inheritDoc} */ @Override public final boolean isAutoExpand() { return autoExpand && recapacityAllowed; } /** * {@inheritDoc} */ @Override public final boolean isAutoShrink() { return autoShrink && recapacityAllowed; } /** * {@inheritDoc} */ @Override public final boolean isDerived() { return derived; } /** * {@inheritDoc} */ @Override public final AdaptiveByteBuffer setAutoExpand(boolean autoExpand) { if (!recapacityAllowed) { throw new IllegalStateException("Derived buffers and their parent can't be expanded."); } this.autoExpand = autoExpand; return this; } /** * {@inheritDoc} */ @Override public final AdaptiveByteBuffer setAutoShrink(boolean autoShrink) { if (!recapacityAllowed) { throw new IllegalStateException("Derived buffers and their parent can't be shrinked."); } this.autoShrink = autoShrink; return this; } /** * {@inheritDoc} */ @Override public final AdaptiveByteBuffer expand(int expectedRemaining) { return expand(position(), expectedRemaining, false); } private AdaptiveByteBuffer expand(int expectedRemaining, boolean autoExpand) { return expand(position(), expectedRemaining, autoExpand); } /** * {@inheritDoc} */ @Override public final AdaptiveByteBuffer expand(int pos, int expectedRemaining) { return expand(pos, expectedRemaining, false); } private AdaptiveByteBuffer expand(int pos, int expectedRemaining, boolean autoExpand) { if (!recapacityAllowed) { throw new IllegalStateException("Derived buffers and their parent can't be expanded."); } int end = pos + expectedRemaining; int newCapacity; if (autoExpand) { newCapacity = AdaptiveByteBuffer.normalizeCapacity(end); } else { newCapacity = end; } if (newCapacity > capacity()) { // The buffer needs expansion. capacity(newCapacity); } if (end > limit()) { // We call limit() directly to prevent StackOverflowError buf().limit(end); } return this; } /** * {@inheritDoc} */ @Override public final AdaptiveByteBuffer shrink() { if (!recapacityAllowed) { throw new IllegalStateException("Derived buffers and their parent can't be expanded."); } int position = position(); int capacity = capacity(); int limit = limit(); if (capacity == limit) { return this; } int newCapacity = capacity; int minCapacity = Math.max(minimumCapacity, limit); for (;;) { if (newCapacity >>> 1 < minCapacity) { break; } newCapacity >>>= 1; if (minCapacity == 0) { break; } } newCapacity = Math.max(minCapacity, newCapacity); if (newCapacity == capacity) { return this; } // Shrink and compact: //// Save the state. ByteOrder bo = order(); //// Reallocate. ByteBuffer oldBuf = buf(); ByteBuffer newBuf = getAllocator().allocateNioBuffer(newCapacity, isDirect()); oldBuf.position(0); oldBuf.limit(limit); newBuf.put(oldBuf); buf(newBuf); //// Restore the state. buf().position(position); buf().limit(limit); buf().order(bo); mark = -1; return this; } /** * {@inheritDoc} */ @Override public final int position() { return buf().position(); } /** * {@inheritDoc} */ @Override public final AdaptiveByteBuffer position(int newPosition) { autoExpand(newPosition, 0); buf().position(newPosition); if (mark > newPosition) { mark = -1; } return this; } /** * {@inheritDoc} */ @Override public final int limit() { return buf().limit(); } /** * {@inheritDoc} */ @Override public final AdaptiveByteBuffer limit(int newLimit) { autoExpand(newLimit, 0); buf().limit(newLimit); if (mark > newLimit) { mark = -1; } return this; } /** * {@inheritDoc} */ @Override public final AdaptiveByteBuffer mark() { ByteBuffer byteBuffer = buf(); byteBuffer.mark(); mark = byteBuffer.position(); return this; } /** * {@inheritDoc} */ @Override public final int markValue() { return mark; } /** * {@inheritDoc} */ @Override public final AdaptiveByteBuffer reset() { buf().reset(); return this; } /** * {@inheritDoc} */ @Override public final AdaptiveByteBuffer clear() { buf().clear(); mark = -1; return this; } /** * {@inheritDoc} */ @Override public final AdaptiveByteBuffer sweep() { clear(); return fillAndReset(remaining()); } /** * {@inheritDoc} */ @Override public final AdaptiveByteBuffer sweep(byte value) { clear(); return fillAndReset(value, remaining()); } /** * {@inheritDoc} */ @Override public final AdaptiveByteBuffer flip() { buf().flip(); mark = -1; return this; } /** * {@inheritDoc} */ @Override public final AdaptiveByteBuffer rewind() { buf().rewind(); mark = -1; return this; } /** * {@inheritDoc} */ @Override public final int remaining() { ByteBuffer byteBuffer = buf(); return byteBuffer.limit() - byteBuffer.position(); } /** * {@inheritDoc} */ @Override public final boolean hasRemaining() { ByteBuffer byteBuffer = buf(); return byteBuffer.limit() > byteBuffer.position(); } /** * {@inheritDoc} */ @Override public final byte get() { return buf().get(); } /** * {@inheritDoc} */ @Override public final short getUnsigned() { return (short) (get() & 0xff); } /** * {@inheritDoc} */ @Override public final AdaptiveByteBuffer put(byte b) { autoExpand(1); buf().put(b); return this; } /** * {@inheritDoc} */ public AdaptiveByteBuffer putUnsigned(byte value) { autoExpand(1); buf().put((byte) (value & 0xff)); return this; } /** * {@inheritDoc} */ public AdaptiveByteBuffer putUnsigned(int index, byte value) { autoExpand(index, 1); buf().put(index, (byte) (value & 0xff)); return this; } /** * {@inheritDoc} */ public AdaptiveByteBuffer putUnsigned(short value) { autoExpand(1); buf().put((byte) (value & 0x00ff)); return this; } /** * {@inheritDoc} */ public AdaptiveByteBuffer putUnsigned(int index, short value) { autoExpand(index, 1); buf().put(index, (byte) (value & 0x00ff)); return this; } /** * {@inheritDoc} */ public AdaptiveByteBuffer putUnsigned(int value) { autoExpand(1); buf().put((byte) (value & 0x000000ff)); return this; } /** * {@inheritDoc} */ public AdaptiveByteBuffer putUnsigned(int index, int value) { autoExpand(index, 1); buf().put(index, (byte) (value & 0x000000ff)); return this; } /** * {@inheritDoc} */ public AdaptiveByteBuffer putUnsigned(long value) { autoExpand(1); buf().put((byte) (value & 0x00000000000000ffL)); return this; } /** * {@inheritDoc} */ public AdaptiveByteBuffer putUnsigned(int index, long value) { autoExpand(index, 1); buf().put(index, (byte) (value & 0x00000000000000ffL)); return this; } /** * {@inheritDoc} */ @Override public final byte get(int index) { return buf().get(index); } /** * {@inheritDoc} */ @Override public final short getUnsigned(int index) { return (short) (get(index) & 0xff); } /** * {@inheritDoc} */ @Override public final AdaptiveByteBuffer put(int index, byte b) { autoExpand(index, 1); buf().put(index, b); return this; } /** * {@inheritDoc} */ @Override public final AdaptiveByteBuffer get(byte[] dst, int offset, int length) { buf().get(dst, offset, length); return this; } /** * {@inheritDoc} */ @Override public final AdaptiveByteBuffer put(ByteBuffer src) { autoExpand(src.remaining()); buf().put(src); return this; } /** * {@inheritDoc} */ @Override public final AdaptiveByteBuffer put(byte[] src, int offset, int length) { autoExpand(length); buf().put(src, offset, length); return this; } /** * {@inheritDoc} */ @Override public final AdaptiveByteBuffer compact() { int remaining = remaining(); int capacity = capacity(); if (capacity == 0) { return this; } if (isAutoShrink() && remaining <= capacity >>> 2 && capacity > minimumCapacity) { int newCapacity = capacity; int minCapacity = Math.max(minimumCapacity, remaining << 1); for (;;) { if (newCapacity >>> 1 < minCapacity) { break; } newCapacity >>>= 1; } newCapacity = Math.max(minCapacity, newCapacity); if (newCapacity == capacity) { return this; } // Shrink and compact: //// Save the state. ByteOrder bo = order(); //// Sanity check. if (remaining > newCapacity) { throw new IllegalStateException("The amount of the remaining bytes is greater than " + "the new capacity."); } //// Reallocate. ByteBuffer oldBuf = buf(); ByteBuffer newBuf = getAllocator().allocateNioBuffer(newCapacity, isDirect()); newBuf.put(oldBuf); buf(newBuf); //// Restore the state. buf().order(bo); } else { buf().compact(); } mark = -1; return this; } /** * {@inheritDoc} */ @Override public final ByteOrder order() { return buf().order(); } /** * {@inheritDoc} */ @Override public final AdaptiveByteBuffer order(ByteOrder bo) { buf().order(bo); return this; } /** * {@inheritDoc} */ @Override public final char getChar() { return buf().getChar(); } /** * {@inheritDoc} */ @Override public final AdaptiveByteBuffer putChar(char value) { autoExpand(2); buf().putChar(value); return this; } /** * {@inheritDoc} */ @Override public final char getChar(int index) { return buf().getChar(index); } /** * {@inheritDoc} */ @Override public final AdaptiveByteBuffer putChar(int index, char value) { autoExpand(index, 2); buf().putChar(index, value); return this; } /** * {@inheritDoc} */ @Override public final CharBuffer asCharBuffer() { return buf().asCharBuffer(); } /** * {@inheritDoc} */ @Override public final short getShort() { return buf().getShort(); } /** * {@inheritDoc} */ @Override public final AdaptiveByteBuffer putShort(short value) { autoExpand(2); buf().putShort(value); return this; } /** * {@inheritDoc} */ @Override public final short getShort(int index) { return buf().getShort(index); } /** * {@inheritDoc} */ @Override public final AdaptiveByteBuffer putShort(int index, short value) { autoExpand(index, 2); buf().putShort(index, value); return this; } /** * {@inheritDoc} */ @Override public final ShortBuffer asShortBuffer() { return buf().asShortBuffer(); } /** * {@inheritDoc} */ @Override public final int getInt() { return buf().getInt(); } /** * {@inheritDoc} */ @Override public final AdaptiveByteBuffer putInt(int value) { autoExpand(4); buf().putInt(value); return this; } /** * {@inheritDoc} */ @Override public final AdaptiveByteBuffer putUnsignedInt(byte value) { autoExpand(4); buf().putInt((value & 0x00ff)); return this; } /** * {@inheritDoc} */ @Override public final AdaptiveByteBuffer putUnsignedInt(int index, byte value) { autoExpand(index, 4); buf().putInt(index, (value & 0x00ff)); return this; } /** * {@inheritDoc} */ @Override public final AdaptiveByteBuffer putUnsignedInt(short value) { autoExpand(4); buf().putInt((value & 0x0000ffff)); return this; } /** * {@inheritDoc} */ @Override public final AdaptiveByteBuffer putUnsignedInt(int index, short value) { autoExpand(index, 4); buf().putInt(index, (value & 0x0000ffff)); return this; } /** * {@inheritDoc} */ @Override public final AdaptiveByteBuffer putUnsignedInt(int value) { autoExpand(4); buf().putInt(value); return this; } /** * {@inheritDoc} */ @Override public final AdaptiveByteBuffer putUnsignedInt(int index, int value) { autoExpand(index, 4); buf().putInt(index, value); return this; } /** * {@inheritDoc} */ @Override public final AdaptiveByteBuffer putUnsignedInt(long value) { autoExpand(4); buf().putInt((int) (value & 0x00000000ffffffff)); return this; } /** * {@inheritDoc} */ @Override public final AdaptiveByteBuffer putUnsignedInt(int index, long value) { autoExpand(index, 4); buf().putInt(index, (int) (value & 0x00000000ffffffffL)); return this; } /** * {@inheritDoc} */ @Override public final AdaptiveByteBuffer putUnsignedShort(byte value) { autoExpand(2); buf().putShort((short) (value & 0x00ff)); return this; } /** * {@inheritDoc} */ @Override public final AdaptiveByteBuffer putUnsignedShort(int index, byte value) { autoExpand(index, 2); buf().putShort(index, (short) (value & 0x00ff)); return this; } /** * {@inheritDoc} */ @Override public final AdaptiveByteBuffer putUnsignedShort(short value) { autoExpand(2); buf().putShort(value); return this; } /** * {@inheritDoc} */ @Override public final AdaptiveByteBuffer putUnsignedShort(int index, short value) { autoExpand(index, 2); buf().putShort(index, value); return this; } /** * {@inheritDoc} */ @Override public final AdaptiveByteBuffer putUnsignedShort(int value) { autoExpand(2); buf().putShort((short) value); return this; } /** * {@inheritDoc} */ @Override public final AdaptiveByteBuffer putUnsignedShort(int index, int value) { autoExpand(index, 2); buf().putShort(index, (short) value); return this; } /** * {@inheritDoc} */ @Override public final AdaptiveByteBuffer putUnsignedShort(long value) { autoExpand(2); buf().putShort((short) (value)); return this; } /** * {@inheritDoc} */ @Override public final AdaptiveByteBuffer putUnsignedShort(int index, long value) { autoExpand(index, 2); buf().putShort(index, (short) (value)); return this; } /** * {@inheritDoc} */ @Override public final int getInt(int index) { return buf().getInt(index); } /** * {@inheritDoc} */ @Override public final AdaptiveByteBuffer putInt(int index, int value) { autoExpand(index, 4); buf().putInt(index, value); return this; } /** * {@inheritDoc} */ @Override public final IntBuffer asIntBuffer() { return buf().asIntBuffer(); } /** * {@inheritDoc} */ @Override public final long getLong() { return buf().getLong(); } /** * {@inheritDoc} */ @Override public final AdaptiveByteBuffer putLong(long value) { autoExpand(8); buf().putLong(value); return this; } /** * {@inheritDoc} */ @Override public final long getLong(int index) { return buf().getLong(index); } /** * {@inheritDoc} */ @Override public final AdaptiveByteBuffer putLong(int index, long value) { autoExpand(index, 8); buf().putLong(index, value); return this; } /** * {@inheritDoc} */ @Override public final LongBuffer asLongBuffer() { return buf().asLongBuffer(); } /** * {@inheritDoc} */ @Override public final float getFloat() { return buf().getFloat(); } /** * {@inheritDoc} */ @Override public final AdaptiveByteBuffer putFloat(float value) { autoExpand(4); buf().putFloat(value); return this; } /** * {@inheritDoc} */ @Override public final float getFloat(int index) { return buf().getFloat(index); } /** * {@inheritDoc} */ @Override public final AdaptiveByteBuffer putFloat(int index, float value) { autoExpand(index, 4); buf().putFloat(index, value); return this; } /** * {@inheritDoc} */ @Override public final FloatBuffer asFloatBuffer() { return buf().asFloatBuffer(); } /** * {@inheritDoc} */ @Override public final double getDouble() { return buf().getDouble(); } /** * {@inheritDoc} */ @Override public final AdaptiveByteBuffer putDouble(double value) { autoExpand(8); buf().putDouble(value); return this; } /** * {@inheritDoc} */ @Override public final double getDouble(int index) { return buf().getDouble(index); } /** * {@inheritDoc} */ @Override public final AdaptiveByteBuffer putDouble(int index, double value) { autoExpand(index, 8); buf().putDouble(index, value); return this; } /** * {@inheritDoc} */ @Override public final DoubleBuffer asDoubleBuffer() { return buf().asDoubleBuffer(); } /** * {@inheritDoc} */ @Override public final AdaptiveByteBuffer asReadOnlyBuffer() { recapacityAllowed = false; return asReadOnlyBuffer0(); } /** * Implement this method to return the unexpandable read only version of * this buffer. */ protected abstract AdaptiveByteBuffer asReadOnlyBuffer0(); /** * {@inheritDoc} */ @Override public final AdaptiveByteBuffer duplicate() { recapacityAllowed = false; return duplicate0(); } /** * Implement this method to return the unexpandable duplicate of this * buffer. */ protected abstract AdaptiveByteBuffer duplicate0(); /** * {@inheritDoc} */ @Override public final AdaptiveByteBuffer slice() { recapacityAllowed = false; return slice0(); } /** * {@inheritDoc} */ @Override public final AdaptiveByteBuffer getSlice(int index, int length) { if (length < 0) { throw new IllegalArgumentException("length: " + length); } int pos = position(); int limit = limit(); if (index > limit) { throw new IllegalArgumentException("index: " + index); } int endIndex = index + length; if (endIndex > limit) { throw new IndexOutOfBoundsException("index + length (" + endIndex + ") is greater " + "than limit (" + limit + ")."); } clear(); position(index); limit(endIndex); AdaptiveByteBuffer slice = slice(); position(pos); limit(limit); return slice; } /** * {@inheritDoc} */ @Override public final AdaptiveByteBuffer getSlice(int length) { if (length < 0) { throw new IllegalArgumentException("length: " + length); } int pos = position(); int limit = limit(); int nextPos = pos + length; if (limit < nextPos) { throw new IndexOutOfBoundsException("position + length (" + nextPos + ") is greater " + "than limit (" + limit + ")."); } limit(pos + length); AdaptiveByteBuffer slice = slice(); position(nextPos); limit(limit); return slice; } /** * Implement this method to return the unexpandable slice of this * buffer. */ protected abstract AdaptiveByteBuffer slice0(); /** * {@inheritDoc} */ @Override public int hashCode() { int h = 1; int p = position(); for (int i = limit() - 1; i >= p; i--) { h = 31 * h + get(i); } return h; } /** * {@inheritDoc} */ @Override public boolean equals(Object o) { if (!(o instanceof AdaptiveByteBuffer)) { return false; } AdaptiveByteBuffer that = (AdaptiveByteBuffer) o; if (this.remaining() != that.remaining()) { return false; } int p = this.position(); for (int i = this.limit() - 1, j = that.limit() - 1; i >= p; i--, j--) { byte v1 = this.get(i); byte v2 = that.get(j); if (v1 != v2) { return false; } } return true; } /** * {@inheritDoc} */ public int compareTo(AdaptiveByteBuffer that) { int n = this.position() + Math.min(this.remaining(), that.remaining()); for (int i = this.position(), j = that.position(); i < n; i++, j++) { byte v1 = this.get(i); byte v2 = that.get(j); if (v1 == v2) { continue; } if (v1 < v2) { return -1; } return +1; } return this.remaining() - that.remaining(); } /** * {@inheritDoc} */ @Override public String toString() { StringBuilder buf = new StringBuilder(); if (isDirect()) { buf.append("DirectBuffer"); } else { buf.append("HeapBuffer"); } buf.append("[pos="); buf.append(position()); buf.append(" lim="); buf.append(limit()); buf.append(" cap="); buf.append(capacity()); buf.append(": "); buf.append(getHexDump(16)); buf.append(']'); return buf.toString(); } /** * {@inheritDoc} */ @Override public AdaptiveByteBuffer get(byte[] dst) { return get(dst, 0, dst.length); } /** * {@inheritDoc} */ @Override public AdaptiveByteBuffer put(AdaptiveByteBuffer src) { return put(src.buf()); } /** * {@inheritDoc} */ @Override public AdaptiveByteBuffer put(byte[] src) { return put(src, 0, src.length); } /** * {@inheritDoc} */ @Override public int getUnsignedShort() { return getShort() & 0xffff; } /** * {@inheritDoc} */ @Override public int getUnsignedShort(int index) { return getShort(index) & 0xffff; } /** * {@inheritDoc} */ @Override public long getUnsignedInt() { return getInt() & 0xffffffffL; } /** * {@inheritDoc} */ @Override public int getMediumInt() { byte b1 = get(); byte b2 = get(); byte b3 = get(); if (ByteOrder.BIG_ENDIAN.equals(order())) { return getMediumInt(b1, b2, b3); } return getMediumInt(b3, b2, b1); } /** * {@inheritDoc} */ @Override public int getUnsignedMediumInt() { int b1 = getUnsigned(); int b2 = getUnsigned(); int b3 = getUnsigned(); if (ByteOrder.BIG_ENDIAN.equals(order())) { return b1 << 16 | b2 << 8 | b3; } return b3 << 16 | b2 << 8 | b1; } /** * {@inheritDoc} */ @Override public int getMediumInt(int index) { byte b1 = get(index); byte b2 = get(index + 1); byte b3 = get(index + 2); if (ByteOrder.BIG_ENDIAN.equals(order())) { return getMediumInt(b1, b2, b3); } return getMediumInt(b3, b2, b1); } /** * {@inheritDoc} */ @Override public int getUnsignedMediumInt(int index) { int b1 = getUnsigned(index); int b2 = getUnsigned(index + 1); int b3 = getUnsigned(index + 2); if (ByteOrder.BIG_ENDIAN.equals(order())) { return b1 << 16 | b2 << 8 | b3; } return b3 << 16 | b2 << 8 | b1; } /** * {@inheritDoc} */ private int getMediumInt(byte b1, byte b2, byte b3) { int ret = b1 << 16 & 0xff0000 | b2 << 8 & 0xff00 | b3 & 0xff; // Check to see if the medium int is negative (high bit in b1 set) if ((b1 & 0x80) == 0x80) { // Make the the whole int negative ret |= 0xff000000; } return ret; } /** * {@inheritDoc} */ @Override public AdaptiveByteBuffer putMediumInt(int value) { byte b1 = (byte) (value >> 16); byte b2 = (byte) (value >> 8); byte b3 = (byte) value; if (ByteOrder.BIG_ENDIAN.equals(order())) { put(b1).put(b2).put(b3); } else { put(b3).put(b2).put(b1); } return this; } /** * {@inheritDoc} */ @Override public AdaptiveByteBuffer putMediumInt(int index, int value) { byte b1 = (byte) (value >> 16); byte b2 = (byte) (value >> 8); byte b3 = (byte) value; if (ByteOrder.BIG_ENDIAN.equals(order())) { put(index, b1).put(index + 1, b2).put(index + 2, b3); } else { put(index, b3).put(index + 1, b2).put(index + 2, b1); } return this; } /** * {@inheritDoc} */ @Override public long getUnsignedInt(int index) { return getInt(index) & 0xffffffffL; } /** * {@inheritDoc} */ @Override public InputStream asInputStream() { return new InputStream() { @Override public int available() { return AbstractAdaptiveByteBuffer.this.remaining(); } @Override public synchronized void mark(int readlimit) { AbstractAdaptiveByteBuffer.this.mark(); } @Override public boolean markSupported() { return true; } @Override public int read() { if (AbstractAdaptiveByteBuffer.this.hasRemaining()) { return AbstractAdaptiveByteBuffer.this.get() & 0xff; } return -1; } @Override public int read(byte[] b, int off, int len) { int remaining = AbstractAdaptiveByteBuffer.this.remaining(); if (remaining > 0) { int readBytes = Math.min(remaining, len); AbstractAdaptiveByteBuffer.this.get(b, off, readBytes); return readBytes; } return -1; } @Override public synchronized void reset() { AbstractAdaptiveByteBuffer.this.reset(); } @Override public long skip(long n) { int bytes; if (n > Integer.MAX_VALUE) { bytes = AbstractAdaptiveByteBuffer.this.remaining(); } else { bytes = Math.min(AbstractAdaptiveByteBuffer.this.remaining(), (int) n); } AbstractAdaptiveByteBuffer.this.skip(bytes); return bytes; } }; } /** * {@inheritDoc} */ @Override public OutputStream asOutputStream() { return new OutputStream() { @Override public void write(byte[] b, int off, int len) { AbstractAdaptiveByteBuffer.this.put(b, off, len); } @Override public void write(int b) { AbstractAdaptiveByteBuffer.this.put((byte) b); } }; } /** * {@inheritDoc} */ @Override public String getHexDump() { return this.getHexDump(Integer.MAX_VALUE); } /** * {@inheritDoc} */ @Override public String getHexDump(int lengthLimit) { return AdaptiveByteBufferHexDumper.getHexdump(this, lengthLimit); } /** * {@inheritDoc} */ @Override public String getString(CharsetDecoder decoder) throws CharacterCodingException { if (!hasRemaining()) { return ""; } boolean utf16 = decoder.charset().name().startsWith("UTF-16"); int oldPos = position(); int oldLimit = limit(); int end = -1; int newPos; if (!utf16) { end = indexOf((byte) 0x00); if (end < 0) { newPos = end = oldLimit; } else { newPos = end + 1; } } else { int i = oldPos; for (;;) { boolean wasZero = get(i) == 0; i++; if (i >= oldLimit) { break; } if (get(i) != 0) { i++; if (i >= oldLimit) { break; } continue; } if (wasZero) { end = i - 1; break; } } if (end < 0) { newPos = end = oldPos + (oldLimit - oldPos & 0xFFFFFFFE); } else { if (end + 2 <= oldLimit) { newPos = end + 2; } else { newPos = end; } } } if (oldPos == end) { position(newPos); return ""; } limit(end); decoder.reset(); int expectedLength = (int) (remaining() * decoder.averageCharsPerByte()) + 1; CharBuffer out = CharBuffer.allocate(expectedLength); for (;;) { CoderResult cr; if (hasRemaining()) { cr = decoder.decode(buf(), out, true); } else { cr = decoder.flush(out); } if (cr.isUnderflow()) { break; } if (cr.isOverflow()) { CharBuffer o = CharBuffer.allocate(out.capacity() + expectedLength); out.flip(); o.put(out); out = o; continue; } if (cr.isError()) { // Revert the buffer back to the previous state. limit(oldLimit); position(oldPos); cr.throwException(); } } limit(oldLimit); position(newPos); return out.flip().toString(); } /** * {@inheritDoc} */ @Override public String getString(int fieldSize, CharsetDecoder decoder) throws CharacterCodingException { checkFieldSize(fieldSize); if (fieldSize == 0) { return ""; } if (!hasRemaining()) { return ""; } boolean utf16 = decoder.charset().name().startsWith("UTF-16"); if (utf16 && (fieldSize & 1) != 0) { throw new IllegalArgumentException("fieldSize is not even."); } int oldPos = position(); int oldLimit = limit(); int end = oldPos + fieldSize; if (oldLimit < end) { throw new BufferUnderflowException(); } int i; if (!utf16) { for (i = oldPos; i < end; i++) { if (get(i) == 0) { break; } } if (i == end) { limit(end); } else { limit(i); } } else { for (i = oldPos; i < end; i += 2) { if (get(i) == 0 && get(i + 1) == 0) { break; } } if (i == end) { limit(end); } else { limit(i); } } if (!hasRemaining()) { limit(oldLimit); position(end); return ""; } decoder.reset(); int expectedLength = (int) (remaining() * decoder.averageCharsPerByte()) + 1; CharBuffer out = CharBuffer.allocate(expectedLength); for (;;) { CoderResult cr; if (hasRemaining()) { cr = decoder.decode(buf(), out, true); } else { cr = decoder.flush(out); } if (cr.isUnderflow()) { break; } if (cr.isOverflow()) { CharBuffer o = CharBuffer.allocate(out.capacity() + expectedLength); out.flip(); o.put(out); out = o; continue; } if (cr.isError()) { // Revert the buffer back to the previous state. limit(oldLimit); position(oldPos); cr.throwException(); } } limit(oldLimit); position(end); return out.flip().toString(); } /** * {@inheritDoc} */ @Override public AdaptiveByteBuffer putString(CharSequence val, CharsetEncoder encoder) throws CharacterCodingException { if (val.length() == 0) { return this; } CharBuffer in = CharBuffer.wrap(val); encoder.reset(); int expandedState = 0; for (;;) { CoderResult cr; if (in.hasRemaining()) { cr = encoder.encode(in, buf(), true); } else { cr = encoder.flush(buf()); } if (cr.isUnderflow()) { break; } if (cr.isOverflow()) { if (isAutoExpand()) { switch (expandedState) { case 0: autoExpand((int) Math.ceil(in.remaining() * encoder.averageBytesPerChar())); expandedState++; break; case 1: autoExpand((int) Math.ceil(in.remaining() * encoder.maxBytesPerChar())); expandedState++; break; default: throw new RuntimeException("Expanded by " + (int) Math.ceil(in.remaining() * encoder.maxBytesPerChar()) + " but that wasn't enough for '" + val + "'"); } continue; } } else { expandedState = 0; } cr.throwException(); } return this; } /** * {@inheritDoc} */ @Override public AdaptiveByteBuffer putString(CharSequence val, int fieldSize, CharsetEncoder encoder) throws CharacterCodingException { checkFieldSize(fieldSize); if (fieldSize == 0) { return this; } autoExpand(fieldSize); boolean utf16 = encoder.charset().name().startsWith("UTF-16"); if (utf16 && (fieldSize & 1) != 0) { throw new IllegalArgumentException("fieldSize is not even."); } int oldLimit = limit(); int end = position() + fieldSize; if (oldLimit < end) { throw new BufferOverflowException(); } if (val.length() == 0) { if (!utf16) { put((byte) 0x00); } else { put((byte) 0x00); put((byte) 0x00); } position(end); return this; } CharBuffer in = CharBuffer.wrap(val); limit(end); encoder.reset(); for (;;) { CoderResult cr; if (in.hasRemaining()) { cr = encoder.encode(in, buf(), true); } else { cr = encoder.flush(buf()); } if (cr.isUnderflow() || cr.isOverflow()) { break; } cr.throwException(); } limit(oldLimit); if (position() < end) { if (!utf16) { put((byte) 0x00); } else { put((byte) 0x00); put((byte) 0x00); } } position(end); return this; } /** * {@inheritDoc} */ @Override public String getPrefixedString(CharsetDecoder decoder) throws CharacterCodingException { return getPrefixedString(2, decoder); } /** * Reads a string which has a length field before the actual * encoded string, using the specified decoder and returns it. * * @param prefixLength the length of the length field (1, 2, or 4) * @param decoder the decoder to use for decoding the string * @return the prefixed string * @throws CharacterCodingException when decoding fails * @throws BufferUnderflowException when there is not enough data available */ @Override public String getPrefixedString(int prefixLength, CharsetDecoder decoder) throws CharacterCodingException { if (!prefixedDataAvailable(prefixLength)) { throw new BufferUnderflowException(); } int fieldSize = 0; switch (prefixLength) { case 1: fieldSize = getUnsigned(); break; case 2: fieldSize = getUnsignedShort(); break; case 4: fieldSize = getInt(); break; } if (fieldSize == 0) { return ""; } boolean utf16 = decoder.charset().name().startsWith("UTF-16"); if (utf16 && (fieldSize & 1) != 0) { throw new IllegalArgumentException("fieldSize is not even for a UTF-16 string."); } int oldLimit = limit(); int end = position() + fieldSize; if (oldLimit < end) { throw new BufferUnderflowException(); } limit(end); decoder.reset(); int expectedLength = (int) (remaining() * decoder.averageCharsPerByte()) + 1; CharBuffer out = CharBuffer.allocate(expectedLength); for (;;) { CoderResult cr; if (hasRemaining()) { cr = decoder.decode(buf(), out, true); } else { cr = decoder.flush(out); } if (cr.isUnderflow()) { break; } if (cr.isOverflow()) { CharBuffer o = CharBuffer.allocate(out.capacity() + expectedLength); out.flip(); o.put(out); out = o; continue; } cr.throwException(); } limit(oldLimit); position(end); return out.flip().toString(); } /** * {@inheritDoc} */ @Override public AdaptiveByteBuffer putPrefixedString(CharSequence in, CharsetEncoder encoder) throws CharacterCodingException { return putPrefixedString(in, 2, 0, encoder); } /** * {@inheritDoc} */ @Override public AdaptiveByteBuffer putPrefixedString(CharSequence in, int prefixLength, CharsetEncoder encoder) throws CharacterCodingException { return putPrefixedString(in, prefixLength, 0, encoder); } /** * {@inheritDoc} */ @Override public AdaptiveByteBuffer putPrefixedString(CharSequence in, int prefixLength, int padding, CharsetEncoder encoder) throws CharacterCodingException { return putPrefixedString(in, prefixLength, padding, (byte) 0, encoder); } /** * {@inheritDoc} */ @Override public AdaptiveByteBuffer putPrefixedString(CharSequence val, int prefixLength, int padding, byte padValue, CharsetEncoder encoder) throws CharacterCodingException { int maxLength; switch (prefixLength) { case 1: maxLength = 255; break; case 2: maxLength = 65535; break; case 4: maxLength = Integer.MAX_VALUE; break; default: throw new IllegalArgumentException("prefixLength: " + prefixLength); } if (val.length() > maxLength) { throw new IllegalArgumentException("The specified string is too long."); } if (val.length() == 0) { switch (prefixLength) { case 1: put((byte) 0); break; case 2: putShort((short) 0); break; case 4: putInt(0); break; } return this; } int padMask; switch (padding) { case 0: case 1: padMask = 0; break; case 2: padMask = 1; break; case 4: padMask = 3; break; default: throw new IllegalArgumentException("padding: " + padding); } CharBuffer in = CharBuffer.wrap(val); skip(prefixLength); // make a room for the length field int oldPos = position(); encoder.reset(); int expandedState = 0; for (;;) { CoderResult cr; if (in.hasRemaining()) { cr = encoder.encode(in, buf(), true); } else { cr = encoder.flush(buf()); } if (position() - oldPos > maxLength) { throw new IllegalArgumentException("The specified string is too long."); } if (cr.isUnderflow()) { break; } if (cr.isOverflow()) { if (isAutoExpand()) { switch (expandedState) { case 0: autoExpand((int) Math.ceil(in.remaining() * encoder.averageBytesPerChar())); expandedState++; break; case 1: autoExpand((int) Math.ceil(in.remaining() * encoder.maxBytesPerChar())); expandedState++; break; default: throw new RuntimeException("Expanded by " + (int) Math.ceil(in.remaining() * encoder.maxBytesPerChar()) + " but that wasn't enough for '" + val + "'"); } continue; } } else { expandedState = 0; } cr.throwException(); } // Write the length field fill(padValue, padding - (position() - oldPos & padMask)); int length = position() - oldPos; switch (prefixLength) { case 1: put(oldPos - 1, (byte) length); break; case 2: putShort(oldPos - 2, (short) length); break; case 4: putInt(oldPos - 4, length); break; } return this; } /** * {@inheritDoc} */ @Override public Object getObject() throws ClassNotFoundException { return getObject(Thread.currentThread().getContextClassLoader()); } /** * {@inheritDoc} */ @Override public Object getObject(final ClassLoader classLoader) throws ClassNotFoundException { if (!prefixedDataAvailable(4)) { throw new BufferUnderflowException(); } int length = getInt(); if (length <= 4) { throw new IllegalArgumentException("Object length should be greater than 4: " + length); } int oldLimit = limit(); limit(position() + length); try { ObjectInputStream in = new ObjectInputStream(asInputStream()) { @Override protected ObjectStreamClass readClassDescriptor() throws IOException, ClassNotFoundException { int type = read(); if (type < 0) { throw new EOFException(); } switch (type) { case 0: // NON-Serializable class or Primitive types return super.readClassDescriptor(); case 1: // Serializable class String className = readUTF(); Class clazz = Class.forName(className, true, classLoader); return ObjectStreamClass.lookup(clazz); default: throw new StreamCorruptedException("Unexpected class descriptor type: " + type); } } @Override protected Class resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException { String name = desc.getName(); try { return Class.forName(name, false, classLoader); } catch (ClassNotFoundException ex) { return super.resolveClass(desc); } } }; return in.readObject(); } catch (IOException e) { throw new RuntimeException(e); } finally { limit(oldLimit); } } /** * {@inheritDoc} */ @Override public AdaptiveByteBuffer putObject(Object o) { int oldPos = position(); skip(4); // Make a room for the length field. try { ObjectOutputStream out = new ObjectOutputStream(asOutputStream()) { @Override protected void writeClassDescriptor(ObjectStreamClass desc) throws IOException { try { Class clz = Class.forName(desc.getName()); if (!Serializable.class.isAssignableFrom(clz)) { // NON-Serializable class write(0); super.writeClassDescriptor(desc); } else { // Serializable class write(1); writeUTF(desc.getName()); } } catch (ClassNotFoundException ex) { // Primitive types write(0); super.writeClassDescriptor(desc); } } }; out.writeObject(o); out.flush(); } catch (IOException e) { throw new RuntimeException(e); } // Fill the length field int newPos = position(); position(oldPos); putInt(newPos - oldPos - 4); position(newPos); return this; } /** * {@inheritDoc} */ @Override public boolean prefixedDataAvailable(int prefixLength) { return prefixedDataAvailable(prefixLength, Integer.MAX_VALUE); } /** * {@inheritDoc} */ @Override public boolean prefixedDataAvailable(int prefixLength, int maxDataLength) { if (remaining() < prefixLength) { return false; } int dataLength; switch (prefixLength) { case 1: dataLength = getUnsigned(position()); break; case 2: dataLength = getUnsignedShort(position()); break; case 4: dataLength = getInt(position()); break; default: throw new IllegalArgumentException("prefixLength: " + prefixLength); } if (dataLength < 0 || dataLength > maxDataLength) { throw new IllegalArgumentException("dataLength: " + dataLength); } return remaining() - prefixLength >= dataLength; } /** * {@inheritDoc} */ @Override public int indexOf(byte b) { if (hasArray()) { int arrayOffset = arrayOffset(); int beginPos = arrayOffset + position(); int limit = arrayOffset + limit(); byte[] array = array(); for (int i = beginPos; i < limit; i++) { if (array[i] == b) { return i - arrayOffset; } } } else { int beginPos = position(); int limit = limit(); for (int i = beginPos; i < limit; i++) { if (get(i) == b) { return i; } } } return -1; } /** * {@inheritDoc} */ @Override public AdaptiveByteBuffer skip(int size) { autoExpand(size); return position(position() + size); } /** * {@inheritDoc} */ @Override public AdaptiveByteBuffer fill(byte value, int size) { autoExpand(size); int q = size >>> 3; int r = size & 7; if (q > 0) { int intValue = (value & 0xff) | value << 8 | value << 16 | value << 24; long longValue = intValue; longValue <<= 32; longValue |= intValue; for (int i = q; i > 0; i--) { putLong(longValue); } } q = r >>> 2; r = r & 3; if (q > 0) { int intValue = (value & 0xff) | value << 8 | value << 16 | value << 24; putInt(intValue); } q = r >> 1; r = r & 1; if (q > 0) { short shortValue = (short) ((value & 0xff) | value << 8); putShort(shortValue); } if (r > 0) { put(value); } return this; } /** * {@inheritDoc} */ @Override public AdaptiveByteBuffer fillAndReset(byte value, int size) { autoExpand(size); int pos = position(); try { fill(value, size); } finally { position(pos); } return this; } /** * {@inheritDoc} */ @Override public AdaptiveByteBuffer fill(int size) { autoExpand(size); int q = size >>> 3; int r = size & 7; for (int i = q; i > 0; i--) { putLong(0L); } q = r >>> 2; r = r & 3; if (q > 0) { putInt(0); } q = r >> 1; r = r & 1; if (q > 0) { putShort((short) 0); } if (r > 0) { put((byte) 0); } return this; } /** * {@inheritDoc} */ @Override public AdaptiveByteBuffer fillAndReset(int size) { autoExpand(size); int pos = position(); try { fill(size); } finally { position(pos); } return this; } /** * {@inheritDoc} */ @Override public > E getEnum(Class enumClass) { return toEnum(enumClass, getUnsigned()); } /** * {@inheritDoc} */ @Override public > E getEnum(int index, Class enumClass) { return toEnum(enumClass, getUnsigned(index)); } /** * {@inheritDoc} */ @Override public > E getEnumShort(Class enumClass) { return toEnum(enumClass, getUnsignedShort()); } /** * {@inheritDoc} */ @Override public > E getEnumShort(int index, Class enumClass) { return toEnum(enumClass, getUnsignedShort(index)); } /** * {@inheritDoc} */ @Override public > E getEnumInt(Class enumClass) { return toEnum(enumClass, getInt()); } /** * {@inheritDoc} */ public > E getEnumInt(int index, Class enumClass) { return toEnum(enumClass, getInt(index)); } /** * {@inheritDoc} */ @Override public AdaptiveByteBuffer putEnum(Enum e) { if (e.ordinal() > BYTE_MASK) { throw new IllegalArgumentException(enumConversionErrorMessage(e, "byte")); } return put((byte) e.ordinal()); } /** * {@inheritDoc} */ @Override public AdaptiveByteBuffer putEnum(int index, Enum e) { if (e.ordinal() > BYTE_MASK) { throw new IllegalArgumentException(enumConversionErrorMessage(e, "byte")); } return put(index, (byte) e.ordinal()); } /** * {@inheritDoc} */ @Override public AdaptiveByteBuffer putEnumShort(Enum e) { if (e.ordinal() > SHORT_MASK) { throw new IllegalArgumentException(enumConversionErrorMessage(e, "short")); } return putShort((short) e.ordinal()); } /** * {@inheritDoc} */ @Override public AdaptiveByteBuffer putEnumShort(int index, Enum e) { if (e.ordinal() > SHORT_MASK) { throw new IllegalArgumentException(enumConversionErrorMessage(e, "short")); } return putShort(index, (short) e.ordinal()); } /** * {@inheritDoc} */ @Override public AdaptiveByteBuffer putEnumInt(Enum e) { return putInt(e.ordinal()); } /** * {@inheritDoc} */ @Override public AdaptiveByteBuffer putEnumInt(int index, Enum e) { return putInt(index, e.ordinal()); } private E toEnum(Class enumClass, int i) { E[] enumConstants = enumClass.getEnumConstants(); if (i > enumConstants.length) { throw new IndexOutOfBoundsException(String.format( "%d is too large of an ordinal to convert to the enum %s", i, enumClass.getName())); } return enumConstants[i]; } private String enumConversionErrorMessage(Enum e, String type) { return String.format("%s.%s has an ordinal value too large for a %s", e.getClass().getName(), e.name(), type); } /** * {@inheritDoc} */ @Override public > EnumSet getEnumSet(Class enumClass) { return toEnumSet(enumClass, get() & BYTE_MASK); } /** * {@inheritDoc} */ @Override public > EnumSet getEnumSet(int index, Class enumClass) { return toEnumSet(enumClass, get(index) & BYTE_MASK); } /** * {@inheritDoc} */ @Override public > EnumSet getEnumSetShort(Class enumClass) { return toEnumSet(enumClass, getShort() & SHORT_MASK); } /** * {@inheritDoc} */ @Override public > EnumSet getEnumSetShort(int index, Class enumClass) { return toEnumSet(enumClass, getShort(index) & SHORT_MASK); } /** * {@inheritDoc} */ @Override public > EnumSet getEnumSetInt(Class enumClass) { return toEnumSet(enumClass, getInt() & INT_MASK); } /** * {@inheritDoc} */ @Override public > EnumSet getEnumSetInt(int index, Class enumClass) { return toEnumSet(enumClass, getInt(index) & INT_MASK); } /** * {@inheritDoc} */ @Override public > EnumSet getEnumSetLong(Class enumClass) { return toEnumSet(enumClass, getLong()); } /** * {@inheritDoc} */ @Override public > EnumSet getEnumSetLong(int index, Class enumClass) { return toEnumSet(enumClass, getLong(index)); } private > EnumSet toEnumSet(Class clazz, long vector) { EnumSet set = EnumSet.noneOf(clazz); long mask = 1; for (E e : clazz.getEnumConstants()) { if ((mask & vector) == mask) { set.add(e); } mask <<= 1; } return set; } /** * {@inheritDoc} */ @Override public > AdaptiveByteBuffer putEnumSet(Set set) { long vector = toLong(set); if ((vector & ~BYTE_MASK) != 0) { throw new IllegalArgumentException("The enum set is too large to fit in a byte: " + set); } return put((byte) vector); } /** * {@inheritDoc} */ @Override public > AdaptiveByteBuffer putEnumSet(int index, Set set) { long vector = toLong(set); if ((vector & ~BYTE_MASK) != 0) { throw new IllegalArgumentException("The enum set is too large to fit in a byte: " + set); } return put(index, (byte) vector); } /** * {@inheritDoc} */ @Override public > AdaptiveByteBuffer putEnumSetShort(Set set) { long vector = toLong(set); if ((vector & ~SHORT_MASK) != 0) { throw new IllegalArgumentException("The enum set is too large to fit in a short: " + set); } return putShort((short) vector); } /** * {@inheritDoc} */ @Override public > AdaptiveByteBuffer putEnumSetShort(int index, Set set) { long vector = toLong(set); if ((vector & ~SHORT_MASK) != 0) { throw new IllegalArgumentException("The enum set is too large to fit in a short: " + set); } return putShort(index, (short) vector); } /** * {@inheritDoc} */ @Override public > AdaptiveByteBuffer putEnumSetInt(Set set) { long vector = toLong(set); if ((vector & ~INT_MASK) != 0) { throw new IllegalArgumentException("The enum set is too large to fit in an int: " + set); } return putInt((int) vector); } /** * {@inheritDoc} */ @Override public > AdaptiveByteBuffer putEnumSetInt(int index, Set set) { long vector = toLong(set); if ((vector & ~INT_MASK) != 0) { throw new IllegalArgumentException("The enum set is too large to fit in an int: " + set); } return putInt(index, (int) vector); } /** * {@inheritDoc} */ @Override public > AdaptiveByteBuffer putEnumSetLong(Set set) { return putLong(toLong(set)); } /** * {@inheritDoc} */ @Override public > AdaptiveByteBuffer putEnumSetLong(int index, Set set) { return putLong(index, toLong(set)); } private > long toLong(Set set) { long vector = 0; for (E e : set) { if (e.ordinal() >= Long.SIZE) { throw new IllegalArgumentException("The enum set is too large to fit in a bit vector: " + set); } vector |= 1L << e.ordinal(); } return vector; } /** * This method forwards the call to {@link #expand(int)} only when * autoExpand property is true. */ private AdaptiveByteBuffer autoExpand(int expectedRemaining) { if (isAutoExpand()) { expand(expectedRemaining, true); } return this; } /** * This method forwards the call to {@link #expand(int)} only when * autoExpand property is true. */ private AdaptiveByteBuffer autoExpand(int pos, int expectedRemaining) { if (isAutoExpand()) { expand(pos, expectedRemaining, true); } return this; } private static void checkFieldSize(int fieldSize) { if (fieldSize < 0) { throw new IllegalArgumentException("fieldSize cannot be negative: " + fieldSize); } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy