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 /*static char sccsid[] = "from: @(#)buf.c 5.5 (Berkeley) 12/28/90";*/ 41 static char rcsid[] = "$Id: buf.c,v 1.2 1993/08/01 18:11:55 mycroft Exp $"; 42 #endif /* not lint */ 43 44 /*- 45 * buf.c -- 46 * Functions for automatically-expanded buffers. 47 */ 48 49 #include "sprite.h" 50 #include "buf.h" 51 52 #ifndef max 53 #define max(a,b) ((a) > (b) ? (a) : (b)) 54 #endif 55 56 /* 57 * BufExpand -- 58 * Expand the given buffer to hold the given number of additional 59 * bytes. 60 * Makes sure there's room for an extra NULL byte at the end of the 61 * buffer in case it holds a string. 62 */ 63 #define BufExpand(bp,nb) \ 64 if (bp->left < (nb)+1) {\ 65 int newSize = (bp)->size + max((nb)+1,BUF_ADD_INC); \ 66 Byte *newBuf = (Byte *) realloc((bp)->buffer, newSize); \ 67 \ 68 (bp)->inPtr = newBuf + ((bp)->inPtr - (bp)->buffer); \ 69 (bp)->outPtr = newBuf + ((bp)->outPtr - (bp)->buffer);\ 70 (bp)->buffer = newBuf;\ 71 (bp)->size = newSize;\ 72 (bp)->left = newSize - ((bp)->inPtr - (bp)->buffer);\ 73 } 74 75 #define BUF_DEF_SIZE 256 /* Default buffer size */ 76 #define BUF_ADD_INC 256 /* Expansion increment when Adding */ 77 #define BUF_UNGET_INC 16 /* Expansion increment when Ungetting */ 78 79 /*- 80 *----------------------------------------------------------------------- 81 * Buf_OvAddByte -- 82 * Add a single byte to the buffer. left is zero or negative. 83 * 84 * Results: 85 * None. 86 * 87 * Side Effects: 88 * The buffer may be expanded. 89 * 90 *----------------------------------------------------------------------- 91 */ 92 void 93 Buf_OvAddByte (bp, byte) 94 register Buffer bp; 95 Byte byte; 96 { 97 98 bp->left = 0; 99 BufExpand (bp, 1); 100 101 *bp->inPtr++ = byte; 102 bp->left--; 103 104 /* 105 * Null-terminate 106 */ 107 *bp->inPtr = 0; 108 } 109 110 /*- 111 *----------------------------------------------------------------------- 112 * Buf_AddBytes -- 113 * Add a number of bytes to the buffer. 114 * 115 * Results: 116 * None. 117 * 118 * Side Effects: 119 * Guess what? 120 * 121 *----------------------------------------------------------------------- 122 */ 123 void 124 Buf_AddBytes (bp, numBytes, bytesPtr) 125 register Buffer bp; 126 int numBytes; 127 Byte *bytesPtr; 128 { 129 130 BufExpand (bp, numBytes); 131 132 bcopy (bytesPtr, bp->inPtr, numBytes); 133 bp->inPtr += numBytes; 134 bp->left -= numBytes; 135 136 /* 137 * Null-terminate 138 */ 139 *bp->inPtr = 0; 140 } 141 142 /*- 143 *----------------------------------------------------------------------- 144 * Buf_UngetByte -- 145 * Place the byte back at the beginning of the buffer. 146 * 147 * Results: 148 * SUCCESS if the byte was added ok. FAILURE if not. 149 * 150 * Side Effects: 151 * The byte is stuffed in the buffer and outPtr is decremented. 152 * 153 *----------------------------------------------------------------------- 154 */ 155 void 156 Buf_UngetByte (bp, byte) 157 register Buffer bp; 158 Byte byte; 159 { 160 161 if (bp->outPtr != bp->buffer) { 162 bp->outPtr--; 163 *bp->outPtr = byte; 164 } else if (bp->outPtr == bp->inPtr) { 165 *bp->inPtr = byte; 166 bp->inPtr++; 167 bp->left--; 168 *bp->inPtr = 0; 169 } else { 170 /* 171 * Yech. have to expand the buffer to stuff this thing in. 172 * We use a different expansion constant because people don't 173 * usually push back many bytes when they're doing it a byte at 174 * a time... 175 */ 176 int numBytes = bp->inPtr - bp->outPtr; 177 Byte *newBuf; 178 179 newBuf = (Byte *)emalloc(bp->size + BUF_UNGET_INC); 180 bcopy ((char *)bp->outPtr, 181 (char *)(newBuf+BUF_UNGET_INC), 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 bcopy (bytesPtr, bp->outPtr, 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 bcopy((char *)bp->outPtr, (char *)(newBuf+newBytes), 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 bcopy ((char *)bytesPtr, (char *)bp->outPtr, 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 bcopy (bp->outPtr, bytesPtr, 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