]>
git.proxmox.com Git - mirror_frr.git/blob - lib/ringbuf.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Circular buffer implementation.
4 * Copyright (C) 2017 Cumulus Networks
12 DEFINE_MTYPE_STATIC(LIB
, RINGBUFFER
, "Ring buffer");
14 struct ringbuf
*ringbuf_new(size_t size
)
16 struct ringbuf
*buf
= XCALLOC(MTYPE_RINGBUFFER
, sizeof(struct ringbuf
));
17 buf
->data
= XCALLOC(MTYPE_RINGBUFFER
, size
);
23 void ringbuf_del(struct ringbuf
*buf
)
25 XFREE(MTYPE_RINGBUFFER
, buf
->data
);
26 XFREE(MTYPE_RINGBUFFER
, buf
);
29 size_t ringbuf_remain(struct ringbuf
*buf
)
31 ssize_t diff
= buf
->end
- buf
->start
;
32 diff
+= ((diff
== 0) && !buf
->empty
) ? buf
->size
: 0;
33 diff
+= (diff
< 0) ? buf
->size
: 0;
37 size_t ringbuf_space(struct ringbuf
*buf
)
39 return buf
->size
- ringbuf_remain(buf
);
42 size_t ringbuf_put(struct ringbuf
*buf
, const void *data
, size_t size
)
44 const uint8_t *dp
= data
;
45 size_t space
= ringbuf_space(buf
);
46 size_t copysize
= MIN(size
, space
);
47 size_t tocopy
= copysize
;
48 if (tocopy
>= buf
->size
- buf
->end
) {
49 size_t ts
= buf
->size
- buf
->end
;
50 memcpy(buf
->data
+ buf
->end
, dp
, ts
);
55 memcpy(buf
->data
+ buf
->end
, dp
, tocopy
);
57 buf
->empty
= (buf
->start
== buf
->end
) && (buf
->empty
&& !copysize
);
61 size_t ringbuf_get(struct ringbuf
*buf
, void *data
, size_t size
)
64 size_t remain
= ringbuf_remain(buf
);
65 size_t copysize
= MIN(remain
, size
);
66 size_t tocopy
= copysize
;
67 if (tocopy
>= buf
->size
- buf
->start
) {
68 size_t ts
= buf
->size
- buf
->start
;
69 memcpy(dp
, buf
->data
+ buf
->start
, ts
);
74 memcpy(dp
, buf
->data
+ buf
->start
, tocopy
);
75 buf
->start
= buf
->start
+ tocopy
;
76 buf
->empty
= (buf
->start
== buf
->end
) && (buf
->empty
|| copysize
);
80 size_t ringbuf_peek(struct ringbuf
*buf
, size_t offset
, void *data
, size_t size
)
83 size_t remain
= ringbuf_remain(buf
);
86 size_t copysize
= MAX(MIN(remain
- offset
, size
), (size_t)0);
87 size_t tocopy
= copysize
;
88 size_t cstart
= (buf
->start
+ offset
) % buf
->size
;
89 if (tocopy
>= buf
->size
- cstart
) {
90 size_t ts
= buf
->size
- cstart
;
91 memcpy(dp
, buf
->data
+ cstart
, ts
);
96 memcpy(dp
, buf
->data
+ cstart
, tocopy
);
100 size_t ringbuf_copy(struct ringbuf
*to
, struct ringbuf
*from
, size_t size
)
102 size_t tocopy
= MIN(ringbuf_space(to
), size
);
103 uint8_t *cbuf
= XCALLOC(MTYPE_TMP
, tocopy
);
104 tocopy
= ringbuf_peek(from
, 0, cbuf
, tocopy
);
105 size_t put
= ringbuf_put(to
, cbuf
, tocopy
);
106 XFREE(MTYPE_TMP
, cbuf
);
110 void ringbuf_reset(struct ringbuf
*buf
)
112 buf
->start
= buf
->end
= 0;
116 void ringbuf_wipe(struct ringbuf
*buf
)
118 memset(buf
->data
, 0x00, buf
->size
);