buf.c revision 103503
1193323Sed/* 2193323Sed * Copyright (c) 1988, 1989, 1990, 1993 3193323Sed * The Regents of the University of California. All rights reserved. 4193323Sed * Copyright (c) 1988, 1989 by Adam de Boor 5193323Sed * Copyright (c) 1989 by Berkeley Softworks 6193323Sed * All rights reserved. 7193323Sed * 8193323Sed * This code is derived from software contributed to Berkeley by 9193323Sed * Adam de Boor. 10193323Sed * 11193323Sed * Redistribution and use in source and binary forms, with or without 12193323Sed * modification, are permitted provided that the following conditions 13193323Sed * are met: 14193323Sed * 1. Redistributions of source code must retain the above copyright 15193323Sed * notice, this list of conditions and the following disclaimer. 16218893Sdim * 2. Redistributions in binary form must reproduce the above copyright 17193323Sed * notice, this list of conditions and the following disclaimer in the 18193323Sed * documentation and/or other materials provided with the distribution. 19193323Sed * 3. All advertising materials mentioning features or use of this software 20198090Srdivacky * must display the following acknowledgement: 21193323Sed * This product includes software developed by the University of 22198090Srdivacky * California, Berkeley and its contributors. 23234353Sdim * 4. Neither the name of the University nor the names of its contributors 24198090Srdivacky * may be used to endorse or promote products derived from this software 25193323Sed * without specific prior written permission. 26234353Sdim * 27193323Sed * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 28193323Sed * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 29218893Sdim * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 30204792Srdivacky * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 31193323Sed * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 32193323Sed * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 33218893Sdim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 34193323Sed * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 35218893Sdim * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 36218893Sdim * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 37218893Sdim * SUCH DAMAGE. 38218893Sdim * 39226633Sdim * @(#)buf.c 8.1 (Berkeley) 6/6/93 40218893Sdim */ 41218893Sdim 42218893Sdim#include <sys/cdefs.h> 43218893Sdim__FBSDID("$FreeBSD: head/usr.bin/make/buf.c 103503 2002-09-17 21:29:06Z jmallett $"); 44218893Sdim 45218893Sdim/*- 46234353Sdim * buf.c -- 47234353Sdim * Functions for automatically-expanded buffers. 48234353Sdim */ 49234353Sdim 50234353Sdim#include "sprite.h" 51234353Sdim#include "make.h" 52234353Sdim#include "buf.h" 53234353Sdim 54234353Sdim#ifndef max 55234353Sdim#define max(a,b) ((a) > (b) ? (a) : (b)) 56234353Sdim#endif 57234353Sdim 58234353Sdim/* 59234353Sdim * BufExpand -- 60234353Sdim * Expand the given buffer to hold the given number of additional 61234353Sdim * bytes. 62234353Sdim * Makes sure there's room for an extra NULL byte at the end of the 63234353Sdim * buffer in case it holds a string. 64234353Sdim */ 65234353Sdim#define BufExpand(bp,nb) \ 66234353Sdim if (bp->left < (nb)+1) {\ 67234353Sdim int newSize = (bp)->size + max((nb)+1,BUF_ADD_INC); \ 68234353Sdim Byte *newBuf = (Byte *) erealloc((bp)->buffer, newSize); \ 69234353Sdim \ 70234353Sdim (bp)->inPtr = newBuf + ((bp)->inPtr - (bp)->buffer); \ 71234353Sdim (bp)->outPtr = newBuf + ((bp)->outPtr - (bp)->buffer);\ 72234353Sdim (bp)->buffer = newBuf;\ 73234353Sdim (bp)->size = newSize;\ 74234353Sdim (bp)->left = newSize - ((bp)->inPtr - (bp)->buffer);\ 75234353Sdim } 76234353Sdim 77234353Sdim#define BUF_DEF_SIZE 256 /* Default buffer size */ 78234353Sdim#define BUF_ADD_INC 256 /* Expansion increment when Adding */ 79234353Sdim#define BUF_UNGET_INC 16 /* Expansion increment when Ungetting */ 80234353Sdim 81234353Sdim/*- 82234353Sdim *----------------------------------------------------------------------- 83234353Sdim * Buf_OvAddByte -- 84234353Sdim * Add a single byte to the buffer. left is zero or negative. 85234353Sdim * 86234353Sdim * Results: 87234353Sdim * None. 88234353Sdim * 89234353Sdim * Side Effects: 90234353Sdim * The buffer may be expanded. 91234353Sdim * 92234353Sdim *----------------------------------------------------------------------- 93234353Sdim */ 94234353Sdimvoid 95234353SdimBuf_OvAddByte (bp, byte) 96234353Sdim Buffer bp; 97234353Sdim int byte; 98234353Sdim{ 99234353Sdim bp->left = 0; 100234353Sdim BufExpand (bp, 1); 101234353Sdim 102234353Sdim *bp->inPtr++ = byte; 103234353Sdim bp->left--; 104234353Sdim 105234353Sdim /* 106234353Sdim * Null-terminate 107234353Sdim */ 108234353Sdim *bp->inPtr = 0; 109234353Sdim} 110234353Sdim 111234353Sdim/*- 112234353Sdim *----------------------------------------------------------------------- 113234353Sdim * Buf_AddBytes -- 114234353Sdim * Add a number of bytes to the buffer. 115234353Sdim * 116234353Sdim * Results: 117234353Sdim * None. 118234353Sdim * 119234353Sdim * Side Effects: 120234353Sdim * Guess what? 121234353Sdim * 122234353Sdim *----------------------------------------------------------------------- 123234353Sdim */ 124234353Sdimvoid 125234353SdimBuf_AddBytes (bp, numBytes, bytesPtr) 126234353Sdim Buffer bp; 127234353Sdim int numBytes; 128234353Sdim const Byte *bytesPtr; 129234353Sdim{ 130234353Sdim 131234353Sdim BufExpand (bp, numBytes); 132234353Sdim 133234353Sdim memcpy (bp->inPtr, bytesPtr, numBytes); 134234353Sdim bp->inPtr += numBytes; 135234353Sdim bp->left -= numBytes; 136234353Sdim 137234353Sdim /* 138234353Sdim * Null-terminate 139234353Sdim */ 140234353Sdim *bp->inPtr = 0; 141234353Sdim} 142234353Sdim 143234353Sdim/*- 144234353Sdim *----------------------------------------------------------------------- 145234353Sdim * Buf_UngetByte -- 146234353Sdim * Place the byte back at the beginning of the buffer. 147234353Sdim * 148234353Sdim * Results: 149234353Sdim * SUCCESS if the byte was added ok. FAILURE if not. 150234353Sdim * 151234353Sdim * Side Effects: 152234353Sdim * The byte is stuffed in the buffer and outPtr is decremented. 153234353Sdim * 154234353Sdim *----------------------------------------------------------------------- 155234353Sdim */ 156234353Sdimvoid 157234353SdimBuf_UngetByte (bp, byte) 158234353Sdim Buffer bp; 159234353Sdim int byte; 160234353Sdim{ 161234353Sdim 162234353Sdim if (bp->outPtr != bp->buffer) { 163234353Sdim bp->outPtr--; 164234353Sdim *bp->outPtr = byte; 165234353Sdim } else if (bp->outPtr == bp->inPtr) { 166234353Sdim *bp->inPtr = byte; 167234353Sdim bp->inPtr++; 168234353Sdim bp->left--; 169234353Sdim *bp->inPtr = 0; 170234353Sdim } else { 171234353Sdim /* 172234353Sdim * Yech. have to expand the buffer to stuff this thing in. 173234353Sdim * We use a different expansion constant because people don't 174234353Sdim * usually push back many bytes when they're doing it a byte at 175234353Sdim * a time... 176234353Sdim */ 177234353Sdim int numBytes = bp->inPtr - bp->outPtr; 178234353Sdim Byte *newBuf; 179234353Sdim 180234353Sdim newBuf = (Byte *)emalloc(bp->size + BUF_UNGET_INC); 181234353Sdim memcpy ((char *)(newBuf+BUF_UNGET_INC), (char *)bp->outPtr, numBytes+1); 182234353Sdim bp->outPtr = newBuf + BUF_UNGET_INC; 183234353Sdim bp->inPtr = bp->outPtr + numBytes; 184234353Sdim free ((char *)bp->buffer); 185234353Sdim bp->buffer = newBuf; 186234353Sdim bp->size += BUF_UNGET_INC; 187234353Sdim bp->left = bp->size - (bp->inPtr - bp->buffer); 188234353Sdim bp->outPtr -= 1; 189234353Sdim *bp->outPtr = byte; 190234353Sdim } 191234353Sdim} 192234353Sdim 193234353Sdim/*- 194234353Sdim *----------------------------------------------------------------------- 195234353Sdim * Buf_UngetBytes -- 196234353Sdim * Push back a series of bytes at the beginning of the buffer. 197234353Sdim * 198234353Sdim * Results: 199234353Sdim * None. 200234353Sdim * 201234353Sdim * Side Effects: 202234353Sdim * outPtr is decremented and the bytes copied into the buffer. 203234353Sdim * 204234353Sdim *----------------------------------------------------------------------- 205234353Sdim */ 206234353Sdimvoid 207234353SdimBuf_UngetBytes (bp, numBytes, bytesPtr) 208234353Sdim Buffer bp; 209234353Sdim int numBytes; 210234353Sdim Byte *bytesPtr; 211234353Sdim{ 212234353Sdim 213234353Sdim if (bp->outPtr - bp->buffer >= numBytes) { 214234353Sdim bp->outPtr -= numBytes; 215234353Sdim memcpy (bp->outPtr, bytesPtr, numBytes); 216193323Sed } else if (bp->outPtr == bp->inPtr) { 217193323Sed Buf_AddBytes (bp, numBytes, bytesPtr); 218193323Sed } else { 219193323Sed int curNumBytes = bp->inPtr - bp->outPtr; 220193323Sed Byte *newBuf; 221193323Sed int newBytes = max(numBytes,BUF_UNGET_INC); 222198090Srdivacky 223198090Srdivacky newBuf = (Byte *)emalloc (bp->size + newBytes); 224198090Srdivacky memcpy((char *)(newBuf+newBytes), (char *)bp->outPtr, curNumBytes+1); 225234353Sdim bp->outPtr = newBuf + newBytes; 226198090Srdivacky bp->inPtr = bp->outPtr + curNumBytes; 227198090Srdivacky free ((char *)bp->buffer); 228234353Sdim bp->buffer = newBuf; 229198090Srdivacky bp->size += newBytes; 230193323Sed bp->left = bp->size - (bp->inPtr - bp->buffer); 231193323Sed bp->outPtr -= numBytes; 232234353Sdim memcpy ((char *)bp->outPtr, (char *)bytesPtr, numBytes); 233234353Sdim } 234234353Sdim} 235234353Sdim 236234353Sdim/*- 237194612Sed *----------------------------------------------------------------------- 238194612Sed * Buf_GetByte -- 239203954Srdivacky * Return the next byte from the buffer. Actually returns an integer. 240194612Sed * 241234353Sdim * Results: 242193323Sed * Returns BUF_ERROR if there's no byte in the buffer, or the byte 243193323Sed * itself if there is one. 244193323Sed * 245193323Sed * Side Effects: 246193323Sed * outPtr is incremented and both outPtr and inPtr will be reset if 247234353Sdim * the buffer is emptied. 248234353Sdim * 249193323Sed *----------------------------------------------------------------------- 250193323Sed */ 251194612Sedint 252194612SedBuf_GetByte (bp) 253194612Sed Buffer bp; 254218893Sdim{ 255234353Sdim int res; 256193323Sed 257193323Sed if (bp->inPtr == bp->outPtr) { 258194612Sed return (BUF_ERROR); 259234353Sdim } else { 260234353Sdim res = (int) *bp->outPtr; 261234353Sdim bp->outPtr += 1; 262234353Sdim if (bp->outPtr == bp->inPtr) { 263234353Sdim bp->outPtr = bp->inPtr = bp->buffer; 264218893Sdim bp->left = bp->size; 265234353Sdim *bp->inPtr = 0; 266234353Sdim } 267234353Sdim return (res); 268234353Sdim } 269234353Sdim} 270194612Sed 271194612Sed/*- 272194612Sed *----------------------------------------------------------------------- 273234353Sdim * Buf_GetBytes -- 274193323Sed * Extract a number of bytes from the buffer. 275193323Sed * 276193323Sed * Results: 277234353Sdim * The number of bytes gotten. 278234353Sdim * 279234353Sdim * Side Effects: 280234353Sdim * The passed array is overwritten. 281234353Sdim * 282234353Sdim *----------------------------------------------------------------------- 283234353Sdim */ 284234353Sdimint 285234353SdimBuf_GetBytes (bp, numBytes, bytesPtr) 286234353Sdim Buffer bp; 287234353Sdim int numBytes; 288234353Sdim Byte *bytesPtr; 289234353Sdim{ 290198090Srdivacky 291193323Sed if (bp->inPtr - bp->outPtr < numBytes) { 292234353Sdim numBytes = bp->inPtr - bp->outPtr; 293234353Sdim } 294193323Sed memcpy (bytesPtr, bp->outPtr, numBytes); 295218893Sdim bp->outPtr += numBytes; 296218893Sdim 297193323Sed if (bp->outPtr == bp->inPtr) { 298193323Sed bp->outPtr = bp->inPtr = bp->buffer; 299198090Srdivacky bp->left = bp->size; 300198090Srdivacky *bp->inPtr = 0; 301198090Srdivacky } 302198090Srdivacky return (numBytes); 303218893Sdim} 304198090Srdivacky 305234353Sdim/*- 306198090Srdivacky *----------------------------------------------------------------------- 307198090Srdivacky * Buf_GetAll -- 308198090Srdivacky * Get all the available data at once. 309223017Sdim * 310223017Sdim * Results: 311223017Sdim * A pointer to the data and the number of bytes available. 312223017Sdim * 313223017Sdim * Side Effects: 314234353Sdim * None. 315234353Sdim * 316223017Sdim *----------------------------------------------------------------------- 317223017Sdim */ 318193323SedByte * 319223017SdimBuf_GetAll (bp, numBytesPtr) 320223017Sdim Buffer bp; 321193323Sed int *numBytesPtr; 322234353Sdim{ 323193323Sed 324193323Sed if (numBytesPtr != (int *)NULL) { 325198090Srdivacky *numBytesPtr = bp->inPtr - bp->outPtr; 326193323Sed } 327193323Sed 328193323Sed return (bp->outPtr); 329198090Srdivacky} 330193323Sed 331234353Sdim/*- 332234353Sdim *----------------------------------------------------------------------- 333234353Sdim * Buf_Discard -- 334234353Sdim * Throw away bytes in a buffer. 335193323Sed * 336193323Sed * Results: 337234353Sdim * None. 338234353Sdim * 339193323Sed * Side Effects: 340193323Sed * The bytes are discarded. 341193323Sed * 342193323Sed *----------------------------------------------------------------------- 343193323Sed */ 344193323Sedvoid 345193323SedBuf_Discard (bp, numBytes) 346193323Sed Buffer bp; 347193323Sed int numBytes; 348193323Sed{ 349234353Sdim 350234353Sdim if (bp->inPtr - bp->outPtr <= numBytes) { 351193323Sed bp->inPtr = bp->outPtr = bp->buffer; 352193323Sed bp->left = bp->size; 353193323Sed *bp->inPtr = 0; 354193323Sed } else { 355193323Sed bp->outPtr += numBytes; 356193323Sed } 357193323Sed} 358193323Sed 359193323Sed/*- 360193323Sed *----------------------------------------------------------------------- 361234353Sdim * Buf_Size -- 362234353Sdim * Returns the number of bytes in the given buffer. Doesn't include 363193323Sed * the null-terminating byte. 364193323Sed * 365193323Sed * Results: 366193323Sed * The number of bytes. 367193323Sed * 368193323Sed * Side Effects: 369193323Sed * None. 370193323Sed * 371193323Sed *----------------------------------------------------------------------- 372193323Sed */ 373193323Sedint 374234353SdimBuf_Size (buf) 375234353Sdim Buffer buf; 376234353Sdim{ 377234353Sdim return (buf->inPtr - buf->outPtr); 378193323Sed} 379193323Sed 380193323Sed/*- 381193323Sed *----------------------------------------------------------------------- 382193323Sed * Buf_Init -- 383234353Sdim * Initialize a buffer. If no initial size is given, a reasonable 384193323Sed * default is used. 385193323Sed * 386218893Sdim * Results: 387218893Sdim * A buffer to be given to other functions in this library. 388234353Sdim * 389193323Sed * Side Effects: 390193323Sed * The buffer is created, the space allocated and pointers 391193323Sed * initialized. 392193323Sed * 393193323Sed *----------------------------------------------------------------------- 394234353Sdim */ 395193323SedBuffer 396193323SedBuf_Init (size) 397193323Sed int size; /* Initial size for the buffer */ 398234353Sdim{ 399234353Sdim Buffer bp; /* New Buffer */ 400193323Sed 401193323Sed bp = (Buffer)emalloc(sizeof(*bp)); 402193323Sed 403193323Sed if (size <= 0) { 404193323Sed size = BUF_DEF_SIZE; 405193323Sed } 406193323Sed bp->left = bp->size = size; 407193323Sed bp->buffer = (Byte *)emalloc(size); 408193323Sed bp->inPtr = bp->outPtr = bp->buffer; 409193323Sed *bp->inPtr = 0; 410193323Sed 411193323Sed return (bp); 412193323Sed} 413193323Sed 414193323Sed/*- 415193323Sed *----------------------------------------------------------------------- 416193323Sed * Buf_Destroy -- 417193323Sed * Nuke a buffer and all its resources. 418193323Sed * 419193323Sed * Results: 420193323Sed * None. 421193323Sed * 422226633Sdim * Side Effects: 423198090Srdivacky * The buffer is freed. 424198090Srdivacky * 425193323Sed *----------------------------------------------------------------------- 426193323Sed */ 427204642Srdivackyvoid 428198090SrdivackyBuf_Destroy (buf, freeData) 429198090Srdivacky Buffer buf; /* Buffer to destroy */ 430198090Srdivacky Boolean freeData; /* TRUE if the data should be destroyed as well */ 431198090Srdivacky{ 432218893Sdim 433218893Sdim if (freeData) { 434234353Sdim free ((char *)buf->buffer); 435218893Sdim } 436218893Sdim free ((char *)buf); 437193323Sed} 438193323Sed 439193323Sed/*- 440193323Sed *----------------------------------------------------------------------- 441193323Sed * Buf_ReplaceLastByte -- 442193323Sed * Replace the last byte in a buffer. 443226633Sdim * 444204642Srdivacky * Results: 445195340Sed * None. 446195340Sed * 447204642Srdivacky * Side Effects: 448234353Sdim * If the buffer was empty intially, then a new byte will be added. 449193323Sed * Otherwise, the last byte is overwritten. 450193323Sed * 451193323Sed *----------------------------------------------------------------------- 452193323Sed */ 453193323Sedvoid 454193323SedBuf_ReplaceLastByte (buf, byte) 455198090Srdivacky Buffer buf; /* buffer to augment */ 456193323Sed int byte; /* byte to be written */ 457218893Sdim{ 458218893Sdim if (buf->inPtr == buf->outPtr) 459234353Sdim Buf_AddByte(buf, byte); 460193323Sed else 461218893Sdim *(buf->inPtr - 1) = byte; 462218893Sdim} 463193323Sed