buf.c revision 141138
1114402Sru/*-
2114402Sru * Copyright (c) 1988, 1989, 1990, 1993
3114402Sru *	The Regents of the University of California.  All rights reserved.
4114402Sru * Copyright (c) 1988, 1989 by Adam de Boor
5114402Sru * Copyright (c) 1989 by Berkeley Softworks
6114402Sru * All rights reserved.
7114402Sru *
8114402Sru * This code is derived from software contributed to Berkeley by
9114402Sru * Adam de Boor.
10114402Sru *
11114402Sru * Redistribution and use in source and binary forms, with or without
12114402Sru * modification, are permitted provided that the following conditions
13114402Sru * are met:
14114402Sru * 1. Redistributions of source code must retain the above copyright
15114402Sru *    notice, this list of conditions and the following disclaimer.
16114402Sru * 2. Redistributions in binary form must reproduce the above copyright
17114402Sru *    notice, this list of conditions and the following disclaimer in the
18114402Sru *    documentation and/or other materials provided with the distribution.
19151497Sru * 3. All advertising materials mentioning features or use of this software
20114402Sru *    must display the following acknowledgement:
21114402Sru *	This product includes software developed by the University of
22114402Sru *	California, Berkeley and its contributors.
23114402Sru * 4. Neither the name of the University nor the names of its contributors
24114402Sru *    may be used to endorse or promote products derived from this software
25114402Sru *    without specific prior written permission.
26114402Sru *
27114402Sru * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
28114402Sru * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29114402Sru * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30114402Sru * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
31114402Sru * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
32114402Sru * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
33114402Sru * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
34114402Sru * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
35114402Sru * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
36114402Sru * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37114402Sru * SUCH DAMAGE.
38114402Sru *
39114402Sru * @(#)buf.c	8.1 (Berkeley) 6/6/93
40114402Sru */
41114402Sru
42114402Sru#include <sys/cdefs.h>
43114402Sru__FBSDID("$FreeBSD: head/usr.bin/make/buf.c 141138 2005-02-02 11:21:26Z harti $");
44114402Sru
45114402Sru/*-
46114402Sru * buf.c --
47114402Sru *	Functions for automatically-expanded buffers.
48114402Sru */
49114402Sru
50114402Sru#include <string.h>
51114402Sru#include <stdlib.h>
52114402Sru
53114402Sru#include "buf.h"
54114402Sru#include "sprite.h"
55114402Sru#include "util.h"
56114402Sru
57114402Sru#ifndef max
58114402Sru#define	max(a,b)  ((a) > (b) ? (a) : (b))
59114402Sru#endif
60114402Sru
61114402Sru/*
62114402Sru * BufExpand --
63114402Sru * 	Expand the given buffer to hold the given number of additional
64114402Sru *	bytes.
65114402Sru *	Makes sure there's room for an extra NULL byte at the end of the
66114402Sru *	buffer in case it holds a string.
67114402Sru */
68114402Sru#define	BufExpand(bp, nb) do {						\
69114402Sru 	if ((bp)->left < (nb) + 1) {					\
70114402Sru		int newSize = (bp)->size + max((nb) + 1, BUF_ADD_INC);	\
71114402Sru		Byte *newBuf = erealloc((bp)->buffer, newSize);		\
72114402Sru									\
73114402Sru		(bp)->inPtr = newBuf + ((bp)->inPtr - (bp)->buffer);	\
74114402Sru		(bp)->outPtr = newBuf + ((bp)->outPtr - (bp)->buffer);	\
75114402Sru		(bp)->buffer = newBuf;					\
76114402Sru		(bp)->size = newSize;					\
77114402Sru		(bp)->left = newSize - ((bp)->inPtr - (bp)->buffer);	\
78114402Sru	}								\
79114402Sru    } while (0)
80114402Sru
81114402Sru#define	BUF_DEF_SIZE	256 	/* Default buffer size */
82114402Sru#define	BUF_ADD_INC	256 	/* Expansion increment when Adding */
83114402Sru#define	BUF_UNGET_INC	16  	/* Expansion increment when Ungetting */
84114402Sru
85114402Sru/*-
86114402Sru *-----------------------------------------------------------------------
87114402Sru * Buf_OvAddByte --
88114402Sru *	Add a single byte to the buffer.  left is zero or negative.
89114402Sru *
90114402Sru * Results:
91114402Sru *	None.
92114402Sru *
93114402Sru * Side Effects:
94114402Sru *	The buffer may be expanded.
95114402Sru *
96114402Sru *-----------------------------------------------------------------------
97114402Sru */
98114402Sruvoid
99114402SruBuf_OvAddByte(Buffer *bp, Byte byte)
100114402Sru{
101114402Sru
102114402Sru	bp->left = 0;
103114402Sru	BufExpand(bp, 1);
104114402Sru
105114402Sru	*bp->inPtr++ = byte;
106114402Sru	bp->left--;
107114402Sru
108114402Sru	/*
109114402Sru	 * Null-terminate
110114402Sru	 */
111114402Sru	*bp->inPtr = 0;
112114402Sru}
113114402Sru
114114402Sru/*-
115114402Sru *-----------------------------------------------------------------------
116114402Sru * Buf_AddBytes --
117114402Sru *	Add a number of bytes to the buffer.
118114402Sru *
119114402Sru * Results:
120114402Sru *	None.
121114402Sru *
122114402Sru * Side Effects:
123114402Sru *	Guess what?
124114402Sru *
125114402Sru *-----------------------------------------------------------------------
126114402Sru */
127114402Sruvoid
128114402SruBuf_AddBytes(Buffer *bp, size_t numBytes, const Byte *bytesPtr)
129114402Sru{
130114402Sru
131114402Sru	BufExpand(bp, numBytes);
132114402Sru
133114402Sru	memcpy(bp->inPtr, bytesPtr, numBytes);
134114402Sru	bp->inPtr += numBytes;
135114402Sru	bp->left -= numBytes;
136114402Sru
137114402Sru	/*
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_Discard --
169 *	Throw away bytes in a buffer.
170 *
171 * Results:
172 *	None.
173 *
174 * Side Effects:
175 *	The bytes are discarded.
176 *
177 *-----------------------------------------------------------------------
178 */
179void
180Buf_Discard(Buffer *bp, size_t numBytes)
181{
182
183	if ((size_t)(bp->inPtr - bp->outPtr) <= numBytes) {
184		bp->inPtr = bp->outPtr = bp->buffer;
185		bp->left = bp->size;
186		*bp->inPtr = 0;
187	} else
188		bp->outPtr += numBytes;
189}
190
191/*-
192 *-----------------------------------------------------------------------
193 * Buf_Size --
194 *	Returns the number of bytes in the given buffer. Doesn't include
195 *	the null-terminating byte.
196 *
197 * Results:
198 *	The number of bytes.
199 *
200 * Side Effects:
201 *	None.
202 *
203 *-----------------------------------------------------------------------
204 */
205size_t
206Buf_Size(Buffer *buf)
207{
208
209	return (buf->inPtr - buf->outPtr);
210}
211
212/*-
213 *-----------------------------------------------------------------------
214 * Buf_Init --
215 *	Initialize a buffer. If no initial size is given, a reasonable
216 *	default is used.
217 *
218 * Results:
219 *	A buffer to be given to other functions in this library.
220 *
221 * Side Effects:
222 *	The buffer is created, the space allocated and pointers
223 *	initialized.
224 *
225 *-----------------------------------------------------------------------
226 */
227Buffer *
228Buf_Init(size_t size)
229{
230	Buffer *bp;	  	/* New Buffer */
231
232	bp = emalloc(sizeof(*bp));
233
234	if (size <= 0)
235		size = BUF_DEF_SIZE;
236
237	bp->left = bp->size = size;
238	bp->buffer = emalloc(size);
239	bp->inPtr = bp->outPtr = bp->buffer;
240	*bp->inPtr = 0;
241
242	return (bp);
243}
244
245/*-
246 *-----------------------------------------------------------------------
247 * Buf_Destroy --
248 *	Destroy a buffer, and optionally free its data, too.
249 *
250 * Results:
251 *	None.
252 *
253 * Side Effects:
254 *	The buffer is freed.
255 *
256 *-----------------------------------------------------------------------
257 */
258void
259Buf_Destroy(Buffer *buf, Boolean freeData)
260{
261
262	if (freeData)
263		free(buf->buffer);
264	free(buf);
265}
266
267/*-
268 *-----------------------------------------------------------------------
269 * Buf_ReplaceLastByte --
270 *     Replace the last byte in a buffer.
271 *
272 * Results:
273 *     None.
274 *
275 * Side Effects:
276 *     If the buffer was empty intially, then a new byte will be added.
277 *     Otherwise, the last byte is overwritten.
278 *
279 *-----------------------------------------------------------------------
280 */
281void
282Buf_ReplaceLastByte(Buffer *buf, Byte byte)
283{
284	if (buf->inPtr == buf->outPtr)
285		Buf_AddByte(buf, byte);
286	else
287		*(buf->inPtr - 1) = byte;
288}
289