1 /* $OpenBSD: abuf.c,v 1.32 2024/12/22 14:17:45 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 "abuf.h" 26 #include "utils.h" 27 28 void 29 abuf_init(struct abuf *buf, unsigned int len) 30 { 31 buf->data = xmalloc(len); 32 buf->len = len; 33 buf->used = 0; 34 buf->start = 0; 35 } 36 37 void 38 abuf_done(struct abuf *buf) 39 { 40 #ifdef DEBUG 41 if (buf->used > 0) 42 logx(3, "deleting non-empty buffer, used = %d", buf->used); 43 #endif 44 xfree(buf->data); 45 buf->data = (void *)0xdeadbeef; 46 } 47 48 /* 49 * return the reader pointer and the number of bytes available 50 */ 51 unsigned char * 52 abuf_rgetblk(struct abuf *buf, int *rsize) 53 { 54 int count; 55 56 count = buf->len - buf->start; 57 if (count > buf->used) 58 count = buf->used; 59 *rsize = count; 60 return buf->data + buf->start; 61 } 62 63 /* 64 * discard "count" bytes at the start position. 65 */ 66 void 67 abuf_rdiscard(struct abuf *buf, int count) 68 { 69 #ifdef DEBUG 70 if (count < 0 || count > buf->used) { 71 logx(0, "%s: bad count = %d", __func__, count); 72 panic(); 73 } 74 #endif 75 buf->used -= count; 76 buf->start += count; 77 if (buf->start >= buf->len) 78 buf->start -= buf->len; 79 } 80 81 /* 82 * advance the writer pointer by "count" bytes 83 */ 84 void 85 abuf_wcommit(struct abuf *buf, int count) 86 { 87 #ifdef DEBUG 88 if (count < 0 || count > (buf->len - buf->used)) { 89 logx(0, "%s: bad count = %d", __func__, count); 90 panic(); 91 } 92 #endif 93 buf->used += count; 94 } 95 96 /* 97 * get writer pointer and the number of bytes writable 98 */ 99 unsigned char * 100 abuf_wgetblk(struct abuf *buf, int *rsize) 101 { 102 int end, avail, count; 103 104 end = buf->start + buf->used; 105 if (end >= buf->len) 106 end -= buf->len; 107 avail = buf->len - buf->used; 108 count = buf->len - end; 109 if (count > avail) 110 count = avail; 111 *rsize = count; 112 return buf->data + end; 113 } 114