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