1141104Sharti/*-
2141290Sharti * Copyright (c) 2005 Max Okumoto
394589Sobrien * Copyright (c) 1988, 1989, 1990, 1993
494589Sobrien *	The Regents of the University of California.  All rights reserved.
55814Sjkh * Copyright (c) 1988, 1989 by Adam de Boor
61590Srgrimes * Copyright (c) 1989 by Berkeley Softworks
71590Srgrimes * All rights reserved.
81590Srgrimes *
91590Srgrimes * This code is derived from software contributed to Berkeley by
101590Srgrimes * Adam de Boor.
111590Srgrimes *
121590Srgrimes * Redistribution and use in source and binary forms, with or without
131590Srgrimes * modification, are permitted provided that the following conditions
141590Srgrimes * are met:
151590Srgrimes * 1. Redistributions of source code must retain the above copyright
161590Srgrimes *    notice, this list of conditions and the following disclaimer.
171590Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
181590Srgrimes *    notice, this list of conditions and the following disclaimer in the
191590Srgrimes *    documentation and/or other materials provided with the distribution.
201590Srgrimes * 3. All advertising materials mentioning features or use of this software
211590Srgrimes *    must display the following acknowledgement:
221590Srgrimes *	This product includes software developed by the University of
231590Srgrimes *	California, Berkeley and its contributors.
241590Srgrimes * 4. Neither the name of the University nor the names of its contributors
251590Srgrimes *    may be used to endorse or promote products derived from this software
261590Srgrimes *    without specific prior written permission.
271590Srgrimes *
281590Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
291590Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
301590Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
311590Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
321590Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
331590Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
341590Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
351590Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
361590Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
371590Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
381590Srgrimes * SUCH DAMAGE.
3962833Swsanchez *
4062833Swsanchez * @(#)buf.c	8.1 (Berkeley) 6/6/93
411590Srgrimes */
421590Srgrimes
4362833Swsanchez#include <sys/cdefs.h>
4494587Sobrien__FBSDID("$FreeBSD$");
451590Srgrimes
46141290Sharti/*
47141290Sharti * buf.c
481590Srgrimes *	Functions for automatically-expanded buffers.
491590Srgrimes */
501590Srgrimes
51141104Sharti#include <string.h>
52141104Sharti#include <stdlib.h>
53141104Sharti
54141104Sharti#include "buf.h"
55141104Sharti#include "util.h"
561590Srgrimes
57141290Sharti/**
58141290Sharti * Returns the number of bytes in the buffer.  Doesn't include the
59141290Sharti * null-terminating byte.
601590Srgrimes */
61187475Srdivackysize_t
62141290ShartiBuf_Size(const Buffer *buf)
63141290Sharti{
641590Srgrimes
65141290Sharti	return (buf->end - buf->buf);
66141290Sharti}
671590Srgrimes
68141290Sharti/**
69143957Sharti * Returns a reference to the data contained in the buffer.
70143957Sharti *
71143957Sharti * @note Adding data to the Buffer object may invalidate the reference.
72143957Sharti */
73187475Srdivackychar *
74143957ShartiBuf_Data(const Buffer *bp)
75143957Sharti{
76143957Sharti
77143957Sharti	return (bp->buf);
78143957Sharti}
79143957Sharti
80143957Sharti/**
81141290Sharti * Expand the buffer to hold the number of additional bytes, plus
82141290Sharti * space to store a terminating NULL byte.
831590Srgrimes */
84141290Shartistatic inline void
85141290ShartiBufExpand(Buffer *bp, size_t nb)
861590Srgrimes{
87141290Sharti	size_t	len = Buf_Size(bp);
88141290Sharti	size_t	size;
89138264Sharti
90141290Sharti	if (bp->size < len + nb + 1) {
91141290Sharti		size = bp->size + MAX(nb + 1, BUF_ADD_INC);
92141290Sharti		bp->size = size;
93141290Sharti		bp->buf = erealloc(bp->buf, size);
94141290Sharti		bp->end = bp->buf + len;
95141290Sharti	}
961590Srgrimes}
97138232Sharti
98141290Sharti/**
99141290Sharti * Add a single byte to the buffer.
1001590Srgrimes */
101187475Srdivackyvoid
102141290ShartiBuf_AddByte(Buffer *bp, Byte byte)
1031590Srgrimes{
1041590Srgrimes
105141290Sharti	BufExpand(bp, 1);
1061590Srgrimes
107141290Sharti	*bp->end = byte;
108141290Sharti	bp->end++;
109141290Sharti	*bp->end = '\0';
1101590Srgrimes}
111138232Sharti
112141290Sharti/**
113141290Sharti * Add bytes to the buffer.
1141590Srgrimes */
115141290Shartivoid
116141290ShartiBuf_AddBytes(Buffer *bp, size_t len, const Byte *bytes)
1171590Srgrimes{
1181590Srgrimes
119141290Sharti	BufExpand(bp, len);
1208874Srgrimes
121141290Sharti	memcpy(bp->end, bytes, len);
122141290Sharti	bp->end += len;
123141290Sharti	*bp->end = '\0';
1241590Srgrimes}
125138232Sharti
126141290Sharti/**
127141290Sharti * Get a reference to the internal buffer.
1281590Srgrimes *
129141290Sharti * len:
130141290Sharti *	Pointer to where we return the number of bytes in the internal buffer.
1311590Srgrimes *
132141290Sharti * Returns:
133141290Sharti *	return A pointer to the data.
1341590Srgrimes */
135141290ShartiByte *
136141290ShartiBuf_GetAll(Buffer *bp, size_t *len)
1371590Srgrimes{
138138264Sharti
139141290Sharti	if (len != NULL)
140141290Sharti		*len = Buf_Size(bp);
141141290Sharti
142141290Sharti	return (bp->buf);
1431590Srgrimes}
144138232Sharti
145141290Sharti/**
146143287Sharti * Get the contents of a buffer and destroy the buffer. If the buffer
147143287Sharti * is NULL, return NULL.
148143287Sharti *
149143287Sharti * Returns:
150143287Sharti *	the pointer to the data.
151143287Sharti */
152143287Shartichar *
153143287ShartiBuf_Peel(Buffer *bp)
154143287Sharti{
155143287Sharti	char *ret;
156143287Sharti
157143287Sharti	if (bp == NULL)
158143287Sharti		return (NULL);
159143287Sharti	ret = bp->buf;
160143287Sharti	free(bp);
161143287Sharti	return (ret);
162143287Sharti}
163143287Sharti
164143287Sharti/**
165141290Sharti * Initialize a buffer. If no initial size is given, a reasonable
166141290Sharti * default is used.
1671590Srgrimes *
168141290Sharti * Returns:
169141290Sharti *	A buffer object to be given to other functions in this library.
1701590Srgrimes *
1711590Srgrimes * Side Effects:
172141290Sharti *	Space is allocated for the Buffer object and a internal buffer.
1731590Srgrimes */
174141133ShartiBuffer *
175138341ShartiBuf_Init(size_t size)
1761590Srgrimes{
177141290Sharti	Buffer *bp;	/* New Buffer */
1781590Srgrimes
179138337Sharti	if (size <= 0)
180138337Sharti		size = BUF_DEF_SIZE;
1811590Srgrimes
182141290Sharti	bp = emalloc(sizeof(*bp));
183141290Sharti	bp->size = size;
184141290Sharti	bp->buf = emalloc(size);
185141290Sharti	bp->end = bp->buf;
186141290Sharti	*bp->end = '\0';
187138337Sharti
188138337Sharti	return (bp);
1891590Srgrimes}
190138232Sharti
191141290Sharti/**
192141290Sharti * Destroy a buffer, and optionally free its data, too.
1931590Srgrimes *
1941590Srgrimes * Side Effects:
195141290Sharti *	Space for the Buffer object and possibly the internal buffer
196141290Sharti *	is de-allocated.
1971590Srgrimes */
1981590Srgrimesvoid
199141133ShartiBuf_Destroy(Buffer *buf, Boolean freeData)
2001590Srgrimes{
2018874Srgrimes
202138337Sharti	if (freeData)
203141290Sharti		free(buf->buf);
204138337Sharti	free(buf);
2051590Srgrimes}
206138232Sharti
207141290Sharti/**
208141290Sharti * Replace the last byte in a buffer.  If the buffer was empty
209228992Suqs * initially, then a new byte will be added.
21018456Ssteve */
21118456Sstevevoid
212141290ShartiBuf_ReplaceLastByte(Buffer *bp, Byte byte)
21318456Ssteve{
214141290Sharti
215141290Sharti	if (bp->end == bp->buf) {
216141290Sharti		Buf_AddByte(bp, byte);
217141290Sharti	} else {
218141290Sharti		*(bp->end - 1) = byte;
219141290Sharti	}
22018456Ssteve}
221141275Sharti
222141290Sharti/**
223141436Sharti * Append characters in str to Buffer object
224141436Sharti */
225141436Shartivoid
226141436ShartiBuf_Append(Buffer *bp, const char str[])
227141436Sharti{
228141436Sharti
229141436Sharti	Buf_AddBytes(bp, strlen(str), str);
230141436Sharti}
231141436Sharti
232141436Sharti/**
233143957Sharti * Append characters in buf to Buffer object
234143957Sharti */
235143957Shartivoid
236143957ShartiBuf_AppendBuf(Buffer *bp, const Buffer *buf)
237143957Sharti{
238143957Sharti
239143957Sharti	Buf_AddBytes(bp, Buf_Size(buf), buf->buf);
240143957Sharti}
241143957Sharti
242143957Sharti/**
243141437Sharti * Append characters between str and end to Buffer object.
244141437Sharti */
245141437Shartivoid
246141437ShartiBuf_AppendRange(Buffer *bp, const char str[], const char *end)
247141437Sharti{
248143957Sharti
249141437Sharti	Buf_AddBytes(bp, end - str, str);
250141437Sharti}
251141437Sharti
252141437Sharti/**
253141454Sharti * Convert newlines in buffer to spaces.  The trailing newline is
254141454Sharti * removed.
255141454Sharti */
256141454Shartivoid
257141454ShartiBuf_StripNewlines(Buffer *bp)
258141454Sharti{
259141454Sharti	char *ptr = bp->end;
260141454Sharti
261141454Sharti	/*
262141454Sharti	 * If there is anything in the buffer, remove the last
263141454Sharti	 * newline character.
264141454Sharti	 */
265141454Sharti	if (ptr != bp->buf) {
266141454Sharti		if (*(ptr - 1) == '\n') {
267141454Sharti			/* shorten buffer */
268141454Sharti			*(ptr - 1) = '\0';
269141454Sharti			--bp->end;
270141454Sharti		}
271141454Sharti		--ptr;
272141454Sharti	}
273141454Sharti
274141454Sharti	/* Convert newline characters to a space characters.  */
275141454Sharti	while (ptr != bp->buf) {
276141454Sharti		if (*ptr == '\n') {
277141454Sharti			*ptr = ' ';
278141454Sharti		}
279141454Sharti		--ptr;
280141454Sharti	}
281141454Sharti}
282141454Sharti/**
283141290Sharti * Clear the contents of the buffer.
284141290Sharti */
285141275Shartivoid
286141275ShartiBuf_Clear(Buffer *bp)
287141275Sharti{
288141290Sharti
289141290Sharti	bp->end = bp->buf;
290141290Sharti	*bp->end = '\0';
291141275Sharti}
292