* Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
* Copyright (c) 1988, 1989 by Adam de Boor
* Copyright (c) 1989 by Berkeley Softworks
* This code is derived from software contributed to Berkeley by
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
static char sccsid
[] = "@(#)buf.c 5.5 (Berkeley) 12/28/90";
* Functions for automatically-expanded buffers.
#define max(a,b) ((a) > (b) ? (a) : (b))
* Expand the given buffer to hold the given number of additional
* Makes sure there's room for an extra NULL byte at the end of the
* buffer in case it holds a string.
#define BufExpand(bp,nb) \
if (bp->left < (nb)+1) {\
int newSize = (bp)->size + max((nb)+1,BUF_ADD_INC); \
Byte *newBuf = (Byte *) realloc((bp)->buffer, newSize); \
(bp)->inPtr = newBuf + ((bp)->inPtr - (bp)->buffer); \
(bp)->outPtr = newBuf + ((bp)->outPtr - (bp)->buffer);\
(bp)->left = newSize - ((bp)->inPtr - (bp)->buffer);\
#define BUF_DEF_SIZE 256 /* Default buffer size */
#define BUF_ADD_INC 256 /* Expansion increment when Adding */
#define BUF_UNGET_INC 16 /* Expansion increment when Ungetting */
*-----------------------------------------------------------------------
* Add a single byte to the buffer. left is zero or negative.
* The buffer may be expanded.
*-----------------------------------------------------------------------
*-----------------------------------------------------------------------
* Add a number of bytes to the buffer.
*-----------------------------------------------------------------------
Buf_AddBytes (bp
, numBytes
, bytesPtr
)
BufExpand (bp
, numBytes
);
bcopy (bytesPtr
, bp
->inPtr
, numBytes
);
*-----------------------------------------------------------------------
* Place the byte back at the beginning of the buffer.
* SUCCESS if the byte was added ok. FAILURE if not.
* The byte is stuffed in the buffer and outPtr is decremented.
*-----------------------------------------------------------------------
if (bp
->outPtr
!= bp
->buffer
) {
} else if (bp
->outPtr
== bp
->inPtr
) {
* Yech. have to expand the buffer to stuff this thing in.
* We use a different expansion constant because people don't
* usually push back many bytes when they're doing it a byte at
int numBytes
= bp
->inPtr
- bp
->outPtr
;
newBuf
= (Byte
*)emalloc(bp
->size
+ BUF_UNGET_INC
);
bcopy ((char *)bp
->outPtr
,
(char *)(newBuf
+BUF_UNGET_INC
), numBytes
+1);
bp
->outPtr
= newBuf
+ BUF_UNGET_INC
;
bp
->inPtr
= bp
->outPtr
+ numBytes
;
free ((char *)bp
->buffer
);
bp
->size
+= BUF_UNGET_INC
;
bp
->left
= bp
->size
- (bp
->inPtr
- bp
->buffer
);
*-----------------------------------------------------------------------
* Push back a series of bytes at the beginning of the buffer.
* outPtr is decremented and the bytes copied into the buffer.
*-----------------------------------------------------------------------
Buf_UngetBytes (bp
, numBytes
, bytesPtr
)
if (bp
->outPtr
- bp
->buffer
>= numBytes
) {
bcopy (bytesPtr
, bp
->outPtr
, numBytes
);
} else if (bp
->outPtr
== bp
->inPtr
) {
Buf_AddBytes (bp
, numBytes
, bytesPtr
);
int curNumBytes
= bp
->inPtr
- bp
->outPtr
;
int newBytes
= max(numBytes
,BUF_UNGET_INC
);
newBuf
= (Byte
*)emalloc (bp
->size
+ newBytes
);
bcopy((char *)bp
->outPtr
, (char *)(newBuf
+newBytes
), curNumBytes
+1);
bp
->outPtr
= newBuf
+ newBytes
;
bp
->inPtr
= bp
->outPtr
+ curNumBytes
;
free ((char *)bp
->buffer
);
bp
->left
= bp
->size
- (bp
->inPtr
- bp
->buffer
);
bcopy ((char *)bytesPtr
, (char *)bp
->outPtr
, numBytes
);
*-----------------------------------------------------------------------
* Return the next byte from the buffer. Actually returns an integer.
* Returns BUF_ERROR if there's no byte in the buffer, or the byte
* itself if there is one.
* outPtr is incremented and both outPtr and inPtr will be reset if
*-----------------------------------------------------------------------
if (bp
->inPtr
== bp
->outPtr
) {
if (bp
->outPtr
== bp
->inPtr
) {
bp
->outPtr
= bp
->inPtr
= bp
->buffer
;
*-----------------------------------------------------------------------
* Extract a number of bytes from the buffer.
* The number of bytes gotten.
* The passed array is overwritten.
*-----------------------------------------------------------------------
Buf_GetBytes (bp
, numBytes
, bytesPtr
)
if (bp
->inPtr
- bp
->outPtr
< numBytes
) {
numBytes
= bp
->inPtr
- bp
->outPtr
;
bcopy (bp
->outPtr
, bytesPtr
, numBytes
);
if (bp
->outPtr
== bp
->inPtr
) {
bp
->outPtr
= bp
->inPtr
= bp
->buffer
;
*-----------------------------------------------------------------------
* Get all the available data at once.
* A pointer to the data and the number of bytes available.
*-----------------------------------------------------------------------
Buf_GetAll (bp
, numBytesPtr
)
if (numBytesPtr
!= (int *)NULL
) {
*numBytesPtr
= bp
->inPtr
- bp
->outPtr
;
*-----------------------------------------------------------------------
* Throw away bytes in a buffer.
* The bytes are discarded.
*-----------------------------------------------------------------------
Buf_Discard (bp
, numBytes
)
if (bp
->inPtr
- bp
->outPtr
<= numBytes
) {
bp
->inPtr
= bp
->outPtr
= bp
->buffer
;
*-----------------------------------------------------------------------
* Returns the number of bytes in the given buffer. Doesn't include
* the null-terminating byte.
*-----------------------------------------------------------------------
return (buf
->inPtr
- buf
->outPtr
);
*-----------------------------------------------------------------------
* Initialize a buffer. If no initial size is given, a reasonable
* A buffer to be given to other functions in this library.
* The buffer is created, the space allocated and pointers
*-----------------------------------------------------------------------
int size
; /* Initial size for the buffer */
Buffer bp
; /* New Buffer */
bp
= (Buffer
)emalloc(sizeof(*bp
));
bp
->left
= bp
->size
= size
;
bp
->buffer
= (Byte
*)emalloc(size
);
bp
->inPtr
= bp
->outPtr
= bp
->buffer
;
*-----------------------------------------------------------------------
* Nuke a buffer and all its resources.
*-----------------------------------------------------------------------
Buf_Destroy (buf
, freeData
)
Buffer buf
; /* Buffer to destroy */
Boolean freeData
; /* TRUE if the data should be destroyed as well */
free ((char *)buf
->buffer
);