buf.c revision 104696
1123281Simp/*
2123281Simp * Copyright (c) 1988, 1989, 1990, 1993
3123281Simp *	The Regents of the University of California.  All rights reserved.
4123281Simp * Copyright (c) 1988, 1989 by Adam de Boor
5123943Sru * Copyright (c) 1989 by Berkeley Softworks
6123281Simp * All rights reserved.
7123281Simp *
8123281Simp * This code is derived from software contributed to Berkeley by
9123281Simp * Adam de Boor.
10123281Simp *
11123281Simp * Redistribution and use in source and binary forms, with or without
12123281Simp * modification, are permitted provided that the following conditions
13123281Simp * are met:
14123281Simp * 1. Redistributions of source code must retain the above copyright
15123281Simp *    notice, this list of conditions and the following disclaimer.
16123281Simp * 2. Redistributions in binary form must reproduce the above copyright
17123281Simp *    notice, this list of conditions and the following disclaimer in the
18123281Simp *    documentation and/or other materials provided with the distribution.
19123281Simp * 3. All advertising materials mentioning features or use of this software
20123281Simp *    must display the following acknowledgement:
21123281Simp *	This product includes software developed by the University of
22123281Simp *	California, Berkeley and its contributors.
23123281Simp * 4. Neither the name of the University nor the names of its contributors
24123281Simp *    may be used to endorse or promote products derived from this software
25123281Simp *    without specific prior written permission.
26123281Simp *
27123281Simp * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
28123281Simp * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29123281Simp * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30123281Simp * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
31123281Simp * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
32123281Simp * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
33123281Simp * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
34123281Simp * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
35123281Simp * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
36123281Simp * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37123281Simp * SUCH DAMAGE.
38123281Simp *
39123281Simp * @(#)buf.c	8.1 (Berkeley) 6/6/93
40123281Simp */
41123281Simp
42123281Simp#include <sys/cdefs.h>
43123281Simp__FBSDID("$FreeBSD: head/usr.bin/make/buf.c 104696 2002-10-09 03:42:10Z jmallett $");
44123281Simp
45123281Simp/*-
46123281Simp * buf.c --
47123281Simp *	Functions for automatically-expanded buffers.
48123281Simp */
49123281Simp
50123281Simp#include    "sprite.h"
51123281Simp#include    "make.h"
52123281Simp#include    "buf.h"
53123281Simp
54123281Simp#ifndef max
55123281Simp#define	max(a,b)  ((a) > (b) ? (a) : (b))
56123281Simp#endif
57123281Simp
58123281Simp/*
59123281Simp * BufExpand --
60123281Simp * 	Expand the given buffer to hold the given number of additional
61123281Simp *	bytes.
62123281Simp *	Makes sure there's room for an extra NULL byte at the end of the
63123281Simp *	buffer in case it holds a string.
64123281Simp */
65123281Simp#define	BufExpand(bp,nb) \
66123281Simp 	if (bp->left < (nb)+1) {\
67123281Simp	    int newSize = (bp)->size + max((nb)+1,BUF_ADD_INC); \
68123281Simp	    Byte  *newBuf = (Byte *) erealloc((bp)->buffer, newSize); \
69123281Simp	    \
70123281Simp	    (bp)->inPtr = newBuf + ((bp)->inPtr - (bp)->buffer); \
71123281Simp	    (bp)->outPtr = newBuf + ((bp)->outPtr - (bp)->buffer);\
72123281Simp	    (bp)->buffer = newBuf;\
73123281Simp	    (bp)->size = newSize;\
74123281Simp	    (bp)->left = newSize - ((bp)->inPtr - (bp)->buffer);\
75123281Simp	}
76123281Simp
77123281Simp#define	BUF_DEF_SIZE	256 	/* Default buffer size */
78123281Simp#define	BUF_ADD_INC	256 	/* Expansion increment when Adding */
79123281Simp#define	BUF_UNGET_INC	16  	/* Expansion increment when Ungetting */
80123281Simp
81123281Simp/*-
82123281Simp *-----------------------------------------------------------------------
83123281Simp * Buf_OvAddByte --
84123281Simp *	Add a single byte to the buffer.  left is zero or negative.
85123281Simp *
86123281Simp * Results:
87123281Simp *	None.
88123281Simp *
89123281Simp * Side Effects:
90123281Simp *	The buffer may be expanded.
91123281Simp *
92123281Simp *-----------------------------------------------------------------------
93123281Simp */
94123281Simpvoid
95123281SimpBuf_OvAddByte (Buffer bp, int byte)
96123281Simp{
97123281Simp    bp->left = 0;
98123281Simp    BufExpand (bp, 1);
99123281Simp
100123281Simp    *bp->inPtr++ = byte;
101123281Simp    bp->left--;
102123281Simp
103123281Simp    /*
104123281Simp     * Null-terminate
105123281Simp     */
106123281Simp    *bp->inPtr = 0;
107123281Simp}
108123281Simp
109123281Simp/*-
110123281Simp *-----------------------------------------------------------------------
111123281Simp * Buf_AddBytes --
112123281Simp *	Add a number of bytes to the buffer.
113123281Simp *
114123281Simp * Results:
115123281Simp *	None.
116123281Simp *
117123281Simp * Side Effects:
118123281Simp *	Guess what?
119123281Simp *
120123281Simp *-----------------------------------------------------------------------
121123281Simp */
122123281Simpvoid
123123281SimpBuf_AddBytes (Buffer bp, int numBytes, const Byte *bytesPtr)
124123281Simp{
125123281Simp
126123281Simp    BufExpand (bp, numBytes);
127123281Simp
128123281Simp    memcpy (bp->inPtr, bytesPtr, numBytes);
129123281Simp    bp->inPtr += numBytes;
130123281Simp    bp->left -= numBytes;
131123281Simp
132123281Simp    /*
133123281Simp     * Null-terminate
134123281Simp     */
135123281Simp    *bp->inPtr = 0;
136123281Simp}
137123281Simp
138123281Simp/*-
139123281Simp *-----------------------------------------------------------------------
140123281Simp * Buf_UngetByte --
141123281Simp *	Place the byte back at the beginning of the buffer.
142123281Simp *
143123281Simp * Results:
144123281Simp *	SUCCESS if the byte was added ok. FAILURE if not.
145123281Simp *
146123281Simp * Side Effects:
147123281Simp *	The byte is stuffed in the buffer and outPtr is decremented.
148123281Simp *
149123281Simp *-----------------------------------------------------------------------
150123281Simp */
151123281Simpvoid
152123281SimpBuf_UngetByte (Buffer bp, int byte)
153123281Simp{
154123281Simp
155123281Simp    if (bp->outPtr != bp->buffer) {
156123281Simp	bp->outPtr--;
157123281Simp	*bp->outPtr = byte;
158123281Simp    } else if (bp->outPtr == bp->inPtr) {
159123281Simp	*bp->inPtr = byte;
160123281Simp	bp->inPtr++;
161123281Simp	bp->left--;
162123281Simp	*bp->inPtr = 0;
163123281Simp    } else {
164123281Simp	/*
165123281Simp	 * Yech. have to expand the buffer to stuff this thing in.
166123281Simp	 * We use a different expansion constant because people don't
167123281Simp	 * usually push back many bytes when they're doing it a byte at
168123281Simp	 * a time...
169123281Simp	 */
170123281Simp	int 	  numBytes = bp->inPtr - bp->outPtr;
171123281Simp	Byte	  *newBuf;
172123281Simp
173123281Simp	newBuf = (Byte *)emalloc(bp->size + BUF_UNGET_INC);
174123281Simp	memcpy ((char *)(newBuf+BUF_UNGET_INC), (char *)bp->outPtr, numBytes+1);
175123281Simp	bp->outPtr = newBuf + BUF_UNGET_INC;
176123281Simp	bp->inPtr = bp->outPtr + numBytes;
177123281Simp	free ((char *)bp->buffer);
178123281Simp	bp->buffer = newBuf;
179123281Simp	bp->size += BUF_UNGET_INC;
180123281Simp	bp->left = bp->size - (bp->inPtr - bp->buffer);
181123281Simp	bp->outPtr -= 1;
182123281Simp	*bp->outPtr = byte;
183123281Simp    }
184123281Simp}
185123281Simp
186123281Simp/*-
187123281Simp *-----------------------------------------------------------------------
188123281Simp * Buf_UngetBytes --
189123281Simp *	Push back a series of bytes at the beginning of the buffer.
190123281Simp *
191123281Simp * Results:
192123281Simp *	None.
193123281Simp *
194123281Simp * Side Effects:
195123281Simp *	outPtr is decremented and the bytes copied into the buffer.
196123281Simp *
197123281Simp *-----------------------------------------------------------------------
198123281Simp */
199123281Simpvoid
200123281SimpBuf_UngetBytes (Buffer bp, int numBytes, Byte *bytesPtr)
201123281Simp{
202123281Simp
203123281Simp    if (bp->outPtr - bp->buffer >= numBytes) {
204123281Simp	bp->outPtr -= numBytes;
205123281Simp	memcpy (bp->outPtr, bytesPtr, numBytes);
206123281Simp    } else if (bp->outPtr == bp->inPtr) {
207123281Simp	Buf_AddBytes (bp, numBytes, bytesPtr);
208123281Simp    } else {
209123281Simp	int 	  curNumBytes = bp->inPtr - bp->outPtr;
210123281Simp	Byte	  *newBuf;
211123281Simp	int 	  newBytes = max(numBytes,BUF_UNGET_INC);
212123281Simp
213123281Simp	newBuf = (Byte *)emalloc (bp->size + newBytes);
214123281Simp	memcpy((char *)(newBuf+newBytes), (char *)bp->outPtr, curNumBytes+1);
215123281Simp	bp->outPtr = newBuf + newBytes;
216123281Simp	bp->inPtr = bp->outPtr + curNumBytes;
217123281Simp	free ((char *)bp->buffer);
218123281Simp	bp->buffer = newBuf;
219123281Simp	bp->size += newBytes;
220123281Simp	bp->left = bp->size - (bp->inPtr - bp->buffer);
221123281Simp	bp->outPtr -= numBytes;
222123281Simp	memcpy ((char *)bp->outPtr, (char *)bytesPtr, numBytes);
223123281Simp    }
224123281Simp}
225123281Simp
226123281Simp/*-
227123281Simp *-----------------------------------------------------------------------
228123281Simp * Buf_GetByte --
229123281Simp *	Return the next byte from the buffer. Actually returns an integer.
230123281Simp *
231123281Simp * Results:
232123281Simp *	Returns BUF_ERROR if there's no byte in the buffer, or the byte
233123281Simp *	itself if there is one.
234123281Simp *
235123281Simp * Side Effects:
236123281Simp *	outPtr is incremented and both outPtr and inPtr will be reset if
237123281Simp *	the buffer is emptied.
238123281Simp *
239123281Simp *-----------------------------------------------------------------------
240123281Simp */
241123281Simpint
242123281SimpBuf_GetByte (Buffer bp)
243123281Simp{
244123281Simp    int	    res;
245123281Simp
246123281Simp    if (bp->inPtr == bp->outPtr) {
247123281Simp	return (BUF_ERROR);
248123281Simp    } else {
249123281Simp	res = (int) *bp->outPtr;
250123281Simp	bp->outPtr += 1;
251123281Simp	if (bp->outPtr == bp->inPtr) {
252123281Simp	    bp->outPtr = bp->inPtr = bp->buffer;
253123281Simp	    bp->left = bp->size;
254123281Simp	    *bp->inPtr = 0;
255123281Simp	}
256123281Simp	return (res);
257123281Simp    }
258123281Simp}
259123281Simp
260123281Simp/*-
261123281Simp *-----------------------------------------------------------------------
262123281Simp * Buf_GetBytes --
263123281Simp *	Extract a number of bytes from the buffer.
264123281Simp *
265123281Simp * Results:
266123281Simp *	The number of bytes gotten.
267123281Simp *
268123281Simp * Side Effects:
269123281Simp *	The passed array is overwritten.
270123281Simp *
271123281Simp *-----------------------------------------------------------------------
272123281Simp */
273123281Simpint
274123281SimpBuf_GetBytes (Buffer bp, int numBytes, Byte *bytesPtr)
275123281Simp{
276123281Simp
277123281Simp    if (bp->inPtr - bp->outPtr < numBytes) {
278123281Simp	numBytes = bp->inPtr - bp->outPtr;
279123281Simp    }
280123281Simp    memcpy (bytesPtr, bp->outPtr, numBytes);
281123281Simp    bp->outPtr += numBytes;
282123281Simp
283123281Simp    if (bp->outPtr == bp->inPtr) {
284123281Simp	bp->outPtr = bp->inPtr = bp->buffer;
285123281Simp	bp->left = bp->size;
286123281Simp	*bp->inPtr = 0;
287123281Simp    }
288123281Simp    return (numBytes);
289123281Simp}
290123281Simp
291123281Simp/*-
292123281Simp *-----------------------------------------------------------------------
293123281Simp * Buf_GetAll --
294123281Simp *	Get all the available data at once.
295123281Simp *
296123281Simp * Results:
297123281Simp *	A pointer to the data and the number of bytes available.
298123281Simp *
299123281Simp * Side Effects:
300123281Simp *	None.
301123281Simp *
302123281Simp *-----------------------------------------------------------------------
303123281Simp */
304123281SimpByte *
305123281SimpBuf_GetAll (Buffer bp, int *numBytesPtr)
306123281Simp{
307123281Simp
308123281Simp    if (numBytesPtr != (int *)NULL) {
309123281Simp	*numBytesPtr = bp->inPtr - bp->outPtr;
310123281Simp    }
311123281Simp
312123281Simp    return (bp->outPtr);
313123281Simp}
314123281Simp
315123281Simp/*-
316123281Simp *-----------------------------------------------------------------------
317123281Simp * Buf_Discard --
318123281Simp *	Throw away bytes in a buffer.
319123281Simp *
320123281Simp * Results:
321123281Simp *	None.
322123281Simp *
323123281Simp * Side Effects:
324123281Simp *	The bytes are discarded.
325123281Simp *
326123281Simp *-----------------------------------------------------------------------
327123281Simp */
328123281Simpvoid
329123281SimpBuf_Discard (Buffer bp, int numBytes)
330123281Simp{
331123281Simp
332123281Simp    if (bp->inPtr - bp->outPtr <= numBytes) {
333123281Simp	bp->inPtr = bp->outPtr = bp->buffer;
334123281Simp	bp->left = bp->size;
335123281Simp	*bp->inPtr = 0;
336123281Simp    } else {
337123281Simp	bp->outPtr += numBytes;
338123281Simp    }
339123281Simp}
340123281Simp
341123281Simp/*-
342123281Simp *-----------------------------------------------------------------------
343123281Simp * Buf_Size --
344123281Simp *	Returns the number of bytes in the given buffer. Doesn't include
345123281Simp *	the null-terminating byte.
346123281Simp *
347123281Simp * Results:
348123281Simp *	The number of bytes.
349123281Simp *
350123281Simp * Side Effects:
351123281Simp *	None.
352123281Simp *
353123281Simp *-----------------------------------------------------------------------
354123281Simp */
355123281Simpint
356123281SimpBuf_Size (Buffer buf)
357123281Simp{
358123281Simp    return (buf->inPtr - buf->outPtr);
359123281Simp}
360123281Simp
361123281Simp/*-
362123281Simp *-----------------------------------------------------------------------
363123281Simp * Buf_Init --
364123281Simp *	Initialize a buffer. If no initial size is given, a reasonable
365123281Simp *	default is used.
366123281Simp *
367123281Simp * Results:
368123281Simp *	A buffer to be given to other functions in this library.
369123281Simp *
370123281Simp * Side Effects:
371123281Simp *	The buffer is created, the space allocated and pointers
372123281Simp *	initialized.
373123281Simp *
374123281Simp *-----------------------------------------------------------------------
375123281Simp */
376123281SimpBuffer
377123281SimpBuf_Init (int size)
378123281Simp{
379123281Simp    Buffer bp;	  	/* New Buffer */
380123281Simp
381123281Simp    bp = (Buffer)emalloc(sizeof(*bp));
382123281Simp
383123281Simp    if (size <= 0) {
384123281Simp	size = BUF_DEF_SIZE;
385123281Simp    }
386123281Simp    bp->left = bp->size = size;
387123281Simp    bp->buffer = (Byte *)emalloc(size);
388123281Simp    bp->inPtr = bp->outPtr = bp->buffer;
389123281Simp    *bp->inPtr = 0;
390123281Simp
391123281Simp    return (bp);
392123281Simp}
393123281Simp
394123281Simp/*-
395123281Simp *-----------------------------------------------------------------------
396123281Simp * Buf_Destroy --
397123281Simp *	Destroy a buffer, and optionally free its data, too.
398123281Simp *
399123281Simp * Results:
400123281Simp *	None.
401123281Simp *
402123281Simp * Side Effects:
403123281Simp *	The buffer is freed.
404123281Simp *
405123281Simp *-----------------------------------------------------------------------
406123281Simp */
407123281Simpvoid
408123281SimpBuf_Destroy (Buffer buf, Boolean freeData)
409123281Simp{
410123281Simp
411123281Simp    if (freeData) {
412123281Simp	free ((char *)buf->buffer);
413123281Simp    }
414123281Simp    free ((char *)buf);
415123281Simp}
416123281Simp
417123281Simp/*-
418123281Simp *-----------------------------------------------------------------------
419123281Simp * Buf_ReplaceLastByte --
420123281Simp *     Replace the last byte in a buffer.
421123281Simp *
422123281Simp * Results:
423123281Simp *     None.
424123281Simp *
425123281Simp * Side Effects:
426123281Simp *     If the buffer was empty intially, then a new byte will be added.
427123281Simp *     Otherwise, the last byte is overwritten.
428123281Simp *
429123281Simp *-----------------------------------------------------------------------
430123281Simp */
431123281Simpvoid
432123281SimpBuf_ReplaceLastByte (Buffer buf, int byte)
433123281Simp{
434123281Simp    if (buf->inPtr == buf->outPtr)
435123281Simp        Buf_AddByte(buf, byte);
436123281Simp    else
437123281Simp        *(buf->inPtr - 1) = byte;
438123281Simp}
439123281Simp