/** * <pre> * copy right meidusa.com * * This program is free software; you can redistribute it and/or modify it under the terms of * the GNU AFFERO GENERAL PUBLIC LICENSE as published by the Free Software Foundation; either version 3 of the License, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU AFFERO GENERAL PUBLIC LICENSE for more details. * You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE along with this program; * if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * </pre> */ package com.meidusa.amoeba.net.packet; import java.io.InputStream; import java.io.OutputStream; import java.nio.ByteBuffer; import java.nio.ByteOrder; import com.meidusa.amoeba.net.Connection; /** * @author struct */ public class AbstractPacketBuffer implements PacketBuffer { protected int length = 0; protected int position = 0; protected byte[] buffer = null; public AbstractPacketBuffer(byte[] buf){ buffer = new byte[buf.length]; System.arraycopy(buf, 0, buffer, 0, buf.length); setPacketLength(buffer.length); position = 0; } public AbstractPacketBuffer(int size){ buffer = new byte[size]; setPacketLength(buffer.length); position = 0; } public ByteOrder getByteOrder(){ return ByteOrder.BIG_ENDIAN; } /* /** * 将从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 = position - this.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) { } 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; } } public static void main(String[] args){ AbstractPacketBuffer buffer = new AbstractPacketBuffer(10); buffer.writeByte((byte)12); buffer.setPosition(10); ByteBuffer byteBuffer = buffer.toByteBuffer(); System.out.println(byteBuffer.get()); buffer.reset(); buffer.writeByte((byte)14); byteBuffer = buffer.toByteBuffer(); System.out.println(byteBuffer.get()); } }