Created ByteOutput and BitOutput

This commit is contained in:
Collin Smith 2020-08-09 20:06:06 -07:00
parent 4e2cd665cd
commit 11555397e3
2 changed files with 249 additions and 0 deletions

View File

@ -0,0 +1,182 @@
package com.riiablo.io;
public class BitOutput {
private static final long[] MASKS = BitConstants.UNSIGNED_MASKS;
private final boolean autoFlush = true;
private final ByteOutput byteOutput;
private final long numBits;
private long bitsWritten;
private int bitsCached;
private long cache;
BitOutput(ByteOutput byteOutput) {
this(byteOutput, 0, 0L, (long) byteOutput.bytesRemaining() * Byte.SIZE);
}
BitOutput(ByteOutput byteOutput, int bitsCached, long cache, long numBits) {
this.byteOutput = byteOutput;
this.bitsCached = bitsCached;
this.cache = cache;
this.numBits = numBits;
}
ByteOutput byteOutput() {
return byteOutput;
}
void clearCache() {
bitsCached = 0;
cache = 0L;
}
long incrementBitsWritten(long bits) {
if ((bitsWritten += bits) > numBits) {
bitsWritten = numBits;
throw new EndOfInput();
}
return bitsWritten;
}
public boolean aligned() {
return true;
}
void align() {
}
void flush(boolean align) {
// write cache and clear it (align stream too?)
if (align) {
align();
// assert cache cleared
} else {
// write byte
// backup writer index 1 byte
}
assert bitsCached < Byte.SIZE : "bitsCached(" + bitsCached + ") > " + (Byte.SIZE - 1);
byteOutput._write8(cache);
clearCache();
}
void _writeUnsigned(long value, int bits) {
assert bits > 0 : "bits(" + bits + ") <= " + 0;
assert bits < Long.SIZE : "bits(" + bits + ") > " + (Long.SIZE - 1);
assert (value & ~MASKS[bits]) == 0 : "value(" + value + ") is larger than bits(" + bits + ")";
incrementBitsWritten(bits);
cache |= (value << bitsCached);
bitsCached += bits;
if (bitsCached > Long.SIZE) {
writeCacheSafe(value, bits);
} else {
writeCacheUnsafe(bits);
}
}
private void writeCacheSafe(long value, int bits) {
assert bits > 0 : "bits(" + bits + ") < " + 1;
assert bits < Long.SIZE : "bits(" + bits + ") > " + (Long.SIZE - 1);
assert bitsCached > Long.SIZE : "bitsCached(" + bitsCached + ") <= " + Long.SIZE;
assert bitsCached - bits < Byte.SIZE : "bitsCached(" + bitsCached + ") - bits(" + bits + ") > " + (Byte.SIZE - 1);
final int overflowBits = bitsCached - Long.SIZE;
final int overflowShift = Long.SIZE - overflowBits;
for (; bitsCached >= Byte.SIZE; bitsCached -= Byte.SIZE) {
final long octet = cache & 0xFF;
byteOutput._write8(octet);
cache >>>= Byte.SIZE;
}
assert overflowBits > 0 : "overflowBits(" + overflowBits + ") < " + 1;
cache = (value >>> overflowShift) & MASKS[overflowBits];
}
private void writeCacheUnsafe(int bits) {
assert bits > 0 : "bits(" + bits + ") < " + 1;
assert bits < Long.SIZE : "bits(" + bits + ") > " + (Long.SIZE - 1);
assert bitsCached >= bits : "bitsCached(" + bitsCached + ") < bits(" + bits + ")";
assert bitsCached <= Long.SIZE : "bitsCached(" + bitsCached + ") > " + Long.SIZE;
for (; bitsCached >= Byte.SIZE; bitsCached -= Byte.SIZE) {
final long octet = cache & 0xFF;
byteOutput._write8(octet);
cache >>>= Byte.SIZE;
}
}
void writeSigned(long value, int bits) {
assert bits > 0 : "bits(" + bits + ") <= " + 0;
assert bits <= Long.SIZE : "bits(" + bits + ") > " + Long.SIZE;
// bits == Long.SIZE write raw?
final int shift = Long.SIZE - bits;
assert shift > 0 : "shift(" + shift + ") <= " + 0;
value = value << shift >> shift;
}
public void writeRaw(long value, int bits) {
BitConstraints.validate64(bits);
}
public void writeUnsigned(long value, int bits) {
write63u(value, bits);
}
public void write7u(byte value, int bits) {
BitConstraints.validate7u(bits);
_writeUnsigned(value, bits);
}
public void write15u(short value, int bits) {
BitConstraints.validate15u(bits);
_writeUnsigned(value, bits);
}
public void write31u(int value, int bits) {
BitConstraints.validate31u(bits);
_writeUnsigned(value, bits);
}
public void write63u(long value, int bits) {
BitConstraints.validate63u(bits);
_writeUnsigned(value, bits);
}
// sign-extends bits
public void write8(int value, int bits) {
BitConstraints.validate8(bits);
}
// sign-extends bits
public void write16(int value, int bits) {
BitConstraints.validate16(bits);
}
// sign-extends bits
public void write32(int value, int bits) {
BitConstraints.validate32(bits);
}
// sign-extends bits
public void write64(long value, int bits) {
BitConstraints.validate64(bits);
}
public void write8(int value) {
write8(value, Byte.SIZE);
}
public void write16(int value) {
write16(value, Short.SIZE);
}
public void write32(int value) {
write32(value, Integer.SIZE);
}
public void write64(long value) {
write64(value, Long.SIZE);
}
}

View File

@ -0,0 +1,67 @@
package com.riiablo.io;
import io.netty.buffer.ByteBuf;
public class ByteOutput {
private final ByteBuf buffer;
private BitOutput bitOutput;
ByteOutput(ByteBuf buffer) {
this.buffer = buffer;
}
BitOutput bitOutput() {
return bitOutput != null ? bitOutput : (bitOutput = new BitOutput(this));
}
public ByteBuf buffer() {
return buffer;
}
public int bytesRemaining() {
return buffer.writableBytes();
}
public boolean aligned() {
throw null;
}
public BitOutput unalign() {
return bitOutput();
}
long incrementBitsWritten(long bits) {
assert (bits & (Byte.SIZE - 1)) == 0;
if (bitOutput == null) return 0;
return bitOutput.incrementBitsWritten(bits);
}
void _write8(long octet) {
assert 0 <= octet && octet < (1 << Byte.SIZE);
buffer.writeByte((int) octet);
}
public void write8(int value) {
assert aligned() : "not aligned";
incrementBitsWritten(Byte.SIZE);
buffer.writeByte(value);
}
public void write16(int value) {
assert aligned() : "not aligned";
incrementBitsWritten(Short.SIZE);
buffer.writeShortLE(value);
}
public void write32(int value) {
assert aligned() : "not aligned";
incrementBitsWritten(Short.SIZE);
buffer.writeIntLE(value);
}
public void write64(long value) {
assert aligned() : "not aligned";
incrementBitsWritten(Short.SIZE);
buffer.writeLongLE(value);
}
}