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