buf.c revision 1590
1/* 2 * Copyright (c) 1988, 1989, 1990, 1993 3 * The Regents of the University of California. All rights reserved. 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 40static char sccsid[] = "@(#)buf.c 8.1 (Berkeley) 6/6/93"; 41#endif /* not lint */ 42 43/*- 44 * buf.c -- 45 * Functions for automatically-expanded buffers. 46 */ 47 48#include "sprite.h" 49#include "make.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 */ 92void 93Buf_OvAddByte (bp, byte) 94 register Buffer bp; 95 int 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 */ 123void 124Buf_AddBytes (bp, numBytes, bytesPtr) 125 register Buffer bp; 126 int numBytes; 127 Byte *bytesPtr; 128{ 129 130 BufExpand (bp, numBytes); 131 132 memcpy (bp->inPtr, bytesPtr, 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 */ 155void 156Buf_UngetByte (bp, byte) 157 register Buffer bp; 158 int 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 memcpy ((char *)(newBuf+BUF_UNGET_INC), (char *)bp->outPtr, 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 */ 205void 206Buf_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 memcpy (bp->outPtr, bytesPtr, 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 memcpy((char *)(newBuf+newBytes), (char *)bp->outPtr, 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 memcpy ((char *)bp->outPtr, (char *)bytesPtr, 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 */ 250int 251Buf_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 */ 283int 284Buf_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 memcpy (bytesPtr, bp->outPtr, 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 */ 317Byte * 318Buf_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 */ 343void 344Buf_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 */ 372int 373Buf_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 */ 394Buffer 395Buf_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 */ 426void 427Buf_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