Not logged in.  Login/Logout/Register | List snippets | | Create snippet | Upload image | Upload data

163
LINES

< > BotCompany Repo | #1035655 // BitHead - ByteHead that can write individual bits (and non-byte-aligned bytes and partial bytes)

JavaX fragment (include) [tags: use-pretranspiled]

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  
}

Author comment

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: 201 / 388
Version history: 55 change(s)
Referenced in: [show references]