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