xref: /original-bsd/usr.bin/make/buf.c (revision 2bd07fe6)
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 are permitted
11  * provided that the above copyright notice and this paragraph are
12  * duplicated in all such forms and that any documentation,
13  * advertising materials, and other materials related to such
14  * distribution and use acknowledge that the software was developed
15  * by the University of California, Berkeley.  The name of the
16  * University may not be used to endorse or promote products derived
17  * from this software without specific prior written permission.
18  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
19  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
20  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
21  */
22 
23 #ifndef lint
24 static char sccsid[] = "@(#)buf.c	5.3 (Berkeley) 03/19/90";
25 #endif /* not lint */
26 
27 /*-
28  * buf.c --
29  *	Functions for automatically-expanded buffers.
30  */
31 
32 #include    "sprite.h"
33 #include    "buf.h"
34 
35 typedef struct {
36     int	    size; 	/* Current size of the buffer */
37     Byte    *buffer;	/* The buffer itself */
38     Byte    *inPtr;	/* Place to write to */
39     Byte    *outPtr;	/* Place to read from */
40 } Buf, *BufPtr;
41 
42 #ifndef max
43 #define max(a,b)  ((a) > (b) ? (a) : (b))
44 #endif
45 
46 /*
47  * BufExpand --
48  * 	Expand the given buffer to hold the given number of additional
49  *	bytes.
50  *	Makes sure there's room for an extra NULL byte at the end of the
51  *	buffer in case it holds a string.
52  */
53 #define BufExpand(bp,nb) \
54  	if (((bp)->size - ((bp)->inPtr - (bp)->buffer)) < (nb)+1) {\
55 	    int newSize = (bp)->size + max((nb)+1,BUF_ADD_INC); \
56 	    Byte  *newBuf = (Byte *) realloc((bp)->buffer, newSize); \
57 	    \
58 	    (bp)->inPtr = newBuf + ((bp)->inPtr - (bp)->buffer); \
59 	    (bp)->outPtr = newBuf + ((bp)->outPtr - (bp)->buffer);\
60 	    (bp)->buffer = newBuf;\
61 	    (bp)->size = newSize;\
62 	}
63 
64 #define BUF_DEF_SIZE	256 	/* Default buffer size */
65 #define BUF_ADD_INC	256 	/* Expansion increment when Adding */
66 #define BUF_UNGET_INC	16  	/* Expansion increment when Ungetting */
67 
68 /*-
69  *-----------------------------------------------------------------------
70  * Buf_AddByte --
71  *	Add a single byte to the buffer.
72  *
73  * Results:
74  *	None.
75  *
76  * Side Effects:
77  *	The buffer may be expanded.
78  *
79  *-----------------------------------------------------------------------
80  */
81 void
82 Buf_AddByte (buf, byte)
83     Buffer  buf;
84     Byte    byte;
85 {
86     register BufPtr  bp = (BufPtr) buf;
87 
88     BufExpand (bp, 1);
89 
90     *bp->inPtr = byte;
91     bp->inPtr += 1;
92 
93     /*
94      * Null-terminate
95      */
96     *bp->inPtr = 0;
97 }
98 
99 /*-
100  *-----------------------------------------------------------------------
101  * Buf_AddBytes --
102  *	Add a number of bytes to the buffer.
103  *
104  * Results:
105  *	None.
106  *
107  * Side Effects:
108  *	Guess what?
109  *
110  *-----------------------------------------------------------------------
111  */
112 void
113 Buf_AddBytes (buf, numBytes, bytesPtr)
114     Buffer  buf;
115     int	    numBytes;
116     Byte    *bytesPtr;
117 {
118     register BufPtr  bp = (BufPtr) buf;
119 
120     BufExpand (bp, numBytes);
121 
122     bcopy (bytesPtr, bp->inPtr, numBytes);
123     bp->inPtr += numBytes;
124 
125     /*
126      * Null-terminate
127      */
128     *bp->inPtr = 0;
129 }
130 
131 /*-
132  *-----------------------------------------------------------------------
133  * Buf_UngetByte --
134  *	Place the byte back at the beginning of the buffer.
135  *
136  * Results:
137  *	SUCCESS if the byte was added ok. FAILURE if not.
138  *
139  * Side Effects:
140  *	The byte is stuffed in the buffer and outPtr is decremented.
141  *
142  *-----------------------------------------------------------------------
143  */
144 void
145 Buf_UngetByte (buf, byte)
146     Buffer  buf;
147     Byte    byte;
148 {
149     register BufPtr	bp = (BufPtr) buf;
150 
151     if (bp->outPtr != bp->buffer) {
152 	bp->outPtr -= 1;
153 	*bp->outPtr = byte;
154     } else if (bp->outPtr == bp->inPtr) {
155 	*bp->inPtr = byte;
156 	bp->inPtr += 1;
157 	*bp->inPtr = 0;
158     } else {
159 	/*
160 	 * Yech. have to expand the buffer to stuff this thing in.
161 	 * We use a different expansion constant because people don't
162 	 * usually push back many bytes when they're doing it a byte at
163 	 * a time...
164 	 */
165 	int 	  numBytes = bp->inPtr - bp->outPtr;
166 	Byte	  *newBuf;
167 
168 	newBuf = (Byte *)emalloc(bp->size + BUF_UNGET_INC);
169 	bcopy ((Address)bp->outPtr,
170 			(Address)(newBuf+BUF_UNGET_INC), numBytes+1);
171 	bp->outPtr = newBuf + BUF_UNGET_INC;
172 	bp->inPtr = bp->outPtr + numBytes;
173 	free ((Address)bp->buffer);
174 	bp->buffer = newBuf;
175 	bp->size += BUF_UNGET_INC;
176 	bp->outPtr -= 1;
177 	*bp->outPtr = byte;
178     }
179 }
180 
181 /*-
182  *-----------------------------------------------------------------------
183  * Buf_UngetBytes --
184  *	Push back a series of bytes at the beginning of the buffer.
185  *
186  * Results:
187  *	None.
188  *
189  * Side Effects:
190  *	outPtr is decremented and the bytes copied into the buffer.
191  *
192  *-----------------------------------------------------------------------
193  */
194 void
195 Buf_UngetBytes (buf, numBytes, bytesPtr)
196     Buffer  buf;
197     int	    numBytes;
198     Byte    *bytesPtr;
199 {
200     register BufPtr	bp = (BufPtr) buf;
201 
202     if (bp->outPtr - bp->buffer >= numBytes) {
203 	bp->outPtr -= numBytes;
204 	bcopy (bytesPtr, bp->outPtr, numBytes);
205     } else if (bp->outPtr == bp->inPtr) {
206 	Buf_AddBytes (buf, numBytes, bytesPtr);
207     } else {
208 	int 	  curNumBytes = bp->inPtr - bp->outPtr;
209 	Byte	  *newBuf;
210 	int 	  newBytes = max(numBytes,BUF_UNGET_INC);
211 
212 	newBuf = (Byte *)emalloc (bp->size + newBytes);
213 	bcopy((Address)bp->outPtr, (Address)(newBuf+newBytes), curNumBytes+1);
214 	bp->outPtr = newBuf + newBytes;
215 	bp->inPtr = bp->outPtr + curNumBytes;
216 	free ((Address)bp->buffer);
217 	bp->buffer = newBuf;
218 	bp->size += newBytes;
219 	bp->outPtr -= numBytes;
220 	bcopy ((Address)bytesPtr, (Address)bp->outPtr, numBytes);
221     }
222 }
223 
224 /*-
225  *-----------------------------------------------------------------------
226  * Buf_GetByte --
227  *	Return the next byte from the buffer. Actually returns an integer.
228  *
229  * Results:
230  *	Returns BUF_ERROR if there's no byte in the buffer, or the byte
231  *	itself if there is one.
232  *
233  * Side Effects:
234  *	outPtr is incremented and both outPtr and inPtr will be reset if
235  *	the buffer is emptied.
236  *
237  *-----------------------------------------------------------------------
238  */
239 int
240 Buf_GetByte (buf)
241     Buffer  buf;
242 {
243     BufPtr  bp = (BufPtr) buf;
244     int	    res;
245 
246     if (bp->inPtr == bp->outPtr) {
247 	return (BUF_ERROR);
248     } else {
249 	res = (int) *bp->outPtr;
250 	bp->outPtr += 1;
251 	if (bp->outPtr == bp->inPtr) {
252 	    bp->outPtr = bp->inPtr = bp->buffer;
253 	    bp->inPtr = 0;
254 	}
255 	return (res);
256     }
257 }
258 
259 /*-
260  *-----------------------------------------------------------------------
261  * Buf_GetBytes --
262  *	Extract a number of bytes from the buffer.
263  *
264  * Results:
265  *	The number of bytes gotten.
266  *
267  * Side Effects:
268  *	The passed array is overwritten.
269  *
270  *-----------------------------------------------------------------------
271  */
272 int
273 Buf_GetBytes (buf, numBytes, bytesPtr)
274     Buffer  buf;
275     int	    numBytes;
276     Byte    *bytesPtr;
277 {
278     BufPtr  bp = (BufPtr) buf;
279 
280     if (bp->inPtr - bp->outPtr < numBytes) {
281 	numBytes = bp->inPtr - bp->outPtr;
282     }
283     bcopy (bp->outPtr, bytesPtr, numBytes);
284     bp->outPtr += numBytes;
285 
286     if (bp->outPtr == bp->inPtr) {
287 	bp->outPtr = bp->inPtr = bp->buffer;
288 	*bp->inPtr = 0;
289     }
290     return (numBytes);
291 }
292 
293 /*-
294  *-----------------------------------------------------------------------
295  * Buf_GetAll --
296  *	Get all the available data at once.
297  *
298  * Results:
299  *	A pointer to the data and the number of bytes available.
300  *
301  * Side Effects:
302  *	None.
303  *
304  *-----------------------------------------------------------------------
305  */
306 Byte *
307 Buf_GetAll (buf, numBytesPtr)
308     Buffer  buf;
309     int	    *numBytesPtr;
310 {
311     BufPtr  bp = (BufPtr)buf;
312 
313     if (numBytesPtr != (int *)NULL) {
314 	*numBytesPtr = bp->inPtr - bp->outPtr;
315     }
316 
317     return (bp->outPtr);
318 }
319 
320 /*-
321  *-----------------------------------------------------------------------
322  * Buf_Discard --
323  *	Throw away bytes in a buffer.
324  *
325  * Results:
326  *	None.
327  *
328  * Side Effects:
329  *	The bytes are discarded.
330  *
331  *-----------------------------------------------------------------------
332  */
333 void
334 Buf_Discard (buf, numBytes)
335     Buffer  buf;
336     int	    numBytes;
337 {
338     register BufPtr	bp = (BufPtr) buf;
339 
340     if (bp->inPtr - bp->outPtr <= numBytes) {
341 	bp->inPtr = bp->outPtr = bp->buffer;
342 	*bp->inPtr = 0;
343     } else {
344 	bp->outPtr += numBytes;
345     }
346 }
347 
348 /*-
349  *-----------------------------------------------------------------------
350  * Buf_Size --
351  *	Returns the number of bytes in the given buffer. Doesn't include
352  *	the null-terminating byte.
353  *
354  * Results:
355  *	The number of bytes.
356  *
357  * Side Effects:
358  *	None.
359  *
360  *-----------------------------------------------------------------------
361  */
362 int
363 Buf_Size (buf)
364     Buffer  buf;
365 {
366     return (((BufPtr)buf)->inPtr - ((BufPtr)buf)->outPtr);
367 }
368 
369 /*-
370  *-----------------------------------------------------------------------
371  * Buf_Init --
372  *	Initialize a buffer. If no initial size is given, a reasonable
373  *	default is used.
374  *
375  * Results:
376  *	A buffer to be given to other functions in this library.
377  *
378  * Side Effects:
379  *	The buffer is created, the space allocated and pointers
380  *	initialized.
381  *
382  *-----------------------------------------------------------------------
383  */
384 Buffer
385 Buf_Init (size)
386     int	    size; 	/* Initial size for the buffer */
387 {
388     BufPtr  bp;	  	/* New Buffer */
389 
390     bp = (Buf *)emalloc(sizeof(Buf));
391 
392     if (size <= 0) {
393 	size = BUF_DEF_SIZE;
394     }
395     bp->size = size;
396     bp->buffer = (Byte *)emalloc (size);
397     bp->inPtr = bp->outPtr = bp->buffer;
398     *bp->inPtr = 0;
399 
400     return ((Buffer) bp);
401 }
402 
403 /*-
404  *-----------------------------------------------------------------------
405  * Buf_Destroy --
406  *	Nuke a buffer and all its resources.
407  *
408  * Results:
409  *	None.
410  *
411  * Side Effects:
412  *	The buffer is freed.
413  *
414  *-----------------------------------------------------------------------
415  */
416 void
417 Buf_Destroy (buf, freeData)
418     Buffer  buf;  	/* Buffer to destroy */
419     Boolean freeData;	/* TRUE if the data should be destroyed as well */
420 {
421     BufPtr  bp = (BufPtr) buf;
422 
423     if (freeData) {
424 	free ((Address)bp->buffer);
425     }
426     free ((Address)bp);
427 }
428