This removes `amount` number of bytes from the `bufq`.
-## unwrite
-
-It is possible to undo writes by calling:
-
-```
-CURLcode Curl_bufq_unwrite(struct bufq *q, size_t len);
-```
-
-This removes `len` bytes from the end of the bufq again. When removing more
-bytes than are present, CURLE_AGAIN is returned and bufq is cleared.
-
## lifetime
`bufq` is initialized and freed similar to the `dynbuf` module. Code using
}
}
-static size_t chunk_unwrite(struct buf_chunk *chunk, size_t len)
-{
- size_t n = chunk->w_offset - chunk->r_offset;
- DEBUGASSERT(chunk->w_offset >= chunk->r_offset);
- if(!n) {
- return 0;
- }
- else if(n <= len) {
- chunk->r_offset = chunk->w_offset = 0;
- return n;
- }
- else {
- chunk->w_offset -= len;
- return len;
- }
-}
-
static ssize_t chunk_slurpn(struct buf_chunk *chunk, size_t max_len,
Curl_bufq_reader *reader,
void *reader_ctx, CURLcode *err)
}
}
-static struct buf_chunk *chunk_prev(struct buf_chunk *head,
- struct buf_chunk *chunk)
-{
- while(head) {
- if(head == chunk)
- return NULL;
- if(head->next == chunk)
- return head;
- head = head->next;
- }
- return NULL;
-}
-
-static void prune_tail(struct bufq *q)
-{
- struct buf_chunk *chunk;
-
- while(q->tail && chunk_is_empty(q->tail)) {
- chunk = q->tail;
- q->tail = chunk_prev(q->head, chunk);
- if(q->tail)
- q->tail->next = NULL;
- if(q->head == chunk)
- q->head = q->tail;
- if(q->pool) {
- bufcp_put(q->pool, chunk);
- --q->chunk_count;
- }
- else if((q->chunk_count > q->max_chunks) ||
- (q->opts & BUFQ_OPT_NO_SPARES)) {
- /* SOFT_LIMIT allowed us more than max. free spares until
- * we are at max again. Or free them if we are configured
- * to not use spares. */
- free(chunk);
- --q->chunk_count;
- }
- else {
- chunk->next = q->spare;
- q->spare = chunk;
- }
- }
-}
-
static struct buf_chunk *get_non_full_tail(struct bufq *q)
{
struct buf_chunk *chunk;
return result;
}
-CURLcode Curl_bufq_unwrite(struct bufq *q, size_t len)
-{
- while(len && q->tail) {
- len -= chunk_unwrite(q->tail, len);
- prune_tail(q);
- }
- return len ? CURLE_AGAIN : CURLE_OK;
-}
-
ssize_t Curl_bufq_read(struct bufq *q, unsigned char *buf, size_t len,
CURLcode *err)
{
const char *buf, size_t len,
size_t *pnwritten);
-/**
- * Remove `len` bytes from the end of the buffer queue again.
- * Returns CURLE_AGAIN if less than `len` bytes were in the queue.
- */
-CURLcode Curl_bufq_unwrite(struct bufq *q, size_t len);
-
/**
* Read buf from the start of the buffer queue. The buf is copied
* and the amount of copied bytes is returned.
}
fail_unless(nread == nwritten, "did not get the same out as put in");
- /* CHECK bufq_unwrite: write a string repeatedly into the second chunk.
- * bufq_unwrite() 1 byte. Read strings again and check for content.
- * We had a bug that unwrite used the head chunk instead of tail, which
- * did corrupt the read values. */
- if(TRUE) {
- const unsigned char buf[] = "0123456789--";
- size_t roffset;
- Curl_bufq_reset(&q);
- while(Curl_bufq_len(&q) < chunk_size) {
- n = Curl_bufq_write(&q, buf, sizeof(buf), &result);
- fail_unless(n > 0 && (size_t)n == sizeof(buf), "write incomplete");
- if(result)
- break;
- }
- result = Curl_bufq_unwrite(&q, 1);
- roffset = 0;
- while(!Curl_bufq_is_empty(&q)) {
- unsigned char rbuf[sizeof(buf)];
- n = Curl_bufq_read(&q, rbuf, sizeof(rbuf), &result);
- fail_unless(n > 0, "read should work");
- if(result)
- break;
- if(n != sizeof(rbuf)) {
- fail_unless(Curl_bufq_is_empty(&q), "should be last read");
- }
- if(memcmp(buf, rbuf, n)) {
- curl_mfprintf(stderr, "at offset %zu expected '%.*s', got '%.*s'\n",
- roffset, (int)n, buf, (int)n, rbuf);
- fail("read buf content wrong");
- }
- roffset += n;
- }
- Curl_bufq_reset(&q);
- }
-
dump_bufq(&q, "at end of test");
Curl_bufq_free(&q);
if(pool_spares > 0)