Быстрый write/read int8, патч выдачи reserved байт при getBuffer
All checks were successful
Build rosetta-wss / build (push) Successful in 7m53s
All checks were successful
Build rosetta-wss / build (push) Successful in 7m53s
This commit is contained in:
@@ -3,17 +3,17 @@ package io.orprotocol;
|
|||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|
||||||
public class Stream {
|
public class Stream {
|
||||||
|
|
||||||
private byte[] stream;
|
private byte[] stream;
|
||||||
private int readPointer = 0;
|
private int readPointer = 0; // bits
|
||||||
private int writePointer = 0;
|
private int writePointer = 0; // bits
|
||||||
|
|
||||||
public Stream() {
|
public Stream() {
|
||||||
this.stream = new byte[0];
|
this.stream = new byte[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
public Stream(byte[] stream) {
|
public Stream(byte[] stream) {
|
||||||
this.stream = stream;
|
this.stream = (stream == null) ? new byte[0] : stream;
|
||||||
this.readPointer = 0;
|
this.readPointer = 0;
|
||||||
this.writePointer = this.stream.length << 3;
|
this.writePointer = this.stream.length << 3;
|
||||||
}
|
}
|
||||||
@@ -23,51 +23,72 @@ public class Stream {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void setStream(byte[] stream) {
|
public void setStream(byte[] stream) {
|
||||||
this.stream = stream;
|
this.stream = (stream == null) ? new byte[0] : stream;
|
||||||
this.readPointer = 0;
|
this.readPointer = 0;
|
||||||
this.writePointer = this.stream.length << 3;
|
this.writePointer = this.stream.length << 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Fast path: write 9 bits (sign + value) in <= 2 byte writes
|
||||||
public void writeInt8(int value) {
|
public void writeInt8(int value) {
|
||||||
int negationBit = value < 0 ? 1 : 0;
|
int negationBit = value < 0 ? 1 : 0;
|
||||||
int int8Value = Math.abs(value) & 0xFF;
|
int int8Value = Math.abs(value) & 0xFF;
|
||||||
/**
|
int packed9 = (negationBit << 8) | int8Value; // 9 bits total
|
||||||
* 1 sign
|
|
||||||
* 8 bits for value
|
|
||||||
*/
|
|
||||||
reserveBits(9);
|
reserveBits(9);
|
||||||
stream[writePointer >> 3] |= (byte) (negationBit << (7 - (writePointer & 7)));
|
|
||||||
writePointer++;
|
int wp = writePointer;
|
||||||
|
int byteIndex = wp >> 3;
|
||||||
for (int i = 0; i < 8; i++) {
|
int bitOffset = wp & 7; // 0..7
|
||||||
int bit = (int8Value >> (7 - i)) & 1;
|
|
||||||
stream[writePointer >> 3] |= (byte) (bit << (7 - (writePointer & 7)));
|
int firstCount = 8 - bitOffset; // bits into current byte
|
||||||
writePointer++;
|
int secondCount = 9 - firstCount; // bits into next byte (1..8)
|
||||||
}
|
|
||||||
|
int firstPart = packed9 >> secondCount; // fits firstCount bits
|
||||||
|
stream[byteIndex] |= (byte) firstPart;
|
||||||
|
|
||||||
|
int secondMask = (1 << secondCount) - 1;
|
||||||
|
int secondPart = (packed9 & secondMask) << (8 - secondCount);
|
||||||
|
stream[byteIndex + 1] |= (byte) secondPart;
|
||||||
|
|
||||||
|
writePointer = wp + 9;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Fast path: read 9 bits (sign + value) from <= 2 bytes
|
||||||
public int readInt8() {
|
public int readInt8() {
|
||||||
int value = 0;
|
if (remainingBits() < 9L) {
|
||||||
int negationBit = (stream[readPointer >> 3] >> (7 - (readPointer & 7))) & 1;
|
throw new IllegalStateException("Not enough bits to read Int8");
|
||||||
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;
|
int rp = readPointer;
|
||||||
|
int byteIndex = rp >> 3;
|
||||||
|
int bitOffset = rp & 7;
|
||||||
|
|
||||||
|
int firstCount = 8 - bitOffset;
|
||||||
|
int secondCount = 9 - firstCount;
|
||||||
|
|
||||||
|
int firstMask = (1 << firstCount) - 1;
|
||||||
|
int firstPart = stream[byteIndex] & firstMask;
|
||||||
|
int secondPart = ((stream[byteIndex + 1] & 0xFF) >> (8 - secondCount));
|
||||||
|
|
||||||
|
int packed9 = (firstPart << secondCount) | secondPart;
|
||||||
|
readPointer = rp + 9;
|
||||||
|
|
||||||
|
int negationBit = (packed9 >> 8) & 1;
|
||||||
|
int int8Value = packed9 & 0xFF;
|
||||||
|
return negationBit == 1 ? -int8Value : int8Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void writeBit(int value) {
|
public void writeBit(int value) {
|
||||||
|
reserveBits(1);
|
||||||
int bit = value & 1;
|
int bit = value & 1;
|
||||||
ensureCapacity(writePointer >> 3);
|
|
||||||
stream[writePointer >> 3] |= (byte) (bit << (7 - (writePointer & 7)));
|
stream[writePointer >> 3] |= (byte) (bit << (7 - (writePointer & 7)));
|
||||||
writePointer++;
|
writePointer++;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int readBit() {
|
public int readBit() {
|
||||||
|
if (remainingBits() < 1L) {
|
||||||
|
throw new IllegalStateException("Not enough bits to read bit");
|
||||||
|
}
|
||||||
int bit = (stream[readPointer >> 3] >> (7 - (readPointer & 7))) & 1;
|
int bit = (stream[readPointer >> 3] >> (7 - (readPointer & 7))) & 1;
|
||||||
readPointer++;
|
readPointer++;
|
||||||
return bit;
|
return bit;
|
||||||
@@ -125,6 +146,10 @@ public class Stream {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void writeString(String value) {
|
public void writeString(String value) {
|
||||||
|
if (value == null) {
|
||||||
|
value = "";
|
||||||
|
}
|
||||||
|
|
||||||
int length = value.length();
|
int length = value.length();
|
||||||
writeInt32(length);
|
writeInt32(length);
|
||||||
|
|
||||||
@@ -132,7 +157,7 @@ public class Stream {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// writeInt16 -> 2 * writeInt8 -> 18 бит на символ
|
// writeInt16 -> 2 * writeInt8 -> 18 bits per char
|
||||||
reserveBits((long) length * 18L);
|
reserveBits((long) length * 18L);
|
||||||
|
|
||||||
for (int i = 0; i < length; i++) {
|
for (int i = 0; i < length; i++) {
|
||||||
@@ -147,10 +172,8 @@ public class Stream {
|
|||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
// На один символ тратится 18 бит (через writeInt16/readInt16)
|
|
||||||
long remainingBits = ((long) stream.length << 3) - readPointer;
|
|
||||||
long requiredBits = (long) length * 18L;
|
long requiredBits = (long) length * 18L;
|
||||||
if (requiredBits > remainingBits) {
|
if (requiredBits > remainingBits()) {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -162,23 +185,34 @@ public class Stream {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void writeBytes(byte[] value) {
|
public void writeBytes(byte[] value) {
|
||||||
|
if (value == null) {
|
||||||
|
value = new byte[0];
|
||||||
|
}
|
||||||
|
|
||||||
writeInt32(value.length);
|
writeInt32(value.length);
|
||||||
|
|
||||||
if (value.length > 0) {
|
if (value.length > 0) {
|
||||||
|
// writeInt8 = 9 bits per byte
|
||||||
reserveBits((long) value.length * 9L);
|
reserveBits((long) value.length * 9L);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < value.length; i++) {
|
for (byte b : value) {
|
||||||
writeInt8(value[i]);
|
writeInt8(b);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte[] readBytes() {
|
public byte[] readBytes() {
|
||||||
int length = readInt32();
|
int length = readInt32();
|
||||||
|
|
||||||
if (length < 0) {
|
if (length < 0) {
|
||||||
return new byte[0];
|
return new byte[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
long requiredBits = (long) length * 9L;
|
||||||
|
if (requiredBits > remainingBits()) {
|
||||||
|
return new byte[0];
|
||||||
|
}
|
||||||
|
|
||||||
byte[] value = new byte[length];
|
byte[] value = new byte[length];
|
||||||
for (int i = 0; i < length; i++) {
|
for (int i = 0; i < length; i++) {
|
||||||
value[i] = (byte) readInt8();
|
value[i] = (byte) readInt8();
|
||||||
@@ -187,15 +221,20 @@ public class Stream {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean isEmpty() {
|
public boolean isEmpty() {
|
||||||
return this.stream.length == 0;
|
return writePointer == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// useful bytes without reserved tail
|
||||||
public int length() {
|
public int length() {
|
||||||
return (writePointer + 7) >> 3;
|
return (writePointer + 7) >> 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte[] getBuffer() {
|
public byte[] getBuffer() {
|
||||||
return this.stream;
|
return getStream();
|
||||||
|
}
|
||||||
|
|
||||||
|
private long remainingBits() {
|
||||||
|
return (long) writePointer - readPointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void reserveBits(long bitsToWrite) {
|
private void reserveBits(long bitsToWrite) {
|
||||||
|
|||||||
Reference in New Issue
Block a user