]> git.sesse.net Git - fjl/blob - bitsource.c
Fix a Makefile typo.
[fjl] / bitsource.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <stdbool.h>
4 #include <string.h>
5
6 #include "bitsource.h"
7
8 #define MARKER_CHAR 0xff
9 #define STUFF_MARKER 0x00
10
11 void init_bit_source(struct bit_source* source, input_func_t* input_func, void* userdata)
12 {
13         memset(source, 0, sizeof(*source));
14         source->bytes = (uint8_t*)malloc(BYTERESERVOIR_SIZE);
15         source->input_func = input_func;
16         source->userdata = userdata;
17 }
18
19 void possibly_refill_slow_path(struct bit_source* source, unsigned num_bits)
20 {
21         // First, make sure there's stuff in the byte reservoir if we can.
22         assert(source->bytes_available <= BYTERESERVOIR_SIZE);
23
24         // Read data from the source until we have enough to satisfy the request.
25         while (source->bits_available + 8 * source->bytes_available < num_bits) {
26                 const size_t bytes_to_read = BYTERESERVOIR_SIZE - source->bytes_available;
27                 const ssize_t bytes_read =
28                         (*source->input_func)(source->userdata,
29                                               source->bytes + source->bytes_available,
30                                               bytes_to_read);
31                 assert(bytes_read <= (ssize_t)bytes_to_read);
32                 assert(bytes_read >= (ssize_t)-1);
33
34                 // TODO: We need better error handling here. setjmp()/longjmp()
35                 // should hopefully do the trick, but we need to take care for
36                 // suspension.
37                 if (bytes_read == (ssize_t)-1) {
38                         fprintf(stderr, "Input function returned error\n");
39                         exit(1);
40                 }
41                 if (bytes_read == 0) {
42                         fprintf(stderr, "Premature EOF\n");
43                         exit(1);
44                 }
45                 
46                 source->bytes_available += bytes_read;
47         }
48
49         // Fill the bit reservoir one by one byte until we have enough.
50         while (source->bits_available < num_bits) {
51                 assert(source->bytes_available > 0);
52                 assert(source->bits_available + 8 <= BITRESERVOIR_SIZE);
53                 uint8_t byte = *(source->bytes);
54                 ++source->bytes;
55                 --source->bytes_available;
56                 source->bits |= ((bitreservoir_t)byte << (BITRESERVOIR_SIZE - source->bits_available - 8));
57                 source->bits_available += 8;
58         }
59 }