buf.c revision 141133
1/*- 2 * Copyright (c) 1988, 1989, 1990, 1993 3 * The Regents of the University of California. All rights reserved. 4 * Copyright (c) 1988, 1989 by Adam de Boor 5 * Copyright (c) 1989 by Berkeley Softworks 6 * All rights reserved. 7 * 8 * This code is derived from software contributed to Berkeley by 9 * Adam de Boor. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 3. All advertising materials mentioning features or use of this software 20 * must display the following acknowledgement: 21 * This product includes software developed by the University of 22 * California, Berkeley and its contributors. 23 * 4. Neither the name of the University nor the names of its contributors 24 * may be used to endorse or promote products derived from this software 25 * without specific prior written permission. 26 * 27 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 28 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 29 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 30 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 31 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 32 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 33 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 34 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 35 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 36 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 37 * SUCH DAMAGE. 38 * 39 * @(#)buf.c 8.1 (Berkeley) 6/6/93 40 */ 41 42#include <sys/cdefs.h> 43__FBSDID("$FreeBSD: head/usr.bin/make/buf.c 141133 2005-02-02 07:36:18Z harti $"); 44 45/*- 46 * buf.c -- 47 * Functions for automatically-expanded buffers. 48 */ 49 50#include <string.h> 51#include <stdlib.h> 52 53#include "buf.h" 54#include "sprite.h" 55#include "util.h" 56 57#ifndef max 58#define max(a,b) ((a) > (b) ? (a) : (b)) 59#endif 60 61/* 62 * BufExpand -- 63 * Expand the given buffer to hold the given number of additional 64 * bytes. 65 * Makes sure there's room for an extra NULL byte at the end of the 66 * buffer in case it holds a string. 67 */ 68#define BufExpand(bp, nb) do { \ 69 if ((bp)->left < (nb) + 1) { \ 70 int newSize = (bp)->size + max((nb) + 1, BUF_ADD_INC); \ 71 Byte *newBuf = erealloc((bp)->buffer, newSize); \ 72 \ 73 (bp)->inPtr = newBuf + ((bp)->inPtr - (bp)->buffer); \ 74 (bp)->outPtr = newBuf + ((bp)->outPtr - (bp)->buffer); \ 75 (bp)->buffer = newBuf; \ 76 (bp)->size = newSize; \ 77 (bp)->left = newSize - ((bp)->inPtr - (bp)->buffer); \ 78 } \ 79 } while (0) 80 81#define BUF_DEF_SIZE 256 /* Default buffer size */ 82#define BUF_ADD_INC 256 /* Expansion increment when Adding */ 83#define BUF_UNGET_INC 16 /* Expansion increment when Ungetting */ 84 85/*- 86 *----------------------------------------------------------------------- 87 * Buf_OvAddByte -- 88 * Add a single byte to the buffer. left is zero or negative. 89 * 90 * Results: 91 * None. 92 * 93 * Side Effects: 94 * The buffer may be expanded. 95 * 96 *----------------------------------------------------------------------- 97 */ 98void 99Buf_OvAddByte(Buffer *bp, Byte byte) 100{ 101 102 bp->left = 0; 103 BufExpand(bp, 1); 104 105 *bp->inPtr++ = byte; 106 bp->left--; 107 108 /* 109 * Null-terminate 110 */ 111 *bp->inPtr = 0; 112} 113 114/*- 115 *----------------------------------------------------------------------- 116 * Buf_AddBytes -- 117 * Add a number of bytes to the buffer. 118 * 119 * Results: 120 * None. 121 * 122 * Side Effects: 123 * Guess what? 124 * 125 *----------------------------------------------------------------------- 126 */ 127void 128Buf_AddBytes(Buffer *bp, size_t numBytes, const Byte *bytesPtr) 129{ 130 131 BufExpand(bp, numBytes); 132 133 memcpy(bp->inPtr, bytesPtr, numBytes); 134 bp->inPtr += numBytes; 135 bp->left -= numBytes; 136 137 /* 138 * Null-terminate 139 */ 140 *bp->inPtr = 0; 141} 142 143/*- 144 *----------------------------------------------------------------------- 145 * Buf_UngetByte -- 146 * Place the byte back at the beginning of the buffer. 147 * 148 * Results: 149 * SUCCESS if the byte was added ok. FAILURE if not. 150 * 151 * Side Effects: 152 * The byte is stuffed in the buffer and outPtr is decremented. 153 * 154 *----------------------------------------------------------------------- 155 */ 156void 157Buf_UngetByte(Buffer *bp, Byte byte) 158{ 159 160 if (bp->outPtr != bp->buffer) { 161 bp->outPtr--; 162 *bp->outPtr = byte; 163 164 } else if (bp->outPtr == bp->inPtr) { 165 *bp->inPtr = byte; 166 bp->inPtr++; 167 bp->left--; 168 *bp->inPtr = 0; 169 170 } else { 171 /* 172 * Yech. have to expand the buffer to stuff this thing in. 173 * We use a different expansion constant because people don't 174 * usually push back many bytes when they're doing it a byte at 175 * a time... 176 */ 177 size_t numBytes = bp->inPtr - bp->outPtr; 178 Byte *newBuf; 179 180 newBuf = emalloc(bp->size + BUF_UNGET_INC); 181 memcpy(newBuf + BUF_UNGET_INC, bp->outPtr, numBytes + 1); 182 bp->outPtr = newBuf + BUF_UNGET_INC; 183 bp->inPtr = bp->outPtr + numBytes; 184 free(bp->buffer); 185 bp->buffer = newBuf; 186 bp->size += BUF_UNGET_INC; 187 bp->left = bp->size - (bp->inPtr - bp->buffer); 188 bp->outPtr -= 1; 189 *bp->outPtr = byte; 190 } 191} 192 193/*- 194 *----------------------------------------------------------------------- 195 * Buf_UngetBytes -- 196 * Push back a series of bytes at the beginning of the buffer. 197 * 198 * Results: 199 * None. 200 * 201 * Side Effects: 202 * outPtr is decremented and the bytes copied into the buffer. 203 * 204 *----------------------------------------------------------------------- 205 */ 206void 207Buf_UngetBytes(Buffer *bp, size_t numBytes, Byte *bytesPtr) 208{ 209 210 if ((size_t)(bp->outPtr - bp->buffer) >= numBytes) { 211 bp->outPtr -= numBytes; 212 memcpy(bp->outPtr, bytesPtr, numBytes); 213 } else if (bp->outPtr == bp->inPtr) { 214 Buf_AddBytes(bp, numBytes, bytesPtr); 215 } else { 216 size_t curNumBytes = bp->inPtr - bp->outPtr; 217 Byte *newBuf; 218 size_t newBytes = max(numBytes, BUF_UNGET_INC); 219 220 newBuf = emalloc(bp->size + newBytes); 221 memcpy(newBuf + newBytes, bp->outPtr, curNumBytes + 1); 222 bp->outPtr = newBuf + newBytes; 223 bp->inPtr = bp->outPtr + curNumBytes; 224 free(bp->buffer); 225 bp->buffer = newBuf; 226 bp->size += newBytes; 227 bp->left = bp->size - (bp->inPtr - bp->buffer); 228 bp->outPtr -= numBytes; 229 memcpy(bp->outPtr, bytesPtr, numBytes); 230 } 231} 232 233/*- 234 *----------------------------------------------------------------------- 235 * Buf_GetByte -- 236 * Return the next byte from the buffer. Actually returns an integer. 237 * 238 * Results: 239 * Returns BUF_ERROR if there's no byte in the buffer, or the byte 240 * itself if there is one. 241 * 242 * Side Effects: 243 * outPtr is incremented and both outPtr and inPtr will be reset if 244 * the buffer is emptied. 245 * 246 *----------------------------------------------------------------------- 247 */ 248int 249Buf_GetByte(Buffer *bp) 250{ 251 int res; 252 253 if (bp->inPtr == bp->outPtr) 254 return (BUF_ERROR); 255 256 res = (int)*bp->outPtr; 257 bp->outPtr += 1; 258 if (bp->outPtr == bp->inPtr) { 259 bp->outPtr = bp->inPtr = bp->buffer; 260 bp->left = bp->size; 261 *bp->inPtr = 0; 262 } 263 return (res); 264} 265 266/*- 267 *----------------------------------------------------------------------- 268 * Buf_GetBytes -- 269 * Extract a number of bytes from the buffer. 270 * 271 * Results: 272 * The number of bytes gotten. 273 * 274 * Side Effects: 275 * The passed array is overwritten. 276 * 277 *----------------------------------------------------------------------- 278 */ 279int 280Buf_GetBytes(Buffer *bp, size_t numBytes, Byte *bytesPtr) 281{ 282 283 if ((size_t)(bp->inPtr - bp->outPtr) < numBytes) 284 numBytes = bp->inPtr - bp->outPtr; 285 286 memcpy(bytesPtr, bp->outPtr, numBytes); 287 bp->outPtr += numBytes; 288 289 if (bp->outPtr == bp->inPtr) { 290 bp->outPtr = bp->inPtr = bp->buffer; 291 bp->left = bp->size; 292 *bp->inPtr = 0; 293 } 294 return (numBytes); 295} 296 297/*- 298 *----------------------------------------------------------------------- 299 * Buf_GetAll -- 300 * Get all the available data at once. 301 * 302 * Results: 303 * A pointer to the data and the number of bytes available. 304 * 305 * Side Effects: 306 * None. 307 * 308 *----------------------------------------------------------------------- 309 */ 310Byte * 311Buf_GetAll(Buffer *bp, size_t *numBytesPtr) 312{ 313 314 if (numBytesPtr != NULL) 315 *numBytesPtr = bp->inPtr - bp->outPtr; 316 317 return (bp->outPtr); 318} 319 320/*- 321 *----------------------------------------------------------------------- 322 * Buf_Discard -- 323 * Throw away bytes in a buffer. 324 * 325 * Results: 326 * None. 327 * 328 * Side Effects: 329 * The bytes are discarded. 330 * 331 *----------------------------------------------------------------------- 332 */ 333void 334Buf_Discard(Buffer *bp, size_t numBytes) 335{ 336 337 if ((size_t)(bp->inPtr - bp->outPtr) <= numBytes) { 338 bp->inPtr = bp->outPtr = bp->buffer; 339 bp->left = bp->size; 340 *bp->inPtr = 0; 341 } else 342 bp->outPtr += numBytes; 343} 344 345/*- 346 *----------------------------------------------------------------------- 347 * Buf_Size -- 348 * Returns the number of bytes in the given buffer. Doesn't include 349 * the null-terminating byte. 350 * 351 * Results: 352 * The number of bytes. 353 * 354 * Side Effects: 355 * None. 356 * 357 *----------------------------------------------------------------------- 358 */ 359size_t 360Buf_Size(Buffer *buf) 361{ 362 363 return (buf->inPtr - buf->outPtr); 364} 365 366/*- 367 *----------------------------------------------------------------------- 368 * Buf_Init -- 369 * Initialize a buffer. If no initial size is given, a reasonable 370 * default is used. 371 * 372 * Results: 373 * A buffer to be given to other functions in this library. 374 * 375 * Side Effects: 376 * The buffer is created, the space allocated and pointers 377 * initialized. 378 * 379 *----------------------------------------------------------------------- 380 */ 381Buffer * 382Buf_Init(size_t size) 383{ 384 Buffer *bp; /* New Buffer */ 385 386 bp = emalloc(sizeof(*bp)); 387 388 if (size <= 0) 389 size = BUF_DEF_SIZE; 390 391 bp->left = bp->size = size; 392 bp->buffer = emalloc(size); 393 bp->inPtr = bp->outPtr = bp->buffer; 394 *bp->inPtr = 0; 395 396 return (bp); 397} 398 399/*- 400 *----------------------------------------------------------------------- 401 * Buf_Destroy -- 402 * Destroy a buffer, and optionally free its data, too. 403 * 404 * Results: 405 * None. 406 * 407 * Side Effects: 408 * The buffer is freed. 409 * 410 *----------------------------------------------------------------------- 411 */ 412void 413Buf_Destroy(Buffer *buf, Boolean freeData) 414{ 415 416 if (freeData) 417 free(buf->buffer); 418 free(buf); 419} 420 421/*- 422 *----------------------------------------------------------------------- 423 * Buf_ReplaceLastByte -- 424 * Replace the last byte in a buffer. 425 * 426 * Results: 427 * None. 428 * 429 * Side Effects: 430 * If the buffer was empty intially, then a new byte will be added. 431 * Otherwise, the last byte is overwritten. 432 * 433 *----------------------------------------------------------------------- 434 */ 435void 436Buf_ReplaceLastByte(Buffer *buf, Byte byte) 437{ 438 if (buf->inPtr == buf->outPtr) 439 Buf_AddByte(buf, byte); 440 else 441 *(buf->inPtr - 1) = byte; 442} 443