Grok 20.3.2
BitIO.h
Go to the documentation of this file.
1/*
2 * Copyright (C) 2016-2026 Grok Image Compression Inc.
3 *
4 * This source code is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU Affero General Public License, version 3,
6 * as published by the Free Software Foundation.
7 *
8 * This source code is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU Affero General Public License for more details.
12 *
13 * You should have received a copy of the GNU Affero General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 */
17
18#pragma once
19
20#include <cassert>
21#include <cstddef>
22#include <cstdint>
23#include <stdexcept>
24
25#include "IStreamWriter.h"
26
27namespace grk::t1_t2
28{
29
30class TruncatedPacketHeaderException : public std::exception
31{
32};
33
34class InvalidMarkerException : public std::exception
35{
36public:
37 explicit InvalidMarkerException(uint16_t marker) : marker_(marker) {}
38
39 uint16_t marker_;
40};
41
46class BitIO
47{
48public:
55 BitIO(uint8_t* bp, uint64_t len, bool isCompressor)
56 : start(bp), offset(0), buf_len(len), buf(0), ct(isCompressor ? 8 : 0), stream(nullptr),
57 read0xFF(false)
58 {
59 assert(isCompressor || bp);
60 }
61
67 BitIO(IStreamWriter* stream, bool isCompressor)
68 : start(nullptr), offset(0), buf_len(0), buf(0), ct(isCompressor ? 8 : 0), stream(stream),
69 read0xFF(false)
70 {}
71
76 size_t numBytes()
77 {
78 return offset;
79 }
80
87 bool write(uint32_t v, uint8_t n)
88 {
89 assert(n != 0 && n <= 32);
90 for(int8_t i = (int8_t)(n - 1); i >= 0; i--)
91 {
92 if(!putbit((v >> i) & 1))
93 return false;
94 }
95 return true;
96 }
97
103 bool write(uint8_t v)
104 {
105 return putbit(v & 1);
106 }
107
113 template<typename T>
114 void read(T* bits, uint8_t n)
115 {
116 assert(n > 0 && n <= sizeof(T) << 3);
117 *bits = 0U;
118 for(int8_t i = (int8_t)(n - 1); i >= 0; i--)
119 {
120 if(ct == 0)
121 bytein();
122 assert(ct > 0);
123 ct = (uint8_t)(ct - 1);
124 *bits |= (T)(((buf >> ct) & 1) << i);
125 }
126 }
127
132 uint8_t read(void)
133 {
134 return getbit();
135 }
136
141 bool flush()
142 {
143 if(!write8u())
144 return false;
145
146 return (ct == 7) ? write8u() : true;
147 }
148
153 {
154 if(buf == 0xff)
155 bytein();
156 ct = 0;
157 }
158
164 bool putcommacode(uint8_t n)
165 {
166 int16_t nn = n;
167 while(--nn >= 0)
168 {
169 if(!write(1))
170 return false;
171 }
172
173 return write(0);
174 }
175
180 uint8_t getcommacode(void)
181 {
182 uint8_t n = 0;
183 uint8_t temp = read();
184 while(temp)
185 {
186 n++;
187 temp = read();
188 }
189
190 return n;
191 }
192
197 bool putnumpasses(uint8_t n)
198 {
199 if(n == 1)
200 {
201 if(!write(0))
202 return false;
203 }
204 else if(n == 2)
205 {
206 if(!write(2, 2))
207 return false;
208 }
209 else if(n <= 5)
210 {
211 if(!write(0xc | (n - 3), 4))
212 return false;
213 }
214 else if(n <= 36)
215 {
216 if(!write(0x1e0 | (n - 6), 9))
217 return false;
218 }
219 else if(n <= 164)
220 {
221 if(!write(0xff80 | (n - 37), 16))
222 return false;
223 }
224
225 return true;
226 }
227
232 void getnumpasses(uint8_t* numpasses)
233 {
234 uint32_t n = read();
235 if(!n)
236 {
237 *numpasses = 1;
238 return;
239 }
240 n = read();
241 if(!n)
242 {
243 *numpasses = 2;
244 return;
245 }
246 read(&n, 2);
247 if(n != 3)
248 {
249 *numpasses = (uint8_t)(n + 3);
250 return;
251 }
252 read(&n, 5);
253 if(n != 31)
254 {
255 *numpasses = (uint8_t)(n + 6);
256 return;
257 }
258 read(&n, 7);
259 *numpasses = (uint8_t)(n + 37);
260 }
261
262private:
263 /* pointer to the start of the buffer */
264 uint8_t* start;
265 size_t offset;
266 size_t buf_len;
267
271 uint8_t buf;
272
277 uint8_t ct;
278
281
282 bool putbit(uint8_t b)
283 {
284 if(ct == 0 && !write8u())
285 return false;
286 ct--;
287 buf = static_cast<uint8_t>(buf | (b << ct));
288
289 return true;
290 }
291
292 uint8_t getbit(void)
293 {
294 if(ct == 0)
295 bytein();
296 assert(ct > 0);
297 ct = (uint8_t)(ct - 1);
298
299 return (buf >> ct) & 1;
300 }
301
302 bool write8u(void)
303 {
304 if(stream)
305 {
306 if(!stream->write8u(buf))
307 return false;
308 }
309 else
310 {
311 // avoid buffer over-run
312 if(offset == buf_len)
313 return false;
314
315 offset++;
316 }
317 ct = buf == 0xff ? 7 : 8;
318 buf = 0;
319
320 return true;
321 }
322
323 void bytein(void)
324 {
325 if(offset == buf_len)
327 if(read0xFF && (buf >= 0x90))
328 {
329 uint16_t marker = (uint16_t)(((uint16_t)0xFF << 8) | (uint16_t)buf);
330 // if(marker != EPH && marker != SOP)
331 // grklog.warn("Invalid marker 0x%x detected in packet header", marker);
332 // else
333 // grklog.warn("Unexpected SOP/EPH marker 0x%x detected in packet header", marker);
334
335 throw InvalidMarkerException(marker);
336 }
337 read0xFF = (buf == 0xff);
338 ct = read0xFF ? 7 : 8;
339 buf = start[offset];
340 offset++;
341 }
342};
343
344} // namespace grk::t1_t2
bool write(uint8_t v)
Writes one bit.
Definition BitIO.h:103
void read(T *bits, uint8_t n)
Reads bits.
Definition BitIO.h:114
bool read0xFF
Definition BitIO.h:280
size_t buf_len
Definition BitIO.h:266
void bytein(void)
Definition BitIO.h:323
bool write8u(void)
Definition BitIO.h:302
BitIO(IStreamWriter *stream, bool isCompressor)
Constructs a t1::BitIO object.
Definition BitIO.h:67
bool putcommacode(uint8_t n)
Writes comma code.
Definition BitIO.h:164
uint8_t buf
Temporary buffer where bytes are read from or written to.
Definition BitIO.h:271
uint8_t ct
Number of bits free to write for encoder or number of bits to read for decoder.
Definition BitIO.h:277
uint8_t * start
Definition BitIO.h:264
bool putbit(uint8_t b)
Definition BitIO.h:282
bool write(uint32_t v, uint8_t n)
Writes bits.
Definition BitIO.h:87
uint8_t read(void)
Reads bit.
Definition BitIO.h:132
void readFinalHeaderByte()
Reads bits at end of packet header.
Definition BitIO.h:152
void getnumpasses(uint8_t *numpasses)
Reads number of passes.
Definition BitIO.h:232
bool flush()
Flushes remaining bits.
Definition BitIO.h:141
uint8_t getcommacode(void)
Reads comma code.
Definition BitIO.h:180
BitIO(uint8_t *bp, uint64_t len, bool isCompressor)
Constructs a t1::BitIO object.
Definition BitIO.h:55
uint8_t getbit(void)
Definition BitIO.h:292
size_t numBytes()
Gets number of bytes written.
Definition BitIO.h:76
size_t offset
Definition BitIO.h:265
bool putnumpasses(uint8_t n)
Writes number of passes.
Definition BitIO.h:197
IStreamWriter * stream
Definition BitIO.h:279
uint16_t marker_
Definition BitIO.h:39
InvalidMarkerException(uint16_t marker)
Definition BitIO.h:37
Definition BitIO.h:28
Definition IStreamWriter.h:9