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