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