package com.meidusa.amoeba.net.packet; import java.io.InputStream; import java.io.OutputStream; import java.nio.ByteBuffer; import com.meidusa.amoeba.net.Connection; /** * @author struct */ public class AbstractPacketBuffer implements PacketBuffer { /** * ���ڱ���buffer����ij��� */ protected int length = 0; protected int position = 0; protected byte[] buffer = null; protected Connection conn; public AbstractPacketBuffer(byte[] buf){ buffer = new byte[buf.length]; System.arraycopy(buf, 0, buffer, 0, buf.length);//��buf�е�����copy��buffer�� setPacketLength(buffer.length); position = 0; } public AbstractPacketBuffer(int size){ buffer = new byte[size]; setPacketLength(buffer.length); position = 0; } /** * ����0����ǰλ�õ������ֽ�д�뵽ByteBuffer��,���ҽ�ByteBuffer.position���õ�0. */ public ByteBuffer toByteBuffer() { ByteBuffer buffer = ByteBuffer.allocate(getPosition()); buffer.put(this.buffer, 0, getPosition()); buffer.rewind(); return buffer; } public int getPacketLength() { return length; } public void setPacketLength(int length) { this.length = length; } public int getPosition() { return position; } public void setPosition(int position) { if (this.position < position) { int length = this.position - position; ensureCapacity(length); } this.position = position; } public byte readByte() { return buffer[position++]; } public byte readByte(int position) { this.position = position; return buffer[this.position++]; } public void writeByte(byte b) { ensureCapacity(1); buffer[position++] = b; } public int writeBytes(byte[] ab) { return writeBytes(ab, 0, ab.length); } public int writeBytes(byte[] ab, int offset, int len) { ensureCapacity(len); System.arraycopy(ab, offset, buffer, position, len); position += len; return len; } public int readBytes(byte[] ab, int offset, int len) { System.arraycopy(buffer, position, ab, offset, len); position += len; return len; } /** * ����buffer���� */ protected void ensureCapacity(int i) { if ((position + i) > getPacketLength()) { if ((position + i) < buffer.length) { setPacketLength(buffer.length); } else { int newLength = (int) (position + i * 1.5); if (newLength <= (buffer.length + i)) { newLength = (buffer.length + i + 1) + (int) (i * 1.25); } byte[] newBytes = new byte[newLength]; System.arraycopy(buffer, 0, newBytes, 0, buffer.length); buffer = newBytes; setPacketLength(buffer.length); } } } protected void init(Connection conn) { this.conn = conn; } public synchronized void reset() { this.position = 0; setPacketLength(buffer.length); } public int remaining() { return this.length - this.position; } public boolean hasRemaining() { return (this.length - this.position > 0); } public void skip(int bytes) { this.position += bytes; } public InputStream asInputStream() { return new InputStream() { @Override public int available() { return AbstractPacketBuffer.this.remaining(); } @Override public int read() { if (AbstractPacketBuffer.this.hasRemaining()) { return AbstractPacketBuffer.this.readByte() & 0xff; } else { return -1; } } @Override public int read(byte[] b, int off, int len) { int remaining = AbstractPacketBuffer.this.remaining(); if (remaining > 0) { int readBytes = Math.min(remaining, len); AbstractPacketBuffer.this.readBytes(b, off, readBytes); return readBytes; } else { return -1; } } @Override public synchronized void reset() { AbstractPacketBuffer.this.reset(); } @Override public long skip(long n) { int bytes; if (n > Integer.MAX_VALUE) { bytes = AbstractPacketBuffer.this.remaining(); } else { bytes = Math.min(AbstractPacketBuffer.this.remaining(), (int) n); } AbstractPacketBuffer.this.skip(bytes); return bytes; } }; } public OutputStream asOutputStream() { return new OutputStream() { @Override public void write(byte[] b, int off, int len) { AbstractPacketBuffer.this.writeBytes(b, off, len); } @Override public void write(int b) { AbstractPacketBuffer.this.writeByte((byte) b); } }; } public static boolean appendBufferToWrite(byte[] byts, PacketBuffer buffer, Connection conn, boolean writeNow) { if (writeNow || buffer.remaining() < byts.length) { if (buffer.getPosition() > 0) { buffer.writeBytes(byts); conn.postMessage(buffer.toByteBuffer()); buffer.reset(); } else { conn.postMessage(byts); } return true; } else { buffer.writeBytes(byts); return true; } } }