1236769Sobrien/*	$NetBSD: buf.c,v 1.25 2012/04/24 20:26:58 sjg Exp $	*/
2236769Sobrien
3236769Sobrien/*
4236769Sobrien * Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
5236769Sobrien * All rights reserved.
6236769Sobrien *
7236769Sobrien * This code is derived from software contributed to Berkeley by
8236769Sobrien * Adam de Boor.
9236769Sobrien *
10236769Sobrien * Redistribution and use in source and binary forms, with or without
11236769Sobrien * modification, are permitted provided that the following conditions
12236769Sobrien * are met:
13236769Sobrien * 1. Redistributions of source code must retain the above copyright
14236769Sobrien *    notice, this list of conditions and the following disclaimer.
15236769Sobrien * 2. Redistributions in binary form must reproduce the above copyright
16236769Sobrien *    notice, this list of conditions and the following disclaimer in the
17236769Sobrien *    documentation and/or other materials provided with the distribution.
18236769Sobrien * 3. Neither the name of the University nor the names of its contributors
19236769Sobrien *    may be used to endorse or promote products derived from this software
20236769Sobrien *    without specific prior written permission.
21236769Sobrien *
22236769Sobrien * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23236769Sobrien * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24236769Sobrien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25236769Sobrien * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26236769Sobrien * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27236769Sobrien * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28236769Sobrien * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29236769Sobrien * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30236769Sobrien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31236769Sobrien * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32236769Sobrien * SUCH DAMAGE.
33236769Sobrien */
34236769Sobrien
35236769Sobrien/*
36236769Sobrien * Copyright (c) 1988, 1989 by Adam de Boor
37236769Sobrien * Copyright (c) 1989 by Berkeley Softworks
38236769Sobrien * All rights reserved.
39236769Sobrien *
40236769Sobrien * This code is derived from software contributed to Berkeley by
41236769Sobrien * Adam de Boor.
42236769Sobrien *
43236769Sobrien * Redistribution and use in source and binary forms, with or without
44236769Sobrien * modification, are permitted provided that the following conditions
45236769Sobrien * are met:
46236769Sobrien * 1. Redistributions of source code must retain the above copyright
47236769Sobrien *    notice, this list of conditions and the following disclaimer.
48236769Sobrien * 2. Redistributions in binary form must reproduce the above copyright
49236769Sobrien *    notice, this list of conditions and the following disclaimer in the
50236769Sobrien *    documentation and/or other materials provided with the distribution.
51236769Sobrien * 3. All advertising materials mentioning features or use of this software
52236769Sobrien *    must display the following acknowledgement:
53236769Sobrien *	This product includes software developed by the University of
54236769Sobrien *	California, Berkeley and its contributors.
55236769Sobrien * 4. Neither the name of the University nor the names of its contributors
56236769Sobrien *    may be used to endorse or promote products derived from this software
57236769Sobrien *    without specific prior written permission.
58236769Sobrien *
59236769Sobrien * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
60236769Sobrien * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
61236769Sobrien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
62236769Sobrien * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
63236769Sobrien * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
64236769Sobrien * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
65236769Sobrien * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
66236769Sobrien * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
67236769Sobrien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
68236769Sobrien * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
69236769Sobrien * SUCH DAMAGE.
70236769Sobrien */
71236769Sobrien
72236769Sobrien#ifndef MAKE_NATIVE
73236769Sobrienstatic char rcsid[] = "$NetBSD: buf.c,v 1.25 2012/04/24 20:26:58 sjg Exp $";
74236769Sobrien#else
75236769Sobrien#include <sys/cdefs.h>
76236769Sobrien#ifndef lint
77236769Sobrien#if 0
78236769Sobrienstatic char sccsid[] = "@(#)buf.c	8.1 (Berkeley) 6/6/93";
79236769Sobrien#else
80236769Sobrien__RCSID("$NetBSD: buf.c,v 1.25 2012/04/24 20:26:58 sjg Exp $");
81236769Sobrien#endif
82236769Sobrien#endif /* not lint */
83236769Sobrien#endif
84236769Sobrien
85236769Sobrien/*-
86236769Sobrien * buf.c --
87236769Sobrien *	Functions for automatically-expanded buffers.
88236769Sobrien */
89236769Sobrien
90236769Sobrien#include    "make.h"
91236769Sobrien#include    "buf.h"
92236769Sobrien
93236769Sobrien#ifndef max
94236769Sobrien#define max(a,b)  ((a) > (b) ? (a) : (b))
95236769Sobrien#endif
96236769Sobrien
97236769Sobrien#define BUF_DEF_SIZE	256 	/* Default buffer size */
98236769Sobrien
99236769Sobrien/*-
100236769Sobrien *-----------------------------------------------------------------------
101236769Sobrien * Buf_Expand_1 --
102236769Sobrien *	Extend buffer for single byte add.
103236769Sobrien *
104236769Sobrien *-----------------------------------------------------------------------
105236769Sobrien */
106236769Sobrienvoid
107236769SobrienBuf_Expand_1(Buffer *bp)
108236769Sobrien{
109236769Sobrien    bp->size += max(bp->size, 16);
110236769Sobrien    bp->buffer = bmake_realloc(bp->buffer, bp->size);
111236769Sobrien}
112236769Sobrien
113236769Sobrien/*-
114236769Sobrien *-----------------------------------------------------------------------
115236769Sobrien * Buf_AddBytes --
116236769Sobrien *	Add a number of bytes to the buffer.
117236769Sobrien *
118236769Sobrien * Results:
119236769Sobrien *	None.
120236769Sobrien *
121236769Sobrien * Side Effects:
122236769Sobrien *	Guess what?
123236769Sobrien *
124236769Sobrien *-----------------------------------------------------------------------
125236769Sobrien */
126236769Sobrienvoid
127236769SobrienBuf_AddBytes(Buffer *bp, int numBytes, const Byte *bytesPtr)
128236769Sobrien{
129236769Sobrien    int count = bp->count;
130236769Sobrien    Byte *ptr;
131236769Sobrien
132236769Sobrien    if (__predict_false(count + numBytes >= bp->size)) {
133236769Sobrien	bp->size += max(bp->size, numBytes + 16);
134236769Sobrien	bp->buffer = bmake_realloc(bp->buffer, bp->size);
135236769Sobrien    }
136236769Sobrien
137236769Sobrien    ptr = bp->buffer + count;
138236769Sobrien    bp->count = count + numBytes;
139236769Sobrien    ptr[numBytes] = 0;
140236769Sobrien    memcpy(ptr, bytesPtr, numBytes);
141236769Sobrien}
142236769Sobrien
143236769Sobrien/*-
144236769Sobrien *-----------------------------------------------------------------------
145236769Sobrien * Buf_GetAll --
146236769Sobrien *	Get all the available data at once.
147236769Sobrien *
148236769Sobrien * Results:
149236769Sobrien *	A pointer to the data and the number of bytes available.
150236769Sobrien *
151236769Sobrien * Side Effects:
152236769Sobrien *	None.
153236769Sobrien *
154236769Sobrien *-----------------------------------------------------------------------
155236769Sobrien */
156236769SobrienByte *
157236769SobrienBuf_GetAll(Buffer *bp, int *numBytesPtr)
158236769Sobrien{
159236769Sobrien
160236769Sobrien    if (numBytesPtr != NULL)
161236769Sobrien	*numBytesPtr = bp->count;
162236769Sobrien
163236769Sobrien    return (bp->buffer);
164236769Sobrien}
165236769Sobrien
166236769Sobrien/*-
167236769Sobrien *-----------------------------------------------------------------------
168236769Sobrien * Buf_Empty --
169236769Sobrien *	Throw away bytes in a buffer.
170236769Sobrien *
171236769Sobrien * Results:
172236769Sobrien *	None.
173236769Sobrien *
174236769Sobrien * Side Effects:
175236769Sobrien *	The bytes are discarded.
176236769Sobrien *
177236769Sobrien *-----------------------------------------------------------------------
178236769Sobrien */
179236769Sobrienvoid
180236769SobrienBuf_Empty(Buffer *bp)
181236769Sobrien{
182236769Sobrien
183236769Sobrien    bp->count = 0;
184236769Sobrien    *bp->buffer = 0;
185236769Sobrien}
186236769Sobrien
187236769Sobrien/*-
188236769Sobrien *-----------------------------------------------------------------------
189236769Sobrien * Buf_Init --
190236769Sobrien *	Initialize a buffer. If no initial size is given, a reasonable
191236769Sobrien *	default is used.
192236769Sobrien *
193236769Sobrien * Input:
194236769Sobrien *	size		Initial size for the buffer
195236769Sobrien *
196236769Sobrien * Results:
197236769Sobrien *	A buffer to be given to other functions in this library.
198236769Sobrien *
199236769Sobrien * Side Effects:
200236769Sobrien *	The buffer is created, the space allocated and pointers
201236769Sobrien *	initialized.
202236769Sobrien *
203236769Sobrien *-----------------------------------------------------------------------
204236769Sobrien */
205236769Sobrienvoid
206236769SobrienBuf_Init(Buffer *bp, int size)
207236769Sobrien{
208236769Sobrien    if (size <= 0) {
209236769Sobrien	size = BUF_DEF_SIZE;
210236769Sobrien    }
211236769Sobrien    bp->size = size;
212236769Sobrien    bp->count = 0;
213236769Sobrien    bp->buffer = bmake_malloc(size);
214236769Sobrien    *bp->buffer = 0;
215236769Sobrien}
216236769Sobrien
217236769Sobrien/*-
218236769Sobrien *-----------------------------------------------------------------------
219236769Sobrien * Buf_Destroy --
220236769Sobrien *	Nuke a buffer and all its resources.
221236769Sobrien *
222236769Sobrien * Input:
223236769Sobrien *	buf		Buffer to destroy
224236769Sobrien *	freeData	TRUE if the data should be destroyed
225236769Sobrien *
226236769Sobrien * Results:
227236769Sobrien *	Data buffer, NULL if freed
228236769Sobrien *
229236769Sobrien * Side Effects:
230236769Sobrien *	The buffer is freed.
231236769Sobrien *
232236769Sobrien *-----------------------------------------------------------------------
233236769Sobrien */
234236769SobrienByte *
235236769SobrienBuf_Destroy(Buffer *buf, Boolean freeData)
236236769Sobrien{
237236769Sobrien    Byte *data;
238236769Sobrien
239236769Sobrien    data = buf->buffer;
240236769Sobrien    if (freeData) {
241236769Sobrien	free(data);
242236769Sobrien	data = NULL;
243236769Sobrien    }
244236769Sobrien
245236769Sobrien    buf->size = 0;
246236769Sobrien    buf->count = 0;
247236769Sobrien    buf->buffer = NULL;
248236769Sobrien
249236769Sobrien    return data;
250236769Sobrien}
251236769Sobrien
252236769Sobrien
253236769Sobrien/*-
254236769Sobrien *-----------------------------------------------------------------------
255236769Sobrien * Buf_DestroyCompact --
256236769Sobrien *	Nuke a buffer and return its data.
257236769Sobrien *
258236769Sobrien * Input:
259236769Sobrien *	buf		Buffer to destroy
260236769Sobrien *
261236769Sobrien * Results:
262236769Sobrien *	Data buffer
263236769Sobrien *
264236769Sobrien * Side Effects:
265236769Sobrien *	If the buffer size is much greater than its content,
266236769Sobrien *	a new buffer will be allocated and the old one freed.
267236769Sobrien *
268236769Sobrien *-----------------------------------------------------------------------
269236769Sobrien */
270236769Sobrien#ifndef BUF_COMPACT_LIMIT
271236769Sobrien# define BUF_COMPACT_LIMIT 128          /* worthwhile saving */
272236769Sobrien#endif
273236769Sobrien
274236769SobrienByte *
275236769SobrienBuf_DestroyCompact(Buffer *buf)
276236769Sobrien{
277236769Sobrien#if BUF_COMPACT_LIMIT > 0
278236769Sobrien    Byte *data;
279236769Sobrien
280236769Sobrien    if (buf->size - buf->count >= BUF_COMPACT_LIMIT) {
281236769Sobrien	/* We trust realloc to be smart */
282236769Sobrien	data = bmake_realloc(buf->buffer, buf->count + 1);
283236769Sobrien	if (data) {
284236769Sobrien	    data[buf->count] = 0;
285236769Sobrien	    Buf_Destroy(buf, FALSE);
286236769Sobrien	    return data;
287236769Sobrien	}
288236769Sobrien    }
289236769Sobrien#endif
290236769Sobrien    return Buf_Destroy(buf, FALSE);
291236769Sobrien}
292