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