com.zusmart.base.buffer.support.AbstractBuffer Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of zusmart-base Show documentation
Show all versions of zusmart-base Show documentation
提供基础的工具类及方法类,Logging,Scanner,Buffer,NetWork,Future,Thread
package com.zusmart.base.buffer.support;
import java.io.IOException;
import java.nio.BufferOverflowException;
import java.nio.BufferUnderflowException;
import java.nio.ByteBuffer;
import java.nio.InvalidMarkException;
import java.nio.ReadOnlyBufferException;
import java.nio.channels.ReadableByteChannel;
import java.nio.channels.WritableByteChannel;
import com.zusmart.base.buffer.Buffer;
import com.zusmart.base.util.Assert;
public abstract class AbstractBuffer implements Buffer {
private static final ReleasedBufferException RELEASED_BUFFER_EXCEPTION = new ReleasedBufferException();
private boolean released;
private boolean readonly;
private boolean permanent;
private boolean bigEndian = false;
private int mark = -1;
private int limit = 0;
private int position = 0;
private int capacity = 0;
private final int offset;
protected AbstractBuffer(int offset, int capacity) {
this.offset = offset;
this.capacity = capacity;
this.limit(capacity);
}
@Override
public void release() {
if (!(this.permanent || this.released)) {
try {
this.doRelease();
} finally {
this.released = true;
}
}
}
@Override
public boolean isReleased() {
return this.released;
}
@Override
public boolean isPermanent() {
return this.permanent;
}
@Override
public boolean isReadOnly() {
return this.readonly;
}
@Override
public boolean isBigEndian() {
return this.bigEndian;
}
@Override
public boolean hasRemaining() {
return this.position < this.limit;
}
@Override
public int indexOf(byte b) {
int startIndex = this.getIndex(0);
int endIndex = startIndex + this.remaining() - 1;
for (int i = startIndex; i <= endIndex; i++) {
if (this.doGet(i) == b) {
return i - startIndex + this.position;
}
}
return -1;
}
@Override
public int indexOf(byte[] b) {
if (b.length == 0) {
return this.position;
}
int startIndex = this.getIndex(0);
int endIndex = startIndex + this.remaining() - b.length;
byte first = b[0];
Label: for (int i = startIndex; i <= endIndex; i++) {
if (this.doGet(i) == first) {
for (int j = 1; j < b.length; j++) {
if (this.doGet(i + j) != b[j]) {
continue Label;
}
}
return i - startIndex + this.position;
}
}
return -1;
}
@Override
public int read(ReadableByteChannel channel) throws IOException {
int count = 0;
try {
count = channel.read(this.asByteBuffer());
} finally {
if (count > 0) {
this.skip(count);
}
}
return count;
}
@Override
public int write(WritableByteChannel channel) throws IOException {
int count = 0;
try {
count = channel.write(this.asByteBuffer());
} finally {
if (count > 0) {
this.skip(count);
}
}
return count;
}
@Override
public int capacity() {
return this.capacity;
}
@Override
public int limit() {
return this.limit;
}
@Override
public int position() {
return this.position;
}
@Override
public int remaining() {
return this.limit - this.position;
}
@Override
public Buffer reset() {
if (this.mark < 0) {
throw new InvalidMarkException();
}
this.position = this.mark;
return this;
}
@Override
public Buffer clear() {
this.mark = -1;
this.position = 0;
this.limit = this.capacity;
return this;
}
@Override
public Buffer flip() {
this.limit = this.position;
this.position = 0;
this.mark = -1;
return this;
}
@Override
public Buffer mark() {
return this.mark(this.position);
}
@Override
public Buffer limit(int limit) {
Assert.isTrue(limit > this.capacity || limit < 0, String.format("limit must >= 0 and <= %d", this.capacity));
this.limit = limit;
return this.position(Math.min(this.position, limit));
}
@Override
public Buffer position(int position) {
Assert.isNull(position > this.limit || position < 0, String.format("position must <= %d and >= 0", this.limit));
this.position = position;
if (this.mark > this.position) {
this.mark = -1;
}
return this;
}
@Override
public Buffer capacity(int capacity) {
Assert.isTrue(capacity < 0, "capacity must >= 0");
this.capacity = capacity;
return this.limit(Math.min(this.limit, this.capacity));
}
@Override
public Buffer skip(int size) {
if (size != 0) {
this.position(this.position + size);
}
return this;
}
@Override
public Buffer rewind() {
this.position = 0;
this.mark = -1;
return this;
}
@Override
public Buffer setPermanent(boolean permanent) {
this.checkReleased();
this.permanent = permanent;
return this;
}
@Override
public Buffer setBigEndian(boolean bigEndian) {
this.bigEndian = bigEndian;
return this;
}
@Override
public Buffer asReadOnlyBuffer() {
return ((AbstractBuffer) this.duplicate()).setReadOnly(true);
}
///////////////////////////////////////////////////////////////////
@Override
public byte get() {
return this.doGet(this.getIndex(1));
}
@Override
public byte get(int index) {
return this.doGet(this.getIndex(index, 1));
}
@Override
public Buffer get(byte[] dst) {
return this.get(dst, 0, dst.length);
}
@Override
public Buffer get(int index, byte[] dst) {
return this.get(index, dst, 0, dst.length);
}
@Override
public Buffer get(byte[] dst, int offset, int length) {
return this.get(ByteBuffer.wrap(dst, offset, length));
}
@Override
public Buffer get(int index, byte[] dst, int offset, int length) {
return this.get(index, ByteBuffer.wrap(dst, offset, length));
}
@Override
public Buffer get(ByteBuffer dst) {
return this.get(dst, dst.remaining());
}
@Override
public Buffer get(int index, ByteBuffer dst) {
return this.get(index, dst, dst.remaining());
}
@Override
public Buffer get(Buffer dst, int length) {
checkBounds(0, length, dst.remaining());
this.getIndex(length);
ByteBuffer buffer = this.asByteBuffer();
buffer.limit(buffer.position());
buffer.position(buffer.position() - length);
dst.put(buffer);
return this;
}
@Override
public Buffer get(int index, Buffer dst, int length) {
checkBounds(0, length, dst.remaining());
this.getIndex(index, length);
ByteBuffer buffer = this.asByteBuffer();
buffer.position(index);
buffer.limit(index + length);
dst.put(buffer);
return this;
}
@Override
public Buffer get(Buffer dst) {
return this.get(dst, dst.remaining());
}
@Override
public Buffer get(int index, Buffer dst) {
return this.get(index, dst, dst.remaining());
}
@Override
public Buffer get(ByteBuffer dst, int length) {
checkBounds(0, length, dst.remaining());
this.getIndex(length);
ByteBuffer buffer = this.asByteBuffer();
buffer.limit(buffer.position());
buffer.position(buffer.position() - length);
dst.put(buffer);
return this;
}
@Override
public Buffer get(int index, ByteBuffer dst, int length) {
checkBounds(0, length, dst.remaining());
this.getIndex(index, length);
ByteBuffer buffer = this.asByteBuffer();
buffer.position(index);
buffer.limit(index + length);
dst.put(buffer);
return this;
}
@Override
public char getChar() {
return (char) this.getShort();
}
@Override
public char getChar(int index) {
return (char) this.getShort(index);
}
@Override
public short getShort() {
return decodeShort(this, this.getIndex(2));
}
@Override
public short getShort(int index) {
return decodeShort(this, this.getIndex(index, 2));
}
@Override
public int getInt() {
return decodeInt(this, this.getIndex(4));
}
@Override
public int getInt(int index) {
return decodeInt(this, this.getIndex(index, 4));
}
@Override
public long getLong() {
return decodeLong(this, this.getIndex(8));
}
@Override
public long getLong(int index) {
return decodeLong(this, this.getIndex(index, 8));
}
@Override
public float getFloat() {
return Float.intBitsToFloat(this.getInt());
}
@Override
public float getFloat(int index) {
return Float.intBitsToFloat(this.getInt(index));
}
@Override
public double getDouble() {
return Double.longBitsToDouble(this.getLong());
}
@Override
public double getDouble(int index) {
return Double.longBitsToDouble(this.getLong(index));
}
@Override
public short getUnsignedByte() {
return (short) (this.get() & 0xff);
}
@Override
public short getUnsignedByte(int index) {
return (short) (this.get(index) & 0xff);
}
@Override
public int getUnsignedShort() {
return this.getShort() & 0xffff;
}
@Override
public int getUnsignedShort(int index) {
return this.getShort(index) & 0xffff;
}
@Override
public long getUnsignedInt() {
return this.getInt() & 0xffffffffL;
}
@Override
public long getUnsignedInt(int index) {
return this.getInt(index) & 0xffffffffL;
}
@Override
public Buffer put(byte b) {
this.doPut(this.putIndex(1), b);
return this;
}
@Override
public Buffer put(int index, byte b) {
this.doPut(this.putIndex(index, 1), b);
return this;
}
@Override
public Buffer put(byte[] src) {
return this.put(src, 0, src.length);
}
@Override
public Buffer put(int index, byte[] src) {
return this.put(index, src, 0, src.length);
}
@Override
public Buffer put(byte[] src, int offset, int length) {
return this.put(ByteBuffer.wrap(src, offset, length));
}
@Override
public Buffer put(int index, byte[] src, int offset, int length) {
return this.put(index, ByteBuffer.wrap(src, offset, length));
}
@Override
public Buffer put(ByteBuffer src) {
return this.put(src, src.remaining());
}
@Override
public Buffer put(int index, ByteBuffer src) {
return this.put(index, src, src.remaining());
}
@Override
public Buffer put(ByteBuffer src, int length) {
checkBounds(0, length, src.remaining());
int pos = this.putIndex(length);
for (int i = 0; i < length; i++) {
this.doPut(pos + i, src.get());
}
return this;
}
@Override
public Buffer put(int index, ByteBuffer src, int length) {
checkBounds(0, length, src.remaining());
int pos = this.putIndex(index, length);
for (int i = 0; i < length; i++) {
this.doPut(pos + i, src.get());
}
return this;
}
@Override
public Buffer put(Buffer src) {
return this.put(src, src.remaining());
}
@Override
public Buffer put(int index, Buffer src) {
return this.put(index, src, src.remaining());
}
@Override
public Buffer put(Buffer src, int length) {
checkBounds(0, length, src.remaining());
int pos = this.putIndex(length);
for (int i = 0; i < length; i++) {
this.doPut(pos + i, src.get());
}
return this;
}
@Override
public Buffer put(int index, Buffer src, int length) {
checkBounds(0, length, src.remaining());
int pos = this.putIndex(index, length);
for (int i = 0; i < length; i++) {
this.doPut(pos + i, src.get());
}
return this;
}
@Override
public Buffer putChar(char c) {
return this.putShort((short) c);
}
@Override
public Buffer putChar(int index, char c) {
return this.putShort(index, (short) c);
}
@Override
public Buffer putShort(short s) {
return encodeShort(this, this.putIndex(2), s);
}
@Override
public Buffer putShort(int index, short s) {
return encodeShort(this, this.putIndex(index, 2), s);
}
@Override
public Buffer putInt(int i) {
return encodeInt(this, this.putIndex(4), i);
}
@Override
public Buffer putInt(int index, int i) {
return encodeInt(this, this.putIndex(index, 4), i);
}
@Override
public Buffer putLong(long l) {
return encodeLong(this, this.putIndex(8), l);
}
@Override
public Buffer putLong(int index, long l) {
return encodeLong(this, this.putIndex(index, 8), l);
}
@Override
public Buffer putFloat(float f) {
return this.putInt(Float.floatToRawIntBits(f));
}
@Override
public Buffer putFloat(int index, float f) {
return this.putInt(index, Float.floatToRawIntBits(f));
}
@Override
public Buffer putDouble(double d) {
return this.putLong(Double.doubleToRawLongBits(d));
}
@Override
public Buffer putDouble(int index, double d) {
return this.putLong(index, Double.doubleToRawLongBits(d));
}
@Override
public Buffer putUnsignedByte(short s) {
if (s < 0 || s > 0xff) {
throw new IllegalArgumentException();
}
return this.put((byte) s);
}
@Override
public Buffer putUnsignedByte(int index, short s) {
if (s < 0 || s > 0xff) {
throw new IllegalArgumentException();
}
return this.put(index, (byte) s);
}
@Override
public Buffer putUnsignedShort(int i) {
if (i < 0 || i > 0xffff) {
throw new IllegalArgumentException();
}
return this.putShort((short) i);
}
@Override
public Buffer putUnsignedShort(int index, int i) {
if (i < 0 || i > 0xffff) {
throw new IllegalArgumentException();
}
return this.putShort(index, (short) i);
}
@Override
public Buffer putUnsignedInt(long l) {
if (l < 0 || l > 0xffffffff) {
throw new IllegalArgumentException();
}
return this.putInt((int) l);
}
@Override
public Buffer putUnsignedInt(int index, long l) {
if (l < 0 || l > 0xffffffff) {
throw new IllegalArgumentException();
}
return this.putInt(index, (int) l);
}
///////////////////////////////////////////////////////////////////
@Override
public boolean equals(Object obj) {
if (!(obj instanceof Buffer)) {
return false;
}
Buffer buffer = (Buffer) obj;
if (this.remaining() != buffer.remaining()) {
return false;
}
int start = this.getIndex(0);
int end = start + this.remaining();
for (int i = start, j = buffer.position(); i < end; i++, j++) {
if (this.doGet(i) != buffer.get(j)) {
return false;
}
}
return true;
}
@Override
public String toString() {
StringBuffer sb = new StringBuffer();
sb.append(this.getClass().getName());
sb.append("[position=").append(this.position).append(" ");
sb.append("limit=").append(this.limit).append(" ");
sb.append("capacity=").append(this.capacity).append("]");
return sb.toString();
}
protected abstract byte doGet(int index);
protected abstract void doPut(int index, byte b);
protected abstract void doRelease();
protected int getMark() {
return this.mark;
}
protected Buffer setReadOnly(boolean readonly) {
this.readonly = readonly;
return this;
}
protected Buffer mark(int mark) {
if (mark < 0) {
this.mark = -1;
} else {
if (mark > this.position) {
throw new IndexOutOfBoundsException();
}
this.mark = mark;
}
return this;
}
protected final int putIndex(int i, int len) {
this.checkReleased();
this.checkReadOnly();
if (this.limit - this.position < len) {
throw new BufferOverflowException();
}
int pos = this.position + this.offset;
this.position += len;
return pos;
}
protected final int putIndex(int len) {
this.checkReleased();
this.checkReadOnly();
if (this.limit - this.position < len) {
throw new BufferOverflowException();
}
int pos = this.position + this.offset;
this.position += len;
return pos;
}
protected final int getIndex(int i, int len) {
this.checkReleased();
if ((len < 0) || (i < 0) || (len > this.limit - i)) {
throw new IndexOutOfBoundsException();
}
return i + this.offset;
}
protected final int getIndex(int len) {
this.checkReleased();
if (this.limit - this.position < len) {
throw new BufferUnderflowException();
}
int pos = this.position + this.offset;
this.position += len;
return pos;
}
protected final void checkReadOnly() {
if (this.isReadOnly()) {
throw new ReadOnlyBufferException();
}
}
protected final void checkReleased() {
if (this.isReleased()) {
throw RELEASED_BUFFER_EXCEPTION;
}
}
protected final static void checkBounds(int off, int len, int size) {
if ((off | len | (off + len) | (size - (off + len))) < 0) {
throw new IndexOutOfBoundsException();
}
}
protected final static Buffer encodeShort(AbstractBuffer buffer, int index, short s) {
byte b1, b2;
if (buffer.isBigEndian()) {
b1 = (byte) (s >> 8);
b2 = (byte) (s >> 0);
} else {
b1 = (byte) (s >> 0);
b2 = (byte) (s >> 8);
}
buffer.doPut(index + 0, b1);
buffer.doPut(index + 1, b2);
return buffer;
}
protected final static short decodeShort(AbstractBuffer buffer, int index) {
byte b1, b2;
if (buffer.isBigEndian()) {
b1 = buffer.doGet(index + 0);
b2 = buffer.doGet(index + 1);
} else {
b1 = buffer.doGet(index + 1);
b2 = buffer.doGet(index + 0);
}
return (short) ((b1 << 8) | (b2 & 0xff));
}
protected final static Buffer encodeInt(AbstractBuffer buffer, int index, int i) {
byte b1, b2, b3, b4;
if (buffer.isBigEndian()) {
b1 = (byte) (i >> 24);
b2 = (byte) (i >> 16);
b3 = (byte) (i >> 8);
b4 = (byte) (i >> 0);
} else {
b1 = (byte) (i >> 0);
b2 = (byte) (i >> 8);
b3 = (byte) (i >> 16);
b4 = (byte) (i >> 24);
}
buffer.doPut(index + 0, b1);
buffer.doPut(index + 1, b2);
buffer.doPut(index + 2, b3);
buffer.doPut(index + 3, b4);
return buffer;
}
protected final static int decodeInt(AbstractBuffer buffer, int index) {
byte b1, b2, b3, b4;
if (buffer.isBigEndian()) {
b1 = buffer.doGet(index + 0);
b2 = buffer.doGet(index + 1);
b3 = buffer.doGet(index + 2);
b4 = buffer.doGet(index + 3);
} else {
b1 = buffer.doGet(index + 3);
b2 = buffer.doGet(index + 2);
b3 = buffer.doGet(index + 1);
b4 = buffer.doGet(index + 0);
}
return (int) ((((b1 & 0xff) << 24) | ((b2 & 0xff) << 16) | ((b3 & 0xff) << 8) | ((b4 & 0xff) << 0)));
}
protected final static Buffer encodeLong(AbstractBuffer buffer, int index, long l) {
byte b1, b2, b3, b4, b5, b6, b7, b8;
if (buffer.isBigEndian()) {
b1 = (byte) (l >> 56);
b2 = (byte) (l >> 48);
b3 = (byte) (l >> 40);
b4 = (byte) (l >> 32);
b5 = (byte) (l >> 24);
b6 = (byte) (l >> 16);
b7 = (byte) (l >> 8);
b8 = (byte) (l >> 0);
} else {
b1 = (byte) (l >> 0);
b2 = (byte) (l >> 8);
b3 = (byte) (l >> 16);
b4 = (byte) (l >> 24);
b5 = (byte) (l >> 32);
b6 = (byte) (l >> 40);
b7 = (byte) (l >> 48);
b8 = (byte) (l >> 56);
}
buffer.doPut(index + 0, b1);
buffer.doPut(index + 1, b2);
buffer.doPut(index + 2, b3);
buffer.doPut(index + 3, b4);
buffer.doPut(index + 4, b5);
buffer.doPut(index + 5, b6);
buffer.doPut(index + 6, b7);
buffer.doPut(index + 7, b8);
return buffer;
}
protected final static long decodeLong(AbstractBuffer buffer, int index) {
byte b1, b2, b3, b4, b5, b6, b7, b8;
if (buffer.isBigEndian()) {
b1 = buffer.doGet(index + 0);
b2 = buffer.doGet(index + 1);
b3 = buffer.doGet(index + 2);
b4 = buffer.doGet(index + 3);
b5 = buffer.doGet(index + 4);
b6 = buffer.doGet(index + 5);
b7 = buffer.doGet(index + 6);
b8 = buffer.doGet(index + 7);
} else {
b1 = buffer.doGet(index + 7);
b2 = buffer.doGet(index + 6);
b3 = buffer.doGet(index + 5);
b4 = buffer.doGet(index + 4);
b5 = buffer.doGet(index + 3);
b6 = buffer.doGet(index + 2);
b7 = buffer.doGet(index + 1);
b8 = buffer.doGet(index + 0);
}
return (((long) b1 & 0xff) << 56) | (((long) b2 & 0xff) << 48) | (((long) b3 & 0xff) << 40) | (((long) b4 & 0xff) << 32) | (((long) b5 & 0xff) << 24) | (((long) b6 & 0xff) << 16) | (((long) b7 & 0xff) << 8) | (((long) b8 & 0xff) << 0);
}
public static class ReleasedBufferException extends RuntimeException {
private static final long serialVersionUID = -8495651006197186862L;
public ReleasedBufferException() {
super();
}
public ReleasedBufferException(String message, Throwable cause) {
super(message, cause);
}
public ReleasedBufferException(String message) {
super(message);
}
public ReleasedBufferException(Throwable cause) {
super(cause);
}
}
}