X-Git-Url: https://git.sesse.net/?p=fjl;a=blobdiff_plain;f=bytesource.c;h=ca260a1f8756ab5924531fd41c0e245176bc4373;hp=fed7551d50721c1e06ed2057c3a23e4dc83c069a;hb=2e753fa3d7ebdc6ff142680461610c9db6cac947;hpb=951b5e437612314d0fabd62689e3805ea23f8439 diff --git a/bytesource.c b/bytesource.c index fed7551..ca260a1 100644 --- a/bytesource.c +++ b/bytesource.c @@ -44,7 +44,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; } @@ -81,7 +81,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 @@ -94,45 +94,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; }