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