buf.c revision 1.10 1 /* $NetBSD: buf.c,v 1.10 1997/07/01 21:17:08 christos Exp $ */
2
3 /*
4 * Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
5 * Copyright (c) 1988, 1989 by Adam de Boor
6 * Copyright (c) 1989 by Berkeley Softworks
7 * All rights reserved.
8 *
9 * This code is derived from software contributed to Berkeley by
10 * Adam de Boor.
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions and the following disclaimer.
17 * 2. Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in the
19 * documentation and/or other materials provided with the distribution.
20 * 3. All advertising materials mentioning features or use of this software
21 * must display the following acknowledgement:
22 * This product includes software developed by the University of
23 * California, Berkeley and its contributors.
24 * 4. Neither the name of the University nor the names of its contributors
25 * may be used to endorse or promote products derived from this software
26 * without specific prior written permission.
27 *
28 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
29 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
30 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
31 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
32 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
36 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
37 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
38 * SUCH DAMAGE.
39 */
40
41 #include <sys/cdefs.h>
42 #ifndef lint
43 #if 0
44 static char sccsid[] = "@(#)buf.c 8.1 (Berkeley) 6/6/93";
45 #else
46 __RCSID("$NetBSD: buf.c,v 1.10 1997/07/01 21:17:08 christos Exp $");
47 #endif
48 #endif /* not lint */
49
50 /*-
51 * buf.c --
52 * Functions for automatically-expanded buffers.
53 */
54
55 #include "sprite.h"
56 #include "make.h"
57 #include "buf.h"
58
59 #ifndef max
60 #define max(a,b) ((a) > (b) ? (a) : (b))
61 #endif
62
63 /*
64 * BufExpand --
65 * Expand the given buffer to hold the given number of additional
66 * bytes.
67 * Makes sure there's room for an extra NULL byte at the end of the
68 * buffer in case it holds a string.
69 */
70 #define BufExpand(bp,nb) \
71 if (bp->left < (nb)+1) {\
72 int newSize = (bp)->size + max((nb)+1,BUF_ADD_INC); \
73 Byte *newBuf = (Byte *) erealloc((bp)->buffer, newSize); \
74 \
75 (bp)->inPtr = newBuf + ((bp)->inPtr - (bp)->buffer); \
76 (bp)->outPtr = newBuf + ((bp)->outPtr - (bp)->buffer);\
77 (bp)->buffer = newBuf;\
78 (bp)->size = newSize;\
79 (bp)->left = newSize - ((bp)->inPtr - (bp)->buffer);\
80 }
81
82 #define BUF_DEF_SIZE 256 /* Default buffer size */
83 #define BUF_ADD_INC 256 /* Expansion increment when Adding */
84 #define BUF_UNGET_INC 16 /* Expansion increment when Ungetting */
85
86 /*-
87 *-----------------------------------------------------------------------
88 * Buf_OvAddByte --
89 * Add a single byte to the buffer. left is zero or negative.
90 *
91 * Results:
92 * None.
93 *
94 * Side Effects:
95 * The buffer may be expanded.
96 *
97 *-----------------------------------------------------------------------
98 */
99 void
100 Buf_OvAddByte (bp, byte)
101 register Buffer bp;
102 int byte;
103 {
104 int nbytes = 1;
105 bp->left = 0;
106 BufExpand (bp, nbytes);
107
108 *bp->inPtr++ = byte;
109 bp->left--;
110
111 /*
112 * Null-terminate
113 */
114 *bp->inPtr = 0;
115 }
116
117 /*-
119 *-----------------------------------------------------------------------
120 * Buf_AddBytes --
121 * Add a number of bytes to the buffer.
122 *
123 * Results:
124 * None.
125 *
126 * Side Effects:
127 * Guess what?
128 *
129 *-----------------------------------------------------------------------
130 */
131 void
132 Buf_AddBytes (bp, numBytes, bytesPtr)
133 register Buffer bp;
134 int numBytes;
135 const Byte *bytesPtr;
136 {
137
138 BufExpand (bp, numBytes);
139
140 memcpy (bp->inPtr, bytesPtr, numBytes);
141 bp->inPtr += numBytes;
142 bp->left -= numBytes;
143
144 /*
145 * Null-terminate
146 */
147 *bp->inPtr = 0;
148 }
149
150 /*-
152 *-----------------------------------------------------------------------
153 * Buf_UngetByte --
154 * Place the byte back at the beginning of the buffer.
155 *
156 * Results:
157 * SUCCESS if the byte was added ok. FAILURE if not.
158 *
159 * Side Effects:
160 * The byte is stuffed in the buffer and outPtr is decremented.
161 *
162 *-----------------------------------------------------------------------
163 */
164 void
165 Buf_UngetByte (bp, byte)
166 register Buffer bp;
167 int byte;
168 {
169
170 if (bp->outPtr != bp->buffer) {
171 bp->outPtr--;
172 *bp->outPtr = byte;
173 } else if (bp->outPtr == bp->inPtr) {
174 *bp->inPtr = byte;
175 bp->inPtr++;
176 bp->left--;
177 *bp->inPtr = 0;
178 } else {
179 /*
180 * Yech. have to expand the buffer to stuff this thing in.
181 * We use a different expansion constant because people don't
182 * usually push back many bytes when they're doing it a byte at
183 * a time...
184 */
185 int numBytes = bp->inPtr - bp->outPtr;
186 Byte *newBuf;
187
188 newBuf = (Byte *)emalloc(bp->size + BUF_UNGET_INC);
189 memcpy ((char *)(newBuf+BUF_UNGET_INC), (char *)bp->outPtr, numBytes+1);
190 bp->outPtr = newBuf + BUF_UNGET_INC;
191 bp->inPtr = bp->outPtr + numBytes;
192 free ((char *)bp->buffer);
193 bp->buffer = newBuf;
194 bp->size += BUF_UNGET_INC;
195 bp->left = bp->size - (bp->inPtr - bp->buffer);
196 bp->outPtr -= 1;
197 *bp->outPtr = byte;
198 }
199 }
200
201 /*-
203 *-----------------------------------------------------------------------
204 * Buf_UngetBytes --
205 * Push back a series of bytes at the beginning of the buffer.
206 *
207 * Results:
208 * None.
209 *
210 * Side Effects:
211 * outPtr is decremented and the bytes copied into the buffer.
212 *
213 *-----------------------------------------------------------------------
214 */
215 void
216 Buf_UngetBytes (bp, numBytes, bytesPtr)
217 register Buffer bp;
218 int numBytes;
219 Byte *bytesPtr;
220 {
221
222 if (bp->outPtr - bp->buffer >= numBytes) {
223 bp->outPtr -= numBytes;
224 memcpy (bp->outPtr, bytesPtr, numBytes);
225 } else if (bp->outPtr == bp->inPtr) {
226 Buf_AddBytes (bp, numBytes, bytesPtr);
227 } else {
228 int curNumBytes = bp->inPtr - bp->outPtr;
229 Byte *newBuf;
230 int newBytes = max(numBytes,BUF_UNGET_INC);
231
232 newBuf = (Byte *)emalloc (bp->size + newBytes);
233 memcpy((char *)(newBuf+newBytes), (char *)bp->outPtr, curNumBytes+1);
234 bp->outPtr = newBuf + newBytes;
235 bp->inPtr = bp->outPtr + curNumBytes;
236 free ((char *)bp->buffer);
237 bp->buffer = newBuf;
238 bp->size += newBytes;
239 bp->left = bp->size - (bp->inPtr - bp->buffer);
240 bp->outPtr -= numBytes;
241 memcpy ((char *)bp->outPtr, (char *)bytesPtr, numBytes);
242 }
243 }
244
245 /*-
247 *-----------------------------------------------------------------------
248 * Buf_GetByte --
249 * Return the next byte from the buffer. Actually returns an integer.
250 *
251 * Results:
252 * Returns BUF_ERROR if there's no byte in the buffer, or the byte
253 * itself if there is one.
254 *
255 * Side Effects:
256 * outPtr is incremented and both outPtr and inPtr will be reset if
257 * the buffer is emptied.
258 *
259 *-----------------------------------------------------------------------
260 */
261 int
262 Buf_GetByte (bp)
263 register Buffer bp;
264 {
265 int res;
266
267 if (bp->inPtr == bp->outPtr) {
268 return (BUF_ERROR);
269 } else {
270 res = (int) *bp->outPtr;
271 bp->outPtr += 1;
272 if (bp->outPtr == bp->inPtr) {
273 bp->outPtr = bp->inPtr = bp->buffer;
274 bp->left = bp->size;
275 *bp->inPtr = 0;
276 }
277 return (res);
278 }
279 }
280
281 /*-
283 *-----------------------------------------------------------------------
284 * Buf_GetBytes --
285 * Extract a number of bytes from the buffer.
286 *
287 * Results:
288 * The number of bytes gotten.
289 *
290 * Side Effects:
291 * The passed array is overwritten.
292 *
293 *-----------------------------------------------------------------------
294 */
295 int
296 Buf_GetBytes (bp, numBytes, bytesPtr)
297 register Buffer bp;
298 int numBytes;
299 Byte *bytesPtr;
300 {
301
302 if (bp->inPtr - bp->outPtr < numBytes) {
303 numBytes = bp->inPtr - bp->outPtr;
304 }
305 memcpy (bytesPtr, bp->outPtr, numBytes);
306 bp->outPtr += numBytes;
307
308 if (bp->outPtr == bp->inPtr) {
309 bp->outPtr = bp->inPtr = bp->buffer;
310 bp->left = bp->size;
311 *bp->inPtr = 0;
312 }
313 return (numBytes);
314 }
315
316 /*-
318 *-----------------------------------------------------------------------
319 * Buf_GetAll --
320 * Get all the available data at once.
321 *
322 * Results:
323 * A pointer to the data and the number of bytes available.
324 *
325 * Side Effects:
326 * None.
327 *
328 *-----------------------------------------------------------------------
329 */
330 Byte *
331 Buf_GetAll (bp, numBytesPtr)
332 register Buffer bp;
333 int *numBytesPtr;
334 {
335
336 if (numBytesPtr != (int *)NULL) {
337 *numBytesPtr = bp->inPtr - bp->outPtr;
338 }
339
340 return (bp->outPtr);
341 }
342
343 /*-
345 *-----------------------------------------------------------------------
346 * Buf_Discard --
347 * Throw away bytes in a buffer.
348 *
349 * Results:
350 * None.
351 *
352 * Side Effects:
353 * The bytes are discarded.
354 *
355 *-----------------------------------------------------------------------
356 */
357 void
358 Buf_Discard (bp, numBytes)
359 register Buffer bp;
360 int numBytes;
361 {
362
363 if (bp->inPtr - bp->outPtr <= numBytes) {
364 bp->inPtr = bp->outPtr = bp->buffer;
365 bp->left = bp->size;
366 *bp->inPtr = 0;
367 } else {
368 bp->outPtr += numBytes;
369 }
370 }
371
372 /*-
374 *-----------------------------------------------------------------------
375 * Buf_Size --
376 * Returns the number of bytes in the given buffer. Doesn't include
377 * the null-terminating byte.
378 *
379 * Results:
380 * The number of bytes.
381 *
382 * Side Effects:
383 * None.
384 *
385 *-----------------------------------------------------------------------
386 */
387 int
388 Buf_Size (buf)
389 Buffer buf;
390 {
391 return (buf->inPtr - buf->outPtr);
392 }
393
394 /*-
396 *-----------------------------------------------------------------------
397 * Buf_Init --
398 * Initialize a buffer. If no initial size is given, a reasonable
399 * default is used.
400 *
401 * Results:
402 * A buffer to be given to other functions in this library.
403 *
404 * Side Effects:
405 * The buffer is created, the space allocated and pointers
406 * initialized.
407 *
408 *-----------------------------------------------------------------------
409 */
410 Buffer
411 Buf_Init (size)
412 int size; /* Initial size for the buffer */
413 {
414 Buffer bp; /* New Buffer */
415
416 bp = (Buffer)emalloc(sizeof(*bp));
417
418 if (size <= 0) {
419 size = BUF_DEF_SIZE;
420 }
421 bp->left = bp->size = size;
422 bp->buffer = (Byte *)emalloc(size);
423 bp->inPtr = bp->outPtr = bp->buffer;
424 *bp->inPtr = 0;
425
426 return (bp);
427 }
428
429 /*-
431 *-----------------------------------------------------------------------
432 * Buf_Destroy --
433 * Nuke a buffer and all its resources.
434 *
435 * Results:
436 * None.
437 *
438 * Side Effects:
439 * The buffer is freed.
440 *
441 *-----------------------------------------------------------------------
442 */
443 void
444 Buf_Destroy (buf, freeData)
445 Buffer buf; /* Buffer to destroy */
446 Boolean freeData; /* TRUE if the data should be destroyed as well */
447 {
448
449 if (freeData) {
450 free ((char *)buf->buffer);
451 }
452 free ((char *)buf);
453 }
454
455 /*-
457 *-----------------------------------------------------------------------
458 * Buf_ReplaceLastByte --
459 * Replace the last byte in a buffer.
460 *
461 * Results:
462 * None.
463 *
464 * Side Effects:
465 * If the buffer was empty intially, then a new byte will be added.
466 * Otherwise, the last byte is overwritten.
467 *
468 *-----------------------------------------------------------------------
469 */
470 void
471 Buf_ReplaceLastByte (buf, byte)
472 Buffer buf; /* buffer to augment */
473 int byte; /* byte to be written */
474 {
475 if (buf->inPtr == buf->outPtr)
476 Buf_AddByte(buf, byte);
477 else
478 *(buf->inPtr - 1) = byte;
479 }
480