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