ring_buf
Loading...
Searching...
No Matches
ring_buf.c
Go to the documentation of this file.
1/*
2 * SPDX-License-Identifier: MIT
3 * SPDX-FileCopyrightText: 2024, Roy Ratcliffe, Northumberland, United Kingdom
4 */
34#include "ring_buf.h"
35
36#include <string.h>
37
45static inline void ring_buf_clamp(ring_buf_size_t *clamp,
46 ring_buf_size_t limit) {
47 if (*clamp > limit)
48 *clamp = limit;
49}
50
58static inline ring_buf_size_t
59ring_buf_zone_head(const struct ring_buf_zone *zone) {
60 return zone->head - zone->base;
61}
62
68static inline ring_buf_size_t
69ring_buf_zone_tail(const struct ring_buf_zone *zone) {
70 return zone->tail - zone->base;
71}
72
79static inline ring_buf_size_t
81 return zone->head - zone->tail;
82}
83
91static inline void ring_buf_zone_reset(struct ring_buf_zone *zone,
92 ring_buf_ptrdiff_t base) {
93 zone->base = zone->head = zone->tail = base;
94}
95
97 ring_buf_zone_reset(&buf->put, base);
98 ring_buf_zone_reset(&buf->get, base);
99}
100
102 ring_buf_size_t size) {
103 ring_buf_ptrdiff_t base = buf->put.base;
105 if (head >= buf->size) {
106 base += buf->size;
107 head -= buf->size;
108 }
109 ring_buf_clamp(&size, buf->size - head);
111 if (space)
112 *space = (uint8_t *)buf->space + (buf->put.head - base);
113 buf->put.head += size;
114 return size;
115}
116
119 if (size > claim)
120 return -EINVAL;
121 buf->put.head = (buf->put.tail += size);
122 if (ring_buf_zone_tail(&buf->put) >= buf->size)
123 buf->put.base += buf->size;
124 return 0;
125}
126
128 ring_buf_size_t size) {
129 ring_buf_ptrdiff_t base = buf->get.base;
131 if (head >= buf->size) {
132 base += buf->size;
133 head -= buf->size;
134 }
135 ring_buf_clamp(&size, buf->size - head);
137 if (space)
138 *space = (uint8_t *)buf->space + (buf->get.head - base);
139 buf->get.head += size;
140 return size;
141}
142
145 if (size > claim)
146 return -EINVAL;
147 buf->get.head = (buf->get.tail += size);
148 if (ring_buf_zone_tail(&buf->get) >= buf->size)
149 buf->get.base += buf->size;
150 return 0;
151}
152
153ring_buf_size_t ring_buf_put(struct ring_buf *buf, const void *data,
154 ring_buf_size_t size) {
155 ring_buf_size_t ack = 0U, claim;
156 do {
157 void *space;
158 claim = ring_buf_put_claim(buf, &space, size);
159 (void)memcpy(space, data, claim);
160 *(const uint8_t **)&data += claim;
161 ack += claim;
162 } while (claim && (size -= claim));
163 return ack;
164}
165
166ring_buf_size_t ring_buf_get(struct ring_buf *buf, void *data,
167 ring_buf_size_t size) {
168 ring_buf_size_t ack = 0U, claim;
169 do {
170 void *space;
171 claim = ring_buf_get_claim(buf, &space, size);
172 if (data) {
173 (void)memcpy(data, space, claim);
174 *(uint8_t **)&data += claim;
175 }
176 ack += claim;
177 } while (claim && (size -= claim));
178 return ack;
179}
180
181int ring_buf_put_all(struct ring_buf *buf, const void *data,
182 ring_buf_size_t size) {
183 ring_buf_size_t ack = ring_buf_put(buf, data, size);
184 int err = ack < size ? -EMSGSIZE : 0;
185 if (err < 0)
186 ack = 0U;
187 (void)ring_buf_put_ack(buf, ack);
188 return err;
189}
190
191int ring_buf_get_all(struct ring_buf *buf, void *data, ring_buf_size_t size) {
192 ring_buf_size_t ack = ring_buf_get(buf, data, size);
193 int err = ack < size ? -EAGAIN : 0;
194 if (err < 0)
195 ack = 0U;
196 (void)ring_buf_get_ack(buf, ack);
197 return err;
198}
int ring_buf_put_ack(struct ring_buf *buf, ring_buf_size_t size)
Acknowledges space claimed for putting data into a ring buffer.
Definition ring_buf.c:117
int ring_buf_get_ack(struct ring_buf *buf, ring_buf_size_t size)
Acknowledges space claimed for getting data from a ring buffer.
Definition ring_buf.c:143
ring_buf_size_t ring_buf_get_claim(struct ring_buf *buf, void **space, ring_buf_size_t size)
Claims contiguous space for getting.
Definition ring_buf.c:127
ring_buf_size_t ring_buf_put_claim(struct ring_buf *buf, void **space, ring_buf_size_t size)
Claims space for putting data into a ring buffer.
Definition ring_buf.c:101
ring_buf_size_t ring_buf_get(struct ring_buf *buf, void *data, ring_buf_size_t size)
Gets data from a ring buffer.
Definition ring_buf.c:166
int ring_buf_put_all(struct ring_buf *buf, const void *data, ring_buf_size_t size)
Puts all or none.
Definition ring_buf.c:181
ring_buf_size_t ring_buf_put(struct ring_buf *buf, const void *data, ring_buf_size_t size)
Puts non-contiguous bytes into the ring buffer.
Definition ring_buf.c:153
int ring_buf_get_all(struct ring_buf *buf, void *data, ring_buf_size_t size)
Gets all or none.
Definition ring_buf.c:191
void ring_buf_reset(struct ring_buf *buf, ring_buf_ptrdiff_t base)
Resets a ring buffer.
Definition ring_buf.c:96
static ring_buf_size_t ring_buf_free_space(const struct ring_buf *buf)
Calculates free space in the ring buffer.
Definition ring_buf.h:183
static ring_buf_size_t ring_buf_used_space(const struct ring_buf *buf)
Calculates used space in the ring buffer.
Definition ring_buf.h:160
static void ring_buf_clamp(ring_buf_size_t *clamp, ring_buf_size_t limit)
Clamp a value to a specified limit.
Definition ring_buf.c:45
static ring_buf_size_t ring_buf_zone_tail(const struct ring_buf_zone *zone)
Tail index of a zone.
Definition ring_buf.c:69
static ring_buf_size_t ring_buf_zone_claim(const struct ring_buf_zone *zone)
Claim size of a zone.
Definition ring_buf.c:80
static ring_buf_size_t ring_buf_zone_head(const struct ring_buf_zone *zone)
Head index of a zone.
Definition ring_buf.c:59
static void ring_buf_zone_reset(struct ring_buf_zone *zone, ring_buf_ptrdiff_t base)
Resets a ring buffer zone.
Definition ring_buf.c:91
Ring buffer function prototypes.
size_t ring_buf_size_t
Ring buffer size type.
Definition ring_buf.h:64
ptrdiff_t ring_buf_ptrdiff_t
Ring buffer pointer difference type.
Definition ring_buf.h:58
#define EMSGSIZE
Message size error code.
Definition ring_buf.h:51
Ring buffer zone.
Definition ring_buf.h:93
ring_buf_ptrdiff_t tail
Tail index of the zone.
Definition ring_buf.h:110
ring_buf_ptrdiff_t head
Head index of the zone.
Definition ring_buf.h:104
ring_buf_ptrdiff_t base
Base index of the zone.
Definition ring_buf.h:98
Ring buffer instance.
Definition ring_buf.h:128
ring_buf_size_t size
Size of the ring buffer.
Definition ring_buf.h:139
void * space
Pointer to the buffer's data space.
Definition ring_buf.h:133
struct ring_buf_zone get
Get zone.
Definition ring_buf.h:151
struct ring_buf_zone put
Put zone.
Definition ring_buf.h:145