buf.c revision 141104
1141104Sharti/*-
294589Sobrien * Copyright (c) 1988, 1989, 1990, 1993
394589Sobrien *	The Regents of the University of California.  All rights reserved.
45814Sjkh * Copyright (c) 1988, 1989 by Adam de Boor
51590Srgrimes * Copyright (c) 1989 by Berkeley Softworks
61590Srgrimes * All rights reserved.
71590Srgrimes *
81590Srgrimes * This code is derived from software contributed to Berkeley by
91590Srgrimes * Adam de Boor.
101590Srgrimes *
111590Srgrimes * Redistribution and use in source and binary forms, with or without
121590Srgrimes * modification, are permitted provided that the following conditions
131590Srgrimes * are met:
141590Srgrimes * 1. Redistributions of source code must retain the above copyright
151590Srgrimes *    notice, this list of conditions and the following disclaimer.
161590Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
171590Srgrimes *    notice, this list of conditions and the following disclaimer in the
181590Srgrimes *    documentation and/or other materials provided with the distribution.
191590Srgrimes * 3. All advertising materials mentioning features or use of this software
201590Srgrimes *    must display the following acknowledgement:
211590Srgrimes *	This product includes software developed by the University of
221590Srgrimes *	California, Berkeley and its contributors.
231590Srgrimes * 4. Neither the name of the University nor the names of its contributors
241590Srgrimes *    may be used to endorse or promote products derived from this software
251590Srgrimes *    without specific prior written permission.
261590Srgrimes *
271590Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
281590Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
291590Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
301590Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
311590Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
321590Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
331590Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
341590Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
351590Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
361590Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
371590Srgrimes * SUCH DAMAGE.
3862833Swsanchez *
3962833Swsanchez * @(#)buf.c	8.1 (Berkeley) 6/6/93
401590Srgrimes */
411590Srgrimes
4262833Swsanchez#include <sys/cdefs.h>
4394587Sobrien__FBSDID("$FreeBSD: head/usr.bin/make/buf.c 141104 2005-02-01 10:50:37Z harti $");
441590Srgrimes
451590Srgrimes/*-
461590Srgrimes * buf.c --
471590Srgrimes *	Functions for automatically-expanded buffers.
481590Srgrimes */
491590Srgrimes
50141104Sharti#include <string.h>
51141104Sharti#include <stdlib.h>
52141104Sharti
53141104Sharti#include "buf.h"
54138337Sharti#include "sprite.h"
55141104Sharti#include "util.h"
561590Srgrimes
571590Srgrimes#ifndef max
58103503Sjmallett#define	max(a,b)  ((a) > (b) ? (a) : (b))
591590Srgrimes#endif
601590Srgrimes
611590Srgrimes/*
621590Srgrimes * BufExpand --
631590Srgrimes * 	Expand the given buffer to hold the given number of additional
641590Srgrimes *	bytes.
651590Srgrimes *	Makes sure there's room for an extra NULL byte at the end of the
661590Srgrimes *	buffer in case it holds a string.
671590Srgrimes */
68138337Sharti#define	BufExpand(bp, nb) do {						\
69138342Sharti 	if ((bp)->left < (nb) + 1) {					\
70138337Sharti		int newSize = (bp)->size + max((nb) + 1, BUF_ADD_INC);	\
71138347Sharti		Byte *newBuf = erealloc((bp)->buffer, newSize);		\
72138337Sharti									\
73138337Sharti		(bp)->inPtr = newBuf + ((bp)->inPtr - (bp)->buffer);	\
74138337Sharti		(bp)->outPtr = newBuf + ((bp)->outPtr - (bp)->buffer);	\
75138337Sharti		(bp)->buffer = newBuf;					\
76138337Sharti		(bp)->size = newSize;					\
77138337Sharti		(bp)->left = newSize - ((bp)->inPtr - (bp)->buffer);	\
78138337Sharti	}								\
79138337Sharti    } while (0)
801590Srgrimes
81103503Sjmallett#define	BUF_DEF_SIZE	256 	/* Default buffer size */
82103503Sjmallett#define	BUF_ADD_INC	256 	/* Expansion increment when Adding */
83103503Sjmallett#define	BUF_UNGET_INC	16  	/* Expansion increment when Ungetting */
841590Srgrimes
851590Srgrimes/*-
861590Srgrimes *-----------------------------------------------------------------------
871590Srgrimes * Buf_OvAddByte --
881590Srgrimes *	Add a single byte to the buffer.  left is zero or negative.
891590Srgrimes *
901590Srgrimes * Results:
911590Srgrimes *	None.
921590Srgrimes *
931590Srgrimes * Side Effects:
941590Srgrimes *	The buffer may be expanded.
951590Srgrimes *
961590Srgrimes *-----------------------------------------------------------------------
971590Srgrimes */
981590Srgrimesvoid
99138341ShartiBuf_OvAddByte(Buffer bp, Byte byte)
1001590Srgrimes{
101138264Sharti
102138337Sharti	bp->left = 0;
103138337Sharti	BufExpand(bp, 1);
1041590Srgrimes
105138337Sharti	*bp->inPtr++ = byte;
106138337Sharti	bp->left--;
1071590Srgrimes
108138337Sharti	/*
109138337Sharti	 * Null-terminate
110138337Sharti	 */
111138337Sharti	*bp->inPtr = 0;
1121590Srgrimes}
113138232Sharti
1141590Srgrimes/*-
1151590Srgrimes *-----------------------------------------------------------------------
1161590Srgrimes * Buf_AddBytes --
1171590Srgrimes *	Add a number of bytes to the buffer.
1181590Srgrimes *
1191590Srgrimes * Results:
1201590Srgrimes *	None.
1211590Srgrimes *
1221590Srgrimes * Side Effects:
1231590Srgrimes *	Guess what?
1241590Srgrimes *
1251590Srgrimes *-----------------------------------------------------------------------
1261590Srgrimes */
1271590Srgrimesvoid
128138341ShartiBuf_AddBytes(Buffer bp, size_t numBytes, const Byte *bytesPtr)
1291590Srgrimes{
1301590Srgrimes
131138337Sharti	BufExpand(bp, numBytes);
1321590Srgrimes
133138337Sharti	memcpy(bp->inPtr, bytesPtr, numBytes);
134138337Sharti	bp->inPtr += numBytes;
135138337Sharti	bp->left -= numBytes;
1361590Srgrimes
137138337Sharti	/*
138138337Sharti	 * Null-terminate
139138337Sharti	 */
140138337Sharti	*bp->inPtr = 0;
1411590Srgrimes}
142138232Sharti
1431590Srgrimes/*-
1441590Srgrimes *-----------------------------------------------------------------------
1451590Srgrimes * Buf_UngetByte --
1461590Srgrimes *	Place the byte back at the beginning of the buffer.
1471590Srgrimes *
1481590Srgrimes * Results:
1491590Srgrimes *	SUCCESS if the byte was added ok. FAILURE if not.
1501590Srgrimes *
1511590Srgrimes * Side Effects:
1521590Srgrimes *	The byte is stuffed in the buffer and outPtr is decremented.
1531590Srgrimes *
1541590Srgrimes *-----------------------------------------------------------------------
1551590Srgrimes */
1561590Srgrimesvoid
157138341ShartiBuf_UngetByte(Buffer bp, Byte byte)
1581590Srgrimes{
1591590Srgrimes
160138337Sharti	if (bp->outPtr != bp->buffer) {
161138337Sharti		bp->outPtr--;
162138337Sharti		*bp->outPtr = byte;
1631590Srgrimes
164138337Sharti	} else if (bp->outPtr == bp->inPtr) {
165138337Sharti		*bp->inPtr = byte;
166138337Sharti		bp->inPtr++;
167138337Sharti		bp->left--;
168138337Sharti		*bp->inPtr = 0;
169138337Sharti
170138337Sharti	} else {
171138337Sharti		/*
172138337Sharti		 * Yech. have to expand the buffer to stuff this thing in.
173138337Sharti		 * We use a different expansion constant because people don't
174138337Sharti		 * usually push back many bytes when they're doing it a byte at
175138337Sharti		 * a time...
176138337Sharti		 */
177138341Sharti		size_t numBytes = bp->inPtr - bp->outPtr;
178138337Sharti		Byte *newBuf;
179138337Sharti
180138337Sharti		newBuf = emalloc(bp->size + BUF_UNGET_INC);
181138337Sharti		memcpy(newBuf + BUF_UNGET_INC, bp->outPtr, numBytes + 1);
182138337Sharti		bp->outPtr = newBuf + BUF_UNGET_INC;
183138337Sharti		bp->inPtr = bp->outPtr + numBytes;
184138337Sharti		free(bp->buffer);
185138337Sharti		bp->buffer = newBuf;
186138337Sharti		bp->size += BUF_UNGET_INC;
187138337Sharti		bp->left = bp->size - (bp->inPtr - bp->buffer);
188138337Sharti		bp->outPtr -= 1;
189138337Sharti		*bp->outPtr = byte;
190138337Sharti	}
1911590Srgrimes}
192138232Sharti
1931590Srgrimes/*-
1941590Srgrimes *-----------------------------------------------------------------------
1951590Srgrimes * Buf_UngetBytes --
1961590Srgrimes *	Push back a series of bytes at the beginning of the buffer.
1971590Srgrimes *
1981590Srgrimes * Results:
1991590Srgrimes *	None.
2001590Srgrimes *
2011590Srgrimes * Side Effects:
2021590Srgrimes *	outPtr is decremented and the bytes copied into the buffer.
2031590Srgrimes *
2041590Srgrimes *-----------------------------------------------------------------------
2051590Srgrimes */
2061590Srgrimesvoid
207138341ShartiBuf_UngetBytes(Buffer bp, size_t numBytes, Byte *bytesPtr)
2081590Srgrimes{
2091590Srgrimes
210138341Sharti	if ((size_t)(bp->outPtr - bp->buffer) >= numBytes) {
211138337Sharti		bp->outPtr -= numBytes;
212138337Sharti		memcpy(bp->outPtr, bytesPtr, numBytes);
213138337Sharti	} else if (bp->outPtr == bp->inPtr) {
214138337Sharti		Buf_AddBytes(bp, numBytes, bytesPtr);
215138337Sharti	} else {
216138341Sharti		size_t curNumBytes = bp->inPtr - bp->outPtr;
217138337Sharti		Byte *newBuf;
218138341Sharti		size_t newBytes = max(numBytes, BUF_UNGET_INC);
2191590Srgrimes
220138337Sharti		newBuf = emalloc(bp->size + newBytes);
221138337Sharti		memcpy(newBuf + newBytes, bp->outPtr, curNumBytes + 1);
222138337Sharti		bp->outPtr = newBuf + newBytes;
223138337Sharti		bp->inPtr = bp->outPtr + curNumBytes;
224138337Sharti		free(bp->buffer);
225138337Sharti		bp->buffer = newBuf;
226138337Sharti		bp->size += newBytes;
227138337Sharti		bp->left = bp->size - (bp->inPtr - bp->buffer);
228138337Sharti		bp->outPtr -= numBytes;
229138337Sharti		memcpy(bp->outPtr, bytesPtr, numBytes);
230138337Sharti	}
2311590Srgrimes}
232138232Sharti
2331590Srgrimes/*-
2341590Srgrimes *-----------------------------------------------------------------------
2351590Srgrimes * Buf_GetByte --
2361590Srgrimes *	Return the next byte from the buffer. Actually returns an integer.
2371590Srgrimes *
2381590Srgrimes * Results:
2391590Srgrimes *	Returns BUF_ERROR if there's no byte in the buffer, or the byte
2401590Srgrimes *	itself if there is one.
2411590Srgrimes *
2421590Srgrimes * Side Effects:
2431590Srgrimes *	outPtr is incremented and both outPtr and inPtr will be reset if
2441590Srgrimes *	the buffer is emptied.
2451590Srgrimes *
2461590Srgrimes *-----------------------------------------------------------------------
2471590Srgrimes */
2481590Srgrimesint
249138232ShartiBuf_GetByte(Buffer bp)
2501590Srgrimes{
251138337Sharti	int res;
2521590Srgrimes
253138337Sharti	if (bp->inPtr == bp->outPtr)
254138337Sharti		return (BUF_ERROR);
255138337Sharti
256138232Sharti	res = (int)*bp->outPtr;
2571590Srgrimes	bp->outPtr += 1;
2581590Srgrimes	if (bp->outPtr == bp->inPtr) {
259138337Sharti		bp->outPtr = bp->inPtr = bp->buffer;
260138337Sharti		bp->left = bp->size;
261138337Sharti		*bp->inPtr = 0;
2621590Srgrimes	}
2631590Srgrimes	return (res);
2641590Srgrimes}
265138232Sharti
2661590Srgrimes/*-
2671590Srgrimes *-----------------------------------------------------------------------
2681590Srgrimes * Buf_GetBytes --
2691590Srgrimes *	Extract a number of bytes from the buffer.
2701590Srgrimes *
2711590Srgrimes * Results:
2721590Srgrimes *	The number of bytes gotten.
2731590Srgrimes *
2741590Srgrimes * Side Effects:
2751590Srgrimes *	The passed array is overwritten.
2761590Srgrimes *
2771590Srgrimes *-----------------------------------------------------------------------
2781590Srgrimes */
2791590Srgrimesint
280138341ShartiBuf_GetBytes(Buffer bp, size_t numBytes, Byte *bytesPtr)
2811590Srgrimes{
2828874Srgrimes
283138341Sharti	if ((size_t)(bp->inPtr - bp->outPtr) < numBytes)
284138337Sharti		numBytes = bp->inPtr - bp->outPtr;
2851590Srgrimes
286138337Sharti	memcpy(bytesPtr, bp->outPtr, numBytes);
287138337Sharti	bp->outPtr += numBytes;
288138337Sharti
289138337Sharti	if (bp->outPtr == bp->inPtr) {
290138337Sharti		bp->outPtr = bp->inPtr = bp->buffer;
291138337Sharti		bp->left = bp->size;
292138337Sharti		*bp->inPtr = 0;
293138337Sharti	}
294138337Sharti	return (numBytes);
2951590Srgrimes}
296138232Sharti
2971590Srgrimes/*-
2981590Srgrimes *-----------------------------------------------------------------------
2991590Srgrimes * Buf_GetAll --
3001590Srgrimes *	Get all the available data at once.
3011590Srgrimes *
3021590Srgrimes * Results:
3031590Srgrimes *	A pointer to the data and the number of bytes available.
3041590Srgrimes *
3051590Srgrimes * Side Effects:
3061590Srgrimes *	None.
3071590Srgrimes *
3081590Srgrimes *-----------------------------------------------------------------------
3091590Srgrimes */
3101590SrgrimesByte *
311138341ShartiBuf_GetAll(Buffer bp, size_t *numBytesPtr)
3121590Srgrimes{
3131590Srgrimes
314138337Sharti	if (numBytesPtr != NULL)
315138337Sharti		*numBytesPtr = bp->inPtr - bp->outPtr;
3168874Srgrimes
317138337Sharti	return (bp->outPtr);
3181590Srgrimes}
319138232Sharti
3201590Srgrimes/*-
3211590Srgrimes *-----------------------------------------------------------------------
3221590Srgrimes * Buf_Discard --
3231590Srgrimes *	Throw away bytes in a buffer.
3241590Srgrimes *
3251590Srgrimes * Results:
3261590Srgrimes *	None.
3271590Srgrimes *
3281590Srgrimes * Side Effects:
3298874Srgrimes *	The bytes are discarded.
3301590Srgrimes *
3311590Srgrimes *-----------------------------------------------------------------------
3321590Srgrimes */
3331590Srgrimesvoid
334138341ShartiBuf_Discard(Buffer bp, size_t numBytes)
3351590Srgrimes{
3361590Srgrimes
337138341Sharti	if ((size_t)(bp->inPtr - bp->outPtr) <= numBytes) {
338138337Sharti		bp->inPtr = bp->outPtr = bp->buffer;
339138337Sharti		bp->left = bp->size;
340138337Sharti		*bp->inPtr = 0;
341138337Sharti	} else
342138337Sharti		bp->outPtr += numBytes;
3431590Srgrimes}
344138232Sharti
3451590Srgrimes/*-
3461590Srgrimes *-----------------------------------------------------------------------
3471590Srgrimes * Buf_Size --
3481590Srgrimes *	Returns the number of bytes in the given buffer. Doesn't include
3491590Srgrimes *	the null-terminating byte.
3501590Srgrimes *
3511590Srgrimes * Results:
3521590Srgrimes *	The number of bytes.
3531590Srgrimes *
3541590Srgrimes * Side Effects:
3551590Srgrimes *	None.
3561590Srgrimes *
3571590Srgrimes *-----------------------------------------------------------------------
3581590Srgrimes */
359138341Shartisize_t
360138232ShartiBuf_Size(Buffer buf)
3611590Srgrimes{
362138264Sharti
363138337Sharti	return (buf->inPtr - buf->outPtr);
3641590Srgrimes}
365138232Sharti
3661590Srgrimes/*-
3671590Srgrimes *-----------------------------------------------------------------------
3681590Srgrimes * Buf_Init --
3691590Srgrimes *	Initialize a buffer. If no initial size is given, a reasonable
3701590Srgrimes *	default is used.
3711590Srgrimes *
3721590Srgrimes * Results:
3731590Srgrimes *	A buffer to be given to other functions in this library.
3741590Srgrimes *
3751590Srgrimes * Side Effects:
3761590Srgrimes *	The buffer is created, the space allocated and pointers
3771590Srgrimes *	initialized.
3781590Srgrimes *
3791590Srgrimes *-----------------------------------------------------------------------
3801590Srgrimes */
3811590SrgrimesBuffer
382138341ShartiBuf_Init(size_t size)
3831590Srgrimes{
384138337Sharti	Buffer bp;	  	/* New Buffer */
3851590Srgrimes
386138337Sharti	bp = emalloc(sizeof(*bp));
3871590Srgrimes
388138337Sharti	if (size <= 0)
389138337Sharti		size = BUF_DEF_SIZE;
3901590Srgrimes
391138337Sharti	bp->left = bp->size = size;
392138337Sharti	bp->buffer = emalloc(size);
393138337Sharti	bp->inPtr = bp->outPtr = bp->buffer;
394138337Sharti	*bp->inPtr = 0;
395138337Sharti
396138337Sharti	return (bp);
3971590Srgrimes}
398138232Sharti
3991590Srgrimes/*-
4001590Srgrimes *-----------------------------------------------------------------------
4011590Srgrimes * Buf_Destroy --
402104696Sjmallett *	Destroy a buffer, and optionally free its data, too.
4031590Srgrimes *
4041590Srgrimes * Results:
4051590Srgrimes *	None.
4061590Srgrimes *
4071590Srgrimes * Side Effects:
4081590Srgrimes *	The buffer is freed.
4091590Srgrimes *
4101590Srgrimes *-----------------------------------------------------------------------
4111590Srgrimes */
4121590Srgrimesvoid
413138232ShartiBuf_Destroy(Buffer buf, Boolean freeData)
4141590Srgrimes{
4158874Srgrimes
416138337Sharti	if (freeData)
417138337Sharti		free(buf->buffer);
418138337Sharti	free(buf);
4191590Srgrimes}
420138232Sharti
42118456Ssteve/*-
42218456Ssteve *-----------------------------------------------------------------------
42318456Ssteve * Buf_ReplaceLastByte --
42418456Ssteve *     Replace the last byte in a buffer.
42518456Ssteve *
42618456Ssteve * Results:
42718456Ssteve *     None.
42818456Ssteve *
42918456Ssteve * Side Effects:
43018456Ssteve *     If the buffer was empty intially, then a new byte will be added.
43118456Ssteve *     Otherwise, the last byte is overwritten.
43218456Ssteve *
43318456Ssteve *-----------------------------------------------------------------------
43418456Ssteve */
43518456Sstevevoid
436138341ShartiBuf_ReplaceLastByte(Buffer buf, Byte byte)
43718456Ssteve{
438138337Sharti	if (buf->inPtr == buf->outPtr)
439138337Sharti		Buf_AddByte(buf, byte);
440138337Sharti	else
441138337Sharti		*(buf->inPtr - 1) = byte;
44218456Ssteve}
443