X-Git-Url: https://git.sesse.net/?p=fjl;a=blobdiff_plain;f=bytesource.c;h=c5e0ed88b1b0fd464e7ceb0849d0f78c98a11aad;hp=9e46d20ec0fdd8411326f097e38e774399075176;hb=d5b9f8f45a79e6f25045bcc10511884a20fc8912;hpb=f61544ef710611cf351ce806c6c62f0e2d98727f diff --git a/bytesource.c b/bytesource.c index 9e46d20..c5e0ed8 100644 --- a/bytesource.c +++ b/bytesource.c @@ -1,4 +1,5 @@ #include +#include #include #include @@ -21,7 +22,7 @@ uint8_t byte_source_read_marker(struct byte_source* src) { // Refill until we have at least two bytes or EOF. while (src->bytes_available < 2) { - const unsigned bytes_to_read = BYTESOURCE_CHUNK_SIZE - src->bytes_available; + const unsigned bytes_to_read = 2 - src->bytes_available; const ssize_t bytes_read = (*src->input_func)(src->userdata, src->bytes + src->bytes_available, @@ -44,7 +45,7 @@ uint8_t byte_source_read_marker(struct byte_source* src) uint8_t ret = src->bytes[1]; memmove(src->bytes, src->bytes + 2, src->bytes_available - 2); src->bytes_available -= 2; - + return ret; } @@ -57,12 +58,13 @@ ssize_t byte_source_input_func(void* source, uint8_t* buf, size_t len) while (src->bytes_available == 0 || (src->bytes_available == 1 && src->bytes[0] == MARKER_CHAR)) { const unsigned space_left = BYTESOURCE_CHUNK_SIZE - src->bytes_available; - const size_t bytes_to_read = (len > space_left ? space_left : len); + const unsigned missing_data = len - src->bytes_available; + const size_t bytes_to_read = (missing_data > space_left ? space_left : missing_data); assert(bytes_to_read <= BYTESOURCE_CHUNK_SIZE); const ssize_t bytes_read = (*src->input_func)(src->userdata, - src->bytes + src->bytes_available, - bytes_to_read); + src->bytes + src->bytes_available, + bytes_to_read); assert(bytes_read >= -1); assert(bytes_read <= (ssize_t)bytes_to_read); @@ -80,7 +82,7 @@ ssize_t byte_source_input_func(void* source, uint8_t* buf, size_t len) src->bytes_available += bytes_read; } - + // Now unstuff as much as we can. First of all, if there's a 0xFF at the // end of the buffer, we don't include it this time; the unstuff function // will only give us an error since it can't decide if it's a marker or @@ -93,45 +95,47 @@ ssize_t byte_source_input_func(void* source, uint8_t* buf, size_t len) end_marker = true; } - int unstuffed_bytes = (*unstuff_choice)(buf, src->bytes, bytes_to_unstuff); - assert(unstuffed_bytes != 0); - if (unstuffed_bytes > 0) { - // Fast path: No markers in the data. We can basically just - // return it. - if (end_marker) { - src->bytes_available = 1; - src->bytes[0] = 0xff; - } else { - src->bytes_available = 0; - src->bytes[0] = 0; + // Fast path: No markers in the data, we don't have more data than we + // need. We can basically just return it. + if (bytes_to_unstuff <= len) { + int unstuffed_bytes = (*unstuff_choice)(buf, src->bytes, bytes_to_unstuff); + assert(unstuffed_bytes != 0); + if (unstuffed_bytes > 0) { + // Fast path: No markers in the data. We can basically just + // return it. + if (end_marker) { + src->bytes_available = 1; + src->bytes[0] = 0xff; + } else { + src->bytes_available = 0; + } + return unstuffed_bytes; } - return unstuffed_bytes; } // Slow path: There was a marker in the data. Unstuff manually until // we hit the marker, then return that. - assert(unstuffed_bytes == -1); unsigned bytes_read; unsigned bytes_written = 0; - for (bytes_read = 0; bytes_read < src->bytes_available; ++bytes_read) { - buf[bytes_written++] = src->bytes[bytes_read]; + for (bytes_read = 0; bytes_read < bytes_to_unstuff && bytes_written < len; ++bytes_read) { if (src->bytes[bytes_read] != MARKER_CHAR) { + buf[bytes_written++] = src->bytes[bytes_read]; continue; } assert(bytes_read < src->bytes_available); if (src->bytes[bytes_read + 1] == STUFF_MARKER) { + src->bytes[bytes_written++] = MARKER_CHAR; + // Skip the stuff byte. ++bytes_read; - continue; } else { // OK, this is our marker. break; - } + } } memmove(src->bytes, src->bytes + bytes_read, src->bytes_available - bytes_read); src->bytes_available -= bytes_read; - assert(bytes_written >= 1); - return bytes_written - 1; + return bytes_written; }