1/*- 2 * Copyright (c) 2005 Max Okumoto 3 * Copyright (c) 1988, 1989, 1990, 1993 4 * The Regents of the University of California. All rights reserved. 5 * Copyright (c) 1988, 1989 by Adam de Boor 6 * Copyright (c) 1989 by Berkeley Softworks 7 * All rights reserved. 8 * 9 * This code is derived from software contributed to Berkeley by 10 * Adam de Boor. 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions 14 * are met: 15 * 1. Redistributions of source code must retain the above copyright 16 * notice, this list of conditions and the following disclaimer. 17 * 2. Redistributions in binary form must reproduce the above copyright 18 * notice, this list of conditions and the following disclaimer in the 19 * documentation and/or other materials provided with the distribution. 20 * 3. All advertising materials mentioning features or use of this software 21 * must display the following acknowledgement: 22 * This product includes software developed by the University of 23 * California, Berkeley and its contributors. 24 * 4. Neither the name of the University nor the names of its contributors 25 * may be used to endorse or promote products derived from this software 26 * without specific prior written permission. 27 * 28 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 29 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 30 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 31 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 32 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 36 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 37 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 38 * SUCH DAMAGE. 39 * 40 * @(#)buf.c 8.1 (Berkeley) 6/6/93 41 */ 42 43#include <sys/cdefs.h> 44__FBSDID("$FreeBSD$"); 45 46/* 47 * buf.c 48 * Functions for automatically-expanded buffers. 49 */ 50 51#include <string.h> 52#include <stdlib.h> 53 54#include "buf.h" 55#include "util.h" 56 57/** 58 * Returns the number of bytes in the buffer. Doesn't include the 59 * null-terminating byte. 60 */ 61size_t 62Buf_Size(const Buffer *buf) 63{ 64 65 return (buf->end - buf->buf); 66} 67 68/** 69 * Returns a reference to the data contained in the buffer. 70 * 71 * @note Adding data to the Buffer object may invalidate the reference. 72 */ 73char * 74Buf_Data(const Buffer *bp) 75{ 76 77 return (bp->buf); 78} 79 80/** 81 * Expand the buffer to hold the number of additional bytes, plus 82 * space to store a terminating NULL byte. 83 */ 84static inline void 85BufExpand(Buffer *bp, size_t nb) 86{ 87 size_t len = Buf_Size(bp); 88 size_t size; 89 90 if (bp->size < len + nb + 1) { 91 size = bp->size + MAX(nb + 1, BUF_ADD_INC); 92 bp->size = size; 93 bp->buf = erealloc(bp->buf, size); 94 bp->end = bp->buf + len; 95 } 96} 97 98/** 99 * Add a single byte to the buffer. 100 */ 101void 102Buf_AddByte(Buffer *bp, Byte byte) 103{ 104 105 BufExpand(bp, 1); 106 107 *bp->end = byte; 108 bp->end++; 109 *bp->end = '\0'; 110} 111 112/** 113 * Add bytes to the buffer. 114 */ 115void 116Buf_AddBytes(Buffer *bp, size_t len, const Byte *bytes) 117{ 118 119 BufExpand(bp, len); 120 121 memcpy(bp->end, bytes, len); 122 bp->end += len; 123 *bp->end = '\0'; 124} 125 126/** 127 * Get a reference to the internal buffer. 128 * 129 * len: 130 * Pointer to where we return the number of bytes in the internal buffer. 131 * 132 * Returns: 133 * return A pointer to the data. 134 */ 135Byte * 136Buf_GetAll(Buffer *bp, size_t *len) 137{ 138 139 if (len != NULL) 140 *len = Buf_Size(bp); 141 142 return (bp->buf); 143} 144 145/** 146 * Get the contents of a buffer and destroy the buffer. If the buffer 147 * is NULL, return NULL. 148 * 149 * Returns: 150 * the pointer to the data. 151 */ 152char * 153Buf_Peel(Buffer *bp) 154{ 155 char *ret; 156 157 if (bp == NULL) 158 return (NULL); 159 ret = bp->buf; 160 free(bp); 161 return (ret); 162} 163 164/** 165 * Initialize a buffer. If no initial size is given, a reasonable 166 * default is used. 167 * 168 * Returns: 169 * A buffer object to be given to other functions in this library. 170 * 171 * Side Effects: 172 * Space is allocated for the Buffer object and a internal buffer. 173 */ 174Buffer * 175Buf_Init(size_t size) 176{ 177 Buffer *bp; /* New Buffer */ 178 179 if (size <= 0) 180 size = BUF_DEF_SIZE; 181 182 bp = emalloc(sizeof(*bp)); 183 bp->size = size; 184 bp->buf = emalloc(size); 185 bp->end = bp->buf; 186 *bp->end = '\0'; 187 188 return (bp); 189} 190 191/** 192 * Destroy a buffer, and optionally free its data, too. 193 * 194 * Side Effects: 195 * Space for the Buffer object and possibly the internal buffer 196 * is de-allocated. 197 */ 198void 199Buf_Destroy(Buffer *buf, Boolean freeData) 200{ 201 202 if (freeData) 203 free(buf->buf); 204 free(buf); 205} 206 207/** 208 * Replace the last byte in a buffer. If the buffer was empty 209 * intially, then a new byte will be added. 210 */ 211void 212Buf_ReplaceLastByte(Buffer *bp, Byte byte) 213{ 214 215 if (bp->end == bp->buf) { 216 Buf_AddByte(bp, byte); 217 } else { 218 *(bp->end - 1) = byte; 219 } 220} 221 222/** 223 * Append characters in str to Buffer object 224 */ 225void 226Buf_Append(Buffer *bp, const char str[]) 227{ 228 229 Buf_AddBytes(bp, strlen(str), str); 230} 231 232/** 233 * Append characters in buf to Buffer object 234 */ 235void 236Buf_AppendBuf(Buffer *bp, const Buffer *buf) 237{ 238 239 Buf_AddBytes(bp, Buf_Size(buf), buf->buf); 240} 241 242/** 243 * Append characters between str and end to Buffer object. 244 */ 245void 246Buf_AppendRange(Buffer *bp, const char str[], const char *end) 247{ 248 249 Buf_AddBytes(bp, end - str, str); 250} 251 252/** 253 * Convert newlines in buffer to spaces. The trailing newline is 254 * removed. 255 */ 256void 257Buf_StripNewlines(Buffer *bp) 258{ 259 char *ptr = bp->end; 260 261 /* 262 * If there is anything in the buffer, remove the last 263 * newline character. 264 */ 265 if (ptr != bp->buf) { 266 if (*(ptr - 1) == '\n') { 267 /* shorten buffer */ 268 *(ptr - 1) = '\0'; 269 --bp->end; 270 } 271 --ptr; 272 } 273 274 /* Convert newline characters to a space characters. */ 275 while (ptr != bp->buf) { 276 if (*ptr == '\n') { 277 *ptr = ' '; 278 } 279 --ptr; 280 } 281} 282/** 283 * Clear the contents of the buffer. 284 */ 285void 286Buf_Clear(Buffer *bp) 287{ 288 289 bp->end = bp->buf; 290 *bp->end = '\0'; 291} 292