com.google.code.yanf4j.buffer.AbstractIoBuffer Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of xmemcached Show documentation
Show all versions of xmemcached Show documentation
Extreme performance modern memcached client for java
/*
* 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 com.google.code.yanf4j.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.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 IoBuffer}. This implementation assumes that
* {@link IoBuffer#buf()} always returns a correct NIO {@link ByteBuffer} instance. Most
* implementations could extend this class and implement their own buffer management mechanism.
*
* @author The Apache MINA Project ([email protected])
* @version $Rev: 748210 $, $Date: 2009-02-26 18:05:40 +0100 (Thu, 26 Feb 2009) $
* @see IoBufferAllocator
*/
public abstract class AbstractIoBuffer extends IoBuffer {
/** Tells if a buffer has been created from an existing buffer */
private final boolean derived;
/** A flag set to true if the buffer can extend automatically */
private boolean autoExpand;
/** A flag set to true if the buffer can shrink automatically */
private boolean autoShrink;
/** Tells if a buffer can be expanded */
private boolean recapacityAllowed = true;
/** The minimum number of bytes the IoBuffer can hold */
private int minimumCapacity;
/** A mask for a byte */
private static final long BYTE_MASK = 0xFFL;
/** A mask for a short */
private static final long SHORT_MASK = 0xFFFFL;
/** A mask for an int */
private static final long INT_MASK = 0xFFFFFFFFL;
/**
* We don't have any access to Buffer.markValue(), so we need to track it down, which will cause
* small extra overhead.
*/
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 AbstractIoBuffer(IoBufferAllocator 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 AbstractIoBuffer(AbstractIoBuffer parent) {
setAllocator(parent.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 IoBuffer 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 IoBuffer 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 IoBuffer 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 IoBuffer 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 IoBuffer expand(int expectedRemaining) {
return expand(position(), expectedRemaining, false);
}
private IoBuffer expand(int expectedRemaining, boolean autoExpand) {
return expand(position(), expectedRemaining, autoExpand);
}
/**
* {@inheritDoc}
*/
@Override
public final IoBuffer expand(int pos, int expectedRemaining) {
return expand(pos, expectedRemaining, false);
}
private IoBuffer 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 = IoBuffer.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 IoBuffer 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;
}
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 IoBuffer 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 IoBuffer limit(int newLimit) {
autoExpand(newLimit, 0);
buf().limit(newLimit);
if (mark > newLimit) {
mark = -1;
}
return this;
}
/**
* {@inheritDoc}
*/
@Override
public final IoBuffer mark() {
buf().mark();
mark = position();
return this;
}
/**
* {@inheritDoc}
*/
@Override
public final int markValue() {
return mark;
}
/**
* {@inheritDoc}
*/
@Override
public final IoBuffer reset() {
buf().reset();
return this;
}
/**
* {@inheritDoc}
*/
@Override
public final IoBuffer clear() {
buf().clear();
mark = -1;
return this;
}
/**
* {@inheritDoc}
*/
@Override
public final IoBuffer sweep() {
clear();
return fillAndReset(remaining());
}
/**
* {@inheritDoc}
*/
@Override
public final IoBuffer sweep(byte value) {
clear();
return fillAndReset(value, remaining());
}
/**
* {@inheritDoc}
*/
@Override
public final IoBuffer flip() {
buf().flip();
mark = -1;
return this;
}
/**
* {@inheritDoc}
*/
@Override
public final IoBuffer rewind() {
buf().rewind();
mark = -1;
return this;
}
/**
* {@inheritDoc}
*/
@Override
public final int remaining() {
return limit() - position();
}
/**
* {@inheritDoc}
*/
@Override
public final boolean hasRemaining() {
return limit() > position();
}
/**
* {@inheritDoc}
*/
@Override
public final byte get() {
return buf().get();
}
/**
* {@inheritDoc}
*/
@Override
public final short getUnsigned() {
return (short) (get() & 0xff);
}
/**
* {@inheritDoc}
*/
@Override
public final IoBuffer put(byte b) {
autoExpand(1);
buf().put(b);
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 IoBuffer put(int index, byte b) {
autoExpand(index, 1);
buf().put(index, b);
return this;
}
/**
* {@inheritDoc}
*/
@Override
public final IoBuffer get(byte[] dst, int offset, int length) {
buf().get(dst, offset, length);
return this;
}
/**
* {@inheritDoc}
*/
@Override
public final IoBuffer put(ByteBuffer src) {
autoExpand(src.remaining());
buf().put(src);
return this;
}
/**
* {@inheritDoc}
*/
@Override
public final IoBuffer put(byte[] src, int offset, int length) {
autoExpand(length);
buf().put(src, offset, length);
return this;
}
/**
* {@inheritDoc}
*/
@Override
public final IoBuffer 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 IoBuffer order(ByteOrder bo) {
buf().order(bo);
return this;
}
/**
* {@inheritDoc}
*/
@Override
public final char getChar() {
return buf().getChar();
}
/**
* {@inheritDoc}
*/
@Override
public final IoBuffer 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 IoBuffer 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 IoBuffer 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 IoBuffer 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 IoBuffer putInt(int value) {
autoExpand(4);
buf().putInt(value);
return this;
}
/**
* {@inheritDoc}
*/
@Override
public final int getInt(int index) {
return buf().getInt(index);
}
/**
* {@inheritDoc}
*/
@Override
public final IoBuffer 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 IoBuffer 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 IoBuffer 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 IoBuffer 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 IoBuffer 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 IoBuffer 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 IoBuffer 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 IoBuffer asReadOnlyBuffer() {
recapacityAllowed = false;
return asReadOnlyBuffer0();
}
/**
* Implement this method to return the unexpandable read only version of this buffer.
*/
protected abstract IoBuffer asReadOnlyBuffer0();
/**
* {@inheritDoc}
*/
@Override
public final IoBuffer duplicate() {
recapacityAllowed = false;
return duplicate0();
}
/**
* Implement this method to return the unexpandable duplicate of this buffer.
*/
protected abstract IoBuffer duplicate0();
/**
* {@inheritDoc}
*/
@Override
public final IoBuffer slice() {
recapacityAllowed = false;
return slice0();
}
/**
* {@inheritDoc}
*/
@Override
public final IoBuffer getSlice(int index, int length) {
if (length < 0) {
throw new IllegalArgumentException("length: " + length);
}
int limit = limit();
if (index > limit) {
throw new IllegalArgumentException("index: " + index);
}
int endIndex = index + length;
if (capacity() < endIndex) {
throw new IndexOutOfBoundsException(
"index + length (" + endIndex + ") is greater " + "than capacity (" + capacity() + ").");
}
clear();
position(index);
limit(endIndex);
IoBuffer slice = slice();
position(index);
limit(limit);
return slice;
}
/**
* {@inheritDoc}
*/
@Override
public final IoBuffer 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);
IoBuffer slice = slice();
position(nextPos);
limit(limit);
return slice;
}
/**
* Implement this method to return the unexpandable slice of this buffer.
*/
protected abstract IoBuffer 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 IoBuffer)) {
return false;
}
IoBuffer that = (IoBuffer) 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(IoBuffer 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 IoBuffer get(byte[] dst) {
return get(dst, 0, dst.length);
}
/**
* {@inheritDoc}
*/
@Override
public IoBuffer put(IoBuffer src) {
return put(src.buf());
}
/**
* {@inheritDoc}
*/
@Override
public IoBuffer 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);
} else {
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;
} else {
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);
} else {
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;
} else {
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 IoBuffer 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 IoBuffer 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 AbstractIoBuffer.this.remaining();
}
@Override
public synchronized void mark(int readlimit) {
AbstractIoBuffer.this.mark();
}
@Override
public boolean markSupported() {
return true;
}
@Override
public int read() {
if (AbstractIoBuffer.this.hasRemaining()) {
return AbstractIoBuffer.this.get() & 0xff;
} else {
return -1;
}
}
@Override
public int read(byte[] b, int off, int len) {
int remaining = AbstractIoBuffer.this.remaining();
if (remaining > 0) {
int readBytes = Math.min(remaining, len);
AbstractIoBuffer.this.get(b, off, readBytes);
return readBytes;
} else {
return -1;
}
}
@Override
public synchronized void reset() {
AbstractIoBuffer.this.reset();
}
@Override
public long skip(long n) {
int bytes;
if (n > Integer.MAX_VALUE) {
bytes = AbstractIoBuffer.this.remaining();
} else {
bytes = Math.min(AbstractIoBuffer.this.remaining(), (int) n);
}
AbstractIoBuffer.this.skip(bytes);
return bytes;
}
};
}
/**
* {@inheritDoc}
*/
@Override
public OutputStream asOutputStream() {
return new OutputStream() {
@Override
public void write(byte[] b, int off, int len) {
AbstractIoBuffer.this.put(b, off, len);
}
@Override
public void write(int b) {
AbstractIoBuffer.this.put((byte) b);
}
};
}
/**
* {@inheritDoc}
*/
@Override
public String getHexDump() {
return this.getHexDump(Integer.MAX_VALUE);
}
/**
* {@inheritDoc}
*/
@Override
public String getHexDump(int lengthLimit) {
return IoBufferHexDumper.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;
} else {
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 IoBuffer 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 IoBuffer 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 BufferDataException("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 IoBuffer putPrefixedString(CharSequence in, CharsetEncoder encoder)
throws CharacterCodingException {
return putPrefixedString(in, 2, 0, encoder);
}
/**
* {@inheritDoc}
*/
@Override
public IoBuffer putPrefixedString(CharSequence in, int prefixLength, CharsetEncoder encoder)
throws CharacterCodingException {
return putPrefixedString(in, prefixLength, 0, encoder);
}
/**
* {@inheritDoc}
*/
@Override
public IoBuffer putPrefixedString(CharSequence in, int prefixLength, int padding,
CharsetEncoder encoder) throws CharacterCodingException {
return putPrefixedString(in, prefixLength, padding, (byte) 0, encoder);
}
/**
* {@inheritDoc}
*/
@Override
public IoBuffer 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 BufferDataException("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: // Primitive types
return super.readClassDescriptor();
case 1: // Non-primitive types
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 BufferDataException(e);
} finally {
limit(oldLimit);
}
}
/**
* {@inheritDoc}
*/
@Override
public IoBuffer 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 {
if (desc.forClass().isPrimitive()) {
write(0);
super.writeClassDescriptor(desc);
} else {
write(1);
writeUTF(desc.getName());
}
}
};
out.writeObject(o);
out.flush();
} catch (IOException e) {
throw new BufferDataException(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 BufferDataException("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 IoBuffer skip(int size) {
autoExpand(size);
return position(position() + size);
}
/**
* {@inheritDoc}
*/
@Override
public IoBuffer fill(byte value, int size) {
autoExpand(size);
int q = size >>> 3;
int r = size & 7;
if (q > 0) {
int intValue = value | 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 | value << 8 | value << 16 | value << 24;
putInt(intValue);
}
q = r >> 1;
r = r & 1;
if (q > 0) {
short shortValue = (short) (value | value << 8);
putShort(shortValue);
}
if (r > 0) {
put(value);
}
return this;
}
/**
* {@inheritDoc}
*/
@Override
public IoBuffer fillAndReset(byte value, int size) {
autoExpand(size);
int pos = position();
try {
fill(value, size);
} finally {
position(pos);
}
return this;
}
/**
* {@inheritDoc}
*/
@Override
public IoBuffer 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 IoBuffer 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}
*/
@Override
public > E getEnumInt(int index, Class enumClass) {
return toEnum(enumClass, getInt(index));
}
/**
* {@inheritDoc}
*/
@Override
public IoBuffer putEnum(Enum> e) {
if (e.ordinal() > BYTE_MASK) {
throw new IllegalArgumentException(enumConversionErrorMessage(e, "byte"));
}
return put((byte) e.ordinal());
}
/**
* {@inheritDoc}
*/
@Override
public IoBuffer 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 IoBuffer putEnumShort(Enum> e) {
if (e.ordinal() > SHORT_MASK) {
throw new IllegalArgumentException(enumConversionErrorMessage(e, "short"));
}
return putShort((short) e.ordinal());
}
/**
* {@inheritDoc}
*/
@Override
public IoBuffer 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 IoBuffer putEnumInt(Enum> e) {
return putInt(e.ordinal());
}
/**
* {@inheritDoc}
*/
@Override
public IoBuffer 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 > IoBuffer 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 > IoBuffer 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 > IoBuffer 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 > IoBuffer 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 > IoBuffer 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 > IoBuffer 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 > IoBuffer putEnumSetLong(Set set) {
return putLong(toLong(set));
}
/**
* {@inheritDoc}
*/
@Override
public > IoBuffer 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 IoBuffer 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 IoBuffer 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 - 2025 Weber Informatics LLC | Privacy Policy