buf.c revision 143287
1198090Srdivacky/*-
2198090Srdivacky * Copyright (c) 2005 Max Okumoto
3198090Srdivacky * Copyright (c) 1988, 1989, 1990, 1993
4198090Srdivacky *	The Regents of the University of California.  All rights reserved.
5198090Srdivacky * Copyright (c) 1988, 1989 by Adam de Boor
6198090Srdivacky * Copyright (c) 1989 by Berkeley Softworks
7198090Srdivacky * All rights reserved.
8198090Srdivacky *
9198090Srdivacky * This code is derived from software contributed to Berkeley by
10198090Srdivacky * Adam de Boor.
11198090Srdivacky *
12198090Srdivacky * Redistribution and use in source and binary forms, with or without
13198090Srdivacky * modification, are permitted provided that the following conditions
14198090Srdivacky * are met:
15198090Srdivacky * 1. Redistributions of source code must retain the above copyright
16198090Srdivacky *    notice, this list of conditions and the following disclaimer.
17198090Srdivacky * 2. Redistributions in binary form must reproduce the above copyright
18198090Srdivacky *    notice, this list of conditions and the following disclaimer in the
19198090Srdivacky *    documentation and/or other materials provided with the distribution.
20198090Srdivacky * 3. All advertising materials mentioning features or use of this software
21198090Srdivacky *    must display the following acknowledgement:
22198090Srdivacky *	This product includes software developed by the University of
23198090Srdivacky *	California, Berkeley and its contributors.
24198090Srdivacky * 4. Neither the name of the University nor the names of its contributors
25198090Srdivacky *    may be used to endorse or promote products derived from this software
26198090Srdivacky *    without specific prior written permission.
27198090Srdivacky *
28198090Srdivacky * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
29198090Srdivacky * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
30198090Srdivacky * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
31198090Srdivacky * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
32198090Srdivacky * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33198090Srdivacky * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
34198090Srdivacky * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35198090Srdivacky * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
36198090Srdivacky * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
37208599Srdivacky * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
38208599Srdivacky * SUCH DAMAGE.
39208599Srdivacky *
40208599Srdivacky * @(#)buf.c	8.1 (Berkeley) 6/6/93
41208599Srdivacky */
42208599Srdivacky
43208599Srdivacky#include <sys/cdefs.h>
44208599Srdivacky__FBSDID("$FreeBSD: head/usr.bin/make/buf.c 143287 2005-03-08 13:15:18Z harti $");
45198090Srdivacky
46198090Srdivacky/*
47198090Srdivacky * buf.c
48198090Srdivacky *	Functions for automatically-expanded buffers.
49198090Srdivacky */
50198090Srdivacky
51198090Srdivacky#include <string.h>
52198090Srdivacky#include <stdlib.h>
53198090Srdivacky
54198090Srdivacky#include "buf.h"
55198090Srdivacky#include "sprite.h"
56198090Srdivacky#include "util.h"
57198090Srdivacky
58198090Srdivacky#ifndef MAX
59198090Srdivacky#define	MAX(a,b)  ((a) > (b) ? (a) : (b))
60198090Srdivacky#endif
61198090Srdivacky
62198090Srdivacky/**
63198090Srdivacky * Returns the number of bytes in the buffer.  Doesn't include the
64198090Srdivacky * null-terminating byte.
65198090Srdivacky */
66198090Srdivackyinline size_t
67198090SrdivackyBuf_Size(const Buffer *buf)
68198090Srdivacky{
69198090Srdivacky
70198090Srdivacky	return (buf->end - buf->buf);
71198090Srdivacky}
72198090Srdivacky
73198090Srdivacky/**
74207618Srdivacky * Expand the buffer to hold the number of additional bytes, plus
75207618Srdivacky * space to store a terminating NULL byte.
76208599Srdivacky */
77207618Srdivackystatic inline void
78207618SrdivackyBufExpand(Buffer *bp, size_t nb)
79207618Srdivacky{
80207618Srdivacky	size_t	len = Buf_Size(bp);
81207618Srdivacky	size_t	size;
82207618Srdivacky
83207618Srdivacky	if (bp->size < len + nb + 1) {
84207618Srdivacky		size = bp->size + MAX(nb + 1, BUF_ADD_INC);
85207618Srdivacky		bp->size = size;
86207618Srdivacky		bp->buf = erealloc(bp->buf, size);
87207618Srdivacky		bp->end = bp->buf + len;
88207618Srdivacky	}
89207618Srdivacky}
90198090Srdivacky
91198090Srdivacky/**
92198090Srdivacky * Add a single byte to the buffer.
93198090Srdivacky */
94198090Srdivackyinline void
95198090SrdivackyBuf_AddByte(Buffer *bp, Byte byte)
96198090Srdivacky{
97198090Srdivacky
98198090Srdivacky	BufExpand(bp, 1);
99198090Srdivacky
100198090Srdivacky	*bp->end = byte;
101198090Srdivacky	bp->end++;
102198090Srdivacky	*bp->end = '\0';
103198090Srdivacky}
104198090Srdivacky
105198090Srdivacky/**
106198090Srdivacky * Add bytes to the buffer.
107198090Srdivacky */
108198090Srdivackyvoid
109198090SrdivackyBuf_AddBytes(Buffer *bp, size_t len, const Byte *bytes)
110198090Srdivacky{
111198090Srdivacky
112198090Srdivacky	BufExpand(bp, len);
113198090Srdivacky
114198090Srdivacky	memcpy(bp->end, bytes, len);
115198090Srdivacky	bp->end += len;
116198090Srdivacky	*bp->end = '\0';
117198090Srdivacky}
118198090Srdivacky
119198090Srdivacky/**
120198090Srdivacky * Get a reference to the internal buffer.
121198090Srdivacky *
122198090Srdivacky * len:
123198090Srdivacky *	Pointer to where we return the number of bytes in the internal buffer.
124198090Srdivacky *
125198090Srdivacky * Returns:
126198090Srdivacky *	return A pointer to the data.
127198090Srdivacky */
128198090SrdivackyByte *
129198090SrdivackyBuf_GetAll(Buffer *bp, size_t *len)
130198090Srdivacky{
131198090Srdivacky
132198090Srdivacky	if (len != NULL)
133198090Srdivacky		*len = Buf_Size(bp);
134198090Srdivacky
135198090Srdivacky	return (bp->buf);
136198090Srdivacky}
137198090Srdivacky
138198090Srdivacky/**
139198090Srdivacky * Get the contents of a buffer and destroy the buffer. If the buffer
140198090Srdivacky * is NULL, return NULL.
141198090Srdivacky *
142198090Srdivacky * Returns:
143198090Srdivacky *	the pointer to the data.
144198090Srdivacky */
145198090Srdivackychar *
146198090SrdivackyBuf_Peel(Buffer *bp)
147198090Srdivacky{
148198090Srdivacky	char *ret;
149198090Srdivacky
150198090Srdivacky	if (bp == NULL)
151198090Srdivacky		return (NULL);
152198090Srdivacky	ret = bp->buf;
153198090Srdivacky	free(bp);
154198090Srdivacky	return (ret);
155198090Srdivacky}
156198090Srdivacky
157198090Srdivacky/**
158198090Srdivacky * Initialize a buffer. If no initial size is given, a reasonable
159198090Srdivacky * default is used.
160198090Srdivacky *
161198090Srdivacky * Returns:
162198090Srdivacky *	A buffer object to be given to other functions in this library.
163198090Srdivacky *
164198090Srdivacky * Side Effects:
165198090Srdivacky *	Space is allocated for the Buffer object and a internal buffer.
166198090Srdivacky */
167198090SrdivackyBuffer *
168198090SrdivackyBuf_Init(size_t size)
169198090Srdivacky{
170198090Srdivacky	Buffer *bp;	/* New Buffer */
171198090Srdivacky
172198090Srdivacky	if (size <= 0)
173198090Srdivacky		size = BUF_DEF_SIZE;
174198090Srdivacky
175198090Srdivacky	bp = emalloc(sizeof(*bp));
176198090Srdivacky	bp->size = size;
177198090Srdivacky	bp->buf = emalloc(size);
178198090Srdivacky	bp->end = bp->buf;
179198090Srdivacky	*bp->end = '\0';
180198090Srdivacky
181198090Srdivacky	return (bp);
182198090Srdivacky}
183198090Srdivacky
184198090Srdivacky/**
185198090Srdivacky * Destroy a buffer, and optionally free its data, too.
186198090Srdivacky *
187198090Srdivacky * Side Effects:
188198090Srdivacky *	Space for the Buffer object and possibly the internal buffer
189198090Srdivacky *	is de-allocated.
190198090Srdivacky */
191198090Srdivackyvoid
192198090SrdivackyBuf_Destroy(Buffer *buf, Boolean freeData)
193198090Srdivacky{
194198090Srdivacky
195198090Srdivacky	if (freeData)
196198090Srdivacky		free(buf->buf);
197198090Srdivacky	free(buf);
198198090Srdivacky}
199198090Srdivacky
200198090Srdivacky/**
201198090Srdivacky * Replace the last byte in a buffer.  If the buffer was empty
202198090Srdivacky * intially, then a new byte will be added.
203198090Srdivacky */
204198090Srdivackyvoid
205198090SrdivackyBuf_ReplaceLastByte(Buffer *bp, Byte byte)
206198090Srdivacky{
207198090Srdivacky
208198090Srdivacky	if (bp->end == bp->buf) {
209198090Srdivacky		Buf_AddByte(bp, byte);
210198090Srdivacky	} else {
211198090Srdivacky		*(bp->end - 1) = byte;
212198090Srdivacky	}
213198090Srdivacky}
214198090Srdivacky
215198090Srdivacky/**
216198090Srdivacky * Append characters in str to Buffer object
217198090Srdivacky */
218198090Srdivackyvoid
219198090SrdivackyBuf_Append(Buffer *bp, const char str[])
220198090Srdivacky{
221198090Srdivacky
222198090Srdivacky	Buf_AddBytes(bp, strlen(str), str);
223198090Srdivacky}
224198090Srdivacky
225198090Srdivacky/**
226198090Srdivacky * Append characters between str and end to Buffer object.
227198090Srdivacky */
228198090Srdivackyvoid
229198090SrdivackyBuf_AppendRange(Buffer *bp, const char str[], const char *end)
230198090Srdivacky{
231198090Srdivacky	Buf_AddBytes(bp, end - str, str);
232198090Srdivacky}
233198090Srdivacky
234198090Srdivacky/**
235198090Srdivacky * Convert newlines in buffer to spaces.  The trailing newline is
236198090Srdivacky * removed.
237198090Srdivacky */
238198090Srdivackyvoid
239198090SrdivackyBuf_StripNewlines(Buffer *bp)
240198090Srdivacky{
241198090Srdivacky	char *ptr = bp->end;
242198090Srdivacky
243198090Srdivacky	/*
244198090Srdivacky	 * If there is anything in the buffer, remove the last
245198090Srdivacky	 * newline character.
246198090Srdivacky	 */
247198090Srdivacky	if (ptr != bp->buf) {
248198090Srdivacky		if (*(ptr - 1) == '\n') {
249198090Srdivacky			/* shorten buffer */
250198090Srdivacky			*(ptr - 1) = '\0';
251198090Srdivacky			--bp->end;
252198090Srdivacky		}
253198090Srdivacky		--ptr;
254198090Srdivacky	}
255198090Srdivacky
256198090Srdivacky	/* Convert newline characters to a space characters.  */
257198090Srdivacky	while (ptr != bp->buf) {
258198090Srdivacky		if (*ptr == '\n') {
259198090Srdivacky			*ptr = ' ';
260198090Srdivacky		}
261198090Srdivacky		--ptr;
262198090Srdivacky	}
263198090Srdivacky}
264198090Srdivacky/**
265198090Srdivacky * Clear the contents of the buffer.
266198090Srdivacky */
267198090Srdivackyvoid
268198090SrdivackyBuf_Clear(Buffer *bp)
269198090Srdivacky{
270198090Srdivacky
271198090Srdivacky	bp->end = bp->buf;
272198090Srdivacky	*bp->end = '\0';
273198090Srdivacky}
274198090Srdivacky