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