7 #include "bytesource.h"
9 #define MARKER_CHAR 0xff
10 #define STUFF_MARKER 0x00
12 void init_byte_source(struct byte_source* source, raw_input_func_t* input_func, void* userdata)
14 // TODO: should this size be a different constant?
15 memset(source, 0, sizeof(*source));
16 source->bytes = (uint8_t*)malloc(BYTESOURCE_CHUNK_SIZE);
17 source->input_func = input_func;
18 source->userdata = userdata;
21 uint8_t byte_source_read_marker(struct byte_source* src)
23 // Refill until we have at least two bytes or EOF.
24 while (src->bytes_available < 2) {
25 const unsigned bytes_to_read = 2 - src->bytes_available;
26 const ssize_t bytes_read =
27 (*src->input_func)(src->userdata,
28 src->bytes + src->bytes_available,
30 assert(bytes_read >= -1);
31 assert(bytes_read <= (ssize_t)bytes_to_read);
33 if (bytes_read == -1 || bytes_read == 0) {
37 src->bytes_available += bytes_read;
40 assert(src->bytes_available >= 2);
41 if (src->bytes[0] != MARKER_CHAR || src->bytes[1] == STUFF_MARKER) {
45 uint8_t ret = src->bytes[1];
46 memmove(src->bytes, src->bytes + 2, src->bytes_available - 2);
47 src->bytes_available -= 2;
52 ssize_t byte_source_input_func(void* source, uint8_t* buf, size_t len)
54 struct byte_source* src = (struct byte_source*)source;
56 // If there's no data in the buffer (or only a partial marker), we have
57 // to read in more from our upstream src.
58 while (src->bytes_available == 0 ||
59 (src->bytes_available == 1 && src->bytes[0] == MARKER_CHAR)) {
60 const unsigned space_left = BYTESOURCE_CHUNK_SIZE - src->bytes_available;
61 const unsigned missing_data = len - src->bytes_available;
62 const size_t bytes_to_read = (missing_data > space_left ? space_left : missing_data);
63 assert(bytes_to_read <= BYTESOURCE_CHUNK_SIZE);
64 const ssize_t bytes_read =
65 (*src->input_func)(src->userdata,
66 src->bytes + src->bytes_available,
68 assert(bytes_read >= -1);
69 assert(bytes_read <= (ssize_t)bytes_to_read);
71 if (bytes_read == -1) {
73 } else if (bytes_read == 0) {
74 if (src->bytes_available == 1) {
75 // EOF in the middle of a marker => read error
78 assert(src->bytes_available == 0);
83 src->bytes_available += bytes_read;
86 // Now unstuff as much as we can. First of all, if there's a 0xFF at the
87 // end of the buffer, we don't include it this time; the unstuff function
88 // will only give us an error since it can't decide if it's a marker or
90 unsigned bytes_to_unstuff = src->bytes_available;
91 bool end_marker = false;
92 assert(bytes_to_unstuff > 0);
93 if (src->bytes[bytes_to_unstuff - 1] == 0xff) {
98 // Fast path: No markers in the data, we don't have more data than we
99 // need. We can basically just return it.
100 if (bytes_to_unstuff <= len) {
101 int unstuffed_bytes = (*unstuff_choice)(buf, src->bytes, bytes_to_unstuff);
102 assert(unstuffed_bytes != 0);
103 if (unstuffed_bytes > 0) {
104 // Fast path: No markers in the data. We can basically just
107 src->bytes_available = 1;
108 src->bytes[0] = 0xff;
110 src->bytes_available = 0;
112 return unstuffed_bytes;
116 // Slow path: There was a marker in the data. Unstuff manually until
117 // we hit the marker, then return that.
119 unsigned bytes_written = 0;
120 for (bytes_read = 0; bytes_read < bytes_to_unstuff && bytes_written < len; ++bytes_read) {
121 if (src->bytes[bytes_read] != MARKER_CHAR) {
122 buf[bytes_written++] = src->bytes[bytes_read];
126 assert(bytes_read < src->bytes_available);
127 if (src->bytes[bytes_read + 1] == STUFF_MARKER) {
128 src->bytes[bytes_written++] = MARKER_CHAR;
130 // Skip the stuff byte.
133 // OK, this is our marker.
138 memmove(src->bytes, src->bytes + bytes_read, src->bytes_available - bytes_read);
139 src->bytes_available -= bytes_read;
140 return bytes_written;