180 lines
4.6 KiB
Java
180 lines
4.6 KiB
Java
package io.orprotocol;
|
|
|
|
public class Stream {
|
|
|
|
private byte[] stream;
|
|
private int readPointer = 0;
|
|
private int writePointer = 0;
|
|
|
|
public Stream() {
|
|
this.stream = new byte[0];
|
|
}
|
|
|
|
public Stream(byte[] stream) {
|
|
this.stream = stream;
|
|
}
|
|
|
|
public byte[] getStream() {
|
|
return this.stream;
|
|
}
|
|
|
|
public void setStream(byte[] stream) {
|
|
this.stream = stream;
|
|
}
|
|
|
|
public void writeInt8(int value) {
|
|
int negationBit = value < 0 ? 1 : 0;
|
|
int int8Value = Math.abs(value) & 0xFF;
|
|
|
|
ensureCapacity(writePointer >> 3);
|
|
stream[writePointer >> 3] |= (byte)(negationBit << (7 - (writePointer & 7)));
|
|
writePointer++;
|
|
|
|
for (int i = 0; i < 8; i++) {
|
|
int bit = (int8Value >> (7 - i)) & 1;
|
|
ensureCapacity(writePointer >> 3);
|
|
stream[writePointer >> 3] |= (byte)(bit << (7 - (writePointer & 7)));
|
|
writePointer++;
|
|
}
|
|
}
|
|
|
|
public int readInt8() {
|
|
int value = 0;
|
|
int negationBit = (stream[readPointer >> 3] >> (7 - (readPointer & 7))) & 1;
|
|
readPointer++;
|
|
|
|
for (int i = 0; i < 8; i++) {
|
|
int bit = (stream[readPointer >> 3] >> (7 - (readPointer & 7))) & 1;
|
|
value |= bit << (7 - i);
|
|
readPointer++;
|
|
}
|
|
|
|
return negationBit == 1 ? -value : value;
|
|
}
|
|
|
|
public void writeBit(int value) {
|
|
int bit = value & 1;
|
|
ensureCapacity(writePointer >> 3);
|
|
stream[writePointer >> 3] |= (byte)(bit << (7 - (writePointer & 7)));
|
|
writePointer++;
|
|
}
|
|
|
|
public int readBit() {
|
|
int bit = (stream[readPointer >> 3] >> (7 - (readPointer & 7))) & 1;
|
|
readPointer++;
|
|
return bit;
|
|
}
|
|
|
|
public void writeBoolean(boolean value) {
|
|
writeBit(value ? 1 : 0);
|
|
}
|
|
|
|
public boolean readBoolean() {
|
|
return readBit() == 1;
|
|
}
|
|
|
|
public void writeInt16(int value) {
|
|
writeInt8(value >> 8);
|
|
writeInt8(value & 0xFF);
|
|
}
|
|
|
|
public int readInt16() {
|
|
int value = readInt8() << 8;
|
|
return value | readInt8();
|
|
}
|
|
|
|
public void writeInt32(int value) {
|
|
writeInt16(value >> 16);
|
|
writeInt16(value & 0xFFFF);
|
|
}
|
|
|
|
public int readInt32() {
|
|
int value = readInt16() << 16;
|
|
return value | readInt16();
|
|
}
|
|
|
|
public void writeInt64(long value) {
|
|
int high = (int)(value >> 32);
|
|
int low = (int)value;
|
|
writeInt32(high);
|
|
writeInt32(low);
|
|
}
|
|
|
|
public long readInt64() {
|
|
long high = readInt32();
|
|
long low = readInt32() & 0xFFFFFFFFL;
|
|
return (high << 32) | low;
|
|
}
|
|
|
|
public void writeFloat32(float value) {
|
|
int floatValue = Float.floatToIntBits(value);
|
|
writeInt32(floatValue);
|
|
}
|
|
|
|
public float readFloat32() {
|
|
int floatValue = readInt32();
|
|
return Float.intBitsToFloat(floatValue);
|
|
}
|
|
|
|
public void writeString(String value) {
|
|
int length = value.length();
|
|
writeInt32(length);
|
|
for (int i = 0; i < value.length(); i++) {
|
|
writeInt16(value.charAt(i));
|
|
}
|
|
}
|
|
|
|
public String readString() {
|
|
int length = readInt32();
|
|
|
|
// Security fix for string length exceeding stream capacity
|
|
if (length < 0 || length > (stream.length - (readPointer >> 3))) {
|
|
System.out.println("Stream readString length invalid: " + length + ", stream length: " + stream.length + ", readPointer: " + readPointer);
|
|
return "";
|
|
}
|
|
|
|
StringBuilder value = new StringBuilder();
|
|
for (int i = 0; i < length; i++) {
|
|
value.append((char)readInt16());
|
|
}
|
|
return value.toString();
|
|
}
|
|
|
|
public void writeBytes(byte[] value) {
|
|
writeInt32(value.length);
|
|
for (int i = 0; i < value.length; i++) {
|
|
writeInt8(value[i]);
|
|
}
|
|
}
|
|
|
|
public byte[] readBytes() {
|
|
int length = readInt32();
|
|
byte[] value = new byte[length];
|
|
for (int i = 0; i < length; i++) {
|
|
value[i] = (byte)readInt8();
|
|
}
|
|
return value;
|
|
}
|
|
|
|
public boolean isEmpty() {
|
|
return this.stream.length == 0;
|
|
}
|
|
|
|
public int length() {
|
|
return this.stream.length;
|
|
}
|
|
|
|
public byte[] getBuffer() {
|
|
return this.stream;
|
|
}
|
|
|
|
private void ensureCapacity(int byteIndex) {
|
|
if (byteIndex >= stream.length) {
|
|
byte[] newStream = new byte[byteIndex + 1];
|
|
System.arraycopy(stream, 0, newStream, 0, stream.length);
|
|
stream = newStream;
|
|
}
|
|
}
|
|
|
|
}
|