2 * Copyright (c) 2009-2015, Olivier MATZ <zer0@droids-corp.org>
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the University of California, Berkeley nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
16 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 * Copyright (c) <2010>, Intel Corporation
30 * All rights reserved.
32 * Redistribution and use in source and binary forms, with or without
33 * modification, are permitted provided that the following conditions
36 * - Redistributions of source code must retain the above copyright
37 * notice, this list of conditions and the following disclaimer.
39 * - Redistributions in binary form must reproduce the above copyright
40 * notice, this list of conditions and the following disclaimer in
41 * the documentation and/or other materials provided with the
44 * - Neither the name of Intel Corporation nor the names of its
45 * contributors may be used to endorse or promote products derived
46 * from this software without specific prior written permission.
48 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
49 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
50 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
51 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
52 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
53 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
54 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
55 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
56 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
57 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
58 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
59 * OF THE POSSIBILITY OF SUCH DAMAGE.
65 #include <ucg_cirbuf.h>
67 /* init a circular buffer */
69 ucg_cirbuf_init(struct ucg_cirbuf *cbuf, char *buf, unsigned start,
72 cbuf->maxlen = maxlen;
78 /* return the index of the tail (contains an empty element) */
80 ucg_cirbuf_get_end(const struct ucg_cirbuf *cbuf)
84 end = cbuf->start + cbuf->len;
85 if (end >= cbuf->maxlen)
91 /* multiple add at head */
93 ucg_cirbuf_add_buf_head(struct ucg_cirbuf *cbuf, const char *buf, unsigned n)
99 if (remain == 0 || remain > ucg_cirbuf_get_freelen(cbuf))
102 copy_start = cbuf->start - remain;
104 copy_start += cbuf->maxlen;
105 cbuf->start = copy_start;
108 if ((unsigned)copy_start + copy_len >= cbuf->maxlen)
109 copy_len = cbuf->maxlen - copy_start;
111 memcpy(cbuf->buf + copy_start, buf, copy_len);
119 memcpy(cbuf->buf, buf, copy_len);
124 /* multiple add at tail */
126 ucg_cirbuf_add_buf_tail(struct ucg_cirbuf *cbuf, const char *buf, unsigned n)
129 unsigned copy_start, copy_len;
131 if (remain == 0 || remain > ucg_cirbuf_get_freelen(cbuf))
134 copy_start = ucg_cirbuf_get_end(cbuf);
137 if (copy_start + copy_len >= cbuf->maxlen)
138 copy_len = cbuf->maxlen - copy_start;
140 memcpy(cbuf->buf + copy_start, buf, copy_len);
148 memcpy(cbuf->buf, buf, copy_len);
153 /* single add at head */
155 __cirbuf_add_head(struct ucg_cirbuf *cbuf, char c)
157 unsigned start = cbuf->start;
160 start = cbuf->maxlen - 1;
163 cbuf->buf[start] = c;
168 /* single add at head, checking if full first */
170 ucg_cirbuf_add_head_safe(struct ucg_cirbuf *cbuf, char c)
172 if (!ucg_cirbuf_is_full(cbuf)) {
173 __cirbuf_add_head(cbuf, c);
179 /* single add at head */
181 ucg_cirbuf_add_head(struct ucg_cirbuf *cbuf, char c)
183 __cirbuf_add_head(cbuf, c);
186 /* single add at tail */
188 __cirbuf_add_tail(struct ucg_cirbuf *cbuf, char c)
190 unsigned end = ucg_cirbuf_get_end(cbuf);
196 /* single add at tail, checking if full first */
198 ucg_cirbuf_add_tail_safe(struct ucg_cirbuf *cbuf, char c)
200 if (!ucg_cirbuf_is_full(cbuf)) {
201 __cirbuf_add_tail(cbuf, c);
207 /* single add at tail */
209 ucg_cirbuf_add_tail(struct ucg_cirbuf *cbuf, char c)
211 __cirbuf_add_tail(cbuf, c);
214 /* multiple delete at head */
216 ucg_cirbuf_del_buf_head(struct ucg_cirbuf *cbuf, unsigned size)
218 if (size == 0 || size > ucg_cirbuf_get_len(cbuf))
222 if (ucg_cirbuf_is_empty(cbuf)) {
223 cbuf->start += size - 1;
224 cbuf->start %= cbuf->maxlen;
228 cbuf->start %= cbuf->maxlen;
233 /* multiple delete at tail */
235 ucg_cirbuf_del_buf_tail(struct ucg_cirbuf *cbuf, unsigned size)
237 if (size == 0 || size > ucg_cirbuf_get_len(cbuf))
244 /* single del at head */
246 __cirbuf_del_head(struct ucg_cirbuf *cbuf)
249 if (!ucg_cirbuf_is_empty(cbuf)) {
251 cbuf->start %= cbuf->maxlen;
255 /* single del at head, checking if empty first */
257 ucg_cirbuf_del_head_safe(struct ucg_cirbuf *cbuf)
259 if (cbuf && !ucg_cirbuf_is_empty(cbuf)) {
260 __cirbuf_del_head(cbuf);
266 /* single del at head */
268 ucg_cirbuf_del_head(struct ucg_cirbuf *cbuf)
270 __cirbuf_del_head(cbuf);
273 /* single del at tail */
275 __cirbuf_del_tail(struct ucg_cirbuf *cbuf)
280 /* single del at tail, checking if empty first */
282 ucg_cirbuf_del_tail_safe(struct ucg_cirbuf *cbuf)
284 if (cbuf && !ucg_cirbuf_is_empty(cbuf)) {
285 __cirbuf_del_tail(cbuf);
291 /* single del at tail */
293 ucg_cirbuf_del_tail(struct ucg_cirbuf *cbuf)
295 __cirbuf_del_tail(cbuf);
298 /* convert to buffer */
300 ucg_cirbuf_get_buf_head(const struct ucg_cirbuf *cbuf, char *buf, unsigned n)
303 unsigned cirbuf_len, copy_start, copy_len;
305 cirbuf_len = ucg_cirbuf_get_len(cbuf);
306 if (remain >= cirbuf_len)
312 copy_start = cbuf->start;
314 if (copy_start + copy_len >= cbuf->maxlen)
315 copy_len = cbuf->maxlen - copy_start;
317 memcpy(buf, cbuf->buf + copy_start, copy_len);
325 memcpy(buf, cbuf->buf, copy_len);
330 /* convert to buffer */
332 ucg_cirbuf_get_buf_tail(const struct ucg_cirbuf *cbuf, char *buf, unsigned n)
336 unsigned cirbuf_len, copy_len;
338 cirbuf_len = ucg_cirbuf_get_len(cbuf);
339 if (remain >= cirbuf_len)
345 copy_start = ucg_cirbuf_get_end(cbuf) - remain;
347 copy_start += cbuf->maxlen;
349 if ((unsigned)copy_start + copy_len >= cbuf->maxlen)
350 copy_len = cbuf->maxlen - copy_start;
352 memcpy(buf, cbuf->buf + copy_start, copy_len);
360 memcpy(buf, cbuf->buf, copy_len);
367 ucg_cirbuf_get_head(const struct ucg_cirbuf *cbuf)
369 return cbuf->buf[cbuf->start];
374 ucg_cirbuf_get_tail(const struct ucg_cirbuf *cbuf)
378 /* should not happen */
382 end = cbuf->start + cbuf->len - 1;
383 if (end >= cbuf->maxlen)
385 return cbuf->buf[end];
389 __ucg_cirbuf_shift(struct ucg_cirbuf *cbuf, unsigned n)
392 unsigned start, cur, min;
401 if (cur >= cbuf->maxlen)
403 tmp2 = cbuf->buf[cur];
404 cbuf->buf[cur] = tmp;
407 if ((cur + 1) == min)
410 tmp = cbuf->buf[cur];
412 } else if (cur < min) {
418 if (cbuf->start >= cbuf->maxlen)
419 cbuf->start -= cbuf->maxlen;
422 void ucg_cirbuf_align_left(struct ucg_cirbuf *cbuf)
424 __ucg_cirbuf_shift(cbuf, cbuf->maxlen - cbuf->start);
427 void ucg_cirbuf_align_right(struct ucg_cirbuf *cbuf)
429 unsigned end = ucg_cirbuf_get_end(cbuf);
430 __ucg_cirbuf_shift(cbuf, cbuf->maxlen - end);
437 void dump_it(struct ucg_cirbuf * cbuf)
443 printf("sta=%2.2d len=%2.2d/%2.2d { ",
445 ucg_cirbuf_get_len(cbuf),
446 ucg_cirbuf_get_maxlen(cbuf));
448 for (i = 0; i < ucg_cirbuf_get_maxlen(cbuf); i++) {
449 idx = i - cbuf->start;
452 if (idx < (int)ucg_cirbuf_get_len(cbuf))
453 printf("%2.2x, ", cbuf->buf[i] & 0xFF);
460 UCG_CIRBUF_FOREACH(cbuf, i, e) {
461 printf("%2.2x, ", e & 0xFF);
469 struct ucg_cirbuf my_fifo;
472 char buf1[] = { 0x10, 0x11, 0x12 };
473 char buf2[] = { 0x20, 0x21, 0x22, 0x23 };
476 char ref_buf[] = { 0x20, 0x21, 0x22, 0x23, 0x01, 0x10, 0x11, 0x12 };
482 ucg_cirbuf_init(&my_fifo, fifo_buf, 0, 4);
483 assert(ucg_cirbuf_is_empty(&my_fifo));
484 assert(!ucg_cirbuf_is_full(&my_fifo));
487 ucg_cirbuf_add_tail(&my_fifo, 1);
488 assert(ucg_cirbuf_get_head(&my_fifo) == 1);
489 assert(ucg_cirbuf_get_tail(&my_fifo) == 1);
493 ucg_cirbuf_add_tail(&my_fifo, 2);
494 assert(!ucg_cirbuf_is_empty(&my_fifo));
495 assert(!ucg_cirbuf_is_full(&my_fifo));
498 ucg_cirbuf_add_tail(&my_fifo, 3);
499 assert(ucg_cirbuf_get_head(&my_fifo) == 1);
500 assert(ucg_cirbuf_get_tail(&my_fifo) == 3);
503 ucg_cirbuf_add_tail(&my_fifo, 4);
504 assert(!ucg_cirbuf_is_empty(&my_fifo));
505 assert(ucg_cirbuf_is_full(&my_fifo));
508 ucg_cirbuf_del_tail(&my_fifo);
510 assert(ucg_cirbuf_get_tail(&my_fifo) == 3);
511 assert(ucg_cirbuf_get_head(&my_fifo) == 1);
513 ucg_cirbuf_del_head(&my_fifo);
514 assert(ucg_cirbuf_get_tail(&my_fifo) == 3);
515 assert(ucg_cirbuf_get_head(&my_fifo) == 2);
518 ucg_cirbuf_del_head(&my_fifo);
519 assert(ucg_cirbuf_get_tail(&my_fifo) == 3);
520 assert(ucg_cirbuf_get_head(&my_fifo) == 3);
523 ucg_cirbuf_del_head(&my_fifo);
524 assert(ucg_cirbuf_is_empty(&my_fifo));
532 ucg_cirbuf_init(&my_fifo, fifo_buf, 2, 4);
535 ucg_cirbuf_add_head(&my_fifo, 4);
536 assert(ucg_cirbuf_get_head(&my_fifo) == 4);
537 assert(ucg_cirbuf_get_tail(&my_fifo) == 4);
541 ucg_cirbuf_add_head(&my_fifo, 3);
542 assert(!ucg_cirbuf_is_empty(&my_fifo));
543 assert(!ucg_cirbuf_is_full(&my_fifo));
546 ucg_cirbuf_add_head(&my_fifo, 2);
547 assert(ucg_cirbuf_get_head(&my_fifo) == 2);
548 assert(ucg_cirbuf_get_tail(&my_fifo) == 4);
551 ucg_cirbuf_add_head(&my_fifo, 1);
552 assert(!ucg_cirbuf_is_empty(&my_fifo));
553 assert(ucg_cirbuf_is_full(&my_fifo));
561 for (i = 0; i < 16; i++) {
562 ucg_cirbuf_init(&my_fifo, fifo_buf, i, 16);
564 ucg_cirbuf_add_buf_head(&my_fifo, buf1, sizeof(buf1));
566 ucg_cirbuf_add_head(&my_fifo, 1);
568 ucg_cirbuf_add_buf_head(&my_fifo, buf2, sizeof(buf2));
570 ucg_cirbuf_get_buf_head(&my_fifo, tmp_buf, sizeof(tmp_buf));
571 assert(memcmp(tmp_buf, ref_buf, sizeof(ref_buf)) == 0);
578 for (i = 0; i < 16; i++) {
579 ucg_cirbuf_init(&my_fifo, fifo_buf, i, 16);
581 ucg_cirbuf_add_buf_tail(&my_fifo, buf2, sizeof(buf2));
583 ucg_cirbuf_add_tail(&my_fifo, 1);
585 ucg_cirbuf_add_buf_tail(&my_fifo, buf1, sizeof(buf1));
587 ucg_cirbuf_get_buf_tail(&my_fifo, tmp_buf, sizeof(tmp_buf));
588 assert(memcmp(tmp_buf, ref_buf, sizeof(ref_buf)) == 0);
590 printf("align left\n");
591 ucg_cirbuf_align_left(&my_fifo);
593 ucg_cirbuf_get_buf_tail(&my_fifo, tmp_buf, sizeof(tmp_buf));
594 assert(memcmp(tmp_buf, ref_buf, sizeof(ref_buf)) == 0);
595 assert(my_fifo.start == 0);
597 printf("align right\n");
598 ucg_cirbuf_align_right(&my_fifo);
600 ucg_cirbuf_get_buf_tail(&my_fifo, tmp_buf, sizeof(tmp_buf));
601 assert(memcmp(tmp_buf, ref_buf, sizeof(ref_buf)) == 0);
602 assert(my_fifo.start + my_fifo.len == my_fifo.maxlen);
609 ucg_cirbuf_init(&my_fifo, fifo_buf, 10, 16);
612 while (ucg_cirbuf_add_tail_safe(&my_fifo, i) == 0)
615 ucg_cirbuf_del_buf_tail(&my_fifo, 10);
617 assert(ucg_cirbuf_get_len(&my_fifo) == 6);
618 assert(ucg_cirbuf_del_buf_tail(&my_fifo, 10) != 0);
619 assert(ucg_cirbuf_get_tail(&my_fifo) == 5);
620 assert(ucg_cirbuf_get_head(&my_fifo) == 0);