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