buf.c revision 18804
1238730Sdelphij/* 2238730Sdelphij * Copyright (c) 1988, 1989, 1990 The Regents of the University of California. 3238730Sdelphij * Copyright (c) 1988, 1989 by Adam de Boor 4238730Sdelphij * Copyright (c) 1989 by Berkeley Softworks 5238730Sdelphij * All rights reserved. 6238730Sdelphij * 7238730Sdelphij * This code is derived from software contributed to Berkeley by 8238730Sdelphij * Adam de Boor. 960786Sps * 1063120Sps * Redistribution and use in source and binary forms, with or without 1160786Sps * modification, are permitted provided that the following conditions 1260786Sps * are met: 1360786Sps * 1. Redistributions of source code must retain the above copyright 1460786Sps * notice, this list of conditions and the following disclaimer. 1560786Sps * 2. Redistributions in binary form must reproduce the above copyright 1660786Sps * notice, this list of conditions and the following disclaimer in the 1760786Sps * documentation and/or other materials provided with the distribution. 1860786Sps * 3. All advertising materials mentioning features or use of this software 1960786Sps * must display the following acknowledgement: 2060786Sps * This product includes software developed by the University of 2160786Sps * California, Berkeley and its contributors. 2260786Sps * 4. Neither the name of the University nor the names of its contributors 2360786Sps * may be used to endorse or promote products derived from this software 2460786Sps * without specific prior written permission. 2560786Sps * 2660786Sps * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2760786Sps * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2860786Sps * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2960786Sps * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 3060786Sps * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 3160786Sps * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 3260786Sps * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 3360786Sps * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 3460786Sps * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3560786Sps * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36161478Sdelphij * SUCH DAMAGE. 37170259Sdelphij * 38170259Sdelphij * $Id$ 3960786Sps */ 4060786Sps 4160786Sps#ifndef lint 4260786Spsstatic char sccsid[] = "@(#)buf.c 8.1 (Berkeley) 6/6/93"; 4360786Sps#endif /* not lint */ 4460786Sps 4560786Sps/*- 4660786Sps * buf.c -- 4760786Sps * Functions for automatically-expanded buffers. 48191930Sdelphij */ 4960786Sps 5060786Sps#include "sprite.h" 5160786Sps#include "make.h" 5260786Sps#include "buf.h" 5360786Sps 5460786Sps#ifndef max 5560786Sps#define max(a,b) ((a) > (b) ? (a) : (b)) 5660786Sps#endif 5760786Sps 5860786Sps/* 5960786Sps * BufExpand -- 6060786Sps * Expand the given buffer to hold the given number of additional 6160786Sps * bytes. 6260786Sps * Makes sure there's room for an extra NULL byte at the end of the 63170259Sdelphij * buffer in case it holds a string. 6463120Sps */ 6560786Sps#define BufExpand(bp,nb) \ 66191930Sdelphij if (bp->left < (nb)+1) {\ 6760786Sps int newSize = (bp)->size + max((nb)+1,BUF_ADD_INC); \ 6860786Sps Byte *newBuf = (Byte *) erealloc((bp)->buffer, newSize); \ 6960786Sps \ 7060786Sps (bp)->inPtr = newBuf + ((bp)->inPtr - (bp)->buffer); \ 7160786Sps (bp)->outPtr = newBuf + ((bp)->outPtr - (bp)->buffer);\ 7260786Sps (bp)->buffer = newBuf;\ 7360786Sps (bp)->size = newSize;\ 7460786Sps (bp)->left = newSize - ((bp)->inPtr - (bp)->buffer);\ 7560786Sps } 7660786Sps 7760786Sps#define BUF_DEF_SIZE 256 /* Default buffer size */ 7860786Sps#define BUF_ADD_INC 256 /* Expansion increment when Adding */ 7960786Sps#define BUF_UNGET_INC 16 /* Expansion increment when Ungetting */ 8060786Sps 8160786Sps/*- 8260786Sps *----------------------------------------------------------------------- 8360786Sps * Buf_OvAddByte -- 8460786Sps * Add a single byte to the buffer. left is zero or negative. 8560786Sps * 8660786Sps * Results: 8760786Sps * None. 8860786Sps * 8960786Sps * Side Effects: 9060786Sps * The buffer may be expanded. 9160786Sps * 9260786Sps *----------------------------------------------------------------------- 9360786Sps */ 9460786Spsvoid 9560786SpsBuf_OvAddByte (bp, byte) 96172471Sdelphij register Buffer bp; 97172471Sdelphij int byte; 9860786Sps{ 9960786Sps int nbytes = 1; 10060786Sps bp->left = 0; 10160786Sps BufExpand (bp, nbytes); 10260786Sps 10360786Sps *bp->inPtr++ = byte; 10460786Sps bp->left--; 10560786Sps 10660786Sps /* 10760786Sps * Null-terminate 10860786Sps */ 10960786Sps *bp->inPtr = 0; 11060786Sps} 11160786Sps 11260786Sps/*- 11360786Sps *----------------------------------------------------------------------- 11460786Sps * Buf_AddBytes -- 11560786Sps * Add a number of bytes to the buffer. 11660786Sps * 11760786Sps * Results: 11860786Sps * None. 11960786Sps * 12060786Sps * Side Effects: 12160786Sps * Guess what? 12260786Sps * 12360786Sps *----------------------------------------------------------------------- 12460786Sps */ 12560786Spsvoid 12660786SpsBuf_AddBytes (bp, numBytes, bytesPtr) 12760786Sps register Buffer bp; 12860786Sps int numBytes; 12960786Sps Byte *bytesPtr; 13060786Sps{ 13160786Sps 13260786Sps BufExpand (bp, numBytes); 13360786Sps 13460786Sps memcpy (bp->inPtr, bytesPtr, numBytes); 13560786Sps bp->inPtr += numBytes; 13660786Sps bp->left -= numBytes; 13760786Sps 13860786Sps /* 13960786Sps * Null-terminate 14060786Sps */ 14160786Sps *bp->inPtr = 0; 14260786Sps} 14360786Sps 14460786Sps/*- 14560786Sps *----------------------------------------------------------------------- 14660786Sps * Buf_UngetByte -- 14760786Sps * Place the byte back at the beginning of the buffer. 14860786Sps * 14960786Sps * Results: 15060786Sps * SUCCESS if the byte was added ok. FAILURE if not. 15160786Sps * 15260786Sps * Side Effects: 15360786Sps * The byte is stuffed in the buffer and outPtr is decremented. 15460786Sps * 15560786Sps *----------------------------------------------------------------------- 15660786Sps */ 15760786Spsvoid 15860786SpsBuf_UngetByte (bp, byte) 15960786Sps register Buffer bp; 16060786Sps int byte; 161170259Sdelphij{ 16260786Sps 16360786Sps if (bp->outPtr != bp->buffer) { 16460786Sps bp->outPtr--; 16560786Sps *bp->outPtr = byte; 16660786Sps } else if (bp->outPtr == bp->inPtr) { 16760786Sps *bp->inPtr = byte; 16860786Sps bp->inPtr++; 16960786Sps bp->left--; 17060786Sps *bp->inPtr = 0; 17160786Sps } else { 17260786Sps /* 17360786Sps * Yech. have to expand the buffer to stuff this thing in. 17460786Sps * We use a different expansion constant because people don't 17560786Sps * usually push back many bytes when they're doing it a byte at 17660786Sps * a time... 17760786Sps */ 17860786Sps int numBytes = bp->inPtr - bp->outPtr; 17960786Sps Byte *newBuf; 18060786Sps 18160786Sps newBuf = (Byte *)emalloc(bp->size + BUF_UNGET_INC); 18260786Sps memcpy ((char *)(newBuf+BUF_UNGET_INC), (char *)bp->outPtr, numBytes+1); 18360786Sps bp->outPtr = newBuf + BUF_UNGET_INC; 18460786Sps bp->inPtr = bp->outPtr + numBytes; 18560786Sps free ((char *)bp->buffer); 18660786Sps bp->buffer = newBuf; 18760786Sps bp->size += BUF_UNGET_INC; 18860786Sps bp->left = bp->size - (bp->inPtr - bp->buffer); 18960786Sps bp->outPtr -= 1; 19060786Sps *bp->outPtr = byte; 19160786Sps } 19260786Sps} 19360786Sps 19460786Sps/*- 19560786Sps *----------------------------------------------------------------------- 19660786Sps * Buf_UngetBytes -- 19760786Sps * Push back a series of bytes at the beginning of the buffer. 19860786Sps * 19960786Sps * Results: 20060786Sps * None. 20160786Sps * 20260786Sps * Side Effects: 20360786Sps * outPtr is decremented and the bytes copied into the buffer. 20460786Sps * 20560786Sps *----------------------------------------------------------------------- 20660786Sps */ 20760786Spsvoid 20860786SpsBuf_UngetBytes (bp, numBytes, bytesPtr) 20960786Sps register Buffer bp; 21060786Sps int numBytes; 21160786Sps Byte *bytesPtr; 21260786Sps{ 21360786Sps 21460786Sps if (bp->outPtr - bp->buffer >= numBytes) { 21560786Sps bp->outPtr -= numBytes; 21660786Sps memcpy (bp->outPtr, bytesPtr, numBytes); 21760786Sps } else if (bp->outPtr == bp->inPtr) { 21860786Sps Buf_AddBytes (bp, numBytes, bytesPtr); 21960786Sps } else { 22060786Sps int curNumBytes = bp->inPtr - bp->outPtr; 22160786Sps Byte *newBuf; 22260786Sps int newBytes = max(numBytes,BUF_UNGET_INC); 22360786Sps 22460786Sps newBuf = (Byte *)emalloc (bp->size + newBytes); 22560786Sps memcpy((char *)(newBuf+newBytes), (char *)bp->outPtr, curNumBytes+1); 22660786Sps bp->outPtr = newBuf + newBytes; 22760786Sps bp->inPtr = bp->outPtr + curNumBytes; 22860786Sps free ((char *)bp->buffer); 22960786Sps bp->buffer = newBuf; 23060786Sps bp->size += newBytes; 23160786Sps bp->left = bp->size - (bp->inPtr - bp->buffer); 23260786Sps bp->outPtr -= numBytes; 23360786Sps memcpy ((char *)bp->outPtr, (char *)bytesPtr, numBytes); 23460786Sps } 23560786Sps} 23660786Sps 23760786Sps/*- 23860786Sps *----------------------------------------------------------------------- 23960786Sps * Buf_GetByte -- 24060786Sps * Return the next byte from the buffer. Actually returns an integer. 24160786Sps * 24260786Sps * Results: 24360786Sps * Returns BUF_ERROR if there's no byte in the buffer, or the byte 24460786Sps * itself if there is one. 24560786Sps * 24660786Sps * Side Effects: 24760786Sps * outPtr is incremented and both outPtr and inPtr will be reset if 24860786Sps * the buffer is emptied. 249170259Sdelphij * 250195941Sdelphij *----------------------------------------------------------------------- 25160786Sps */ 25260786Spsint 25360786SpsBuf_GetByte (bp) 25460786Sps register Buffer bp; 25560786Sps{ 25660786Sps int res; 257161478Sdelphij 258221715Sdelphij if (bp->inPtr == bp->outPtr) { 25960786Sps return (BUF_ERROR); 26060786Sps } 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 register 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 register 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 register 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 Byte 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