- Notifications
You must be signed in to change notification settings - Fork 2.1k
/
Copy pathringbuffer.h
164 lines (147 loc) · 5.33 KB
/
ringbuffer.h
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
158
159
160
161
162
163
164
/*
* 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.
*/
#pragma once
/**
* @ingroup core_util
* @{
* @file
* @author Kaspar Schleiser <kaspar@schleiser.de>
* @author René Kijewski <rene.kijewski@fu-berlin.de>
*
* @brief A utility for storing and retrieving byte data using a ring buffer.
*
* @details The ringbuffer is useful for buffering data in the same
* thread context but it is not thread-safe. For a thread-safe ring
* buffer, see @ref sys_tsrb in the System library.
* @}
*/
#ifdef__cplusplus
extern"C" {
#endif
/**
* @brief Ringbuffer.
* @details Non thread-safe FIFO ringbuffer implementation around a `char` array.
*/
typedefstruct {
char*buf; /**< Buffer to operate on. */
unsigned intsize; /**< Size of buf. */
unsigned intstart; /**< Current read position in the ring buffer. */
unsigned intavail; /**< 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.
*/
#defineRINGBUFFER_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)`
*/
staticinlinevoidringbuffer_init(ringbuffer_t*__restrict rb, char*buffer,
unsignedbufsize)
{
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.
*/
intringbuffer_add_one(ringbuffer_t*__restrict rb, charc);
/**
* @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.
*/
unsignedringbuffer_add(ringbuffer_t*__restrict rb, constchar*buf,
unsignedn);
/**
* @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.
*/
intringbuffer_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.
*/
unsignedringbuffer_get(ringbuffer_t*__restrict rb, char*buf, unsignedn);
/**
* @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.
*/
unsignedringbuffer_remove(ringbuffer_t*__restrict rb, unsignedn);
/**
* @brief Test if the ringbuffer is empty.
* @param[in,out] rb Ringbuffer to operate on.
* @returns 0 iff not empty
*/
staticinlineintringbuffer_empty(constringbuffer_t*__restrict rb)
{
returnrb->avail==0;
}
/**
* @brief Test if the ringbuffer is full.
* @param[in,out] rb Ringbuffer to operate on.
* @returns 0 iff not full
*/
staticinlineintringbuffer_full(constringbuffer_t*__restrict rb)
{
returnrb->avail==rb->size;
}
/**
* @brief Return available space in ringbuffer
* @param[in,out] rb Ringbuffer to query.
* @returns number of available bytes
*/
staticinlineunsigned intringbuffer_get_free(
constringbuffer_t*__restrict rb)
{
returnrb->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()
*/
intringbuffer_peek_one(constringbuffer_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()
*/
unsignedringbuffer_peek(constringbuffer_t*__restrict rb, char*buf,
unsignedn);
#ifdef__cplusplus
}
#endif