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