xref: /netbsd-src/usr.bin/make/buf.c (revision ce63d6c20fc4ec8ddc95c84bb229e3c4ecf82b69)
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 /*-
110  *-----------------------------------------------------------------------
111  * Buf_AddBytes --
112  *	Add a number of bytes to the buffer.
113  *
114  * Results:
115  *	None.
116  *
117  * Side Effects:
118  *	Guess what?
119  *
120  *-----------------------------------------------------------------------
121  */
122 void
123 Buf_AddBytes (bp, numBytes, bytesPtr)
124     register Buffer bp;
125     int	    numBytes;
126     Byte    *bytesPtr;
127 {
128 
129     BufExpand (bp, numBytes);
130 
131     bcopy (bytesPtr, bp->inPtr, numBytes);
132     bp->inPtr += numBytes;
133     bp->left -= numBytes;
134 
135     /*
136      * Null-terminate
137      */
138     *bp->inPtr = 0;
139 }
140 
141 /*-
142  *-----------------------------------------------------------------------
143  * Buf_UngetByte --
144  *	Place the byte back at the beginning of the buffer.
145  *
146  * Results:
147  *	SUCCESS if the byte was added ok. FAILURE if not.
148  *
149  * Side Effects:
150  *	The byte is stuffed in the buffer and outPtr is decremented.
151  *
152  *-----------------------------------------------------------------------
153  */
154 void
155 Buf_UngetByte (bp, byte)
156     register Buffer bp;
157     Byte    byte;
158 {
159 
160     if (bp->outPtr != bp->buffer) {
161 	bp->outPtr--;
162 	*bp->outPtr = byte;
163     } else if (bp->outPtr == bp->inPtr) {
164 	*bp->inPtr = byte;
165 	bp->inPtr++;
166 	bp->left--;
167 	*bp->inPtr = 0;
168     } else {
169 	/*
170 	 * Yech. have to expand the buffer to stuff this thing in.
171 	 * We use a different expansion constant because people don't
172 	 * usually push back many bytes when they're doing it a byte at
173 	 * a time...
174 	 */
175 	int 	  numBytes = bp->inPtr - bp->outPtr;
176 	Byte	  *newBuf;
177 
178 	newBuf = (Byte *)emalloc(bp->size + BUF_UNGET_INC);
179 	bcopy ((char *)bp->outPtr,
180 			(char *)(newBuf+BUF_UNGET_INC), numBytes+1);
181 	bp->outPtr = newBuf + BUF_UNGET_INC;
182 	bp->inPtr = bp->outPtr + numBytes;
183 	free ((char *)bp->buffer);
184 	bp->buffer = newBuf;
185 	bp->size += BUF_UNGET_INC;
186 	bp->left = bp->size - (bp->inPtr - bp->buffer);
187 	bp->outPtr -= 1;
188 	*bp->outPtr = byte;
189     }
190 }
191 
192 /*-
193  *-----------------------------------------------------------------------
194  * Buf_UngetBytes --
195  *	Push back a series of bytes at the beginning of the buffer.
196  *
197  * Results:
198  *	None.
199  *
200  * Side Effects:
201  *	outPtr is decremented and the bytes copied into the buffer.
202  *
203  *-----------------------------------------------------------------------
204  */
205 void
206 Buf_UngetBytes (bp, numBytes, bytesPtr)
207     register Buffer bp;
208     int	    numBytes;
209     Byte    *bytesPtr;
210 {
211 
212     if (bp->outPtr - bp->buffer >= numBytes) {
213 	bp->outPtr -= numBytes;
214 	bcopy (bytesPtr, bp->outPtr, numBytes);
215     } else if (bp->outPtr == bp->inPtr) {
216 	Buf_AddBytes (bp, numBytes, bytesPtr);
217     } else {
218 	int 	  curNumBytes = bp->inPtr - bp->outPtr;
219 	Byte	  *newBuf;
220 	int 	  newBytes = max(numBytes,BUF_UNGET_INC);
221 
222 	newBuf = (Byte *)emalloc (bp->size + newBytes);
223 	bcopy((char *)bp->outPtr, (char *)(newBuf+newBytes), curNumBytes+1);
224 	bp->outPtr = newBuf + newBytes;
225 	bp->inPtr = bp->outPtr + curNumBytes;
226 	free ((char *)bp->buffer);
227 	bp->buffer = newBuf;
228 	bp->size += newBytes;
229 	bp->left = bp->size - (bp->inPtr - bp->buffer);
230 	bp->outPtr -= numBytes;
231 	bcopy ((char *)bytesPtr, (char *)bp->outPtr, numBytes);
232     }
233 }
234 
235 /*-
236  *-----------------------------------------------------------------------
237  * Buf_GetByte --
238  *	Return the next byte from the buffer. Actually returns an integer.
239  *
240  * Results:
241  *	Returns BUF_ERROR if there's no byte in the buffer, or the byte
242  *	itself if there is one.
243  *
244  * Side Effects:
245  *	outPtr is incremented and both outPtr and inPtr will be reset if
246  *	the buffer is emptied.
247  *
248  *-----------------------------------------------------------------------
249  */
250 int
251 Buf_GetByte (bp)
252     register Buffer bp;
253 {
254     int	    res;
255 
256     if (bp->inPtr == bp->outPtr) {
257 	return (BUF_ERROR);
258     } else {
259 	res = (int) *bp->outPtr;
260 	bp->outPtr += 1;
261 	if (bp->outPtr == bp->inPtr) {
262 	    bp->outPtr = bp->inPtr = bp->buffer;
263 	    bp->left = bp->size;
264 	    *bp->inPtr = 0;
265 	}
266 	return (res);
267     }
268 }
269 
270 /*-
271  *-----------------------------------------------------------------------
272  * Buf_GetBytes --
273  *	Extract a number of bytes from the buffer.
274  *
275  * Results:
276  *	The number of bytes gotten.
277  *
278  * Side Effects:
279  *	The passed array is overwritten.
280  *
281  *-----------------------------------------------------------------------
282  */
283 int
284 Buf_GetBytes (bp, numBytes, bytesPtr)
285     register Buffer bp;
286     int	    numBytes;
287     Byte    *bytesPtr;
288 {
289 
290     if (bp->inPtr - bp->outPtr < numBytes) {
291 	numBytes = bp->inPtr - bp->outPtr;
292     }
293     bcopy (bp->outPtr, bytesPtr, numBytes);
294     bp->outPtr += numBytes;
295 
296     if (bp->outPtr == bp->inPtr) {
297 	bp->outPtr = bp->inPtr = bp->buffer;
298 	bp->left = bp->size;
299 	*bp->inPtr = 0;
300     }
301     return (numBytes);
302 }
303 
304 /*-
305  *-----------------------------------------------------------------------
306  * Buf_GetAll --
307  *	Get all the available data at once.
308  *
309  * Results:
310  *	A pointer to the data and the number of bytes available.
311  *
312  * Side Effects:
313  *	None.
314  *
315  *-----------------------------------------------------------------------
316  */
317 Byte *
318 Buf_GetAll (bp, numBytesPtr)
319     register Buffer bp;
320     int	    *numBytesPtr;
321 {
322 
323     if (numBytesPtr != (int *)NULL) {
324 	*numBytesPtr = bp->inPtr - bp->outPtr;
325     }
326 
327     return (bp->outPtr);
328 }
329 
330 /*-
331  *-----------------------------------------------------------------------
332  * Buf_Discard --
333  *	Throw away bytes in a buffer.
334  *
335  * Results:
336  *	None.
337  *
338  * Side Effects:
339  *	The bytes are discarded.
340  *
341  *-----------------------------------------------------------------------
342  */
343 void
344 Buf_Discard (bp, numBytes)
345     register Buffer bp;
346     int	    numBytes;
347 {
348 
349     if (bp->inPtr - bp->outPtr <= numBytes) {
350 	bp->inPtr = bp->outPtr = bp->buffer;
351 	bp->left = bp->size;
352 	*bp->inPtr = 0;
353     } else {
354 	bp->outPtr += numBytes;
355     }
356 }
357 
358 /*-
359  *-----------------------------------------------------------------------
360  * Buf_Size --
361  *	Returns the number of bytes in the given buffer. Doesn't include
362  *	the null-terminating byte.
363  *
364  * Results:
365  *	The number of bytes.
366  *
367  * Side Effects:
368  *	None.
369  *
370  *-----------------------------------------------------------------------
371  */
372 int
373 Buf_Size (buf)
374     Buffer  buf;
375 {
376     return (buf->inPtr - buf->outPtr);
377 }
378 
379 /*-
380  *-----------------------------------------------------------------------
381  * Buf_Init --
382  *	Initialize a buffer. If no initial size is given, a reasonable
383  *	default is used.
384  *
385  * Results:
386  *	A buffer to be given to other functions in this library.
387  *
388  * Side Effects:
389  *	The buffer is created, the space allocated and pointers
390  *	initialized.
391  *
392  *-----------------------------------------------------------------------
393  */
394 Buffer
395 Buf_Init (size)
396     int	    size; 	/* Initial size for the buffer */
397 {
398     Buffer bp;	  	/* New Buffer */
399 
400     bp = (Buffer)emalloc(sizeof(*bp));
401 
402     if (size <= 0) {
403 	size = BUF_DEF_SIZE;
404     }
405     bp->left = bp->size = size;
406     bp->buffer = (Byte *)emalloc(size);
407     bp->inPtr = bp->outPtr = bp->buffer;
408     *bp->inPtr = 0;
409 
410     return (bp);
411 }
412 
413 /*-
414  *-----------------------------------------------------------------------
415  * Buf_Destroy --
416  *	Nuke a buffer and all its resources.
417  *
418  * Results:
419  *	None.
420  *
421  * Side Effects:
422  *	The buffer is freed.
423  *
424  *-----------------------------------------------------------------------
425  */
426 void
427 Buf_Destroy (buf, freeData)
428     Buffer  buf;  	/* Buffer to destroy */
429     Boolean freeData;	/* TRUE if the data should be destroyed as well */
430 {
431 
432     if (freeData) {
433 	free ((char *)buf->buffer);
434     }
435     free ((char *)buf);
436 }
437