buf.c revision 144386
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: head/usr.bin/make/buf.c 144386 2005-03-31 11:12:45Z harti $"); 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 "sprite.h" 56#include "util.h" 57 58/** 59 * Returns the number of bytes in the buffer. Doesn't include the 60 * null-terminating byte. 61 */ 62inline size_t 63Buf_Size(const Buffer *buf) 64{ 65 66 return (buf->end - buf->buf); 67} 68 69/** 70 * Returns a reference to the data contained in the buffer. 71 * 72 * @note Adding data to the Buffer object may invalidate the reference. 73 */ 74inline char * 75Buf_Data(const Buffer *bp) 76{ 77 78 return (bp->buf); 79} 80 81/** 82 * Expand the buffer to hold the number of additional bytes, plus 83 * space to store a terminating NULL byte. 84 */ 85static inline void 86BufExpand(Buffer *bp, size_t nb) 87{ 88 size_t len = Buf_Size(bp); 89 size_t size; 90 91 if (bp->size < len + nb + 1) { 92 size = bp->size + MAX(nb + 1, BUF_ADD_INC); 93 bp->size = size; 94 bp->buf = erealloc(bp->buf, size); 95 bp->end = bp->buf + len; 96 } 97} 98 99/** 100 * Add a single byte to the buffer. 101 */ 102inline void 103Buf_AddByte(Buffer *bp, Byte byte) 104{ 105 106 BufExpand(bp, 1); 107 108 *bp->end = byte; 109 bp->end++; 110 *bp->end = '\0'; 111} 112 113/** 114 * Add bytes to the buffer. 115 */ 116void 117Buf_AddBytes(Buffer *bp, size_t len, const Byte *bytes) 118{ 119 120 BufExpand(bp, len); 121 122 memcpy(bp->end, bytes, len); 123 bp->end += len; 124 *bp->end = '\0'; 125} 126 127/** 128 * Get a reference to the internal buffer. 129 * 130 * len: 131 * Pointer to where we return the number of bytes in the internal buffer. 132 * 133 * Returns: 134 * return A pointer to the data. 135 */ 136Byte * 137Buf_GetAll(Buffer *bp, size_t *len) 138{ 139 140 if (len != NULL) 141 *len = Buf_Size(bp); 142 143 return (bp->buf); 144} 145 146/** 147 * Get the contents of a buffer and destroy the buffer. If the buffer 148 * is NULL, return NULL. 149 * 150 * Returns: 151 * the pointer to the data. 152 */ 153char * 154Buf_Peel(Buffer *bp) 155{ 156 char *ret; 157 158 if (bp == NULL) 159 return (NULL); 160 ret = bp->buf; 161 free(bp); 162 return (ret); 163} 164 165/** 166 * Initialize a buffer. If no initial size is given, a reasonable 167 * default is used. 168 * 169 * Returns: 170 * A buffer object to be given to other functions in this library. 171 * 172 * Side Effects: 173 * Space is allocated for the Buffer object and a internal buffer. 174 */ 175Buffer * 176Buf_Init(size_t size) 177{ 178 Buffer *bp; /* New Buffer */ 179 180 if (size <= 0) 181 size = BUF_DEF_SIZE; 182 183 bp = emalloc(sizeof(*bp)); 184 bp->size = size; 185 bp->buf = emalloc(size); 186 bp->end = bp->buf; 187 *bp->end = '\0'; 188 189 return (bp); 190} 191 192/** 193 * Destroy a buffer, and optionally free its data, too. 194 * 195 * Side Effects: 196 * Space for the Buffer object and possibly the internal buffer 197 * is de-allocated. 198 */ 199void 200Buf_Destroy(Buffer *buf, Boolean freeData) 201{ 202 203 if (freeData) 204 free(buf->buf); 205 free(buf); 206} 207 208/** 209 * Replace the last byte in a buffer. If the buffer was empty 210 * intially, then a new byte will be added. 211 */ 212void 213Buf_ReplaceLastByte(Buffer *bp, Byte byte) 214{ 215 216 if (bp->end == bp->buf) { 217 Buf_AddByte(bp, byte); 218 } else { 219 *(bp->end - 1) = byte; 220 } 221} 222 223/** 224 * Append characters in str to Buffer object 225 */ 226void 227Buf_Append(Buffer *bp, const char str[]) 228{ 229 230 Buf_AddBytes(bp, strlen(str), str); 231} 232 233/** 234 * Append characters in buf to Buffer object 235 */ 236void 237Buf_AppendBuf(Buffer *bp, const Buffer *buf) 238{ 239 240 Buf_AddBytes(bp, Buf_Size(buf), buf->buf); 241} 242 243/** 244 * Append characters between str and end to Buffer object. 245 */ 246void 247Buf_AppendRange(Buffer *bp, const char str[], const char *end) 248{ 249 250 Buf_AddBytes(bp, end - str, str); 251} 252 253/** 254 * Convert newlines in buffer to spaces. The trailing newline is 255 * removed. 256 */ 257void 258Buf_StripNewlines(Buffer *bp) 259{ 260 char *ptr = bp->end; 261 262 /* 263 * If there is anything in the buffer, remove the last 264 * newline character. 265 */ 266 if (ptr != bp->buf) { 267 if (*(ptr - 1) == '\n') { 268 /* shorten buffer */ 269 *(ptr - 1) = '\0'; 270 --bp->end; 271 } 272 --ptr; 273 } 274 275 /* Convert newline characters to a space characters. */ 276 while (ptr != bp->buf) { 277 if (*ptr == '\n') { 278 *ptr = ' '; 279 } 280 --ptr; 281 } 282} 283/** 284 * Clear the contents of the buffer. 285 */ 286void 287Buf_Clear(Buffer *bp) 288{ 289 290 bp->end = bp->buf; 291 *bp->end = '\0'; 292} 293