buf.c revision 94589
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 94589 2002-04-13 10:57:56Z obrien $"); 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) \ 66 if (bp->left < (nb)+1) {\ 67 int newSize = (bp)->size + max((nb)+1,BUF_ADD_INC); \ 68 Byte *newBuf = (Byte *) 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 77#define BUF_DEF_SIZE 256 /* Default buffer size */ 78#define BUF_ADD_INC 256 /* Expansion increment when Adding */ 79#define BUF_UNGET_INC 16 /* Expansion increment when Ungetting */ 80 81/*- 82 *----------------------------------------------------------------------- 83 * Buf_OvAddByte -- 84 * Add a single byte to the buffer. left is zero or negative. 85 * 86 * Results: 87 * None. 88 * 89 * Side Effects: 90 * The buffer may be expanded. 91 * 92 *----------------------------------------------------------------------- 93 */ 94void 95Buf_OvAddByte (bp, byte) 96 Buffer bp; 97 int byte; 98{ 99 int nbytes = 1; 100 bp->left = 0; 101 BufExpand (bp, nbytes); 102 103 *bp->inPtr++ = byte; 104 bp->left--; 105 106 /* 107 * Null-terminate 108 */ 109 *bp->inPtr = 0; 110} 111 112/*- 113 *----------------------------------------------------------------------- 114 * Buf_AddBytes -- 115 * Add a number of bytes to the buffer. 116 * 117 * Results: 118 * None. 119 * 120 * Side Effects: 121 * Guess what? 122 * 123 *----------------------------------------------------------------------- 124 */ 125void 126Buf_AddBytes (bp, numBytes, bytesPtr) 127 Buffer bp; 128 int numBytes; 129 const Byte *bytesPtr; 130{ 131 132 BufExpand (bp, numBytes); 133 134 memcpy (bp->inPtr, bytesPtr, numBytes); 135 bp->inPtr += numBytes; 136 bp->left -= numBytes; 137 138 /* 139 * Null-terminate 140 */ 141 *bp->inPtr = 0; 142} 143 144/*- 145 *----------------------------------------------------------------------- 146 * Buf_UngetByte -- 147 * Place the byte back at the beginning of the buffer. 148 * 149 * Results: 150 * SUCCESS if the byte was added ok. FAILURE if not. 151 * 152 * Side Effects: 153 * The byte is stuffed in the buffer and outPtr is decremented. 154 * 155 *----------------------------------------------------------------------- 156 */ 157void 158Buf_UngetByte (bp, byte) 159 Buffer bp; 160 int byte; 161{ 162 163 if (bp->outPtr != bp->buffer) { 164 bp->outPtr--; 165 *bp->outPtr = byte; 166 } else if (bp->outPtr == bp->inPtr) { 167 *bp->inPtr = byte; 168 bp->inPtr++; 169 bp->left--; 170 *bp->inPtr = 0; 171 } else { 172 /* 173 * Yech. have to expand the buffer to stuff this thing in. 174 * We use a different expansion constant because people don't 175 * usually push back many bytes when they're doing it a byte at 176 * a time... 177 */ 178 int numBytes = bp->inPtr - bp->outPtr; 179 Byte *newBuf; 180 181 newBuf = (Byte *)emalloc(bp->size + BUF_UNGET_INC); 182 memcpy ((char *)(newBuf+BUF_UNGET_INC), (char *)bp->outPtr, numBytes+1); 183 bp->outPtr = newBuf + BUF_UNGET_INC; 184 bp->inPtr = bp->outPtr + numBytes; 185 free ((char *)bp->buffer); 186 bp->buffer = newBuf; 187 bp->size += BUF_UNGET_INC; 188 bp->left = bp->size - (bp->inPtr - bp->buffer); 189 bp->outPtr -= 1; 190 *bp->outPtr = byte; 191 } 192} 193 194/*- 195 *----------------------------------------------------------------------- 196 * Buf_UngetBytes -- 197 * Push back a series of bytes at the beginning of the buffer. 198 * 199 * Results: 200 * None. 201 * 202 * Side Effects: 203 * outPtr is decremented and the bytes copied into the buffer. 204 * 205 *----------------------------------------------------------------------- 206 */ 207void 208Buf_UngetBytes (bp, numBytes, bytesPtr) 209 Buffer bp; 210 int numBytes; 211 Byte *bytesPtr; 212{ 213 214 if (bp->outPtr - bp->buffer >= numBytes) { 215 bp->outPtr -= numBytes; 216 memcpy (bp->outPtr, bytesPtr, numBytes); 217 } else if (bp->outPtr == bp->inPtr) { 218 Buf_AddBytes (bp, numBytes, bytesPtr); 219 } else { 220 int curNumBytes = bp->inPtr - bp->outPtr; 221 Byte *newBuf; 222 int newBytes = max(numBytes,BUF_UNGET_INC); 223 224 newBuf = (Byte *)emalloc (bp->size + newBytes); 225 memcpy((char *)(newBuf+newBytes), (char *)bp->outPtr, curNumBytes+1); 226 bp->outPtr = newBuf + newBytes; 227 bp->inPtr = bp->outPtr + curNumBytes; 228 free ((char *)bp->buffer); 229 bp->buffer = newBuf; 230 bp->size += newBytes; 231 bp->left = bp->size - (bp->inPtr - bp->buffer); 232 bp->outPtr -= numBytes; 233 memcpy ((char *)bp->outPtr, (char *)bytesPtr, numBytes); 234 } 235} 236 237/*- 238 *----------------------------------------------------------------------- 239 * Buf_GetByte -- 240 * Return the next byte from the buffer. Actually returns an integer. 241 * 242 * Results: 243 * Returns BUF_ERROR if there's no byte in the buffer, or the byte 244 * itself if there is one. 245 * 246 * Side Effects: 247 * outPtr is incremented and both outPtr and inPtr will be reset if 248 * the buffer is emptied. 249 * 250 *----------------------------------------------------------------------- 251 */ 252int 253Buf_GetByte (bp) 254 Buffer bp; 255{ 256 int res; 257 258 if (bp->inPtr == bp->outPtr) { 259 return (BUF_ERROR); 260 } else { 261 res = (int) *bp->outPtr; 262 bp->outPtr += 1; 263 if (bp->outPtr == bp->inPtr) { 264 bp->outPtr = bp->inPtr = bp->buffer; 265 bp->left = bp->size; 266 *bp->inPtr = 0; 267 } 268 return (res); 269 } 270} 271 272/*- 273 *----------------------------------------------------------------------- 274 * Buf_GetBytes -- 275 * Extract a number of bytes from the buffer. 276 * 277 * Results: 278 * The number of bytes gotten. 279 * 280 * Side Effects: 281 * The passed array is overwritten. 282 * 283 *----------------------------------------------------------------------- 284 */ 285int 286Buf_GetBytes (bp, numBytes, bytesPtr) 287 Buffer bp; 288 int numBytes; 289 Byte *bytesPtr; 290{ 291 292 if (bp->inPtr - bp->outPtr < numBytes) { 293 numBytes = bp->inPtr - bp->outPtr; 294 } 295 memcpy (bytesPtr, bp->outPtr, numBytes); 296 bp->outPtr += numBytes; 297 298 if (bp->outPtr == bp->inPtr) { 299 bp->outPtr = bp->inPtr = bp->buffer; 300 bp->left = bp->size; 301 *bp->inPtr = 0; 302 } 303 return (numBytes); 304} 305 306/*- 307 *----------------------------------------------------------------------- 308 * Buf_GetAll -- 309 * Get all the available data at once. 310 * 311 * Results: 312 * A pointer to the data and the number of bytes available. 313 * 314 * Side Effects: 315 * None. 316 * 317 *----------------------------------------------------------------------- 318 */ 319Byte * 320Buf_GetAll (bp, numBytesPtr) 321 Buffer bp; 322 int *numBytesPtr; 323{ 324 325 if (numBytesPtr != (int *)NULL) { 326 *numBytesPtr = bp->inPtr - bp->outPtr; 327 } 328 329 return (bp->outPtr); 330} 331 332/*- 333 *----------------------------------------------------------------------- 334 * Buf_Discard -- 335 * Throw away bytes in a buffer. 336 * 337 * Results: 338 * None. 339 * 340 * Side Effects: 341 * The bytes are discarded. 342 * 343 *----------------------------------------------------------------------- 344 */ 345void 346Buf_Discard (bp, numBytes) 347 Buffer bp; 348 int numBytes; 349{ 350 351 if (bp->inPtr - bp->outPtr <= numBytes) { 352 bp->inPtr = bp->outPtr = bp->buffer; 353 bp->left = bp->size; 354 *bp->inPtr = 0; 355 } else { 356 bp->outPtr += numBytes; 357 } 358} 359 360/*- 361 *----------------------------------------------------------------------- 362 * Buf_Size -- 363 * Returns the number of bytes in the given buffer. Doesn't include 364 * the null-terminating byte. 365 * 366 * Results: 367 * The number of bytes. 368 * 369 * Side Effects: 370 * None. 371 * 372 *----------------------------------------------------------------------- 373 */ 374int 375Buf_Size (buf) 376 Buffer buf; 377{ 378 return (buf->inPtr - buf->outPtr); 379} 380 381/*- 382 *----------------------------------------------------------------------- 383 * Buf_Init -- 384 * Initialize a buffer. If no initial size is given, a reasonable 385 * default is used. 386 * 387 * Results: 388 * A buffer to be given to other functions in this library. 389 * 390 * Side Effects: 391 * The buffer is created, the space allocated and pointers 392 * initialized. 393 * 394 *----------------------------------------------------------------------- 395 */ 396Buffer 397Buf_Init (size) 398 int size; /* Initial size for the buffer */ 399{ 400 Buffer bp; /* New Buffer */ 401 402 bp = (Buffer)emalloc(sizeof(*bp)); 403 404 if (size <= 0) { 405 size = BUF_DEF_SIZE; 406 } 407 bp->left = bp->size = size; 408 bp->buffer = (Byte *)emalloc(size); 409 bp->inPtr = bp->outPtr = bp->buffer; 410 *bp->inPtr = 0; 411 412 return (bp); 413} 414 415/*- 416 *----------------------------------------------------------------------- 417 * Buf_Destroy -- 418 * Nuke a buffer and all its resources. 419 * 420 * Results: 421 * None. 422 * 423 * Side Effects: 424 * The buffer is freed. 425 * 426 *----------------------------------------------------------------------- 427 */ 428void 429Buf_Destroy (buf, freeData) 430 Buffer buf; /* Buffer to destroy */ 431 Boolean freeData; /* TRUE if the data should be destroyed as well */ 432{ 433 434 if (freeData) { 435 free ((char *)buf->buffer); 436 } 437 free ((char *)buf); 438} 439 440/*- 441 *----------------------------------------------------------------------- 442 * Buf_ReplaceLastByte -- 443 * Replace the last byte in a buffer. 444 * 445 * Results: 446 * None. 447 * 448 * Side Effects: 449 * If the buffer was empty intially, then a new byte will be added. 450 * Otherwise, the last byte is overwritten. 451 * 452 *----------------------------------------------------------------------- 453 */ 454void 455Buf_ReplaceLastByte (buf, byte) 456 Buffer buf; /* buffer to augment */ 457 int byte; /* byte to be written */ 458{ 459 if (buf->inPtr == buf->outPtr) 460 Buf_AddByte(buf, byte); 461 else 462 *(buf->inPtr - 1) = byte; 463} 464