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