All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.timewalker.ffmq4.utils.RawDataBuffer Maven / Gradle / Ivy

package net.timewalker.ffmq4.utils;

import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.ByteBuffer;

/**
 * 

A RawDataBuffer is a dynamically growing byte array.

*

* It implements {@link java.io.DataOutput} and {@link java.io.DataInput} * to write or read data plus additional null-safe versions of the methods. *

*

* This class does not implement any synchronization nor bound checking * for maximum performance.
* Note that the UTF read/write methods are not compatible with the JDK implementation * because they were modified to take advantage of the RawDataBuffer layout. *

*/ public final class RawDataBuffer implements DataOutput, DataInput { // --- Internal constants ------------------------------ private static final byte NULL_VALUE = 0; private static final byte NOT_NULL_VALUE = 1; private static final byte TYPE_BOOLEAN = 10; private static final byte TYPE_BYTE = 11; private static final byte TYPE_SHORT = 12; private static final byte TYPE_INT = 13; private static final byte TYPE_LONG = 14; private static final byte TYPE_FLOAT = 15; private static final byte TYPE_DOUBLE = 16; private static final byte TYPE_STRING = 17; private static final byte TYPE_BYTEARRAY = 18; private static final byte TYPE_CHARACTER = 19; private static final byte UTF_TYPE_1 = 1; private static final byte UTF_TYPE_2 = 2; private static final byte UTF_TYPE_4 = 4; //------------------------------------------------------ // Runtime private byte[] buf; // Underlying byte array buffer private int capacity; // Buffer capacity private int size; // Actual used size private int pos; // Current read cursor /** * Constructor * @param initialCapacity initial buffer capacity */ public RawDataBuffer( int initialCapacity ) { this.buf = new byte[initialCapacity]; this.capacity = initialCapacity; } /** * Constructor * @param initialBuffer the initial buffer to use internally */ public RawDataBuffer( byte[] initialBuffer ) { this.buf = initialBuffer; this.size = this.capacity = initialBuffer.length; } /** * Write a string or null value to the stream */ public void writeNullableUTF(String str) { if (str == null) write(NULL_VALUE); else { write(NOT_NULL_VALUE); writeUTF(str); } } /** * Ensure that the buffer internal capacity is at least targetCapacity * @param targetCapacity the expected capacity */ public final void ensureCapacity( int targetCapacity ) { if (targetCapacity > capacity) { int newLength = Math.max(capacity << 1, targetCapacity); byte[] copy = new byte[newLength]; System.arraycopy(buf, 0, copy, 0, capacity); buf = copy; capacity = newLength; } } /** * Set the buffer size (buffer is enlarged as necessary and padded with zeroes) * @param size */ public void setSize( int size ) { ensureCapacity(size); this.size = size; } /* * (non-Javadoc) * @see java.io.DataOutput#write(int) */ @Override public void write(int b) { ensureCapacity(size+1); buf[size++] = (byte)b; } /* * (non-Javadoc) * @see java.io.DataOutput#write(byte[]) */ @Override public void write(byte[] data) { int newCount = size+data.length; ensureCapacity(newCount); System.arraycopy(data, 0, buf, size, data.length); size = newCount; } /* (non-Javadoc) * @see java.io.DataOutput#writeBytes(java.lang.String) */ @Override public void writeBytes(String s) { int len = s.length(); ensureCapacity(size+len); for (int i = 0 ; i < len ; i++) buf[pos++] = (byte)s.charAt(i); } /* (non-Javadoc) * @see java.io.DataOutput#writeChars(java.lang.String) */ @Override public void writeChars(String s) { int len = s.length(); ensureCapacity(size+len*2); for (int i = 0 ; i < len ; i++) { int v = s.charAt(i); buf[pos++] = (byte)((v >>> 8) & 0xFF); buf[pos++] = (byte)((v >>> 0) & 0xFF); } } /* * (non-Javadoc) * @see java.io.DataOutput#write(byte[], int, int) */ @Override public void write(byte[] data,int offset,int len) { int newCount = size+len; ensureCapacity(newCount); System.arraycopy(data, offset, buf, size, len); size = newCount; } /* * (non-Javadoc) * @see java.io.DataOutput#writeByte(int) */ @Override public void writeByte(int b) { ensureCapacity(size+1); buf[size++] = (byte)b; } /* * (non-Javadoc) * @see java.io.DataOutput#writeBoolean(boolean) */ @Override public void writeBoolean(boolean v) { write(v ? 1 : 0); } /** * Read a byte value at an arbitrary position in the buffer * @param position the target position */ public byte readByte(int position) { return buf[position]; } /** * Write a byte value at an arbitrary position in the buffer * @param v the byte value * @param position the target position */ public void writeByte(byte v,int position) { buf[position] = v; } /* * (non-Javadoc) * @see java.io.DataOutput#writeShort(int) */ @Override public void writeShort(int v) { ensureCapacity(size + 2); buf[size++] = (byte)((v >>> 8) & 0xFF); buf[size++] = (byte)((v >>> 0) & 0xFF); } /* * (non-Javadoc) * @see java.io.DataOutput#writeInt(int) */ @Override public void writeInt(int v) { ensureCapacity(size + 4); buf[size++] = (byte)((v >>> 24) & 0xFF); buf[size++] = (byte)((v >>> 16) & 0xFF); buf[size++] = (byte)((v >>> 8) & 0xFF); buf[size++] = (byte)((v >>> 0) & 0xFF); } /** * Write a int value at an arbitrary position in the stream * @param v the int value * @param pos the target position */ public void writeInt(int v,int pos) { buf[pos++] = (byte)((v >>> 24) & 0xFF); buf[pos++] = (byte)((v >>> 16) & 0xFF); buf[pos++] = (byte)((v >>> 8) & 0xFF); buf[pos] = (byte)((v >>> 0) & 0xFF); } /* * (non-Javadoc) * @see java.io.DataOutput#writeLong(long) */ @Override public void writeLong(long v) { ensureCapacity(size + 8); buf[size++] = (byte)(v >>> 56); buf[size++] = (byte)(v >>> 48); buf[size++] = (byte)(v >>> 40); buf[size++] = (byte)(v >>> 32); buf[size++] = (byte)(v >>> 24); buf[size++] = (byte)(v >>> 16); buf[size++] = (byte)(v >>> 8); buf[size++] = (byte)(v >>> 0); } /* * (non-Javadoc) * @see java.io.DataOutput#writeFloat(float) */ @Override public void writeFloat(float v) { writeInt(Float.floatToIntBits(v)); } /* * (non-Javadoc) * @see java.io.DataOutput#writeDouble(double) */ @Override public void writeDouble(double v) { writeLong(Double.doubleToLongBits(v)); } /* * (non-Javadoc) * @see java.io.DataOutput#writeChar(int) */ @Override public void writeChar(int v) { ensureCapacity(size + 2); buf[size++] = (byte)((v >>> 8) & 0xFF); buf[size++] = (byte)((v >>> 0) & 0xFF); } /* * (non-Javadoc) * @see java.io.DataOutput#writeUTF(java.lang.String) */ @Override public void writeUTF(String str) { int strlen = str.length(); if (strlen < 255) writeUTF(str,UTF_TYPE_1); else if (strlen < 65535) writeUTF(str,UTF_TYPE_2); else writeUTF(str,UTF_TYPE_4); } private void writeUTF( String str , byte type ) { // We need at least type + strlen bytes (1 byte/char) + 1 int strlen = str.length(); int rawlen = size+type+strlen+1; ensureCapacity(rawlen); // Write UTF type prefix buf[size++] = type; // Write the string length switch (type) { case UTF_TYPE_1 : buf[size++] = (byte)((strlen >>> 0) & 0xFF); break; case UTF_TYPE_2 : buf[size++] = (byte)((strlen >>> 8) & 0xFF); buf[size++] = (byte)((strlen >>> 0) & 0xFF); break; case UTF_TYPE_4 : buf[size++] = (byte)((strlen >>> 24) & 0xFF); buf[size++] = (byte)((strlen >>> 16) & 0xFF); buf[size++] = (byte)((strlen >>> 8) & 0xFF); buf[size++] = (byte)((strlen >>> 0) & 0xFF); break; default: throw new IllegalArgumentException("Invalid UTF type : "+type); } // Write the string int c,i = 0; for (i = 0 ; i < strlen ; i++) { c = str.charAt(i); if (!((c >= 0x0001) && (c <= 0x007F))) break; buf[size++] = (byte)c; } // Are we done ? if (i == strlen) return; // Fallback to full encoding mode for ( ; i < strlen ; i++) { c = str.charAt(i); if ((c >= 0x0001) && (c <= 0x007F)) { // One byte buf[size++] = (byte)c; } else if (c > 0x07FF) { rawlen += 3; ensureCapacity(rawlen); buf[size++] = (byte)(0xE0 | ((c >> 12) & 0x0F)); buf[size++] = (byte)(0x80 | ((c >> 6) & 0x3F)); buf[size++] = (byte)(0x80 | ((c >> 0) & 0x3F)); } else { rawlen += 2; ensureCapacity(rawlen); buf[size++] = (byte)(0xC0 | ((c >> 6) & 0x1F)); buf[size++] = (byte)(0x80 | ((c >> 0) & 0x3F)); } } } /** * Write a nullable byte array to the stream */ public void writeNullableByteArray( byte[] value ) { if (value == null) write(NULL_VALUE); else { write(NOT_NULL_VALUE); writeInt(value.length); write(value); } } /** * Write a nullable byte array to the stream */ public void writeByteArray( byte[] value ) { writeInt(value.length); write(value); } /** * Write a generic type to the stream */ public void writeGeneric( Object value ) { if (value == null) write(NULL_VALUE); else { if (value instanceof String) { writeByte(TYPE_STRING); writeUTF((String)value); } else if (value instanceof Boolean) { writeByte(TYPE_BOOLEAN); writeBoolean(((Boolean)value).booleanValue()); } else if (value instanceof Byte) { writeByte(TYPE_BYTE); writeByte(((Byte)value).byteValue()); } else if (value instanceof Short) { writeByte(TYPE_SHORT); writeShort(((Short)value).shortValue()); } else if (value instanceof Integer) { writeByte(TYPE_INT); writeInt(((Integer)value).intValue()); } else if (value instanceof Long) { writeByte(TYPE_LONG); writeLong(((Long)value).longValue()); } else if (value instanceof Float) { writeByte(TYPE_FLOAT); writeFloat(((Float)value).floatValue()); } else if (value instanceof Double) { writeByte(TYPE_DOUBLE); writeDouble(((Double)value).doubleValue()); } else if (value instanceof byte[]) { writeByte(TYPE_BYTEARRAY); writeByteArray((byte[])value); } else if (value instanceof Character) { writeByte(TYPE_CHARACTER); writeChar(((Character)value).charValue()); } else throw new IllegalArgumentException("Unsupported type : "+value.getClass().getName()); } } /* * (non-Javadoc) * @see java.io.DataInput#readBoolean() */ @Override public boolean readBoolean() { int ch = buf[pos++]; return (ch != 0); } public void read(byte b[]) { read(b, 0, b.length); } public void read(byte b[], int off, int len) { System.arraycopy(buf, pos, b, off, len); pos += len; } public byte[] readBytes( int len ) { byte[] data = new byte[len]; readFully(data); return data; } /* * (non-Javadoc) * @see java.io.DataInput#readFully(byte[]) */ @Override public void readFully(byte b[]) { readFully(b, 0, b.length); } /* * (non-Javadoc) * @see java.io.DataInput#readFully(byte[], int, int) */ @Override public void readFully(byte b[], int off, int len) { System.arraycopy(buf, pos, b, off, len); pos += len; } /* * (non-Javadoc) * @see java.io.DataInput#readByte() */ @Override public byte readByte() { return buf[pos++]; } /* (non-Javadoc) * @see java.io.DataInput#readUnsignedByte() */ @Override public int readUnsignedByte() { return buf[pos++] & 0xff; } /* (non-Javadoc) * @see java.io.DataInput#readLine() */ @Override public String readLine() { throw new IllegalStateException("Unsupported operation (deprecated)"); } /* (non-Javadoc) * @see java.io.DataInput#skipBytes(int) */ @Override public int skipBytes(int n) { int skippable = Math.min(n, size-pos); pos += skippable; return skippable; } /* * (non-Javadoc) * @see java.io.DataInput#readShort() */ @Override public short readShort() { int ch1 = buf[pos++] & 0xff; int ch2 = buf[pos++] & 0xff; return (short)((ch1 << 8) + (ch2 << 0)); } /* (non-Javadoc) * @see java.io.DataInput#readUnsignedShort() */ @Override public int readUnsignedShort() { int ch1 = buf[pos++] & 0xff; int ch2 = buf[pos++] & 0xff; return (ch1 << 8) + (ch2 << 0); } /* * (non-Javadoc) * @see java.io.DataInput#readInt() */ @Override public int readInt() { int ch1 = buf[pos++] & 0xff; int ch2 = buf[pos++] & 0xff; int ch3 = buf[pos++] & 0xff; int ch4 = buf[pos++] & 0xff; return ((ch1 << 24) + (ch2 << 16) + (ch3 << 8) + (ch4 << 0)); } /* * (non-Javadoc) * @see java.io.DataInput#readLong() */ @Override public long readLong() { return (((long)buf[pos++] << 56) + ((long)(buf[pos++] & 255) << 48) + ((long)(buf[pos++] & 255) << 40) + ((long)(buf[pos++] & 255) << 32) + ((long)(buf[pos++] & 255) << 24) + ((buf[pos++] & 255) << 16) + ((buf[pos++] & 255) << 8) + ((buf[pos++] & 255) << 0)); } /* * (non-Javadoc) * @see java.io.DataInput#readFloat() */ @Override public float readFloat() { return Float.intBitsToFloat(readInt()); } /* * (non-Javadoc) * @see java.io.DataInput#readDouble() */ @Override public double readDouble() { return Double.longBitsToDouble(readLong()); } /* * (non-Javadoc) * @see java.io.DataInput#readChar() */ @Override public char readChar() { int ch1 = buf[pos++] & 0xFF; int ch2 = buf[pos++] & 0xFF; return (char)((ch1 << 8) + (ch2 << 0)); } /* * (non-Javadoc) * @see java.io.DataInput#readUTF() */ @Override public String readUTF() { int type = buf[pos++] & 0xff; // Read UTF type prefix // Read UTF length int strlen; switch (type) { case UTF_TYPE_1 : strlen = buf[pos++] & 0xff; break; case UTF_TYPE_2 : int ch1 = buf[pos++] & 0xff; int ch2 = buf[pos++] & 0xff; strlen = (ch1 << 8) + (ch2 << 0); break; case UTF_TYPE_4 : ch1 = buf[pos++] & 0xff; ch2 = buf[pos++] & 0xff; int ch3 = buf[pos++] & 0xff; int ch4 = buf[pos++] & 0xff; strlen = ((ch1 << 24) + (ch2 << 16) + (ch3 << 8) + (ch4 << 0)); break; default: throw new IllegalArgumentException("Invalid UTF type : "+type); } char[] chars = new char[strlen]; int c,char2,char3; int count = 0; while (count < strlen) { c = buf[pos] & 0xff; if (c > 127) break; pos++; chars[count++]=(char)c; } while (count < strlen) { c = buf[pos++] & 0xff; switch (c >> 4) { case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7: /* 0xxxxxxx*/ chars[count++]=(char)c; break; case 12: case 13: /* 110x xxxx 10xx xxxx*/ char2 = buf[pos++]; chars[count++]=(char)(((c & 0x1F) << 6) | (char2 & 0x3F)); break; case 14: /* 1110 xxxx 10xx xxxx 10xx xxxx */ char2 = buf[pos++]; char3 = buf[pos++]; chars[count++]=(char)(((c & 0x0F) << 12) | ((char2 & 0x3F) << 6) | ((char3 & 0x3F) << 0)); break; default: /* 10xx xxxx, 1111 xxxx */ throw new IllegalStateException("Malformed input around byte " + count); } } return new String(chars); } /** * Read a string or null value from the stream */ public String readNullableUTF() { byte isNull = readByte(); if (isNull == NULL_VALUE) return null; return readUTF(); } /** * Read a nullable byte array from the stream */ public byte[] readNullableByteArray() { byte isNull = readByte(); if (isNull == NULL_VALUE) return null; int arraySize = readInt(); byte[] value = new byte[arraySize]; readFully(value); return value; } /** * Read a nullable byte array from the stream */ public byte[] readByteArray() { int arraySize = readInt(); byte[] value = new byte[arraySize]; readFully(value); return value; } /** * Read a generic type from the stream */ public Object readGeneric() { byte type = readByte(); switch (type) { case NULL_VALUE : return null; case TYPE_STRING : return readUTF(); case TYPE_BOOLEAN : return Boolean.valueOf(readBoolean()); case TYPE_BYTE : return Byte.valueOf(readByte()); case TYPE_SHORT : return Short.valueOf(readShort()); case TYPE_INT : return Integer.valueOf(readInt()); case TYPE_LONG : return Long.valueOf(readLong()); case TYPE_FLOAT : return new Float(readFloat()); case TYPE_DOUBLE : return new Double(readDouble()); case TYPE_BYTEARRAY : return readByteArray(); case TYPE_CHARACTER : return new Character(readChar()); default: throw new IllegalArgumentException("Unsupported type : "+type); } } public void clear() { size = 0; } public void reset() { pos = 0; } public int size() { return size; } public int pos() { return pos; } public byte[] toByteArray() { byte[] copy = new byte[size]; System.arraycopy(buf, 0, copy, 0, size); return copy; } public byte[] toByteArray( int offset , int len ) { byte[] copy = new byte[len]; System.arraycopy(buf, offset, copy, 0, len); return copy; } public void writeTo( OutputStream out ) throws IOException { out.write(buf, 0, size); } public void putTo( ByteBuffer byteBuffer , int offset , int len ) { byteBuffer.put(buf,offset,len); } public int readFrom(InputStream in , int offset, int len) throws IOException { ensureCapacity(offset+len); int readSize = in.read(buf, offset, len); if (readSize == -1) return -1; if (offset+readSize > size) size = offset+readSize; return readSize; } public void getFrom( ByteBuffer byteBuffer , int offset , int len ) { ensureCapacity(offset+len); byteBuffer.get(buf,offset,len); } public void writeTo( RawDataBuffer otherBuffer ) { otherBuffer.write(buf,0,size); } /** * Create a copy of this buffer * @return a copy of this buffer */ public RawDataBuffer copy() { RawDataBuffer copy = new RawDataBuffer(capacity); System.arraycopy(buf, 0, copy.buf, 0, capacity); copy.size = this.size; copy.pos = this.pos; return copy; } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy