buf.c revision 138337
1/* 2 * Copyright (c) 1988, 1989, 1990, 1993 3 * The Regents of the University of California. All rights reserved. 4 * Copyright (c) 1988, 1989 by Adam de Boor 5 * Copyright (c) 1989 by Berkeley Softworks 6 * All rights reserved. 7 * 8 * This code is derived from software contributed to Berkeley by 9 * Adam de Boor. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 3. All advertising materials mentioning features or use of this software 20 * must display the following acknowledgement: 21 * This product includes software developed by the University of 22 * California, Berkeley and its contributors. 23 * 4. Neither the name of the University nor the names of its contributors 24 * may be used to endorse or promote products derived from this software 25 * without specific prior written permission. 26 * 27 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 28 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 29 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 30 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 31 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 32 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 33 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 34 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 35 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 36 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 37 * SUCH DAMAGE. 38 * 39 * @(#)buf.c 8.1 (Berkeley) 6/6/93 40 */ 41 42#include <sys/cdefs.h> 43__FBSDID("$FreeBSD: head/usr.bin/make/buf.c 138337 2004-12-03 08:43:07Z harti $"); 44 45/*- 46 * buf.c -- 47 * Functions for automatically-expanded buffers. 48 */ 49 50#include "sprite.h" 51#include "make.h" 52#include "buf.h" 53 54#ifndef max 55#define max(a,b) ((a) > (b) ? (a) : (b)) 56#endif 57 58/* 59 * BufExpand -- 60 * Expand the given buffer to hold the given number of additional 61 * bytes. 62 * Makes sure there's room for an extra NULL byte at the end of the 63 * buffer in case it holds a string. 64 */ 65#define BufExpand(bp, nb) do { \ 66 if (bp->left < (nb) + 1) { \ 67 int newSize = (bp)->size + max((nb) + 1, BUF_ADD_INC); \ 68 Byte *newBuf = erealloc((bp)->buffer, newSize); \ 69 \ 70 (bp)->inPtr = newBuf + ((bp)->inPtr - (bp)->buffer); \ 71 (bp)->outPtr = newBuf + ((bp)->outPtr - (bp)->buffer); \ 72 (bp)->buffer = newBuf; \ 73 (bp)->size = newSize; \ 74 (bp)->left = newSize - ((bp)->inPtr - (bp)->buffer); \ 75 } \ 76 } while (0) 77 78#define BUF_DEF_SIZE 256 /* Default buffer size */ 79#define BUF_ADD_INC 256 /* Expansion increment when Adding */ 80#define BUF_UNGET_INC 16 /* Expansion increment when Ungetting */ 81 82/*- 83 *----------------------------------------------------------------------- 84 * Buf_OvAddByte -- 85 * Add a single byte to the buffer. left is zero or negative. 86 * 87 * Results: 88 * None. 89 * 90 * Side Effects: 91 * The buffer may be expanded. 92 * 93 *----------------------------------------------------------------------- 94 */ 95void 96Buf_OvAddByte(Buffer bp, int byte) 97{ 98 99 bp->left = 0; 100 BufExpand(bp, 1); 101 102 *bp->inPtr++ = byte; 103 bp->left--; 104 105 /* 106 * Null-terminate 107 */ 108 *bp->inPtr = 0; 109} 110 111/*- 112 *----------------------------------------------------------------------- 113 * Buf_AddBytes -- 114 * Add a number of bytes to the buffer. 115 * 116 * Results: 117 * None. 118 * 119 * Side Effects: 120 * Guess what? 121 * 122 *----------------------------------------------------------------------- 123 */ 124void 125Buf_AddBytes(Buffer bp, int numBytes, const Byte *bytesPtr) 126{ 127 128 BufExpand(bp, numBytes); 129 130 memcpy(bp->inPtr, bytesPtr, numBytes); 131 bp->inPtr += numBytes; 132 bp->left -= numBytes; 133 134 /* 135 * Null-terminate 136 */ 137 *bp->inPtr = 0; 138} 139 140/*- 141 *----------------------------------------------------------------------- 142 * Buf_UngetByte -- 143 * Place the byte back at the beginning of the buffer. 144 * 145 * Results: 146 * SUCCESS if the byte was added ok. FAILURE if not. 147 * 148 * Side Effects: 149 * The byte is stuffed in the buffer and outPtr is decremented. 150 * 151 *----------------------------------------------------------------------- 152 */ 153void 154Buf_UngetByte(Buffer bp, int byte) 155{ 156 157 if (bp->outPtr != bp->buffer) { 158 bp->outPtr--; 159 *bp->outPtr = byte; 160 161 } else if (bp->outPtr == bp->inPtr) { 162 *bp->inPtr = byte; 163 bp->inPtr++; 164 bp->left--; 165 *bp->inPtr = 0; 166 167 } else { 168 /* 169 * Yech. have to expand the buffer to stuff this thing in. 170 * We use a different expansion constant because people don't 171 * usually push back many bytes when they're doing it a byte at 172 * a time... 173 */ 174 int numBytes = bp->inPtr - bp->outPtr; 175 Byte *newBuf; 176 177 newBuf = emalloc(bp->size + BUF_UNGET_INC); 178 memcpy(newBuf + BUF_UNGET_INC, bp->outPtr, numBytes + 1); 179 bp->outPtr = newBuf + BUF_UNGET_INC; 180 bp->inPtr = bp->outPtr + numBytes; 181 free(bp->buffer); 182 bp->buffer = newBuf; 183 bp->size += BUF_UNGET_INC; 184 bp->left = bp->size - (bp->inPtr - bp->buffer); 185 bp->outPtr -= 1; 186 *bp->outPtr = byte; 187 } 188} 189 190/*- 191 *----------------------------------------------------------------------- 192 * Buf_UngetBytes -- 193 * Push back a series of bytes at the beginning of the buffer. 194 * 195 * Results: 196 * None. 197 * 198 * Side Effects: 199 * outPtr is decremented and the bytes copied into the buffer. 200 * 201 *----------------------------------------------------------------------- 202 */ 203void 204Buf_UngetBytes(Buffer bp, int numBytes, Byte *bytesPtr) 205{ 206 207 if (bp->outPtr - bp->buffer >= numBytes) { 208 bp->outPtr -= numBytes; 209 memcpy(bp->outPtr, bytesPtr, numBytes); 210 } else if (bp->outPtr == bp->inPtr) { 211 Buf_AddBytes(bp, numBytes, bytesPtr); 212 } else { 213 int curNumBytes = bp->inPtr - bp->outPtr; 214 Byte *newBuf; 215 int newBytes = max(numBytes, BUF_UNGET_INC); 216 217 newBuf = emalloc(bp->size + newBytes); 218 memcpy(newBuf + newBytes, bp->outPtr, curNumBytes + 1); 219 bp->outPtr = newBuf + newBytes; 220 bp->inPtr = bp->outPtr + curNumBytes; 221 free(bp->buffer); 222 bp->buffer = newBuf; 223 bp->size += newBytes; 224 bp->left = bp->size - (bp->inPtr - bp->buffer); 225 bp->outPtr -= numBytes; 226 memcpy(bp->outPtr, bytesPtr, numBytes); 227 } 228} 229 230/*- 231 *----------------------------------------------------------------------- 232 * Buf_GetByte -- 233 * Return the next byte from the buffer. Actually returns an integer. 234 * 235 * Results: 236 * Returns BUF_ERROR if there's no byte in the buffer, or the byte 237 * itself if there is one. 238 * 239 * Side Effects: 240 * outPtr is incremented and both outPtr and inPtr will be reset if 241 * the buffer is emptied. 242 * 243 *----------------------------------------------------------------------- 244 */ 245int 246Buf_GetByte(Buffer bp) 247{ 248 int res; 249 250 if (bp->inPtr == bp->outPtr) 251 return (BUF_ERROR); 252 253 res = (int)*bp->outPtr; 254 bp->outPtr += 1; 255 if (bp->outPtr == bp->inPtr) { 256 bp->outPtr = bp->inPtr = bp->buffer; 257 bp->left = bp->size; 258 *bp->inPtr = 0; 259 } 260 return (res); 261} 262 263/*- 264 *----------------------------------------------------------------------- 265 * Buf_GetBytes -- 266 * Extract a number of bytes from the buffer. 267 * 268 * Results: 269 * The number of bytes gotten. 270 * 271 * Side Effects: 272 * The passed array is overwritten. 273 * 274 *----------------------------------------------------------------------- 275 */ 276int 277Buf_GetBytes(Buffer bp, int numBytes, Byte *bytesPtr) 278{ 279 280 if (bp->inPtr - bp->outPtr < numBytes) 281 numBytes = bp->inPtr - bp->outPtr; 282 283 memcpy(bytesPtr, bp->outPtr, numBytes); 284 bp->outPtr += numBytes; 285 286 if (bp->outPtr == bp->inPtr) { 287 bp->outPtr = bp->inPtr = bp->buffer; 288 bp->left = bp->size; 289 *bp->inPtr = 0; 290 } 291 return (numBytes); 292} 293 294/*- 295 *----------------------------------------------------------------------- 296 * Buf_GetAll -- 297 * Get all the available data at once. 298 * 299 * Results: 300 * A pointer to the data and the number of bytes available. 301 * 302 * Side Effects: 303 * None. 304 * 305 *----------------------------------------------------------------------- 306 */ 307Byte * 308Buf_GetAll(Buffer bp, int *numBytesPtr) 309{ 310 311 if (numBytesPtr != NULL) 312 *numBytesPtr = bp->inPtr - bp->outPtr; 313 314 return (bp->outPtr); 315} 316 317/*- 318 *----------------------------------------------------------------------- 319 * Buf_Discard -- 320 * Throw away bytes in a buffer. 321 * 322 * Results: 323 * None. 324 * 325 * Side Effects: 326 * The bytes are discarded. 327 * 328 *----------------------------------------------------------------------- 329 */ 330void 331Buf_Discard(Buffer bp, int numBytes) 332{ 333 334 if (bp->inPtr - bp->outPtr <= numBytes) { 335 bp->inPtr = bp->outPtr = bp->buffer; 336 bp->left = bp->size; 337 *bp->inPtr = 0; 338 } else 339 bp->outPtr += numBytes; 340} 341 342/*- 343 *----------------------------------------------------------------------- 344 * Buf_Size -- 345 * Returns the number of bytes in the given buffer. Doesn't include 346 * the null-terminating byte. 347 * 348 * Results: 349 * The number of bytes. 350 * 351 * Side Effects: 352 * None. 353 * 354 *----------------------------------------------------------------------- 355 */ 356int 357Buf_Size(Buffer buf) 358{ 359 360 return (buf->inPtr - buf->outPtr); 361} 362 363/*- 364 *----------------------------------------------------------------------- 365 * Buf_Init -- 366 * Initialize a buffer. If no initial size is given, a reasonable 367 * default is used. 368 * 369 * Results: 370 * A buffer to be given to other functions in this library. 371 * 372 * Side Effects: 373 * The buffer is created, the space allocated and pointers 374 * initialized. 375 * 376 *----------------------------------------------------------------------- 377 */ 378Buffer 379Buf_Init(int size) 380{ 381 Buffer bp; /* New Buffer */ 382 383 bp = emalloc(sizeof(*bp)); 384 385 if (size <= 0) 386 size = BUF_DEF_SIZE; 387 388 bp->left = bp->size = size; 389 bp->buffer = emalloc(size); 390 bp->inPtr = bp->outPtr = bp->buffer; 391 *bp->inPtr = 0; 392 393 return (bp); 394} 395 396/*- 397 *----------------------------------------------------------------------- 398 * Buf_Destroy -- 399 * Destroy a buffer, and optionally free its data, too. 400 * 401 * Results: 402 * None. 403 * 404 * Side Effects: 405 * The buffer is freed. 406 * 407 *----------------------------------------------------------------------- 408 */ 409void 410Buf_Destroy(Buffer buf, Boolean freeData) 411{ 412 413 if (freeData) 414 free(buf->buffer); 415 free(buf); 416} 417 418/*- 419 *----------------------------------------------------------------------- 420 * Buf_ReplaceLastByte -- 421 * Replace the last byte in a buffer. 422 * 423 * Results: 424 * None. 425 * 426 * Side Effects: 427 * If the buffer was empty intially, then a new byte will be added. 428 * Otherwise, the last byte is overwritten. 429 * 430 *----------------------------------------------------------------------- 431 */ 432void 433Buf_ReplaceLastByte(Buffer buf, int byte) 434{ 435 if (buf->inPtr == buf->outPtr) 436 Buf_AddByte(buf, byte); 437 else 438 *(buf->inPtr - 1) = byte; 439} 440