xref: /openbsd-src/usr.bin/aucat/abuf.c (revision f2da64fbbbf1b03f09f390ab01267c93dfd77c4c)
1 /*	$OpenBSD: abuf.c,v 1.28 2016/01/10 11:06:44 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 #ifdef DEBUG
33 void
34 abuf_log(struct abuf *buf)
35 {
36 	log_putu(buf->start);
37 	log_puts("+");
38 	log_putu(buf->used);
39 	log_puts("/");
40 	log_putu(buf->len);
41 }
42 #endif
43 
44 void
45 abuf_init(struct abuf *buf, unsigned int len)
46 {
47 	buf->data = xmalloc(len);
48 	buf->len = len;
49 	buf->used = 0;
50 	buf->start = 0;
51 }
52 
53 void
54 abuf_done(struct abuf *buf)
55 {
56 #ifdef DEBUG
57 	if (buf->used > 0) {
58 		if (log_level >= 3) {
59 			log_puts("deleting non-empty buffer, used = ");
60 			log_putu(buf->used);
61 			log_puts("\n");
62 		}
63 	}
64 #endif
65 	free(buf->data);
66 	buf->data = (void *)0xdeadbeef;
67 }
68 
69 /*
70  * return the reader pointer and the number of bytes available
71  */
72 unsigned char *
73 abuf_rgetblk(struct abuf *buf, int *rsize)
74 {
75 	int count;
76 
77 	count = buf->len - buf->start;
78 	if (count > buf->used)
79 		count = buf->used;
80 	*rsize = count;
81 	return buf->data + buf->start;
82 }
83 
84 /*
85  * discard "count" bytes at the start postion.
86  */
87 void
88 abuf_rdiscard(struct abuf *buf, int count)
89 {
90 #ifdef DEBUG
91 	if (count < 0 || count > buf->used) {
92 		log_puts("abuf_rdiscard: bad count = ");
93 		log_putu(count);
94 		log_puts("\n");
95 		panic();
96 	}
97 #endif
98 	buf->used -= count;
99 	buf->start += count;
100 	if (buf->start >= buf->len)
101 		buf->start -= buf->len;
102 }
103 
104 /*
105  * advance the writer pointer by "count" bytes
106  */
107 void
108 abuf_wcommit(struct abuf *buf, int count)
109 {
110 #ifdef DEBUG
111 	if (count < 0 || count > (buf->len - buf->used)) {
112 		log_puts("abuf_wcommit: bad count = ");
113 		log_putu(count);
114 		log_puts("\n");
115 		panic();
116 	}
117 #endif
118 	buf->used += count;
119 }
120 
121 /*
122  * get writer pointer and the number of bytes writable
123  */
124 unsigned char *
125 abuf_wgetblk(struct abuf *buf, int *rsize)
126 {
127 	int end, avail, count;
128 
129 	end = buf->start + buf->used;
130 	if (end >= buf->len)
131 		end -= buf->len;
132 	avail = buf->len - buf->used;
133 	count = buf->len - end;
134 	if (count > avail)
135 		count = avail;
136 	*rsize = count;
137 	return buf->data + end;
138 }
139