ringbuffer.h
5.05 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
/**
* Ringbuffer header
*
* Copyright (C) 2013 Freie Universität Berlin
* Copyright (C) 2013 INRIA
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*
* @ingroup core_util
* @{
* @file
* @author Kaspar Schleiser <kaspar@schleiser.de>
* @author René Kijewski <rene.kijewski@fu-berlin.de>
* @}
*/
#ifndef RINGBUFFER_H
#define RINGBUFFER_H
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Ringbuffer.
* @details Non thread-safe FIFO ringbuffer implementation around a `char` array.
*/
typedef struct {
char *buf; /**< Buffer to operate on. */
unsigned int size; /**< Size of buf. */
unsigned int start; /**< Current read position in the ring buffer. */
unsigned int avail; /**< Number of elements available for reading. */
} ringbuffer_t;
/**
* @def RINGBUFFER_INIT(BUF)
* @brief Initialize a ringbuffer.
* @details This macro is meant for static ringbuffers.
* @param[in] BUF Buffer to use for the ringbuffer. The size is deduced through `sizeof (BUF)`.
* @returns The static initializer.
*/
#define RINGBUFFER_INIT(BUF) { (BUF), sizeof (BUF), 0, 0 }
/**
* @brief Initialize a ringbuffer.
* @param[out] rb Datum to initialize.
* @param[in] buffer Buffer to use by rb.
* @param[in] bufsize `sizeof (buffer)`
*/
static inline void ringbuffer_init(ringbuffer_t *__restrict rb, char *buffer, unsigned bufsize)
{
rb->buf = buffer;
rb->size = bufsize;
rb->start = 0;
rb->avail = 0;
}
/**
* @brief Add an element to the ringbuffer.
* @details If rb is full, then the oldest element gets overwritten.
* Test ringbuffer_full() first if overwriting is not intended.
* @param[in,out] rb Ringbuffer to operate on.
* @param[in] c Element to add.
* @returns The element that was dropped, iff the buffer was full.
* -1 iff the buffer was not full.
*/
int ringbuffer_add_one(ringbuffer_t *__restrict rb, char c);
/**
* @brief Add a number of elements to the ringbuffer.
* @details Only so many elements are added as fit in the ringbuffer.
* No elements get overwritten.
* If this is not the intended behavior, then use ringbuffer_add_one() in a loop instead.
* @param[in,out] rb Ringbuffer to operate on.
* @param[in] buf Buffer to add elements from.
* @param[in] n Maximum number of elements to add.
* @returns Number of elements actually added. 0 if rb is full.
*/
unsigned ringbuffer_add(ringbuffer_t *__restrict rb, const char *buf, unsigned n);
/**
* @brief Peek and remove oldest element from the ringbuffer.
* @param[in,out] rb Ringbuffer to operate on.
* @returns The oldest element that was added, or `-1` if rb is empty.
*/
int ringbuffer_get_one(ringbuffer_t *__restrict rb);
/**
* @brief Read and remove a number of elements from the ringbuffer.
* @param[in,out] rb Ringbuffer to operate on.
* @param[out] buf Buffer to write into.
* @param[in] n Read at most n elements.
* @returns Number of elements actually read.
*/
unsigned ringbuffer_get(ringbuffer_t *__restrict rb, char *buf, unsigned n);
/**
* @brief Remove a number of elements from the ringbuffer.
* @param[in,out] rb Ringbuffer to operate on.
* @param[in] n Read at most n elements.
* @returns Number of elements actually removed.
*/
unsigned ringbuffer_remove(ringbuffer_t *__restrict rb, unsigned n);
/**
* @brief Test if the ringbuffer is empty.
* @param[in,out] rb Ringbuffer to operate on.
* @returns 0 iff not empty
*/
static inline int ringbuffer_empty(const ringbuffer_t *__restrict rb)
{
return rb->avail == 0;
}
/**
* @brief Test if the ringbuffer is full.
* @param[in,out] rb Ringbuffer to operate on.
* @returns 0 iff not full
*/
static inline int ringbuffer_full(const ringbuffer_t *__restrict rb)
{
return rb->avail == rb->size;
}
/**
* @brief Return available space in ringbuffer
* @param[in,out] rb Ringbuffer to query.
* @returns number of available bytes
*/
static inline unsigned int ringbuffer_get_free(const ringbuffer_t *__restrict rb)
{
return rb->size - rb->avail;
}
/**
* @brief Read, but don't remove, the oldest element in the buffer.
* @param[in] rb Ringbuffer to operate on.
* @returns Same as ringbuffer_get_one()
*/
int ringbuffer_peek_one(const ringbuffer_t *__restrict rb);
/**
* @brief Read, but don't remove, the a number of element of the buffer.
* @param[in] rb Ringbuffer to operate on.
* @param[out] buf Buffer to write into.
* @param[in] n Read at most n elements.
* @returns Same as ringbuffer_get()
*/
unsigned ringbuffer_peek(const ringbuffer_t *__restrict rb, char *buf, unsigned n);
#ifdef __cplusplus
}
#endif
#endif /* RINGBUFFER_H */