1 /* $OpenBSD: buf.c,v 1.23 2010/07/19 19:46:43 espie Exp $ */ 2 /* $NetBSD: buf.c,v 1.9 1996/12/31 17:53:21 christos Exp $ */ 3 4 /* 5 * Copyright (c) 1999 Marc Espie. 6 * 7 * Extensive code changes for the OpenBSD project. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE OPENBSD PROJECT AND CONTRIBUTORS 19 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OPENBSD 22 * PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 /* 31 * Copyright (c) 1988, 1989, 1990 The Regents of the University of California. 32 * Copyright (c) 1988, 1989 by Adam de Boor 33 * Copyright (c) 1989 by Berkeley Softworks 34 * All rights reserved. 35 * 36 * This code is derived from software contributed to Berkeley by 37 * Adam de Boor. 38 * 39 * Redistribution and use in source and binary forms, with or without 40 * modification, are permitted provided that the following conditions 41 * are met: 42 * 1. Redistributions of source code must retain the above copyright 43 * notice, this list of conditions and the following disclaimer. 44 * 2. Redistributions in binary form must reproduce the above copyright 45 * notice, this list of conditions and the following disclaimer in the 46 * documentation and/or other materials provided with the distribution. 47 * 3. Neither the name of the University nor the names of its contributors 48 * may be used to endorse or promote products derived from this software 49 * without specific prior written permission. 50 * 51 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 52 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 53 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 54 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 55 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 56 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 57 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 58 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 59 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 60 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 61 * SUCH DAMAGE. 62 */ 63 64 /*- 65 * buf.c -- 66 * Functions for automatically expanded buffers. 67 */ 68 69 #include <ctype.h> 70 #include <stddef.h> 71 #include <string.h> 72 #include "config.h" 73 #include "defines.h" 74 #include "buf.h" 75 #include "stats.h" 76 #include "memory.h" 77 78 #ifdef STATS_BUF 79 #define DO_STAT_BUF(bp, nb) \ 80 STAT_BUFS_EXPANSION++; \ 81 if ((bp)->endPtr - (bp)->buffer == 1) \ 82 STAT_WEIRD_INEFFICIENT++; 83 #else 84 #define DO_STAT_BUF(a, b) 85 #endif 86 87 /* BufExpand(bp, nb) 88 * Expand buffer bp to hold upto nb additional 89 * chars. Makes sure there's room for an extra '\0' char at 90 * the end of the buffer to terminate the string. */ 91 #define BufExpand(bp,nb) \ 92 do { \ 93 size_t occupied = (bp)->inPtr - (bp)->buffer; \ 94 size_t size = (bp)->endPtr - (bp)->buffer; \ 95 DO_STAT_BUF(bp, nb); \ 96 \ 97 do { \ 98 size *= 2 ; \ 99 } while (size - occupied < (nb)+1+BUF_MARGIN); \ 100 (bp)->buffer = (bp)->inPtr = (bp)->endPtr = \ 101 erealloc((bp)->buffer, size); \ 102 (bp)->inPtr += occupied; \ 103 (bp)->endPtr += size; \ 104 } while (0); 105 106 #define BUF_DEF_SIZE 256 /* Default buffer size */ 107 #define BUF_MARGIN 256 /* Make sure we are comfortable */ 108 109 /* the hard case for Buf_AddChar: buffer must be expanded to accommodate 110 * one more char. */ 111 void 112 BufOverflow(Buffer bp) 113 { 114 BufExpand(bp, 1); 115 } 116 117 118 void 119 Buf_AddChars(Buffer bp, size_t numBytes, const char *bytesPtr) 120 { 121 122 if ((size_t)(bp->endPtr - bp->inPtr) < numBytes+1) 123 BufExpand(bp, numBytes); 124 125 memcpy(bp->inPtr, bytesPtr, numBytes); 126 bp->inPtr += numBytes; 127 } 128 129 130 void 131 Buf_Init(Buffer bp, size_t size) 132 { 133 #ifdef STATS_BUF 134 STAT_TOTAL_BUFS++; 135 if (size == 0) 136 STAT_DEFAULT_BUFS++; 137 if (size == 1) 138 STAT_WEIRD_BUFS++; 139 #endif 140 if (size == 0) 141 size = BUF_DEF_SIZE; 142 bp->inPtr = bp->endPtr = bp->buffer = emalloc(size); 143 bp->endPtr += size; 144 } 145 146 void 147 Buf_KillTrailingSpaces(Buffer bp) 148 { 149 while (bp->inPtr > bp->buffer + 1 && isspace(bp->inPtr[-1])) { 150 if (bp->inPtr[-2] == '\\') 151 break; 152 bp->inPtr--; 153 } 154 } 155