buf.c revision 18804
1238730Sdelphij/*
2238730Sdelphij * Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
3238730Sdelphij * Copyright (c) 1988, 1989 by Adam de Boor
4238730Sdelphij * Copyright (c) 1989 by Berkeley Softworks
5238730Sdelphij * All rights reserved.
6238730Sdelphij *
7238730Sdelphij * This code is derived from software contributed to Berkeley by
8238730Sdelphij * Adam de Boor.
960786Sps *
1063120Sps * Redistribution and use in source and binary forms, with or without
1160786Sps * modification, are permitted provided that the following conditions
1260786Sps * are met:
1360786Sps * 1. Redistributions of source code must retain the above copyright
1460786Sps *    notice, this list of conditions and the following disclaimer.
1560786Sps * 2. Redistributions in binary form must reproduce the above copyright
1660786Sps *    notice, this list of conditions and the following disclaimer in the
1760786Sps *    documentation and/or other materials provided with the distribution.
1860786Sps * 3. All advertising materials mentioning features or use of this software
1960786Sps *    must display the following acknowledgement:
2060786Sps *	This product includes software developed by the University of
2160786Sps *	California, Berkeley and its contributors.
2260786Sps * 4. Neither the name of the University nor the names of its contributors
2360786Sps *    may be used to endorse or promote products derived from this software
2460786Sps *    without specific prior written permission.
2560786Sps *
2660786Sps * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2760786Sps * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2860786Sps * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2960786Sps * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
3060786Sps * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
3160786Sps * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
3260786Sps * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3360786Sps * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3460786Sps * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3560786Sps * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36161478Sdelphij * SUCH DAMAGE.
37170259Sdelphij *
38170259Sdelphij *	$Id$
3960786Sps */
4060786Sps
4160786Sps#ifndef lint
4260786Spsstatic char sccsid[] = "@(#)buf.c	8.1 (Berkeley) 6/6/93";
4360786Sps#endif /* not lint */
4460786Sps
4560786Sps/*-
4660786Sps * buf.c --
4760786Sps *	Functions for automatically-expanded buffers.
48191930Sdelphij */
4960786Sps
5060786Sps#include    "sprite.h"
5160786Sps#include    "make.h"
5260786Sps#include    "buf.h"
5360786Sps
5460786Sps#ifndef max
5560786Sps#define max(a,b)  ((a) > (b) ? (a) : (b))
5660786Sps#endif
5760786Sps
5860786Sps/*
5960786Sps * BufExpand --
6060786Sps * 	Expand the given buffer to hold the given number of additional
6160786Sps *	bytes.
6260786Sps *	Makes sure there's room for an extra NULL byte at the end of the
63170259Sdelphij *	buffer in case it holds a string.
6463120Sps */
6560786Sps#define BufExpand(bp,nb) \
66191930Sdelphij 	if (bp->left < (nb)+1) {\
6760786Sps	    int newSize = (bp)->size + max((nb)+1,BUF_ADD_INC); \
6860786Sps	    Byte  *newBuf = (Byte *) erealloc((bp)->buffer, newSize); \
6960786Sps	    \
7060786Sps	    (bp)->inPtr = newBuf + ((bp)->inPtr - (bp)->buffer); \
7160786Sps	    (bp)->outPtr = newBuf + ((bp)->outPtr - (bp)->buffer);\
7260786Sps	    (bp)->buffer = newBuf;\
7360786Sps	    (bp)->size = newSize;\
7460786Sps	    (bp)->left = newSize - ((bp)->inPtr - (bp)->buffer);\
7560786Sps	}
7660786Sps
7760786Sps#define BUF_DEF_SIZE	256 	/* Default buffer size */
7860786Sps#define BUF_ADD_INC	256 	/* Expansion increment when Adding */
7960786Sps#define BUF_UNGET_INC	16  	/* Expansion increment when Ungetting */
8060786Sps
8160786Sps/*-
8260786Sps *-----------------------------------------------------------------------
8360786Sps * Buf_OvAddByte --
8460786Sps *	Add a single byte to the buffer.  left is zero or negative.
8560786Sps *
8660786Sps * Results:
8760786Sps *	None.
8860786Sps *
8960786Sps * Side Effects:
9060786Sps *	The buffer may be expanded.
9160786Sps *
9260786Sps *-----------------------------------------------------------------------
9360786Sps */
9460786Spsvoid
9560786SpsBuf_OvAddByte (bp, byte)
96172471Sdelphij    register Buffer bp;
97172471Sdelphij    int    byte;
9860786Sps{
9960786Sps    int nbytes = 1;
10060786Sps    bp->left = 0;
10160786Sps    BufExpand (bp, nbytes);
10260786Sps
10360786Sps    *bp->inPtr++ = byte;
10460786Sps    bp->left--;
10560786Sps
10660786Sps    /*
10760786Sps     * Null-terminate
10860786Sps     */
10960786Sps    *bp->inPtr = 0;
11060786Sps}
11160786Sps
11260786Sps/*-
11360786Sps *-----------------------------------------------------------------------
11460786Sps * Buf_AddBytes --
11560786Sps *	Add a number of bytes to the buffer.
11660786Sps *
11760786Sps * Results:
11860786Sps *	None.
11960786Sps *
12060786Sps * Side Effects:
12160786Sps *	Guess what?
12260786Sps *
12360786Sps *-----------------------------------------------------------------------
12460786Sps */
12560786Spsvoid
12660786SpsBuf_AddBytes (bp, numBytes, bytesPtr)
12760786Sps    register Buffer bp;
12860786Sps    int	    numBytes;
12960786Sps    Byte    *bytesPtr;
13060786Sps{
13160786Sps
13260786Sps    BufExpand (bp, numBytes);
13360786Sps
13460786Sps    memcpy (bp->inPtr, bytesPtr, numBytes);
13560786Sps    bp->inPtr += numBytes;
13660786Sps    bp->left -= numBytes;
13760786Sps
13860786Sps    /*
13960786Sps     * Null-terminate
14060786Sps     */
14160786Sps    *bp->inPtr = 0;
14260786Sps}
14360786Sps
14460786Sps/*-
14560786Sps *-----------------------------------------------------------------------
14660786Sps * Buf_UngetByte --
14760786Sps *	Place the byte back at the beginning of the buffer.
14860786Sps *
14960786Sps * Results:
15060786Sps *	SUCCESS if the byte was added ok. FAILURE if not.
15160786Sps *
15260786Sps * Side Effects:
15360786Sps *	The byte is stuffed in the buffer and outPtr is decremented.
15460786Sps *
15560786Sps *-----------------------------------------------------------------------
15660786Sps */
15760786Spsvoid
15860786SpsBuf_UngetByte (bp, byte)
15960786Sps    register Buffer bp;
16060786Sps    int    byte;
161170259Sdelphij{
16260786Sps
16360786Sps    if (bp->outPtr != bp->buffer) {
16460786Sps	bp->outPtr--;
16560786Sps	*bp->outPtr = byte;
16660786Sps    } else if (bp->outPtr == bp->inPtr) {
16760786Sps	*bp->inPtr = byte;
16860786Sps	bp->inPtr++;
16960786Sps	bp->left--;
17060786Sps	*bp->inPtr = 0;
17160786Sps    } else {
17260786Sps	/*
17360786Sps	 * Yech. have to expand the buffer to stuff this thing in.
17460786Sps	 * We use a different expansion constant because people don't
17560786Sps	 * usually push back many bytes when they're doing it a byte at
17660786Sps	 * a time...
17760786Sps	 */
17860786Sps	int 	  numBytes = bp->inPtr - bp->outPtr;
17960786Sps	Byte	  *newBuf;
18060786Sps
18160786Sps	newBuf = (Byte *)emalloc(bp->size + BUF_UNGET_INC);
18260786Sps	memcpy ((char *)(newBuf+BUF_UNGET_INC), (char *)bp->outPtr, numBytes+1);
18360786Sps	bp->outPtr = newBuf + BUF_UNGET_INC;
18460786Sps	bp->inPtr = bp->outPtr + numBytes;
18560786Sps	free ((char *)bp->buffer);
18660786Sps	bp->buffer = newBuf;
18760786Sps	bp->size += BUF_UNGET_INC;
18860786Sps	bp->left = bp->size - (bp->inPtr - bp->buffer);
18960786Sps	bp->outPtr -= 1;
19060786Sps	*bp->outPtr = byte;
19160786Sps    }
19260786Sps}
19360786Sps
19460786Sps/*-
19560786Sps *-----------------------------------------------------------------------
19660786Sps * Buf_UngetBytes --
19760786Sps *	Push back a series of bytes at the beginning of the buffer.
19860786Sps *
19960786Sps * Results:
20060786Sps *	None.
20160786Sps *
20260786Sps * Side Effects:
20360786Sps *	outPtr is decremented and the bytes copied into the buffer.
20460786Sps *
20560786Sps *-----------------------------------------------------------------------
20660786Sps */
20760786Spsvoid
20860786SpsBuf_UngetBytes (bp, numBytes, bytesPtr)
20960786Sps    register Buffer bp;
21060786Sps    int	    numBytes;
21160786Sps    Byte    *bytesPtr;
21260786Sps{
21360786Sps
21460786Sps    if (bp->outPtr - bp->buffer >= numBytes) {
21560786Sps	bp->outPtr -= numBytes;
21660786Sps	memcpy (bp->outPtr, bytesPtr, numBytes);
21760786Sps    } else if (bp->outPtr == bp->inPtr) {
21860786Sps	Buf_AddBytes (bp, numBytes, bytesPtr);
21960786Sps    } else {
22060786Sps	int 	  curNumBytes = bp->inPtr - bp->outPtr;
22160786Sps	Byte	  *newBuf;
22260786Sps	int 	  newBytes = max(numBytes,BUF_UNGET_INC);
22360786Sps
22460786Sps	newBuf = (Byte *)emalloc (bp->size + newBytes);
22560786Sps	memcpy((char *)(newBuf+newBytes), (char *)bp->outPtr, curNumBytes+1);
22660786Sps	bp->outPtr = newBuf + newBytes;
22760786Sps	bp->inPtr = bp->outPtr + curNumBytes;
22860786Sps	free ((char *)bp->buffer);
22960786Sps	bp->buffer = newBuf;
23060786Sps	bp->size += newBytes;
23160786Sps	bp->left = bp->size - (bp->inPtr - bp->buffer);
23260786Sps	bp->outPtr -= numBytes;
23360786Sps	memcpy ((char *)bp->outPtr, (char *)bytesPtr, numBytes);
23460786Sps    }
23560786Sps}
23660786Sps
23760786Sps/*-
23860786Sps *-----------------------------------------------------------------------
23960786Sps * Buf_GetByte --
24060786Sps *	Return the next byte from the buffer. Actually returns an integer.
24160786Sps *
24260786Sps * Results:
24360786Sps *	Returns BUF_ERROR if there's no byte in the buffer, or the byte
24460786Sps *	itself if there is one.
24560786Sps *
24660786Sps * Side Effects:
24760786Sps *	outPtr is incremented and both outPtr and inPtr will be reset if
24860786Sps *	the buffer is emptied.
249170259Sdelphij *
250195941Sdelphij *-----------------------------------------------------------------------
25160786Sps */
25260786Spsint
25360786SpsBuf_GetByte (bp)
25460786Sps    register Buffer bp;
25560786Sps{
25660786Sps    int	    res;
257161478Sdelphij
258221715Sdelphij    if (bp->inPtr == bp->outPtr) {
25960786Sps	return (BUF_ERROR);
26060786Sps    } else {
261	res = (int) *bp->outPtr;
262	bp->outPtr += 1;
263	if (bp->outPtr == bp->inPtr) {
264	    bp->outPtr = bp->inPtr = bp->buffer;
265	    bp->left = bp->size;
266	    *bp->inPtr = 0;
267	}
268	return (res);
269    }
270}
271
272/*-
273 *-----------------------------------------------------------------------
274 * Buf_GetBytes --
275 *	Extract a number of bytes from the buffer.
276 *
277 * Results:
278 *	The number of bytes gotten.
279 *
280 * Side Effects:
281 *	The passed array is overwritten.
282 *
283 *-----------------------------------------------------------------------
284 */
285int
286Buf_GetBytes (bp, numBytes, bytesPtr)
287    register Buffer bp;
288    int	    numBytes;
289    Byte    *bytesPtr;
290{
291
292    if (bp->inPtr - bp->outPtr < numBytes) {
293	numBytes = bp->inPtr - bp->outPtr;
294    }
295    memcpy (bytesPtr, bp->outPtr, numBytes);
296    bp->outPtr += numBytes;
297
298    if (bp->outPtr == bp->inPtr) {
299	bp->outPtr = bp->inPtr = bp->buffer;
300	bp->left = bp->size;
301	*bp->inPtr = 0;
302    }
303    return (numBytes);
304}
305
306/*-
307 *-----------------------------------------------------------------------
308 * Buf_GetAll --
309 *	Get all the available data at once.
310 *
311 * Results:
312 *	A pointer to the data and the number of bytes available.
313 *
314 * Side Effects:
315 *	None.
316 *
317 *-----------------------------------------------------------------------
318 */
319Byte *
320Buf_GetAll (bp, numBytesPtr)
321    register Buffer bp;
322    int	    *numBytesPtr;
323{
324
325    if (numBytesPtr != (int *)NULL) {
326	*numBytesPtr = bp->inPtr - bp->outPtr;
327    }
328
329    return (bp->outPtr);
330}
331
332/*-
333 *-----------------------------------------------------------------------
334 * Buf_Discard --
335 *	Throw away bytes in a buffer.
336 *
337 * Results:
338 *	None.
339 *
340 * Side Effects:
341 *	The bytes are discarded.
342 *
343 *-----------------------------------------------------------------------
344 */
345void
346Buf_Discard (bp, numBytes)
347    register Buffer bp;
348    int	    numBytes;
349{
350
351    if (bp->inPtr - bp->outPtr <= numBytes) {
352	bp->inPtr = bp->outPtr = bp->buffer;
353	bp->left = bp->size;
354	*bp->inPtr = 0;
355    } else {
356	bp->outPtr += numBytes;
357    }
358}
359
360/*-
361 *-----------------------------------------------------------------------
362 * Buf_Size --
363 *	Returns the number of bytes in the given buffer. Doesn't include
364 *	the null-terminating byte.
365 *
366 * Results:
367 *	The number of bytes.
368 *
369 * Side Effects:
370 *	None.
371 *
372 *-----------------------------------------------------------------------
373 */
374int
375Buf_Size (buf)
376    Buffer  buf;
377{
378    return (buf->inPtr - buf->outPtr);
379}
380
381/*-
382 *-----------------------------------------------------------------------
383 * Buf_Init --
384 *	Initialize a buffer. If no initial size is given, a reasonable
385 *	default is used.
386 *
387 * Results:
388 *	A buffer to be given to other functions in this library.
389 *
390 * Side Effects:
391 *	The buffer is created, the space allocated and pointers
392 *	initialized.
393 *
394 *-----------------------------------------------------------------------
395 */
396Buffer
397Buf_Init (size)
398    int	    size; 	/* Initial size for the buffer */
399{
400    Buffer bp;	  	/* New Buffer */
401
402    bp = (Buffer)emalloc(sizeof(*bp));
403
404    if (size <= 0) {
405	size = BUF_DEF_SIZE;
406    }
407    bp->left = bp->size = size;
408    bp->buffer = (Byte *)emalloc(size);
409    bp->inPtr = bp->outPtr = bp->buffer;
410    *bp->inPtr = 0;
411
412    return (bp);
413}
414
415/*-
416 *-----------------------------------------------------------------------
417 * Buf_Destroy --
418 *	Nuke a buffer and all its resources.
419 *
420 * Results:
421 *	None.
422 *
423 * Side Effects:
424 *	The buffer is freed.
425 *
426 *-----------------------------------------------------------------------
427 */
428void
429Buf_Destroy (buf, freeData)
430    Buffer  buf;  	/* Buffer to destroy */
431    Boolean freeData;	/* TRUE if the data should be destroyed as well */
432{
433
434    if (freeData) {
435	free ((char *)buf->buffer);
436    }
437    free ((char *)buf);
438}
439
440/*-
441 *-----------------------------------------------------------------------
442 * Buf_ReplaceLastByte --
443 *     Replace the last byte in a buffer.
444 *
445 * Results:
446 *     None.
447 *
448 * Side Effects:
449 *     If the buffer was empty intially, then a new byte will be added.
450 *     Otherwise, the last byte is overwritten.
451 *
452 *-----------------------------------------------------------------------
453 */
454void
455Buf_ReplaceLastByte (buf, byte)
456    Buffer buf;	/* buffer to augment */
457    Byte byte;	/* byte to be written */
458{
459    if (buf->inPtr == buf->outPtr)
460        Buf_AddByte(buf, byte);
461    else
462        *(buf->inPtr - 1) = byte;
463}
464