3 ringbuf
*ringbuf_new(size_t sz
) {
4 ringbuf
*r
= malloc(sizeof(*r
) + sz
);
6 fprintf(stderr
,"out of memory\n");
10 r
->u
= r
->i
= r
->o
= 0;
17 void ringbuf_free(ringbuf
* r
) {
21 /* copy data in. fails if ringbuf has insuff space. */
22 #define MIN(a,b) (((a) < (b)) ? (a) : (b))
23 int ringbuf_put(ringbuf
*r
, const void *_data
, size_t len
) {
24 char *data
= (char*)_data
;
26 if (r
->i
< r
->o
) { // available space is a contiguous buffer
28 assert(a
== r
->n
- r
->u
);
29 if (len
> a
) return -1;
30 memcpy(&r
->d
[r
->i
], data
, len
);
31 } else { // available space wraps; it's two buffers
32 b
= r
->n
- r
->i
; // in-head to eob (receives leading input)
33 c
= r
->o
; // out-head to in-head (receives trailing input)
34 a
= b
+ c
; // available space
35 // the only ambiguous case is i==o, that's why u is needed
36 if (r
->i
== r
->o
) a
= r
->n
- r
->u
;
37 assert(a
== r
->n
- r
->u
);
38 if (len
> a
) return -1;
39 memcpy(&r
->d
[r
->i
], data
, MIN(b
, len
));
40 if (len
> b
) memcpy(r
->d
, &data
[b
], len
-b
);
42 r
->i
= (r
->i
+ len
) % r
->n
;
47 size_t ringbuf_get_pending_size(ringbuf
*r
) {
51 size_t ringbuf_get_next_chunk(ringbuf
*r
, char **data
) {
52 // in this case the next chunk is the whole pending buffer
54 assert(r
->u
== r
->i
- r
->o
);
58 // in this case (i==o) either the buffer is empty of full.
59 // r->u tells distinguishes these cases.
60 if ((r
->o
== r
->i
) && (r
->u
== 0)) { *data
=NULL
; return 0; }
61 // if we're here, that means r->o > r->i. the pending
62 // output is wrapped around the buffer. this function
63 // returns the chunk prior to eob. the next call gets
64 // the next chunk that's wrapped around the buffer.
66 b
= r
->n
- r
->o
; // length of the part we're returning
67 c
= r
->i
; // wrapped part length- a sanity check
68 assert(r
->u
== b
+ c
);
73 void ringbuf_mark_consumed(ringbuf
*r
, size_t len
) {
75 r
->o
= (r
->o
+ len
) % r
->n
;
79 void ringbuf_clear(ringbuf
*r
) {
80 r
->u
= r
->i
= r
->o
= 0;