Hiding pointer in typedefs is evil. 'Buffer *' -> 'Buffer'
[dragonfly.git] / usr.bin / make / buf.c
1 /*
2  * Copyright (c) 1988, 1989, 1990, 1993
3  *      The Regents of the University of California.  All rights reserved.
4  * Copyright (c) 1988, 1989 by Adam de Boor
5  * Copyright (c) 1989 by Berkeley Softworks
6  * All rights reserved.
7  *
8  * This code is derived from software contributed to Berkeley by
9  * Adam de Boor.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions and the following disclaimer.
16  * 2. Redistributions in binary form must reproduce the above copyright
17  *    notice, this list of conditions and the following disclaimer in the
18  *    documentation and/or other materials provided with the distribution.
19  * 3. All advertising materials mentioning features or use of this software
20  *    must display the following acknowledgement:
21  *      This product includes software developed by the University of
22  *      California, Berkeley and its contributors.
23  * 4. Neither the name of the University nor the names of its contributors
24  *    may be used to endorse or promote products derived from this software
25  *    without specific prior written permission.
26  *
27  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
28  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
31  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
32  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
33  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
34  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
35  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
36  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37  * SUCH DAMAGE.
38  *
39  * @(#)buf.c    8.1 (Berkeley) 6/6/93
40  * $FreeBSD: src/usr.bin/make/buf.c,v 1.11 1999/09/11 13:08:01 hoek Exp $
41  * $DragonFly: src/usr.bin/make/buf.c,v 1.13 2005/01/06 13:18:58 okumoto Exp $
42  */
43
44 /*-
45  * buf.c --
46  *      Functions for automatically-expanded buffers.
47  */
48
49 #include <string.h>
50 #include <stdlib.h>
51
52 #include "buf.h"
53 #include "sprite.h"
54 #include "util.h"
55
56 #ifndef max
57 #define max(a,b)  ((a) > (b) ? (a) : (b))
58 #endif
59
60 /*
61  * BufExpand --
62  *      Expand the given buffer to hold the given number of additional
63  *      bytes.
64  *      Makes sure there's room for an extra NULL byte at the end of the
65  *      buffer in case it holds a string.
66  */
67 #define BufExpand(bp, nb) do {                                          \
68         if ((bp)->left < (nb) + 1) {                                    \
69                 int newSize = (bp)->size + max((nb) + 1, BUF_ADD_INC);  \
70                 Byte *newBuf = erealloc((bp)->buffer, newSize);         \
71                                                                         \
72                 (bp)->inPtr = newBuf + ((bp)->inPtr - (bp)->buffer);    \
73                 (bp)->outPtr = newBuf + ((bp)->outPtr - (bp)->buffer);  \
74                 (bp)->buffer = newBuf;                                  \
75                 (bp)->size = newSize;                                   \
76                 (bp)->left = newSize - ((bp)->inPtr - (bp)->buffer);    \
77         }                                                               \
78     } while (0)
79
80 #define BUF_DEF_SIZE    256     /* Default buffer size */
81 #define BUF_ADD_INC     256     /* Expansion increment when Adding */
82 #define BUF_UNGET_INC   16      /* Expansion increment when Ungetting */
83
84 /*-
85  *-----------------------------------------------------------------------
86  * Buf_OvAddByte --
87  *      Add a single byte to the buffer.  left is zero or negative.
88  *
89  * Results:
90  *      None.
91  *
92  * Side Effects:
93  *      The buffer may be expanded.
94  *
95  *-----------------------------------------------------------------------
96  */
97 void
98 Buf_OvAddByte(Buffer *bp, Byte byte)
99 {
100
101         bp->left = 0;
102         BufExpand(bp, 1);
103
104         *bp->inPtr++ = byte;
105         bp->left--;
106
107         /*
108          * Null-terminate
109          */
110         *bp->inPtr = 0;
111 }
112
113 /*-
114  *-----------------------------------------------------------------------
115  * Buf_AddBytes --
116  *      Add a number of bytes to the buffer.
117  *
118  * Results:
119  *      None.
120  *
121  * Side Effects:
122  *      Guess what?
123  *
124  *-----------------------------------------------------------------------
125  */
126 void
127 Buf_AddBytes(Buffer *bp, size_t numBytes, const Byte *bytesPtr)
128 {
129
130         BufExpand(bp, numBytes);
131
132         memcpy(bp->inPtr, bytesPtr, numBytes);
133         bp->inPtr += numBytes;
134         bp->left -= numBytes;
135
136         /*
137          * Null-terminate
138          */
139         *bp->inPtr = 0;
140 }
141
142 /*-
143  *-----------------------------------------------------------------------
144  * Buf_UngetByte --
145  *      Place the byte back at the beginning of the buffer.
146  *
147  * Results:
148  *      SUCCESS if the byte was added ok. FAILURE if not.
149  *
150  * Side Effects:
151  *      The byte is stuffed in the buffer and outPtr is decremented.
152  *
153  *-----------------------------------------------------------------------
154  */
155 void
156 Buf_UngetByte(Buffer *bp, Byte byte)
157 {
158
159         if (bp->outPtr != bp->buffer) {
160                 bp->outPtr--;
161                 *bp->outPtr = byte;
162
163         } else if (bp->outPtr == bp->inPtr) {
164                 *bp->inPtr = byte;
165                 bp->inPtr++;
166                 bp->left--;
167                 *bp->inPtr = 0;
168
169         } else {
170                 /*
171                  * Yech. have to expand the buffer to stuff this thing in.
172                  * We use a different expansion constant because people don't
173                  * usually push back many bytes when they're doing it a byte at
174                  * a time...
175                  */
176                 size_t numBytes = bp->inPtr - bp->outPtr;
177                 Byte *newBuf;
178
179                 newBuf = emalloc(bp->size + BUF_UNGET_INC);
180                 memcpy(newBuf + BUF_UNGET_INC, bp->outPtr, numBytes + 1);
181                 bp->outPtr = newBuf + BUF_UNGET_INC;
182                 bp->inPtr = bp->outPtr + numBytes;
183                 free(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(Buffer *bp, size_t numBytes, Byte *bytesPtr)
207 {
208
209         if ((size_t)(bp->outPtr - bp->buffer) >= numBytes) {
210                 bp->outPtr -= numBytes;
211                 memcpy(bp->outPtr, bytesPtr, numBytes);
212         } else if (bp->outPtr == bp->inPtr) {
213                 Buf_AddBytes(bp, numBytes, bytesPtr);
214         } else {
215                 size_t curNumBytes = bp->inPtr - bp->outPtr;
216                 Byte *newBuf;
217                 size_t newBytes = max(numBytes, BUF_UNGET_INC);
218
219                 newBuf = emalloc(bp->size + newBytes);
220                 memcpy(newBuf + newBytes, bp->outPtr, curNumBytes + 1);
221                 bp->outPtr = newBuf + newBytes;
222                 bp->inPtr = bp->outPtr + curNumBytes;
223                 free(bp->buffer);
224                 bp->buffer = newBuf;
225                 bp->size += newBytes;
226                 bp->left = bp->size - (bp->inPtr - bp->buffer);
227                 bp->outPtr -= numBytes;
228                 memcpy(bp->outPtr, bytesPtr, numBytes);
229         }
230 }
231
232 /*-
233  *-----------------------------------------------------------------------
234  * Buf_GetByte --
235  *      Return the next byte from the buffer. Actually returns an integer.
236  *
237  * Results:
238  *      Returns BUF_ERROR if there's no byte in the buffer, or the byte
239  *      itself if there is one.
240  *
241  * Side Effects:
242  *      outPtr is incremented and both outPtr and inPtr will be reset if
243  *      the buffer is emptied.
244  *
245  *-----------------------------------------------------------------------
246  */
247 int
248 Buf_GetByte(Buffer *bp)
249 {
250         int res;
251
252         if (bp->inPtr == bp->outPtr)
253                 return (BUF_ERROR);
254
255         res = (int)*bp->outPtr;
256         bp->outPtr += 1;
257         if (bp->outPtr == bp->inPtr) {
258                 bp->outPtr = bp->inPtr = bp->buffer;
259                 bp->left = bp->size;
260                 *bp->inPtr = 0;
261         }
262         return (res);
263 }
264
265 /*-
266  *-----------------------------------------------------------------------
267  * Buf_GetBytes --
268  *      Extract a number of bytes from the buffer.
269  *
270  * Results:
271  *      The number of bytes gotten.
272  *
273  * Side Effects:
274  *      The passed array is overwritten.
275  *
276  *-----------------------------------------------------------------------
277  */
278 int
279 Buf_GetBytes(Buffer *bp, size_t numBytes, Byte *bytesPtr)
280 {
281
282         if ((size_t)(bp->inPtr - bp->outPtr) < numBytes)
283                 numBytes = bp->inPtr - bp->outPtr;
284
285         memcpy(bytesPtr, bp->outPtr, numBytes);
286         bp->outPtr += numBytes;
287
288         if (bp->outPtr == bp->inPtr) {
289                 bp->outPtr = bp->inPtr = bp->buffer;
290                 bp->left = bp->size;
291                 *bp->inPtr = 0;
292         }
293         return (numBytes);
294 }
295
296 /*-
297  *-----------------------------------------------------------------------
298  * Buf_GetAll --
299  *      Get all the available data at once.
300  *
301  * Results:
302  *      A pointer to the data and the number of bytes available.
303  *
304  * Side Effects:
305  *      None.
306  *
307  *-----------------------------------------------------------------------
308  */
309 Byte *
310 Buf_GetAll(Buffer *bp, size_t *numBytesPtr)
311 {
312
313         if (numBytesPtr != NULL)
314                 *numBytesPtr = bp->inPtr - bp->outPtr;
315
316         return (bp->outPtr);
317 }
318
319 /*-
320  *-----------------------------------------------------------------------
321  * Buf_Discard --
322  *      Throw away bytes in a buffer.
323  *
324  * Results:
325  *      None.
326  *
327  * Side Effects:
328  *      The bytes are discarded.
329  *
330  *-----------------------------------------------------------------------
331  */
332 void
333 Buf_Discard(Buffer *bp, size_t numBytes)
334 {
335
336         if ((size_t)(bp->inPtr - bp->outPtr) <= numBytes) {
337                 bp->inPtr = bp->outPtr = bp->buffer;
338                 bp->left = bp->size;
339                 *bp->inPtr = 0;
340         } else
341                 bp->outPtr += numBytes;
342 }
343
344 /*-
345  *-----------------------------------------------------------------------
346  * Buf_Size --
347  *      Returns the number of bytes in the given buffer. Doesn't include
348  *      the null-terminating byte.
349  *
350  * Results:
351  *      The number of bytes.
352  *
353  * Side Effects:
354  *      None.
355  *
356  *-----------------------------------------------------------------------
357  */
358 size_t
359 Buf_Size(Buffer *buf)
360 {
361
362         return (buf->inPtr - buf->outPtr);
363 }
364
365 /*-
366  *-----------------------------------------------------------------------
367  * Buf_Init --
368  *      Initialize a buffer. If no initial size is given, a reasonable
369  *      default is used.
370  *
371  * Results:
372  *      A buffer to be given to other functions in this library.
373  *
374  * Side Effects:
375  *      The buffer is created, the space allocated and pointers
376  *      initialized.
377  *
378  *-----------------------------------------------------------------------
379  */
380 Buffer *
381 Buf_Init(size_t size)
382 {
383         Buffer *bp;             /* New Buffer */
384
385         bp = emalloc(sizeof(*bp));
386
387         if (size <= 0)
388                 size = BUF_DEF_SIZE;
389
390         bp->left = bp->size = size;
391         bp->buffer = emalloc(size);
392         bp->inPtr = bp->outPtr = bp->buffer;
393         *bp->inPtr = 0;
394
395         return (bp);
396 }
397
398 /*-
399  *-----------------------------------------------------------------------
400  * Buf_Destroy --
401  *      Destroy a buffer, and optionally free its data, too.
402  *
403  * Results:
404  *      None.
405  *
406  * Side Effects:
407  *      The buffer is freed.
408  *
409  *-----------------------------------------------------------------------
410  */
411 void
412 Buf_Destroy(Buffer *buf, Boolean freeData)
413 {
414
415         if (freeData)
416                 free(buf->buffer);
417         free(buf);
418 }
419
420 /*-
421  *-----------------------------------------------------------------------
422  * Buf_ReplaceLastByte --
423  *     Replace the last byte in a buffer.
424  *
425  * Results:
426  *     None.
427  *
428  * Side Effects:
429  *     If the buffer was empty intially, then a new byte will be added.
430  *     Otherwise, the last byte is overwritten.
431  *
432  *-----------------------------------------------------------------------
433  */
434 void
435 Buf_ReplaceLastByte(Buffer *buf, Byte byte)
436 {
437         if (buf->inPtr == buf->outPtr)
438                 Buf_AddByte(buf, byte);
439         else
440                 *(buf->inPtr - 1) = byte;
441 }