* 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 are permitted
* provided that the above copyright notice and this paragraph are
* duplicated in all such forms and that any documentation,
* advertising materials, and other materials related to such
* distribution and use acknowledge that the software was developed
* by the University of California, Berkeley. The name of the
* University may not be used to endorse or promote products derived
* from this software without specific prior written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
static char sccsid
[] = "@(#)buf.c 5.3 (Berkeley) %G%";
* Functions for automatically-expanded buffers.
int size
; /* Current size of the buffer */
Byte
*buffer
; /* The buffer itself */
Byte
*inPtr
; /* Place to write to */
Byte
*outPtr
; /* Place to read from */
#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)->size - ((bp)->inPtr - (bp)->buffer)) < (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);\
#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.
* The buffer may be expanded.
*-----------------------------------------------------------------------
register BufPtr bp
= (BufPtr
) buf
;
*-----------------------------------------------------------------------
* Add a number of bytes to the buffer.
*-----------------------------------------------------------------------
Buf_AddBytes (buf
, numBytes
, bytesPtr
)
register BufPtr bp
= (BufPtr
) buf
;
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.
*-----------------------------------------------------------------------
Buf_UngetByte (buf
, byte
)
register BufPtr bp
= (BufPtr
) buf
;
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 ((Address
)bp
->outPtr
,
(Address
)(newBuf
+BUF_UNGET_INC
), numBytes
+1);
bp
->outPtr
= newBuf
+ BUF_UNGET_INC
;
bp
->inPtr
= bp
->outPtr
+ numBytes
;
free ((Address
)bp
->buffer
);
bp
->size
+= BUF_UNGET_INC
;
*-----------------------------------------------------------------------
* Push back a series of bytes at the beginning of the buffer.
* outPtr is decremented and the bytes copied into the buffer.
*-----------------------------------------------------------------------
Buf_UngetBytes (buf
, numBytes
, bytesPtr
)
register BufPtr bp
= (BufPtr
) buf
;
if (bp
->outPtr
- bp
->buffer
>= numBytes
) {
bcopy (bytesPtr
, bp
->outPtr
, numBytes
);
} else if (bp
->outPtr
== bp
->inPtr
) {
Buf_AddBytes (buf
, numBytes
, bytesPtr
);
int curNumBytes
= bp
->inPtr
- bp
->outPtr
;
int newBytes
= max(numBytes
,BUF_UNGET_INC
);
newBuf
= (Byte
*)emalloc (bp
->size
+ newBytes
);
bcopy((Address
)bp
->outPtr
, (Address
)(newBuf
+newBytes
), curNumBytes
+1);
bp
->outPtr
= newBuf
+ newBytes
;
bp
->inPtr
= bp
->outPtr
+ curNumBytes
;
free ((Address
)bp
->buffer
);
bcopy ((Address
)bytesPtr
, (Address
)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
*-----------------------------------------------------------------------
BufPtr bp
= (BufPtr
) buf
;
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 (buf
, numBytes
, bytesPtr
)
BufPtr bp
= (BufPtr
) buf
;
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 (buf
, numBytesPtr
)
if (numBytesPtr
!= (int *)NULL
) {
*numBytesPtr
= bp
->inPtr
- bp
->outPtr
;
*-----------------------------------------------------------------------
* Throw away bytes in a buffer.
* The bytes are discarded.
*-----------------------------------------------------------------------
Buf_Discard (buf
, numBytes
)
register BufPtr bp
= (BufPtr
) buf
;
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 (((BufPtr
)buf
)->inPtr
- ((BufPtr
)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 */
BufPtr bp
; /* New Buffer */
bp
= (Buf
*)emalloc(sizeof(Buf
));
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 */
BufPtr bp
= (BufPtr
) buf
;
free ((Address
)bp
->buffer
);