1*7b639200Sratchov /* $OpenBSD: abuf.c,v 1.6 2024/12/20 07:35:56 ratchov Exp $ */ 287bc9f6aSratchov /* 387bc9f6aSratchov * Copyright (c) 2008-2012 Alexandre Ratchov <alex@caoua.org> 487bc9f6aSratchov * 587bc9f6aSratchov * Permission to use, copy, modify, and distribute this software for any 687bc9f6aSratchov * purpose with or without fee is hereby granted, provided that the above 787bc9f6aSratchov * copyright notice and this permission notice appear in all copies. 887bc9f6aSratchov * 987bc9f6aSratchov * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 1087bc9f6aSratchov * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 1187bc9f6aSratchov * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 1287bc9f6aSratchov * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 1387bc9f6aSratchov * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 1487bc9f6aSratchov * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 1587bc9f6aSratchov * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 1687bc9f6aSratchov */ 1787bc9f6aSratchov /* 1887bc9f6aSratchov * Simple byte fifo. 1987bc9f6aSratchov * 2087bc9f6aSratchov * The abuf data is split in two parts: (1) valid data available to the reader 2187bc9f6aSratchov * (2) space available to the writer, which is not necessarily unused. It works 2287bc9f6aSratchov * as follows: the write starts filling at offset (start + used), once the data 2387bc9f6aSratchov * is ready, the writer adds to used the count of bytes available. 2487bc9f6aSratchov */ 2587bc9f6aSratchov #include <stdio.h> 2687bc9f6aSratchov #include <stdlib.h> 2787bc9f6aSratchov #include <string.h> 2887bc9f6aSratchov 2987bc9f6aSratchov #include "abuf.h" 3087bc9f6aSratchov #include "utils.h" 3187bc9f6aSratchov 3287bc9f6aSratchov void 3387bc9f6aSratchov abuf_init(struct abuf *buf, unsigned int len) 3487bc9f6aSratchov { 3587bc9f6aSratchov buf->data = xmalloc(len); 3687bc9f6aSratchov buf->len = len; 3787bc9f6aSratchov buf->used = 0; 3887bc9f6aSratchov buf->start = 0; 3987bc9f6aSratchov } 4087bc9f6aSratchov 4187bc9f6aSratchov void 4287bc9f6aSratchov abuf_done(struct abuf *buf) 4387bc9f6aSratchov { 4487bc9f6aSratchov #ifdef DEBUG 45*7b639200Sratchov if (buf->used > 0) 46*7b639200Sratchov logx(3, "deleting non-empty buffer, used = %d", buf->used); 4787bc9f6aSratchov #endif 4887bc9f6aSratchov xfree(buf->data); 4987bc9f6aSratchov buf->data = (void *)0xdeadbeef; 5087bc9f6aSratchov } 5187bc9f6aSratchov 5287bc9f6aSratchov /* 5387bc9f6aSratchov * return the reader pointer and the number of bytes available 5487bc9f6aSratchov */ 5587bc9f6aSratchov unsigned char * 5687bc9f6aSratchov abuf_rgetblk(struct abuf *buf, int *rsize) 5787bc9f6aSratchov { 5838b693edSratchov int count; 5987bc9f6aSratchov 6087bc9f6aSratchov count = buf->len - buf->start; 6187bc9f6aSratchov if (count > buf->used) 6287bc9f6aSratchov count = buf->used; 6387bc9f6aSratchov *rsize = count; 6487bc9f6aSratchov return buf->data + buf->start; 6587bc9f6aSratchov } 6687bc9f6aSratchov 6787bc9f6aSratchov /* 68d9a51c35Sjmc * discard "count" bytes at the start position. 6987bc9f6aSratchov */ 7087bc9f6aSratchov void 7187bc9f6aSratchov abuf_rdiscard(struct abuf *buf, int count) 7287bc9f6aSratchov { 7387bc9f6aSratchov #ifdef DEBUG 7487bc9f6aSratchov if (count < 0 || count > buf->used) { 75*7b639200Sratchov logx(0, "%s: bad count = %d", __func__, count); 7687bc9f6aSratchov panic(); 7787bc9f6aSratchov } 7887bc9f6aSratchov #endif 7987bc9f6aSratchov buf->used -= count; 8087bc9f6aSratchov buf->start += count; 8187bc9f6aSratchov if (buf->start >= buf->len) 8287bc9f6aSratchov buf->start -= buf->len; 8387bc9f6aSratchov } 8487bc9f6aSratchov 8587bc9f6aSratchov /* 8687bc9f6aSratchov * advance the writer pointer by "count" bytes 8787bc9f6aSratchov */ 8887bc9f6aSratchov void 8987bc9f6aSratchov abuf_wcommit(struct abuf *buf, int count) 9087bc9f6aSratchov { 9187bc9f6aSratchov #ifdef DEBUG 9287bc9f6aSratchov if (count < 0 || count > (buf->len - buf->used)) { 93*7b639200Sratchov logx(0, "%s: bad count = %d", __func__, count); 9487bc9f6aSratchov panic(); 9587bc9f6aSratchov } 9687bc9f6aSratchov #endif 9787bc9f6aSratchov buf->used += count; 9887bc9f6aSratchov } 9987bc9f6aSratchov 10087bc9f6aSratchov /* 10187bc9f6aSratchov * get writer pointer and the number of bytes writable 10287bc9f6aSratchov */ 10387bc9f6aSratchov unsigned char * 10487bc9f6aSratchov abuf_wgetblk(struct abuf *buf, int *rsize) 10587bc9f6aSratchov { 10687bc9f6aSratchov int end, avail, count; 10787bc9f6aSratchov 10887bc9f6aSratchov end = buf->start + buf->used; 10987bc9f6aSratchov if (end >= buf->len) 11087bc9f6aSratchov end -= buf->len; 11187bc9f6aSratchov avail = buf->len - buf->used; 11287bc9f6aSratchov count = buf->len - end; 11387bc9f6aSratchov if (count > avail) 11487bc9f6aSratchov count = avail; 11587bc9f6aSratchov *rsize = count; 11687bc9f6aSratchov return buf->data + end; 11787bc9f6aSratchov } 118