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