xref: /openbsd-src/usr.bin/sndiod/abuf.c (revision 7b6392009e6e5a7f8e494c162a4d259ea5e13a62)
1 /*	$OpenBSD: abuf.c,v 1.6 2024/12/20 07:35:56 ratchov Exp $	*/
2 /*
3  * Copyright (c) 2008-2012 Alexandre Ratchov <alex@caoua.org>
4  *
5  * Permission to use, copy, modify, and distribute this software for any
6  * purpose with or without fee is hereby granted, provided that the above
7  * copyright notice and this permission notice appear in all copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16  */
17 /*
18  * Simple byte fifo.
19  *
20  * The abuf data is split in two parts: (1) valid data available to the reader
21  * (2) space available to the writer, which is not necessarily unused. It works
22  * as follows: the write starts filling at offset (start + used), once the data
23  * is ready, the writer adds to used the count of bytes available.
24  */
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 
29 #include "abuf.h"
30 #include "utils.h"
31 
32 void
33 abuf_init(struct abuf *buf, unsigned int len)
34 {
35 	buf->data = xmalloc(len);
36 	buf->len = len;
37 	buf->used = 0;
38 	buf->start = 0;
39 }
40 
41 void
42 abuf_done(struct abuf *buf)
43 {
44 #ifdef DEBUG
45 	if (buf->used > 0)
46 		logx(3, "deleting non-empty buffer, used = %d", buf->used);
47 #endif
48 	xfree(buf->data);
49 	buf->data = (void *)0xdeadbeef;
50 }
51 
52 /*
53  * return the reader pointer and the number of bytes available
54  */
55 unsigned char *
56 abuf_rgetblk(struct abuf *buf, int *rsize)
57 {
58 	int count;
59 
60 	count = buf->len - buf->start;
61 	if (count > buf->used)
62 		count = buf->used;
63 	*rsize = count;
64 	return buf->data + buf->start;
65 }
66 
67 /*
68  * discard "count" bytes at the start position.
69  */
70 void
71 abuf_rdiscard(struct abuf *buf, int count)
72 {
73 #ifdef DEBUG
74 	if (count < 0 || count > buf->used) {
75 		logx(0, "%s: bad count = %d", __func__, count);
76 		panic();
77 	}
78 #endif
79 	buf->used -= count;
80 	buf->start += count;
81 	if (buf->start >= buf->len)
82 		buf->start -= buf->len;
83 }
84 
85 /*
86  * advance the writer pointer by "count" bytes
87  */
88 void
89 abuf_wcommit(struct abuf *buf, int count)
90 {
91 #ifdef DEBUG
92 	if (count < 0 || count > (buf->len - buf->used)) {
93 		logx(0, "%s: bad count = %d", __func__, count);
94 		panic();
95 	}
96 #endif
97 	buf->used += count;
98 }
99 
100 /*
101  * get writer pointer and the number of bytes writable
102  */
103 unsigned char *
104 abuf_wgetblk(struct abuf *buf, int *rsize)
105 {
106 	int end, avail, count;
107 
108 	end = buf->start + buf->used;
109 	if (end >= buf->len)
110 		end -= buf->len;
111 	avail = buf->len - buf->used;
112 	count = buf->len - end;
113 	if (count > avail)
114 		count = avail;
115 	*rsize = count;
116 	return buf->data + end;
117 }
118