buf.c revision 141275
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 */
41
42#include <sys/cdefs.h>
43__FBSDID("$FreeBSD: head/usr.bin/make/buf.c 141275 2005-02-04 13:34:16Z harti $");
44
45/*-
46 * buf.c --
47 *	Functions for automatically-expanded buffers.
48 */
49
50#include <string.h>
51#include <stdlib.h>
52
53#include "buf.h"
54#include "sprite.h"
55#include "util.h"
56
57#ifndef max
58#define	max(a,b)  ((a) > (b) ? (a) : (b))
59#endif
60
61/*
62 * BufExpand --
63 * 	Expand the given buffer to hold the given number of additional
64 *	bytes.
65 *	Makes sure there's room for an extra NULL byte at the end of the
66 *	buffer in case it holds a string.
67 */
68#define	BufExpand(bp, nb) do {						\
69 	if ((bp)->left < (nb) + 1) {					\
70		int newSize = (bp)->size + max((nb) + 1, BUF_ADD_INC);	\
71		Byte *newBuf = erealloc((bp)->buffer, newSize);		\
72									\
73		(bp)->inPtr = newBuf + ((bp)->inPtr - (bp)->buffer);	\
74		(bp)->outPtr = newBuf + ((bp)->outPtr - (bp)->buffer);	\
75		(bp)->buffer = newBuf;					\
76		(bp)->size = newSize;					\
77		(bp)->left = newSize - ((bp)->inPtr - (bp)->buffer);	\
78	}								\
79    } while (0)
80
81#define	BUF_DEF_SIZE	256 	/* Default buffer size */
82#define	BUF_ADD_INC	256 	/* Expansion increment when Adding */
83#define	BUF_UNGET_INC	16  	/* Expansion increment when Ungetting */
84
85/*-
86 *-----------------------------------------------------------------------
87 * Buf_OvAddByte --
88 *	Add a single byte to the buffer.  left is zero or negative.
89 *
90 * Results:
91 *	None.
92 *
93 * Side Effects:
94 *	The buffer may be expanded.
95 *
96 *-----------------------------------------------------------------------
97 */
98void
99Buf_OvAddByte(Buffer *bp, Byte byte)
100{
101
102	bp->left = 0;
103	BufExpand(bp, 1);
104
105	*bp->inPtr++ = byte;
106	bp->left--;
107
108	/*
109	 * Null-terminate
110	 */
111	*bp->inPtr = 0;
112}
113
114/*-
115 *-----------------------------------------------------------------------
116 * Buf_AddBytes --
117 *	Add a number of bytes to the buffer.
118 *
119 * Results:
120 *	None.
121 *
122 * Side Effects:
123 *	Guess what?
124 *
125 *-----------------------------------------------------------------------
126 */
127void
128Buf_AddBytes(Buffer *bp, size_t numBytes, const Byte *bytesPtr)
129{
130
131	BufExpand(bp, numBytes);
132
133	memcpy(bp->inPtr, bytesPtr, numBytes);
134	bp->inPtr += numBytes;
135	bp->left -= numBytes;
136
137	/*
138	 * Null-terminate
139	 */
140	*bp->inPtr = 0;
141}
142
143/*-
144 *-----------------------------------------------------------------------
145 * Buf_GetAll --
146 *	Get all the available data at once.
147 *
148 * Results:
149 *	A pointer to the data and the number of bytes available.
150 *
151 * Side Effects:
152 *	None.
153 *
154 *-----------------------------------------------------------------------
155 */
156Byte *
157Buf_GetAll(Buffer *bp, size_t *numBytesPtr)
158{
159
160	if (numBytesPtr != NULL)
161		*numBytesPtr = bp->inPtr - bp->outPtr;
162
163	return (bp->outPtr);
164}
165
166/*-
167 *-----------------------------------------------------------------------
168 * Buf_Size --
169 *	Returns the number of bytes in the given buffer. Doesn't include
170 *	the null-terminating byte.
171 *
172 * Results:
173 *	The number of bytes.
174 *
175 * Side Effects:
176 *	None.
177 *
178 *-----------------------------------------------------------------------
179 */
180size_t
181Buf_Size(Buffer *buf)
182{
183
184	return (buf->inPtr - buf->outPtr);
185}
186
187/*-
188 *-----------------------------------------------------------------------
189 * Buf_Init --
190 *	Initialize a buffer. If no initial size is given, a reasonable
191 *	default is used.
192 *
193 * Results:
194 *	A buffer to be given to other functions in this library.
195 *
196 * Side Effects:
197 *	The buffer is created, the space allocated and pointers
198 *	initialized.
199 *
200 *-----------------------------------------------------------------------
201 */
202Buffer *
203Buf_Init(size_t size)
204{
205	Buffer *bp;	  	/* New Buffer */
206
207	bp = emalloc(sizeof(*bp));
208
209	if (size <= 0)
210		size = BUF_DEF_SIZE;
211
212	bp->left = bp->size = size;
213	bp->buffer = emalloc(size);
214	bp->inPtr = bp->outPtr = bp->buffer;
215	*bp->inPtr = 0;
216
217	return (bp);
218}
219
220/*-
221 *-----------------------------------------------------------------------
222 * Buf_Destroy --
223 *	Destroy a buffer, and optionally free its data, too.
224 *
225 * Results:
226 *	None.
227 *
228 * Side Effects:
229 *	The buffer is freed.
230 *
231 *-----------------------------------------------------------------------
232 */
233void
234Buf_Destroy(Buffer *buf, Boolean freeData)
235{
236
237	if (freeData)
238		free(buf->buffer);
239	free(buf);
240}
241
242/*-
243 *-----------------------------------------------------------------------
244 * Buf_ReplaceLastByte --
245 *     Replace the last byte in a buffer.
246 *
247 * Results:
248 *     None.
249 *
250 * Side Effects:
251 *     If the buffer was empty intially, then a new byte will be added.
252 *     Otherwise, the last byte is overwritten.
253 *
254 *-----------------------------------------------------------------------
255 */
256void
257Buf_ReplaceLastByte(Buffer *buf, Byte byte)
258{
259	if (buf->inPtr == buf->outPtr)
260		Buf_AddByte(buf, byte);
261	else
262		*(buf->inPtr - 1) = byte;
263}
264
265void
266Buf_Clear(Buffer *bp)
267{
268	bp->inPtr	= bp->buffer;
269	bp->outPtr	= bp->buffer;
270	bp->left	= bp->size;
271	bp->inPtr[0]	= '\0';
272}
273
274