mirror of
https://github.com/collinsmith/riiablo.git
synced 2025-01-20 09:17:29 +07:00
Created ByteOutput and BitOutput
This commit is contained in:
parent
4e2cd665cd
commit
11555397e3
182
core/src/com/riiablo/io/BitOutput.java
Normal file
182
core/src/com/riiablo/io/BitOutput.java
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
67
core/src/com/riiablo/io/ByteOutput.java
Normal file
67
core/src/com/riiablo/io/ByteOutput.java
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user