1 /**
2 * @file lv_circle_buf.c
3 *
4 */
5
6 /*********************
7 * INCLUDES
8 *********************/
9
10 #include "lv_assert.h"
11
12 #include "lv_circle_buf.h"
13 #include "lv_array.h"
14
15 /*********************
16 * DEFINES
17 *********************/
18
19 /**********************
20 * TYPEDEFS
21 **********************/
22
23 struct _lv_circle_buf_t {
24 lv_array_t array;
25 uint32_t head;
26 uint32_t tail; /**< The next write position */
27
28 bool inner_alloc; /**< true: the array is allocated by the buffer, false: the array is created from an external buffer */
29 };
30
31 /**********************
32 * STATIC PROTOTYPES
33 **********************/
34
35 static void circle_buf_prepare_empty(lv_circle_buf_t * circle_buf);
36
37 /**********************
38 * GLOBAL VARIABLES
39 **********************/
40
41 /**********************
42 * STATIC VARIABLES
43 **********************/
44
45 /**********************
46 * MACROS
47 **********************/
48
49 /**********************
50 * GLOBAL FUNCTIONS
51 **********************/
52
lv_circle_buf_create(const uint32_t capacity,const uint32_t element_size)53 lv_circle_buf_t * lv_circle_buf_create(const uint32_t capacity, const uint32_t element_size)
54 {
55 lv_circle_buf_t * circle_buf = lv_malloc(sizeof(lv_circle_buf_t));
56 LV_ASSERT_MALLOC(circle_buf);
57
58 if(circle_buf == NULL) {
59 return NULL;
60 }
61
62 lv_array_init(&circle_buf->array, capacity, element_size);
63 circle_buf->head = 0;
64 circle_buf->tail = 0;
65 circle_buf->inner_alloc = true;
66
67 circle_buf_prepare_empty(circle_buf);
68
69 return circle_buf;
70 }
71
lv_circle_buf_create_from_buf(void * buf,const uint32_t capacity,const uint32_t element_size)72 lv_circle_buf_t * lv_circle_buf_create_from_buf(void * buf, const uint32_t capacity, const uint32_t element_size)
73 {
74 LV_ASSERT_NULL(buf);
75
76 lv_circle_buf_t * circle_buf = lv_malloc(sizeof(lv_circle_buf_t));
77 LV_ASSERT_MALLOC(circle_buf);
78
79 if(circle_buf == NULL) {
80 return NULL;
81 }
82
83 lv_array_init_from_buf(&circle_buf->array, buf, capacity, element_size);
84 circle_buf->head = 0;
85 circle_buf->tail = 0;
86 circle_buf->inner_alloc = false;
87
88 circle_buf_prepare_empty(circle_buf);
89
90 return circle_buf;
91 }
92
lv_circle_buf_create_from_array(const lv_array_t * array)93 lv_circle_buf_t * lv_circle_buf_create_from_array(const lv_array_t * array)
94 {
95 LV_ASSERT_NULL(array);
96 if(array == NULL) {
97 return NULL;
98 }
99
100 lv_circle_buf_t * circle_buf = lv_malloc(sizeof(lv_circle_buf_t));
101 LV_ASSERT_MALLOC(circle_buf);
102
103 if(circle_buf == NULL) {
104 return NULL;
105 }
106
107 circle_buf->array = *array;
108 circle_buf->head = 0;
109 circle_buf->tail = 0;
110 circle_buf->inner_alloc = false;
111
112 circle_buf_prepare_empty(circle_buf);
113
114 return circle_buf;
115 }
116
lv_circle_buf_resize(lv_circle_buf_t * circle_buf,const uint32_t capacity)117 lv_result_t lv_circle_buf_resize(lv_circle_buf_t * circle_buf, const uint32_t capacity)
118 {
119 LV_ASSERT_NULL(circle_buf);
120
121 if(lv_array_resize(&circle_buf->array, capacity) == false) {
122 return LV_RESULT_INVALID;
123 }
124
125 circle_buf->head = 0;
126 circle_buf->tail = 0;
127
128 circle_buf_prepare_empty(circle_buf);
129
130 return LV_RESULT_OK;
131 }
132
lv_circle_buf_destroy(lv_circle_buf_t * circle_buf)133 void lv_circle_buf_destroy(lv_circle_buf_t * circle_buf)
134 {
135 LV_ASSERT_NULL(circle_buf);
136
137 lv_array_deinit(&circle_buf->array);
138
139 lv_free(circle_buf);
140 }
141
lv_circle_buf_size(const lv_circle_buf_t * circle_buf)142 uint32_t lv_circle_buf_size(const lv_circle_buf_t * circle_buf)
143 {
144 LV_ASSERT_NULL(circle_buf);
145
146 return circle_buf->tail - circle_buf->head;
147 }
148
lv_circle_buf_capacity(const lv_circle_buf_t * circle_buf)149 uint32_t lv_circle_buf_capacity(const lv_circle_buf_t * circle_buf)
150 {
151 LV_ASSERT_NULL(circle_buf);
152
153 return lv_array_capacity(&circle_buf->array);
154 }
155
lv_circle_buf_remain(const lv_circle_buf_t * circle_buf)156 uint32_t lv_circle_buf_remain(const lv_circle_buf_t * circle_buf)
157 {
158 LV_ASSERT_NULL(circle_buf);
159
160 return lv_circle_buf_capacity(circle_buf) - lv_circle_buf_size(circle_buf);
161 }
162
lv_circle_buf_is_empty(const lv_circle_buf_t * circle_buf)163 bool lv_circle_buf_is_empty(const lv_circle_buf_t * circle_buf)
164 {
165 LV_ASSERT_NULL(circle_buf);
166
167 return !lv_circle_buf_size(circle_buf);
168 }
169
lv_circle_buf_is_full(const lv_circle_buf_t * circle_buf)170 bool lv_circle_buf_is_full(const lv_circle_buf_t * circle_buf)
171 {
172 LV_ASSERT_NULL(circle_buf);
173
174 return !lv_circle_buf_remain(circle_buf);
175 }
176
lv_circle_buf_reset(lv_circle_buf_t * circle_buf)177 void lv_circle_buf_reset(lv_circle_buf_t * circle_buf)
178 {
179 LV_ASSERT_NULL(circle_buf);
180
181 lv_array_clear(&circle_buf->array);
182 circle_buf->head = 0;
183 circle_buf->tail = 0;
184 }
185
lv_circle_buf_head(const lv_circle_buf_t * circle_buf)186 void * lv_circle_buf_head(const lv_circle_buf_t * circle_buf)
187 {
188 LV_ASSERT_NULL(circle_buf);
189
190 return lv_array_at(&circle_buf->array,
191 circle_buf->head % lv_circle_buf_capacity(circle_buf));
192 }
193
lv_circle_buf_tail(const lv_circle_buf_t * circle_buf)194 void * lv_circle_buf_tail(const lv_circle_buf_t * circle_buf)
195 {
196 LV_ASSERT_NULL(circle_buf);
197
198 return lv_array_at(&circle_buf->array,
199 circle_buf->tail % lv_circle_buf_capacity(circle_buf));
200 }
201
lv_circle_buf_read(lv_circle_buf_t * circle_buf,void * data)202 lv_result_t lv_circle_buf_read(lv_circle_buf_t * circle_buf, void * data)
203 {
204 LV_ASSERT_NULL(circle_buf);
205
206 if(lv_circle_buf_is_empty(circle_buf)) {
207 circle_buf->head = 0;
208 circle_buf->tail = 0;
209 return LV_RESULT_INVALID;
210 }
211
212 lv_circle_buf_peek_at(circle_buf, 0, data);
213 circle_buf->head++;
214
215 return LV_RESULT_OK;
216 }
217
lv_circle_buf_write(lv_circle_buf_t * circle_buf,const void * data)218 lv_result_t lv_circle_buf_write(lv_circle_buf_t * circle_buf, const void * data)
219 {
220 LV_ASSERT_NULL(circle_buf);
221
222 if(lv_circle_buf_is_full(circle_buf)) {
223 return LV_RESULT_INVALID;
224 }
225
226 lv_array_assign(&circle_buf->array, circle_buf->tail % lv_circle_buf_capacity(circle_buf), data);
227 circle_buf->tail++;
228
229 return LV_RESULT_OK;
230 }
231
lv_circle_buf_fill(lv_circle_buf_t * circle_buf,uint32_t count,lv_circle_buf_fill_cb_t fill_cb,void * user_data)232 uint32_t lv_circle_buf_fill(lv_circle_buf_t * circle_buf, uint32_t count, lv_circle_buf_fill_cb_t fill_cb,
233 void * user_data)
234 {
235 LV_ASSERT_NULL(circle_buf);
236 LV_ASSERT_NULL(fill_cb);
237
238 uint32_t filled = 0;
239 while(count > 0 && !lv_circle_buf_is_full(circle_buf)) {
240 void * data = lv_circle_buf_tail(circle_buf);
241 if(fill_cb(data, circle_buf->array.element_size, (int32_t)filled, user_data) == LV_RESULT_OK) {
242 circle_buf->tail++;
243 filled++;
244 }
245 else break;
246
247 count--;
248 }
249
250 return filled;
251 }
252
lv_circle_buf_skip(lv_circle_buf_t * circle_buf)253 lv_result_t lv_circle_buf_skip(lv_circle_buf_t * circle_buf)
254 {
255 LV_ASSERT_NULL(circle_buf);
256
257 if(lv_circle_buf_is_empty(circle_buf)) {
258 circle_buf->head = 0;
259 circle_buf->tail = 0;
260 return LV_RESULT_INVALID;
261 }
262
263 circle_buf->head++;
264
265 return LV_RESULT_OK;
266 }
267
lv_circle_buf_peek(const lv_circle_buf_t * circle_buf,void * data)268 lv_result_t lv_circle_buf_peek(const lv_circle_buf_t * circle_buf, void * data)
269 {
270 LV_ASSERT_NULL(circle_buf);
271 LV_ASSERT_NULL(data);
272
273 return lv_circle_buf_peek_at(circle_buf, 0, data);
274 }
275
lv_circle_buf_peek_at(const lv_circle_buf_t * circle_buf,const uint32_t index,void * data)276 lv_result_t lv_circle_buf_peek_at(const lv_circle_buf_t * circle_buf, const uint32_t index, void * data)
277 {
278 LV_ASSERT_NULL(circle_buf);
279 LV_ASSERT_NULL(data);
280
281 const uint32_t real_index = (index % lv_circle_buf_size(circle_buf) + circle_buf->head) % lv_circle_buf_capacity(
282 circle_buf);
283 lv_memcpy(data, lv_array_at(&circle_buf->array, real_index), circle_buf->array.element_size);
284
285 return LV_RESULT_OK;
286 }
287
288 /**********************
289 * STATIC FUNCTIONS
290 **********************/
291
circle_buf_prepare_empty(lv_circle_buf_t * circle_buf)292 static void circle_buf_prepare_empty(lv_circle_buf_t * circle_buf)
293 {
294 const uint32_t required = lv_array_capacity(&circle_buf->array) - lv_array_size(&circle_buf->array);
295 for(uint32_t i = 0; i < required; i++) lv_array_push_back(&circle_buf->array, NULL);
296 }
297