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