uint8_t block_src[BLOCK_SIZE];
uint8_t block_dst[BLOCK_SIZE];
- while (ringbuffer_size(rb_src) > 0) {
- zs.avail_in = ringbuffer_pop(rb_src, block_src, BLOCK_SIZE);
+ const size_t num_blocks = (ringbuffer_size(rb_src) + BLOCK_SIZE - 1) / BLOCK_SIZE;
+ for (size_t i = 0; i < num_blocks; ++i) {
+ zs.avail_in = ringbuffer_peek(rb_src, i * BLOCK_SIZE, block_src, BLOCK_SIZE);
zs.next_in = block_src;
do {
zs.avail_out = BLOCK_SIZE;
zs.next_out = block_dst;
- int err = deflate(&zs, ringbuffer_size(rb_src) == 0 ? Z_FINISH : Z_NO_FLUSH);
+ int err = deflate(&zs, (i == num_blocks - 1) ? Z_FINISH : Z_NO_FLUSH);
if (err == Z_STREAM_ERROR) {
rc = false;
break;
// is full.
size_t ringbuffer_insert(ringbuffer_t *rb, const uint8_t *p, size_t length);
-// Peek |length| number of bytes from the ringbuffer into the buffer |p|
-// Return the actual number of bytes peeked. Can be less than |length| if
-// there is less than |length| data available.
-size_t ringbuffer_peek(const ringbuffer_t *rb, uint8_t *p, size_t length);
+// Peek |length| number of bytes from the ringbuffer, starting at |offset|,
+// into the buffer |p|. Return the actual number of bytes peeked. Can be less
+// than |length| if there is less than |length| data available. |offset| must
+// be non-negative.
+size_t ringbuffer_peek(const ringbuffer_t *rb, off_t offset, uint8_t *p, size_t length);
// Does the same as |ringbuffer_peek|, but also advances the ring buffer head
size_t ringbuffer_pop(ringbuffer_t *rb, uint8_t *p, size_t length);
return length;
}
-size_t ringbuffer_peek(const ringbuffer_t *rb, uint8_t *p, size_t length) {
+size_t ringbuffer_peek(const ringbuffer_t *rb, off_t offset, uint8_t *p, size_t length) {
assert(rb);
assert(p);
+ assert(offset >= 0);
+ assert((size_t)offset <= ringbuffer_size(rb));
- uint8_t *b = rb->head;
- size_t copied = 0;
+ uint8_t *b = ((rb->head - rb->base + offset) % rb->total) + rb->base;
+ const size_t bytes_to_copy = (offset + length > ringbuffer_size(rb)) ? ringbuffer_size(rb) - offset : length;
- while (copied < length && copied < ringbuffer_size(rb)) {
+ for (size_t copied = 0; copied < bytes_to_copy; ++copied) {
*p++ = *b++;
if (b >= (rb->base + rb->total))
b = rb->base;
- ++copied;
}
- return copied;
+ return bytes_to_copy;
}
size_t ringbuffer_pop(ringbuffer_t *rb, uint8_t *p, size_t length) {
assert(rb);
assert(p);
- const size_t copied = ringbuffer_peek(rb, p, length);
+ const size_t copied = ringbuffer_peek(rb, 0, p, length);
rb->head += copied;
if (rb->head >= (rb->base + rb->total))
rb->head -= rb->total;
EXPECT_EQ(6, ringbuffer_available(rb));
uint8_t peek[10] = {0};
- size_t peeked = ringbuffer_peek(rb, peek, 10);
+ size_t peeked = ringbuffer_peek(rb, 0, peek, 10);
EXPECT_EQ(10, ringbuffer_size(rb)); // Ensure size doesn't change
EXPECT_EQ(6, ringbuffer_available(rb));
EXPECT_EQ(10, peeked);
EXPECT_EQ(0, ringbuffer_available(rb));
EXPECT_EQ(5, ringbuffer_size(rb));
- size_t peeked = ringbuffer_peek(rb, peek, 5);
+ size_t peeked = ringbuffer_peek(rb, 0, peek, 5);
EXPECT_EQ(5, peeked);
EXPECT_EQ(0, ringbuffer_available(rb));
EXPECT_EQ(5, ringbuffer_size(rb));
uint8_t content[] = {0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB};
uint8_t peek[16] = {0};
- size_t peeked = ringbuffer_peek(rb, peek, 16);
+ size_t peeked = ringbuffer_peek(rb, 0, peek, 16);
EXPECT_EQ(13, peeked);
ASSERT_TRUE(0 == memcmp(content, peek, peeked));
EXPECT_EQ(14, ringbuffer_size(rb));
uint8_t content2[] = {0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xCC, 0xCC};
- peeked = ringbuffer_peek(rb, peek, 7);
+ peeked = ringbuffer_peek(rb, 0, peek, 7);
EXPECT_EQ(7, peeked);
ASSERT_TRUE(0 == memcmp(content2, peek, peeked));