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