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