Libraryless. Click here for Pure Java version (13163L/75K).
1 | sclass BitHead > ByteHead { |
2 | gettable int align = 8; |
3 | gettable int currentByte; |
4 | settable bool debug; |
5 | |
6 | replace SomethingIO with BitIO. |
7 | replace print with if (debug) print. |
8 | |
9 | *() {} |
10 | *(InputStream inputStream) { super(inputStream); } |
11 | *(OutputStream outputStream) { super(outputStream); } |
12 | |
13 | bool writeArraysSlowly() { false; } |
14 | |
15 | // choose fast or slow version depending on alignment |
16 | void write(byte[] data) { |
17 | if (align == 0 && !writeArraysSlowly()) |
18 | super.write(data); |
19 | else |
20 | for (b : data) write(b); |
21 | } |
22 | |
23 | void writeByte(int i) { |
24 | i &= 0xFF; |
25 | |
26 | print("writeByte: align=" + align + ", byteCounter=" + byteCounter + ", value=" + i); |
27 | if (align == 0) |
28 | super.writeByte(i); |
29 | else { |
30 | currentByte |= i << align; |
31 | super.writeByte(currentByte); |
32 | currentByte = i >> (8-align); |
33 | } |
34 | } |
35 | |
36 | void writePartialByte(int i, int bits) { |
37 | for bit to bits: { |
38 | writeBit(i); |
39 | i >>>= 1; |
40 | } |
41 | } |
42 | |
43 | void writeBit(int i) { |
44 | writeBit((i & 1) != 0); |
45 | } |
46 | |
47 | void writeBit(bool b) { |
48 | align &= 7; |
49 | if (b) currentByte |= 1 << align; |
50 | if (align == 7) { |
51 | super.writeByte(currentByte); |
52 | currentByte = align = 0; |
53 | } else |
54 | ++align; |
55 | } |
56 | |
57 | int readPartialByte(int bits) { |
58 | int value = 0; |
59 | for bit to bits: |
60 | if (readBit()) value |= 1 << bit; |
61 | ret isEOF() ? -1 : value; |
62 | } |
63 | |
64 | int readByte() { |
65 | print("readByte: align=" + align + ", byteCounter=" + byteCounter); |
66 | int value; |
67 | if (align == 0) { |
68 | value = currentByte; |
69 | align = 8; |
70 | } else if (align == 8) |
71 | value = super.readByte(); |
72 | else { |
73 | value = currentByte >> align; |
74 | int align = this.align; |
75 | bufferNextByte(); |
76 | if (isEOF()) ret -1; |
77 | this.align = align; |
78 | value |= (currentByte << (8-align)) & 0xFF; |
79 | } |
80 | |
81 | print("value: " + value); |
82 | ret value; |
83 | } |
84 | |
85 | bool readBit() { |
86 | bool bitSet = peekBit(); |
87 | advanceBit(); |
88 | ret bitSet; |
89 | } |
90 | |
91 | bool peekBit() { |
92 | if (currentByte < 0) |
93 | fail("eof"); |
94 | |
95 | if (align == 8) |
96 | bufferNextByte(); |
97 | ret (currentByte & (1 << align)) != 0; |
98 | } |
99 | |
100 | void bufferNextByte { |
101 | currentByte = super.readByte(); |
102 | align = 0; |
103 | } |
104 | |
105 | void advanceBit { |
106 | if (currentByte < 0) ret; |
107 | if (align == 8) |
108 | bufferNextByte(); |
109 | ++align; |
110 | } |
111 | |
112 | bool byteAligned() { |
113 | ret (align & 7) == 0; |
114 | } |
115 | |
116 | void completeByte aka flushBits aka finishByte aka finish(bool padWithOnes default false) { |
117 | print("Finishing byte " + byteCounter + " (align " + align + ")"); |
118 | if (byteAligned()) ret; |
119 | |
120 | if (writeMode()) { |
121 | if (padWithOnes) currentByte |= 0xFF << align; |
122 | super.writeByte(currentByte); |
123 | } |
124 | currentByte = 0; |
125 | align = readMode() ? 8 : 0; |
126 | } |
127 | |
128 | // TODO: switch to more compact version saving 5 bits on average |
129 | void writeTrailingBitCount aka trailingBitCount(bool padWithOnes default false) { |
130 | if (!writeMode()) ret; |
131 | |
132 | int bitCount = modRange_incl(align(), 1, 8); |
133 | completeByte(padWithOnes); |
134 | writeByte(bitCount); |
135 | } |
136 | |
137 | void exchange(SomethingIO writable) { |
138 | if (writable != null) writable.readWrite(this); |
139 | } |
140 | |
141 | void exchangeBit(IF0<Bool> getter, IVF1<Bool> setter) { |
142 | if (writeMode()) |
143 | writeBit(getter!); |
144 | |
145 | if (readMode()) |
146 | setter.get(readBit()); |
147 | } |
148 | |
149 | void exchangeBit(int i) { exchangeBit(odd(i)); } |
150 | void exchangeBit(bool i) { |
151 | exchangeBit(-> i, j -> assertEquals(i, j)); |
152 | } |
153 | |
154 | void exchange(BitIO getter, Runnable setter) { |
155 | if (writeMode()) |
156 | getter.readWrite(this); |
157 | |
158 | if (readMode()) |
159 | setter.run(); |
160 | } |
161 | |
162 | bool isEOF() { ret currentByte < 0; } |
163 | } |
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: | 301 / 526 |
Version history: | 55 change(s) |
Referenced in: | [show references] |