buf.c revision 187475
1212795Sdim/*- 2212795Sdim * Copyright (c) 2005 Max Okumoto 3212795Sdim * Copyright (c) 1988, 1989, 1990, 1993 4212795Sdim * The Regents of the University of California. All rights reserved. 5212795Sdim * Copyright (c) 1988, 1989 by Adam de Boor 6212795Sdim * Copyright (c) 1989 by Berkeley Softworks 7212795Sdim * All rights reserved. 8212795Sdim * 9212795Sdim * This code is derived from software contributed to Berkeley by 10212795Sdim * Adam de Boor. 11212795Sdim * 12212795Sdim * Redistribution and use in source and binary forms, with or without 13212795Sdim * modification, are permitted provided that the following conditions 14212795Sdim * are met: 15212795Sdim * 1. Redistributions of source code must retain the above copyright 16212795Sdim * notice, this list of conditions and the following disclaimer. 17212795Sdim * 2. Redistributions in binary form must reproduce the above copyright 18212795Sdim * notice, this list of conditions and the following disclaimer in the 19212795Sdim * documentation and/or other materials provided with the distribution. 20212795Sdim * 3. All advertising materials mentioning features or use of this software 21212795Sdim * must display the following acknowledgement: 22218893Sdim * This product includes software developed by the University of 23212795Sdim * California, Berkeley and its contributors. 24212795Sdim * 4. Neither the name of the University nor the names of its contributors 25212795Sdim * may be used to endorse or promote products derived from this software 26212795Sdim * without specific prior written permission. 27212795Sdim * 28212795Sdim * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 29212795Sdim * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 30226633Sdim * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 31226633Sdim * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 32226633Sdim * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 33226633Sdim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 34226633Sdim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 35226633Sdim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 36226633Sdim * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 37212795Sdim * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 38212795Sdim * SUCH DAMAGE. 39218893Sdim * 40226633Sdim * @(#)buf.c 8.1 (Berkeley) 6/6/93 41212795Sdim */ 42212795Sdim 43226633Sdim#include <sys/cdefs.h> 44226633Sdim__FBSDID("$FreeBSD: head/usr.bin/make/buf.c 187475 2009-01-20 17:15:12Z rdivacky $"); 45226633Sdim 46212795Sdim/* 47212795Sdim * buf.c 48212795Sdim * Functions for automatically-expanded buffers. 49218893Sdim */ 50212795Sdim 51212795Sdim#include <string.h> 52226633Sdim#include <stdlib.h> 53212795Sdim 54212795Sdim#include "buf.h" 55212795Sdim#include "util.h" 56212795Sdim 57212795Sdim/** 58212795Sdim * Returns the number of bytes in the buffer. Doesn't include the 59212795Sdim * null-terminating byte. 60212795Sdim */ 61212795Sdimsize_t 62212795SdimBuf_Size(const Buffer *buf) 63212795Sdim{ 64218893Sdim 65226633Sdim return (buf->end - buf->buf); 66218893Sdim} 67218893Sdim 68212795Sdim/** 69212795Sdim * Returns a reference to the data contained in the buffer. 70212795Sdim * 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