📄 abstractbuffer.java
字号:
/*
* Copyright 2004-2006 the original author or authors.
*
* Licensed 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 net.sf.cindy.buffer;
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 net.sf.cindy.Buffer;
import net.sf.cindy.util.Charset;
import net.sf.cindy.util.Configuration;
/**
* Abstract buffer.
*
* @author <a href="chenrui@gmail.com">Roger Chen</a>
* @version $id$
*/
public abstract class AbstractBuffer implements Buffer {
protected static final int WRITE_PACKET_SIZE = Configuration
.getWritePacketSize();
private boolean readonly;
private boolean bigEndian = true;
private boolean permanent;
private boolean released;
private int mark = -1;
private int position = 0;
private int limit;
private int capacity;
private final int offset;
protected AbstractBuffer(int offset, int capacity) {
this.offset = offset;
this.capacity = capacity;
limit(capacity);
}
public boolean isPermanent() {
return permanent;
}
public void setPermanent(boolean b) {
checkReleased();
this.permanent = b;
}
public boolean isReleased() {
return released;
}
public synchronized void release() {
if (!(permanent || released)) {
try {
_release();
} finally {
released = true;
}
}
}
protected abstract void _release();
public boolean isReadonly() {
return readonly;
}
protected Buffer setReadonly(boolean readonly) {
this.readonly = readonly;
return this;
}
public boolean isBigEndian() {
return bigEndian;
}
public Buffer setBigEndian(boolean bigEndian) {
this.bigEndian = bigEndian;
return this;
}
public Buffer skip(int size) {
if (size != 0)
position(position + size);
return this;
}
public int capacity() {
return capacity;
}
protected Buffer capacity(int newCapacity) {
if (newCapacity < 0)
throw new IllegalArgumentException();
capacity = newCapacity;
return limit(Math.min(limit, capacity));
}
public int limit() {
return limit;
}
public Buffer limit(int newLimit) {
if ((newLimit > capacity) || (newLimit < 0))
throw new IllegalArgumentException();
limit = newLimit;
return position(Math.min(position, limit));
}
public int position() {
return position;
}
public Buffer position(int newPosition) {
if ((newPosition > limit) || (newPosition < 0))
throw new IllegalArgumentException();
position = newPosition;
if (mark > position)
mark = -1;
return this;
}
public Buffer mark() {
return mark(position);
}
protected Buffer mark(int mark) {
if (mark < 0)
this.mark = -1;
else {
if (mark > position)
throw new IndexOutOfBoundsException();
this.mark = mark;
}
return this;
}
protected int getMark() {
return mark;
}
protected final int getIndex(int i, int len) {
checkReleased();
if ((len < 0) || (i < 0) || (len > limit - i))
throw new IndexOutOfBoundsException();
return i + offset;
}
protected final int getIndex(int len) {
checkReleased();
if (limit - position < len)
throw new BufferUnderflowException();
int p = position + offset;
position += len;
return p;
}
protected final int putIndex(int i, int len) {
checkReleased();
checkReadonly();
if ((len < 0) || (i < 0) || (len > limit - i))
throw new IndexOutOfBoundsException();
return i + offset;
}
protected final int putIndex(int len) {
checkReleased();
checkReadonly();
if (limit - position < len)
throw new BufferOverflowException();
int p = position + offset;
position += len;
return p;
}
protected final static void checkBounds(int off, int len, int size) {
// all less than 0
if ((off | len | (off + len) | (size - (off + len))) < 0)
throw new IndexOutOfBoundsException();
}
protected final void checkReadonly() {
if (isReadonly())
throw new ReadOnlyBufferException();
}
protected final void checkReleased() {
if (isReleased())
throw new ReleasedBufferException();
}
public Buffer reset() {
if (mark < 0)
throw new InvalidMarkException();
position = mark;
return this;
}
public Buffer clear() {
position = 0;
limit = capacity;
mark = -1;
return this;
}
public Buffer flip() {
limit = position;
position = 0;
mark = -1;
return this;
}
public Buffer rewind() {
position = 0;
mark = -1;
return this;
}
public int remaining() {
return limit - position;
}
public boolean hasRemaining() {
return position < limit;
}
public int indexOf(byte[] b) {
if (b.length == 0)
return position;
int startIndex = getIndex(0);
int endIndex = startIndex + remaining() - b.length;
byte first = b[0];
Label: for (int i = startIndex; i <= endIndex; i++) {
// look for the first character
if (_get(i) == first) {
for (int j = 1; j < b.length; j++) {
if (_get(i + j) != b[j])
continue Label;
}
return i - startIndex + position;
}
}
return -1;
}
public int write(WritableByteChannel channel) throws IOException {
int writeCount = 0;
ByteBuffer buffer = asByteBuffer();
if (buffer.remaining() > WRITE_PACKET_SIZE)
buffer.limit(buffer.position() + WRITE_PACKET_SIZE);
try {
writeCount = channel.write(buffer);
} finally {
skip(writeCount);
}
return writeCount;
}
public int read(ReadableByteChannel channel) throws IOException {
int readCount = 0;
try {
readCount = channel.read(asByteBuffer());
} finally {
if (readCount > 0)
skip(readCount);
}
return readCount;
}
public Buffer asReadOnlyBuffer() {
return ((AbstractBuffer) duplicate()).setReadonly(true);
}
public boolean equals(Object obj) {
if (!(obj instanceof Buffer))
return false;
Buffer buffer = (Buffer) obj;
if (this.remaining() != buffer.remaining())
return false;
int start = getIndex(0);
int end = start + remaining();
for (int i = start, j = buffer.position(); i < end; i++, j++) {
if (_get(i) != buffer.get(j))
return false;
}
return true;
}
public String toString() {
StringBuffer sb = new StringBuffer();
sb.append(getClass().getName());
sb.append("[pos=").append(position);
sb.append(" lim=").append(limit);
sb.append(" cap=").append(capacity);
sb.append("]");
return sb.toString();
}
public String dump() {
ByteBuffer content = (ByteBuffer) asByteBuffer().clear();
String separator = System.getProperty("line.separator");
int cols = 16;
int rows = (int) Math.ceil((double) capacity / cols);
StringBuffer sb = new StringBuffer(rows * cols * 6);
byte[] row = new byte[cols];
sb.append(toString()).append(separator);
int pos = 0;
for (int i = 0; i < rows; i++) {
// dump position
if (pos != 0)
sb.append(separator);
String posHex = Integer.toHexString(pos);
for (int j = 8 - posHex.length(); j > 0; j--) {
sb.append(0);
}
sb.append(posHex).append("h:");
// dump hex content
if (content.remaining() < cols)
row = new byte[content.remaining()];
content.get(row);
for (int j = 0; j < cols; j++) {
if (pos == position || pos == limit)
sb.append("'");
else
sb.append(" ");
pos++;
if (j < row.length) {
String hex = Integer.toHexString(row[j] & 0xff);
if (hex.length() < 2)
sb.append(0);
sb.append(hex.toUpperCase());
} else
sb.append(" ");
}
sb.append(" ; ");
// dump content
String s = Charset.SYSTEM.decode(row);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -