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 39 #ifndef lint 40 /* from: static char sccsid[] = "@(#)buf.c 5.5 (Berkeley) 12/28/90"; */ 41 static char *rcsid = "$Id: buf.c,v 1.5 1994/06/06 22:45:19 jtc Exp $"; 42 #endif /* not lint */ 43 44 /*- 45 * buf.c -- 46 * Functions for automatically-expanded buffers. 47 */ 48 49 #include "sprite.h" 50 #include "make.h" 51 #include "buf.h" 52 53 #ifndef max 54 #define max(a,b) ((a) > (b) ? (a) : (b)) 55 #endif 56 57 /* 58 * BufExpand -- 59 * Expand the given buffer to hold the given number of additional 60 * bytes. 61 * Makes sure there's room for an extra NULL byte at the end of the 62 * buffer in case it holds a string. 63 */ 64 #define BufExpand(bp,nb) \ 65 if (bp->left < (nb)+1) {\ 66 int newSize = (bp)->size + max((nb)+1,BUF_ADD_INC); \ 67 Byte *newBuf = (Byte *) realloc((bp)->buffer, newSize); \ 68 \ 69 (bp)->inPtr = newBuf + ((bp)->inPtr - (bp)->buffer); \ 70 (bp)->outPtr = newBuf + ((bp)->outPtr - (bp)->buffer);\ 71 (bp)->buffer = newBuf;\ 72 (bp)->size = newSize;\ 73 (bp)->left = newSize - ((bp)->inPtr - (bp)->buffer);\ 74 } 75 76 #define BUF_DEF_SIZE 256 /* Default buffer size */ 77 #define BUF_ADD_INC 256 /* Expansion increment when Adding */ 78 #define BUF_UNGET_INC 16 /* Expansion increment when Ungetting */ 79 80 /*- 81 *----------------------------------------------------------------------- 82 * Buf_OvAddByte -- 83 * Add a single byte to the buffer. left is zero or negative. 84 * 85 * Results: 86 * None. 87 * 88 * Side Effects: 89 * The buffer may be expanded. 90 * 91 *----------------------------------------------------------------------- 92 */ 93 void 94 Buf_OvAddByte (bp, byte) 95 register Buffer bp; 96 int byte; 97 { 98 int nbytes = 1; 99 bp->left = 0; 100 BufExpand (bp, nbytes); 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 */ 124 void 125 Buf_AddBytes (bp, numBytes, bytesPtr) 126 register Buffer bp; 127 int numBytes; 128 Byte *bytesPtr; 129 { 130 131 BufExpand (bp, numBytes); 132 133 memcpy (bp->inPtr, bytesPtr, numBytes); 134 bp->inPtr += numBytes; 135 bp->left -= numBytes; 136 137 /* 138 * Null-terminate 139 */ 140 *bp->inPtr = 0; 141 } 142 143 /*- 144 *----------------------------------------------------------------------- 145 * Buf_UngetByte -- 146 * Place the byte back at the beginning of the buffer. 147 * 148 * Results: 149 * SUCCESS if the byte was added ok. FAILURE if not. 150 * 151 * Side Effects: 152 * The byte is stuffed in the buffer and outPtr is decremented. 153 * 154 *----------------------------------------------------------------------- 155 */ 156 void 157 Buf_UngetByte (bp, byte) 158 register Buffer bp; 159 int byte; 160 { 161 162 if (bp->outPtr != bp->buffer) { 163 bp->outPtr--; 164 *bp->outPtr = byte; 165 } else if (bp->outPtr == bp->inPtr) { 166 *bp->inPtr = byte; 167 bp->inPtr++; 168 bp->left--; 169 *bp->inPtr = 0; 170 } else { 171 /* 172 * Yech. have to expand the buffer to stuff this thing in. 173 * We use a different expansion constant because people don't 174 * usually push back many bytes when they're doing it a byte at 175 * a time... 176 */ 177 int numBytes = bp->inPtr - bp->outPtr; 178 Byte *newBuf; 179 180 newBuf = (Byte *)emalloc(bp->size + BUF_UNGET_INC); 181 memcpy ((char *)(newBuf+BUF_UNGET_INC), (char *)bp->outPtr, numBytes+1); 182 bp->outPtr = newBuf + BUF_UNGET_INC; 183 bp->inPtr = bp->outPtr + numBytes; 184 free ((char *)bp->buffer); 185 bp->buffer = newBuf; 186 bp->size += BUF_UNGET_INC; 187 bp->left = bp->size - (bp->inPtr - bp->buffer); 188 bp->outPtr -= 1; 189 *bp->outPtr = byte; 190 } 191 } 192 193 /*- 194 *----------------------------------------------------------------------- 195 * Buf_UngetBytes -- 196 * Push back a series of bytes at the beginning of the buffer. 197 * 198 * Results: 199 * None. 200 * 201 * Side Effects: 202 * outPtr is decremented and the bytes copied into the buffer. 203 * 204 *----------------------------------------------------------------------- 205 */ 206 void 207 Buf_UngetBytes (bp, numBytes, bytesPtr) 208 register Buffer bp; 209 int numBytes; 210 Byte *bytesPtr; 211 { 212 213 if (bp->outPtr - bp->buffer >= numBytes) { 214 bp->outPtr -= numBytes; 215 memcpy (bp->outPtr, bytesPtr, numBytes); 216 } else if (bp->outPtr == bp->inPtr) { 217 Buf_AddBytes (bp, numBytes, bytesPtr); 218 } else { 219 int curNumBytes = bp->inPtr - bp->outPtr; 220 Byte *newBuf; 221 int newBytes = max(numBytes,BUF_UNGET_INC); 222 223 newBuf = (Byte *)emalloc (bp->size + newBytes); 224 memcpy((char *)(newBuf+newBytes), (char *)bp->outPtr, curNumBytes+1); 225 bp->outPtr = newBuf + newBytes; 226 bp->inPtr = bp->outPtr + curNumBytes; 227 free ((char *)bp->buffer); 228 bp->buffer = newBuf; 229 bp->size += newBytes; 230 bp->left = bp->size - (bp->inPtr - bp->buffer); 231 bp->outPtr -= numBytes; 232 memcpy ((char *)bp->outPtr, (char *)bytesPtr, numBytes); 233 } 234 } 235 236 /*- 237 *----------------------------------------------------------------------- 238 * Buf_GetByte -- 239 * Return the next byte from the buffer. Actually returns an integer. 240 * 241 * Results: 242 * Returns BUF_ERROR if there's no byte in the buffer, or the byte 243 * itself if there is one. 244 * 245 * Side Effects: 246 * outPtr is incremented and both outPtr and inPtr will be reset if 247 * the buffer is emptied. 248 * 249 *----------------------------------------------------------------------- 250 */ 251 int 252 Buf_GetByte (bp) 253 register Buffer bp; 254 { 255 int res; 256 257 if (bp->inPtr == bp->outPtr) { 258 return (BUF_ERROR); 259 } else { 260 res = (int) *bp->outPtr; 261 bp->outPtr += 1; 262 if (bp->outPtr == bp->inPtr) { 263 bp->outPtr = bp->inPtr = bp->buffer; 264 bp->left = bp->size; 265 *bp->inPtr = 0; 266 } 267 return (res); 268 } 269 } 270 271 /*- 272 *----------------------------------------------------------------------- 273 * Buf_GetBytes -- 274 * Extract a number of bytes from the buffer. 275 * 276 * Results: 277 * The number of bytes gotten. 278 * 279 * Side Effects: 280 * The passed array is overwritten. 281 * 282 *----------------------------------------------------------------------- 283 */ 284 int 285 Buf_GetBytes (bp, numBytes, bytesPtr) 286 register Buffer bp; 287 int numBytes; 288 Byte *bytesPtr; 289 { 290 291 if (bp->inPtr - bp->outPtr < numBytes) { 292 numBytes = bp->inPtr - bp->outPtr; 293 } 294 memcpy (bytesPtr, bp->outPtr, numBytes); 295 bp->outPtr += numBytes; 296 297 if (bp->outPtr == bp->inPtr) { 298 bp->outPtr = bp->inPtr = bp->buffer; 299 bp->left = bp->size; 300 *bp->inPtr = 0; 301 } 302 return (numBytes); 303 } 304 305 /*- 306 *----------------------------------------------------------------------- 307 * Buf_GetAll -- 308 * Get all the available data at once. 309 * 310 * Results: 311 * A pointer to the data and the number of bytes available. 312 * 313 * Side Effects: 314 * None. 315 * 316 *----------------------------------------------------------------------- 317 */ 318 Byte * 319 Buf_GetAll (bp, numBytesPtr) 320 register Buffer bp; 321 int *numBytesPtr; 322 { 323 324 if (numBytesPtr != (int *)NULL) { 325 *numBytesPtr = bp->inPtr - bp->outPtr; 326 } 327 328 return (bp->outPtr); 329 } 330 331 /*- 332 *----------------------------------------------------------------------- 333 * Buf_Discard -- 334 * Throw away bytes in a buffer. 335 * 336 * Results: 337 * None. 338 * 339 * Side Effects: 340 * The bytes are discarded. 341 * 342 *----------------------------------------------------------------------- 343 */ 344 void 345 Buf_Discard (bp, numBytes) 346 register Buffer bp; 347 int numBytes; 348 { 349 350 if (bp->inPtr - bp->outPtr <= numBytes) { 351 bp->inPtr = bp->outPtr = bp->buffer; 352 bp->left = bp->size; 353 *bp->inPtr = 0; 354 } else { 355 bp->outPtr += numBytes; 356 } 357 } 358 359 /*- 360 *----------------------------------------------------------------------- 361 * Buf_Size -- 362 * Returns the number of bytes in the given buffer. Doesn't include 363 * the null-terminating byte. 364 * 365 * Results: 366 * The number of bytes. 367 * 368 * Side Effects: 369 * None. 370 * 371 *----------------------------------------------------------------------- 372 */ 373 int 374 Buf_Size (buf) 375 Buffer buf; 376 { 377 return (buf->inPtr - buf->outPtr); 378 } 379 380 /*- 381 *----------------------------------------------------------------------- 382 * Buf_Init -- 383 * Initialize a buffer. If no initial size is given, a reasonable 384 * default is used. 385 * 386 * Results: 387 * A buffer to be given to other functions in this library. 388 * 389 * Side Effects: 390 * The buffer is created, the space allocated and pointers 391 * initialized. 392 * 393 *----------------------------------------------------------------------- 394 */ 395 Buffer 396 Buf_Init (size) 397 int size; /* Initial size for the buffer */ 398 { 399 Buffer bp; /* New Buffer */ 400 401 bp = (Buffer)emalloc(sizeof(*bp)); 402 403 if (size <= 0) { 404 size = BUF_DEF_SIZE; 405 } 406 bp->left = bp->size = size; 407 bp->buffer = (Byte *)emalloc(size); 408 bp->inPtr = bp->outPtr = bp->buffer; 409 *bp->inPtr = 0; 410 411 return (bp); 412 } 413 414 /*- 415 *----------------------------------------------------------------------- 416 * Buf_Destroy -- 417 * Nuke a buffer and all its resources. 418 * 419 * Results: 420 * None. 421 * 422 * Side Effects: 423 * The buffer is freed. 424 * 425 *----------------------------------------------------------------------- 426 */ 427 void 428 Buf_Destroy (buf, freeData) 429 Buffer buf; /* Buffer to destroy */ 430 Boolean freeData; /* TRUE if the data should be destroyed as well */ 431 { 432 433 if (freeData) { 434 free ((char *)buf->buffer); 435 } 436 free ((char *)buf); 437 } 438