buf.c revision 138264
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 138264 2004-12-01 10:29:20Z harti $"); 44 45/*- 46 * buf.c -- 47 * Functions for automatically-expanded buffers. 48 */ 49 50#include "sprite.h" 51#include "make.h" 52#include "buf.h" 53 54#ifndef max 55#define max(a,b) ((a) > (b) ? (a) : (b)) 56#endif 57 58/* 59 * BufExpand -- 60 * Expand the given buffer to hold the given number of additional 61 * bytes. 62 * Makes sure there's room for an extra NULL byte at the end of the 63 * buffer in case it holds a string. 64 */ 65#define BufExpand(bp,nb) \ 66 if (bp->left < (nb)+1) {\ 67 int newSize = (bp)->size + max((nb) + 1, BUF_ADD_INC); \ 68 Byte *newBuf = erealloc((bp)->buffer, newSize); \ 69 \ 70 (bp)->inPtr = newBuf + ((bp)->inPtr - (bp)->buffer); \ 71 (bp)->outPtr = newBuf + ((bp)->outPtr - (bp)->buffer);\ 72 (bp)->buffer = newBuf;\ 73 (bp)->size = newSize;\ 74 (bp)->left = newSize - ((bp)->inPtr - (bp)->buffer);\ 75 } 76 77#define BUF_DEF_SIZE 256 /* Default buffer size */ 78#define BUF_ADD_INC 256 /* Expansion increment when Adding */ 79#define BUF_UNGET_INC 16 /* Expansion increment when Ungetting */ 80 81/*- 82 *----------------------------------------------------------------------- 83 * Buf_OvAddByte -- 84 * Add a single byte to the buffer. left is zero or negative. 85 * 86 * Results: 87 * None. 88 * 89 * Side Effects: 90 * The buffer may be expanded. 91 * 92 *----------------------------------------------------------------------- 93 */ 94void 95Buf_OvAddByte(Buffer bp, int byte) 96{ 97 98 bp->left = 0; 99 BufExpand(bp, 1); 100 101 *bp->inPtr++ = byte; 102 bp->left--; 103 104 /* 105 * Null-terminate 106 */ 107 *bp->inPtr = 0; 108} 109 110/*- 111 *----------------------------------------------------------------------- 112 * Buf_AddBytes -- 113 * Add a number of bytes to the buffer. 114 * 115 * Results: 116 * None. 117 * 118 * Side Effects: 119 * Guess what? 120 * 121 *----------------------------------------------------------------------- 122 */ 123void 124Buf_AddBytes(Buffer bp, int numBytes, const Byte *bytesPtr) 125{ 126 127 BufExpand(bp, numBytes); 128 129 memcpy(bp->inPtr, bytesPtr, numBytes); 130 bp->inPtr += numBytes; 131 bp->left -= numBytes; 132 133 /* 134 * Null-terminate 135 */ 136 *bp->inPtr = 0; 137} 138 139/*- 140 *----------------------------------------------------------------------- 141 * Buf_UngetByte -- 142 * Place the byte back at the beginning of the buffer. 143 * 144 * Results: 145 * SUCCESS if the byte was added ok. FAILURE if not. 146 * 147 * Side Effects: 148 * The byte is stuffed in the buffer and outPtr is decremented. 149 * 150 *----------------------------------------------------------------------- 151 */ 152void 153Buf_UngetByte(Buffer bp, int byte) 154{ 155 156 if (bp->outPtr != bp->buffer) { 157 bp->outPtr--; 158 *bp->outPtr = byte; 159 } else if (bp->outPtr == bp->inPtr) { 160 *bp->inPtr = byte; 161 bp->inPtr++; 162 bp->left--; 163 *bp->inPtr = 0; 164 } else { 165 /* 166 * Yech. have to expand the buffer to stuff this thing in. 167 * We use a different expansion constant because people don't 168 * usually push back many bytes when they're doing it a byte at 169 * a time... 170 */ 171 int numBytes = bp->inPtr - bp->outPtr; 172 Byte *newBuf; 173 174 newBuf = emalloc(bp->size + BUF_UNGET_INC); 175 memcpy(newBuf + BUF_UNGET_INC, bp->outPtr, numBytes + 1); 176 bp->outPtr = newBuf + BUF_UNGET_INC; 177 bp->inPtr = bp->outPtr + numBytes; 178 free(bp->buffer); 179 bp->buffer = newBuf; 180 bp->size += BUF_UNGET_INC; 181 bp->left = bp->size - (bp->inPtr - bp->buffer); 182 bp->outPtr -= 1; 183 *bp->outPtr = byte; 184 } 185} 186 187/*- 188 *----------------------------------------------------------------------- 189 * Buf_UngetBytes -- 190 * Push back a series of bytes at the beginning of the buffer. 191 * 192 * Results: 193 * None. 194 * 195 * Side Effects: 196 * outPtr is decremented and the bytes copied into the buffer. 197 * 198 *----------------------------------------------------------------------- 199 */ 200void 201Buf_UngetBytes(Buffer bp, int numBytes, Byte *bytesPtr) 202{ 203 204 if (bp->outPtr - bp->buffer >= numBytes) { 205 bp->outPtr -= numBytes; 206 memcpy(bp->outPtr, bytesPtr, numBytes); 207 } else if (bp->outPtr == bp->inPtr) { 208 Buf_AddBytes(bp, numBytes, bytesPtr); 209 } else { 210 int curNumBytes = bp->inPtr - bp->outPtr; 211 Byte *newBuf; 212 int newBytes = max(numBytes,BUF_UNGET_INC); 213 214 newBuf = emalloc(bp->size + newBytes); 215 memcpy(newBuf + newBytes, bp->outPtr, curNumBytes + 1); 216 bp->outPtr = newBuf + newBytes; 217 bp->inPtr = bp->outPtr + curNumBytes; 218 free(bp->buffer); 219 bp->buffer = newBuf; 220 bp->size += newBytes; 221 bp->left = bp->size - (bp->inPtr - bp->buffer); 222 bp->outPtr -= numBytes; 223 memcpy(bp->outPtr, bytesPtr, numBytes); 224 } 225} 226 227/*- 228 *----------------------------------------------------------------------- 229 * Buf_GetByte -- 230 * Return the next byte from the buffer. Actually returns an integer. 231 * 232 * Results: 233 * Returns BUF_ERROR if there's no byte in the buffer, or the byte 234 * itself if there is one. 235 * 236 * Side Effects: 237 * outPtr is incremented and both outPtr and inPtr will be reset if 238 * the buffer is emptied. 239 * 240 *----------------------------------------------------------------------- 241 */ 242int 243Buf_GetByte(Buffer bp) 244{ 245 int res; 246 247 if (bp->inPtr == bp->outPtr) { 248 return (BUF_ERROR); 249 } else { 250 res = (int)*bp->outPtr; 251 bp->outPtr += 1; 252 if (bp->outPtr == bp->inPtr) { 253 bp->outPtr = bp->inPtr = bp->buffer; 254 bp->left = bp->size; 255 *bp->inPtr = 0; 256 } 257 return (res); 258 } 259} 260 261/*- 262 *----------------------------------------------------------------------- 263 * Buf_GetBytes -- 264 * Extract a number of bytes from the buffer. 265 * 266 * Results: 267 * The number of bytes gotten. 268 * 269 * Side Effects: 270 * The passed array is overwritten. 271 * 272 *----------------------------------------------------------------------- 273 */ 274int 275Buf_GetBytes(Buffer bp, int numBytes, Byte *bytesPtr) 276{ 277 278 if (bp->inPtr - bp->outPtr < numBytes) { 279 numBytes = bp->inPtr - bp->outPtr; 280 } 281 memcpy(bytesPtr, bp->outPtr, numBytes); 282 bp->outPtr += numBytes; 283 284 if (bp->outPtr == bp->inPtr) { 285 bp->outPtr = bp->inPtr = bp->buffer; 286 bp->left = bp->size; 287 *bp->inPtr = 0; 288 } 289 return (numBytes); 290} 291 292/*- 293 *----------------------------------------------------------------------- 294 * Buf_GetAll -- 295 * Get all the available data at once. 296 * 297 * Results: 298 * A pointer to the data and the number of bytes available. 299 * 300 * Side Effects: 301 * None. 302 * 303 *----------------------------------------------------------------------- 304 */ 305Byte * 306Buf_GetAll(Buffer bp, int *numBytesPtr) 307{ 308 309 if (numBytesPtr != NULL) { 310 *numBytesPtr = bp->inPtr - bp->outPtr; 311 } 312 313 return (bp->outPtr); 314} 315 316/*- 317 *----------------------------------------------------------------------- 318 * Buf_Discard -- 319 * Throw away bytes in a buffer. 320 * 321 * Results: 322 * None. 323 * 324 * Side Effects: 325 * The bytes are discarded. 326 * 327 *----------------------------------------------------------------------- 328 */ 329void 330Buf_Discard(Buffer bp, int numBytes) 331{ 332 333 if (bp->inPtr - bp->outPtr <= numBytes) { 334 bp->inPtr = bp->outPtr = bp->buffer; 335 bp->left = bp->size; 336 *bp->inPtr = 0; 337 } else { 338 bp->outPtr += numBytes; 339 } 340} 341 342/*- 343 *----------------------------------------------------------------------- 344 * Buf_Size -- 345 * Returns the number of bytes in the given buffer. Doesn't include 346 * the null-terminating byte. 347 * 348 * Results: 349 * The number of bytes. 350 * 351 * Side Effects: 352 * None. 353 * 354 *----------------------------------------------------------------------- 355 */ 356int 357Buf_Size(Buffer buf) 358{ 359 360 return (buf->inPtr - buf->outPtr); 361} 362 363/*- 364 *----------------------------------------------------------------------- 365 * Buf_Init -- 366 * Initialize a buffer. If no initial size is given, a reasonable 367 * default is used. 368 * 369 * Results: 370 * A buffer to be given to other functions in this library. 371 * 372 * Side Effects: 373 * The buffer is created, the space allocated and pointers 374 * initialized. 375 * 376 *----------------------------------------------------------------------- 377 */ 378Buffer 379Buf_Init(int size) 380{ 381 Buffer bp; /* New Buffer */ 382 383 bp = emalloc(sizeof(*bp)); 384 385 if (size <= 0) { 386 size = BUF_DEF_SIZE; 387 } 388 bp->left = bp->size = size; 389 bp->buffer = emalloc(size); 390 bp->inPtr = bp->outPtr = bp->buffer; 391 *bp->inPtr = 0; 392 393 return (bp); 394} 395 396/*- 397 *----------------------------------------------------------------------- 398 * Buf_Destroy -- 399 * Destroy a buffer, and optionally free its data, too. 400 * 401 * Results: 402 * None. 403 * 404 * Side Effects: 405 * The buffer is freed. 406 * 407 *----------------------------------------------------------------------- 408 */ 409void 410Buf_Destroy(Buffer buf, Boolean freeData) 411{ 412 413 if (freeData) { 414 free(buf->buffer); 415 } 416 free(buf); 417} 418 419/*- 420 *----------------------------------------------------------------------- 421 * Buf_ReplaceLastByte -- 422 * Replace the last byte in a buffer. 423 * 424 * Results: 425 * None. 426 * 427 * Side Effects: 428 * If the buffer was empty intially, then a new byte will be added. 429 * Otherwise, the last byte is overwritten. 430 * 431 *----------------------------------------------------------------------- 432 */ 433void 434Buf_ReplaceLastByte(Buffer buf, int byte) 435{ 436 if (buf->inPtr == buf->outPtr) 437 Buf_AddByte(buf, byte); 438 else 439 *(buf->inPtr - 1) = byte; 440} 441