forked from urbit/vere
-
Notifications
You must be signed in to change notification settings - Fork 0
/
bitstream.h
239 lines (203 loc) · 4.56 KB
/
bitstream.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
/// @file
#ifndef UR_BITSTREAM_H
#define UR_BITSTREAM_H
#include <inttypes.h>
#include "defs.h"
/*
** stateful bitstream reader, backed by a byte-buffer,
** maintaing a 64-bit bit-cursor, and supporting a variety
** of read sizes and patterns.
**
** NB: ur_bsr*_any() functions behave as if the stream were infinite,
** subject to the overall limit of the bit-cursor.
**
*/
typedef struct ur_bsr_s {
uint64_t left;
uint64_t bits;
uint8_t off;
const uint8_t *bytes;
} ur_bsr_t;
/*
** generalized bitstream-reader/cue response enum
*/
typedef enum {
ur_cue_good = 0, // successful read
ur_cue_back = 1, // missing backreference
ur_cue_gone = 2, // read off the end of the stream
ur_cue_meme = 3 // exceeded memory representation
} ur_cue_res_e;
/*
** jam/cue type tag enumeration
*/
typedef enum {
ur_jam_atom = 0,
ur_jam_cell = 1,
ur_jam_back = 2
} ur_cue_tag_e;
/*
** stateful bitstream writer, backed by a byte-buffer automatically
** reallocated with fibonacc growth, maintaing a 64-bit bit-cursor,
** and supporting a variety of write sizes and patterns.
**
*/
typedef struct ur_bsw_s {
uint64_t prev;
uint64_t size;
uint64_t fill;
uint64_t bits;
uint8_t off;
uint8_t *bytes;
} ur_bsw_t;
/*
** initialize bitstream-reader and check for 64-bit bit-cursor overflow.
*/
ur_cue_res_e
ur_bsr_init(ur_bsr_t *bsr, uint64_t len, const uint8_t *bytes);
/*
** validate bitstream-reader invariants.
*/
ur_bool_t
ur_bsr_sane(ur_bsr_t *bsr);
/*
** read a bit, failing at EOS
*/
ur_cue_res_e
ur_bsr_bit(ur_bsr_t *bsr, uint8_t *out);
/*
** read a bit
*/
uint8_t
ur_bsr_bit_any(ur_bsr_t *bsr);
/*
** read N (up to 8) bits into a uint8.
*/
uint8_t
ur_bsr8_any(ur_bsr_t *bsr, uint8_t len);
/*
** read N (up to 32) bits into a uint32.
*/
uint32_t
ur_bsr32_any(ur_bsr_t *bsr, uint8_t len);
/*
** read N (up to 64) bits into a uint64.
*/
uint64_t
ur_bsr64_any(ur_bsr_t *bsr, uint8_t len);
/*
** read N bits into a zero-initialized byte array.
*/
void
ur_bsr_bytes_any(ur_bsr_t *bsr, uint64_t len, uint8_t *out);
/*
** advance the bitstream cursor as if we had read N bits.
*/
void
ur_bsr_skip_any(ur_bsr_t *bsr, uint64_t len);
/*
** read a jam/cue type tag.
*/
ur_cue_res_e
ur_bsr_tag(ur_bsr_t *bsr, ur_cue_tag_e *out);
/*
** read a binary exponent, producing the binary log.
**
** read N (up to 255) zero bits followed by a 1, produce N.
*/
ur_cue_res_e
ur_bsr_log(ur_bsr_t *bsr, uint8_t *out);
/*
** read an atomic run-length (a la +rub).
**
** read a binary log N, then read N (up to 64) bits,
** produce (N-bits ^ (1 << N))
*/
ur_cue_res_e
ur_bsr_rub_len(ur_bsr_t *bsr, uint64_t *out);
/*
** initialize bitstream-writer with prev/size for fibonacci growth.
*/
void
ur_bsw_init(ur_bsw_t *bsw, uint64_t prev, uint64_t size);
/*
** reallocate bitstream write buffer with max(fibonacci, step) growth.
*/
void
ur_bsw_grow(ur_bsw_t *bsw, uint64_t step);
/*
** validate bitstream-writer invariants.
*/
ur_bool_t
ur_bsw_sane(ur_bsw_t *bsw);
/*
** return bit-length, produce byte-buffer.
*/
uint64_t
ur_bsw_done(ur_bsw_t *bsw, uint64_t *len, uint8_t **byt);
/*
** write a bit
*/
void
ur_bsw_bit(ur_bsw_t *bsw, uint8_t bit);
/*
** write N (up to 8) bits of a uint8.
*/
void
ur_bsw8(ur_bsw_t *bsw, uint8_t len, uint8_t byt);
/*
** write N (up to 32) bits of a uint32.
*/
void
ur_bsw32(ur_bsw_t *bsw, uint8_t len, uint32_t val);
/*
** write N (up to 64) bits of a uint64.
*/
void
ur_bsw64(ur_bsw_t *bsw, uint8_t len, uint64_t val);
/*
** write N bits of a byte array.
**
** NB: [byt] must contain at least N bits.
*/
void
ur_bsw_bytes(ur_bsw_t *bsw, uint64_t len, uint8_t *byt);
/*
** write a binary exponent (N zero bits, followed by a 1).
*/
void
ur_bsw_bex(ur_bsw_t *bsw, uint8_t n);
/*
** write N (up to 64) run-length prefixed bits (a la +mat).
*/
void
ur_bsw_mat64(ur_bsw_t *bsw, uint8_t len, uint64_t val);
/*
** write N run-length prefixed bits (a la +mat).
**
** NB: [byt] must contain at least N bits.
*/
void
ur_bsw_mat_bytes(ur_bsw_t *bsw, uint64_t len, uint8_t *byt);
/*
** write a backref tag (1, 1) and N (up to 64) run-length prefixed bits.
*/
void
ur_bsw_back64(ur_bsw_t *bsw, uint8_t len, uint64_t val);
/*
** write an atom tag (0) and N (up to 64) run-length prefixed bits.
*/
void
ur_bsw_atom64(ur_bsw_t *bsw, uint8_t len, uint64_t val);
/*
** write an atom tag (0) and N run-length prefixed bits.
**
** NB: [byt] must contain at least N bits.
*/
void
ur_bsw_atom_bytes(ur_bsw_t *bsw, uint64_t len, uint8_t *byt);
/*
** write a cell tag (1, 0)
*/
void
ur_bsw_cell(ur_bsw_t *bsw);
#endif