Semi-decennial update. 50% code inflation.
[cbaos.git] / lib / circ_buf.c
blobc27a4cbefaed21bd3b938af6e56dec97c2dd5b5b
1 /* Author: Domen Puncer <domen@cba.si>. License: WTFPL, see file LICENSE */
2 #include <circ_buf.h>
3 #include <string.h>
4 #include <errno.h>
6 void circ_buf_init(struct circ_buf *cb, u8 *buf, unsigned size)
8 cb->data = buf;
9 cb->size = size;
10 cb->head = cb->tail = 0;
13 unsigned circ_buf_len(struct circ_buf *cb)
15 unsigned tmp;
16 tmp = cb->size + cb->head - cb->tail;
17 if (tmp >= cb->size)
18 tmp -= cb->size;
19 return tmp;
22 unsigned circ_buf_free(struct circ_buf *cb)
24 unsigned tmp;
25 tmp = cb->size + cb->tail - cb->head - 1;
26 if (tmp >= cb->size)
27 tmp -= cb->size;
28 return tmp;
31 __inline static void memcpy_(u8 *dest, const u8 *src, int len)
33 while (len-- > 0)
34 *dest++ = *src++;
37 unsigned circ_buf_put(struct circ_buf *cb, const u8 *data, unsigned len)
39 unsigned size;
40 unsigned len_til_end;
42 size = circ_buf_free(cb);
43 if (size == 0)
44 return -EAGAIN;
46 if (len > size)
47 len = size;
49 len_til_end = cb->size - cb->head;
50 if (len_til_end > len)
51 len_til_end = len;
53 memcpy_(cb->data+cb->head, data, len_til_end);
54 memcpy_(cb->data, data+len_til_end, len-len_til_end);
56 cb->head += len;
57 if (cb->head >= cb->size)
58 cb->head -= cb->size;
59 return len;
62 unsigned circ_buf_get(struct circ_buf *cb, u8 *data, unsigned len)
64 unsigned size;
65 unsigned len_til_end;
67 size = circ_buf_len(cb);
68 if (size == 0)
69 return -EAGAIN;
71 if (len > size)
72 len = size;
74 len_til_end = cb->size - cb->tail;
75 if (len_til_end > len)
76 len_til_end = len;
78 memcpy_(data, cb->data+cb->tail, len_til_end);
79 memcpy_(data+len_til_end, cb->data, len-len_til_end);
81 cb->tail += len;
82 if (cb->tail >= cb->size)
83 cb->tail -= cb->size;
84 return len;
87 /* for convenience */
88 int circ_buf_put_one(struct circ_buf *cb, u8 data)
90 if (circ_buf_free(cb) == 0)
91 return -EAGAIN;
93 cb->data[cb->head++] = data;
94 if (cb->head >= cb->size)
95 cb->head -= cb->size;
96 return 0;
99 int circ_buf_get_one(struct circ_buf *cb)
101 u8 data;
102 if (circ_buf_len(cb) == 0)
103 return -EAGAIN;
105 data = cb->data[cb->tail++];
106 if (cb->tail >= cb->size)
107 cb->tail -= cb->size;
108 return data;