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