Libraryless. Click here for Pure Java version (13163L/75K).
sclass BitHead > ByteHead { gettable int align = 8; gettable int currentByte; settable bool debug; replace SomethingIO with BitIO. replace print with if (debug) print. *() {} *(InputStream inputStream) { super(inputStream); } *(OutputStream outputStream) { super(outputStream); } bool writeArraysSlowly() { false; } // choose fast or slow version depending on alignment void write(byte[] data) { if (align == 0 && !writeArraysSlowly()) super.write(data); else for (b : data) write(b); } void writeByte(int i) { i &= 0xFF; print("writeByte: align=" + align + ", byteCounter=" + byteCounter + ", value=" + i); if (align == 0) super.writeByte(i); else { currentByte |= i << align; super.writeByte(currentByte); currentByte = i >> (8-align); } } void writePartialByte(int i, int bits) { for bit to bits: { writeBit(i); i >>>= 1; } } void writeBit(int i) { writeBit((i & 1) != 0); } void writeBit(bool b) { align &= 7; if (b) currentByte |= 1 << align; if (align == 7) { super.writeByte(currentByte); currentByte = align = 0; } else ++align; } int readPartialByte(int bits) { int value = 0; for bit to bits: if (readBit()) value |= 1 << bit; ret isEOF() ? -1 : value; } int readByte() { print("readByte: align=" + align + ", byteCounter=" + byteCounter); int value; if (align == 0) { value = currentByte; align = 8; } else if (align == 8) value = super.readByte(); else { value = currentByte >> align; int align = this.align; bufferNextByte(); if (isEOF()) ret -1; this.align = align; value |= (currentByte << (8-align)) & 0xFF; } print("value: " + value); ret value; } bool readBit() { bool bitSet = peekBit(); advanceBit(); ret bitSet; } bool peekBit() { if (currentByte < 0) fail("eof"); if (align == 8) bufferNextByte(); ret (currentByte & (1 << align)) != 0; } void bufferNextByte { currentByte = super.readByte(); align = 0; } void advanceBit { if (currentByte < 0) ret; if (align == 8) bufferNextByte(); ++align; } bool byteAligned() { ret (align & 7) == 0; } void completeByte aka flushBits aka finishByte aka finish(bool padWithOnes default false) { print("Finishing byte " + byteCounter + " (align " + align + ")"); if (byteAligned()) ret; if (writeMode()) { if (padWithOnes) currentByte |= 0xFF << align; super.writeByte(currentByte); } currentByte = 0; align = readMode() ? 8 : 0; } // TODO: switch to more compact version saving 5 bits on average void writeTrailingBitCount aka trailingBitCount(bool padWithOnes default false) { if (!writeMode()) ret; int bitCount = modRange_incl(align(), 1, 8); completeByte(padWithOnes); writeByte(bitCount); } void exchange(SomethingIO writable) { if (writable != null) writable.readWrite(this); } void exchangeBit(IF0<Bool> getter, IVF1<Bool> setter) { if (writeMode()) writeBit(getter!); if (readMode()) setter.get(readBit()); } void exchangeBit(int i) { exchangeBit(odd(i)); } void exchangeBit(bool i) { exchangeBit(-> i, j -> assertEquals(i, j)); } void exchange(BitIO getter, Runnable setter) { if (writeMode()) getter.readWrite(this); if (readMode()) setter.run(); } bool isEOF() { ret currentByte < 0; } }
Began life as a copy of #1035632
download show line numbers debug dex old transpilations
Travelled to 2 computer(s): elmgxqgtpvxh, mqqgnosmbjvj
No comments. add comment
Snippet ID: | #1035655 |
Snippet name: | BitHead - ByteHead that can write individual bits (and non-byte-aligned bytes and partial bytes) |
Eternal ID of this version: | #1035655/56 |
Text MD5: | 6c7a0725aa50d99764dff38fe513fa4d |
Transpilation MD5: | 9f070c46881096d3bf677774469803ae |
Author: | stefan |
Category: | javax / io |
Type: | JavaX fragment (include) |
Public (visible to everyone): | Yes |
Archived (hidden from active list): | No |
Created/modified: | 2022-07-15 20:59:06 |
Source code size: | 3802 bytes / 163 lines |
Pitched / IR pitched: | No / No |
Views / Downloads: | 298 / 522 |
Version history: | 55 change(s) |
Referenced in: | [show references] |