goto have_match;
}
+ /* old is the trailing edge of the checksum window. */
if (buffer_size(ctx) >= ctx->block_size)
old = ctx->buffer + ctx->buffer_start;
else
*old, *p,
ctx->uncrc_tab);
old++;
+ /* End of stored buffer? Start on data they gave us. */
if (old == ctx->buffer + ctx->buffer_end)
old = buf;
} else {
p++;
}
- /* Make sure we have a copy of the last block_size bytes.
- * First, copy down the old data. */
- if (buffer_size(ctx)) {
- }
-
if (crcmatch >= 0) {
/* We have a match! */
if (ctx->literal_bytes > ctx->block_size) {
assert(ctx->literal_bytes == 0);
ctx->have_match = -1;
ctx->running_crc = 0;
+ /* Nothing more in the buffer. */
+ ctx->buffer_start = ctx->buffer_end = 0;
}
} else {
/* Output literal if it's more than 1 block ago. */
if (ctx->literal_bytes > ctx->block_size) {
*result = ctx->literal_bytes - ctx->block_size;
- ctx->literal_bytes = ctx->block_size;
+ ctx->literal_bytes -= *result;
+ /* Advance buffer. */
+ if (*result >= buffer_size(ctx))
+ ctx->buffer_start = ctx->buffer_end = 0;
+ else
+ ctx->buffer_start += *result;
} else
*result = 0;
ctx->buffer_end -= ctx->buffer_start;
ctx->buffer_start = 0;
}
- memcpy(ctx->buffer + ctx->buffer_end, buf, len);
+
+ /* Copy len bytes from tail of buffer. */
+ memcpy(ctx->buffer + ctx->buffer_end, buf + buflen - len, len);
ctx->buffer_end += len;
assert(buffer_size(ctx) <= ctx->block_size);
}
long crc_read_flush(struct crc_context *ctx)
{
long ret;
+ size_t final;
- /* In case we ended on a whole block match. */
- if (ctx->have_match == -1) {
- size_t final;
-
- final = final_block_match(ctx);
- if (!final) {
- /* This is how many bytes we're about to consume. */
- ret = buffer_size(ctx);
- ctx->buffer_start += ret;
- ctx->literal_bytes -= ret;
+ /* We might have ended right on a matched block. */
+ if (ctx->have_match != -1) {
+ ctx->literal_bytes -= ctx->block_size;
+ assert(ctx->literal_bytes == 0);
+ ret = -ctx->have_match-1;
+ ctx->have_match = -1;
+ ctx->running_crc = 0;
+ /* Nothing more in the buffer. */
+ ctx->buffer_start = ctx->buffer_end;
+ return ret;
+ }
- return ret;
- }
- ctx->buffer_start += final;
- ctx->literal_bytes -= final;
- ctx->have_match = ctx->num_crcs-1;
+ /* Look for truncated final block. */
+ final = final_block_match(ctx);
+ if (!final) {
+ /* Nope? Just a literal. */
+ ret = buffer_size(ctx);
+ ctx->buffer_start += ret;
+ ctx->literal_bytes -= ret;
+ return ret;
}
- /* It might be a partial block match, so no assert */
- ctx->literal_bytes = 0;
- ret = -ctx->have_match-1;
- ctx->have_match = -1;
+ /* We matched (some of) what's left. */
+ ret = -((int)ctx->num_crcs-1)-1;
+ ctx->buffer_start += final;
+ ctx->literal_bytes -= final;
return ret;
}