buf.c revision 1.8 1 /* $NetBSD: buf.c,v 1.8 1996/11/06 17:59:00 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 #ifndef lint
42 #if 0
43 static char sccsid[] = "@(#)buf.c 8.1 (Berkeley) 6/6/93";
44 #else
45 static char rcsid[] = "$NetBSD: buf.c,v 1.8 1996/11/06 17:59:00 christos Exp $";
46 #endif
47 #endif /* not lint */
48
49 /*-
50 * buf.c --
51 * Functions for automatically-expanded buffers.
52 */
53
54 #include "sprite.h"
55 #include "make.h"
56 #include "buf.h"
57
58 #ifndef max
59 #define max(a,b) ((a) > (b) ? (a) : (b))
60 #endif
61
62 /*
63 * BufExpand --
64 * Expand the given buffer to hold the given number of additional
65 * bytes.
66 * Makes sure there's room for an extra NULL byte at the end of the
67 * buffer in case it holds a string.
68 */
69 #define BufExpand(bp,nb) \
70 if (bp->left < (nb)+1) {\
71 int newSize = (bp)->size + max((nb)+1,BUF_ADD_INC); \
72 Byte *newBuf = (Byte *) erealloc((bp)->buffer, newSize); \
73 \
74 (bp)->inPtr = newBuf + ((bp)->inPtr - (bp)->buffer); \
75 (bp)->outPtr = newBuf + ((bp)->outPtr - (bp)->buffer);\
76 (bp)->buffer = newBuf;\
77 (bp)->size = newSize;\
78 (bp)->left = newSize - ((bp)->inPtr - (bp)->buffer);\
79 }
80
81 #define BUF_DEF_SIZE 256 /* Default buffer size */
82 #define BUF_ADD_INC 256 /* Expansion increment when Adding */
83 #define BUF_UNGET_INC 16 /* Expansion increment when Ungetting */
84
85 /*-
86 *-----------------------------------------------------------------------
87 * Buf_OvAddByte --
88 * Add a single byte to the buffer. left is zero or negative.
89 *
90 * Results:
91 * None.
92 *
93 * Side Effects:
94 * The buffer may be expanded.
95 *
96 *-----------------------------------------------------------------------
97 */
98 void
99 Buf_OvAddByte (bp, byte)
100 register Buffer bp;
101 int byte;
102 {
103 int nbytes = 1;
104 bp->left = 0;
105 BufExpand (bp, nbytes);
106
107 *bp->inPtr++ = byte;
108 bp->left--;
109
110 /*
111 * Null-terminate
112 */
113 *bp->inPtr = 0;
114 }
115
116 /*-
118 *-----------------------------------------------------------------------
119 * Buf_AddBytes --
120 * Add a number of bytes to the buffer.
121 *
122 * Results:
123 * None.
124 *
125 * Side Effects:
126 * Guess what?
127 *
128 *-----------------------------------------------------------------------
129 */
130 void
131 Buf_AddBytes (bp, numBytes, bytesPtr)
132 register Buffer bp;
133 int numBytes;
134 const Byte *bytesPtr;
135 {
136
137 BufExpand (bp, numBytes);
138
139 memcpy (bp->inPtr, bytesPtr, numBytes);
140 bp->inPtr += numBytes;
141 bp->left -= numBytes;
142
143 /*
144 * Null-terminate
145 */
146 *bp->inPtr = 0;
147 }
148
149 /*-
151 *-----------------------------------------------------------------------
152 * Buf_UngetByte --
153 * Place the byte back at the beginning of the buffer.
154 *
155 * Results:
156 * SUCCESS if the byte was added ok. FAILURE if not.
157 *
158 * Side Effects:
159 * The byte is stuffed in the buffer and outPtr is decremented.
160 *
161 *-----------------------------------------------------------------------
162 */
163 void
164 Buf_UngetByte (bp, byte)
165 register Buffer bp;
166 int byte;
167 {
168
169 if (bp->outPtr != bp->buffer) {
170 bp->outPtr--;
171 *bp->outPtr = byte;
172 } else if (bp->outPtr == bp->inPtr) {
173 *bp->inPtr = byte;
174 bp->inPtr++;
175 bp->left--;
176 *bp->inPtr = 0;
177 } else {
178 /*
179 * Yech. have to expand the buffer to stuff this thing in.
180 * We use a different expansion constant because people don't
181 * usually push back many bytes when they're doing it a byte at
182 * a time...
183 */
184 int numBytes = bp->inPtr - bp->outPtr;
185 Byte *newBuf;
186
187 newBuf = (Byte *)emalloc(bp->size + BUF_UNGET_INC);
188 memcpy ((char *)(newBuf+BUF_UNGET_INC), (char *)bp->outPtr, numBytes+1);
189 bp->outPtr = newBuf + BUF_UNGET_INC;
190 bp->inPtr = bp->outPtr + numBytes;
191 free ((char *)bp->buffer);
192 bp->buffer = newBuf;
193 bp->size += BUF_UNGET_INC;
194 bp->left = bp->size - (bp->inPtr - bp->buffer);
195 bp->outPtr -= 1;
196 *bp->outPtr = byte;
197 }
198 }
199
200 /*-
202 *-----------------------------------------------------------------------
203 * Buf_UngetBytes --
204 * Push back a series of bytes at the beginning of the buffer.
205 *
206 * Results:
207 * None.
208 *
209 * Side Effects:
210 * outPtr is decremented and the bytes copied into the buffer.
211 *
212 *-----------------------------------------------------------------------
213 */
214 void
215 Buf_UngetBytes (bp, numBytes, bytesPtr)
216 register Buffer bp;
217 int numBytes;
218 Byte *bytesPtr;
219 {
220
221 if (bp->outPtr - bp->buffer >= numBytes) {
222 bp->outPtr -= numBytes;
223 memcpy (bp->outPtr, bytesPtr, numBytes);
224 } else if (bp->outPtr == bp->inPtr) {
225 Buf_AddBytes (bp, numBytes, bytesPtr);
226 } else {
227 int curNumBytes = bp->inPtr - bp->outPtr;
228 Byte *newBuf;
229 int newBytes = max(numBytes,BUF_UNGET_INC);
230
231 newBuf = (Byte *)emalloc (bp->size + newBytes);
232 memcpy((char *)(newBuf+newBytes), (char *)bp->outPtr, curNumBytes+1);
233 bp->outPtr = newBuf + newBytes;
234 bp->inPtr = bp->outPtr + curNumBytes;
235 free ((char *)bp->buffer);
236 bp->buffer = newBuf;
237 bp->size += newBytes;
238 bp->left = bp->size - (bp->inPtr - bp->buffer);
239 bp->outPtr -= numBytes;
240 memcpy ((char *)bp->outPtr, (char *)bytesPtr, numBytes);
241 }
242 }
243
244 /*-
246 *-----------------------------------------------------------------------
247 * Buf_GetByte --
248 * Return the next byte from the buffer. Actually returns an integer.
249 *
250 * Results:
251 * Returns BUF_ERROR if there's no byte in the buffer, or the byte
252 * itself if there is one.
253 *
254 * Side Effects:
255 * outPtr is incremented and both outPtr and inPtr will be reset if
256 * the buffer is emptied.
257 *
258 *-----------------------------------------------------------------------
259 */
260 int
261 Buf_GetByte (bp)
262 register Buffer bp;
263 {
264 int res;
265
266 if (bp->inPtr == bp->outPtr) {
267 return (BUF_ERROR);
268 } else {
269 res = (int) *bp->outPtr;
270 bp->outPtr += 1;
271 if (bp->outPtr == bp->inPtr) {
272 bp->outPtr = bp->inPtr = bp->buffer;
273 bp->left = bp->size;
274 *bp->inPtr = 0;
275 }
276 return (res);
277 }
278 }
279
280 /*-
282 *-----------------------------------------------------------------------
283 * Buf_GetBytes --
284 * Extract a number of bytes from the buffer.
285 *
286 * Results:
287 * The number of bytes gotten.
288 *
289 * Side Effects:
290 * The passed array is overwritten.
291 *
292 *-----------------------------------------------------------------------
293 */
294 int
295 Buf_GetBytes (bp, numBytes, bytesPtr)
296 register Buffer bp;
297 int numBytes;
298 Byte *bytesPtr;
299 {
300
301 if (bp->inPtr - bp->outPtr < numBytes) {
302 numBytes = bp->inPtr - bp->outPtr;
303 }
304 memcpy (bytesPtr, bp->outPtr, numBytes);
305 bp->outPtr += numBytes;
306
307 if (bp->outPtr == bp->inPtr) {
308 bp->outPtr = bp->inPtr = bp->buffer;
309 bp->left = bp->size;
310 *bp->inPtr = 0;
311 }
312 return (numBytes);
313 }
314
315 /*-
317 *-----------------------------------------------------------------------
318 * Buf_GetAll --
319 * Get all the available data at once.
320 *
321 * Results:
322 * A pointer to the data and the number of bytes available.
323 *
324 * Side Effects:
325 * None.
326 *
327 *-----------------------------------------------------------------------
328 */
329 Byte *
330 Buf_GetAll (bp, numBytesPtr)
331 register Buffer bp;
332 int *numBytesPtr;
333 {
334
335 if (numBytesPtr != (int *)NULL) {
336 *numBytesPtr = bp->inPtr - bp->outPtr;
337 }
338
339 return (bp->outPtr);
340 }
341
342 /*-
344 *-----------------------------------------------------------------------
345 * Buf_Discard --
346 * Throw away bytes in a buffer.
347 *
348 * Results:
349 * None.
350 *
351 * Side Effects:
352 * The bytes are discarded.
353 *
354 *-----------------------------------------------------------------------
355 */
356 void
357 Buf_Discard (bp, numBytes)
358 register Buffer bp;
359 int numBytes;
360 {
361
362 if (bp->inPtr - bp->outPtr <= numBytes) {
363 bp->inPtr = bp->outPtr = bp->buffer;
364 bp->left = bp->size;
365 *bp->inPtr = 0;
366 } else {
367 bp->outPtr += numBytes;
368 }
369 }
370
371 /*-
373 *-----------------------------------------------------------------------
374 * Buf_Size --
375 * Returns the number of bytes in the given buffer. Doesn't include
376 * the null-terminating byte.
377 *
378 * Results:
379 * The number of bytes.
380 *
381 * Side Effects:
382 * None.
383 *
384 *-----------------------------------------------------------------------
385 */
386 int
387 Buf_Size (buf)
388 Buffer buf;
389 {
390 return (buf->inPtr - buf->outPtr);
391 }
392
393 /*-
395 *-----------------------------------------------------------------------
396 * Buf_Init --
397 * Initialize a buffer. If no initial size is given, a reasonable
398 * default is used.
399 *
400 * Results:
401 * A buffer to be given to other functions in this library.
402 *
403 * Side Effects:
404 * The buffer is created, the space allocated and pointers
405 * initialized.
406 *
407 *-----------------------------------------------------------------------
408 */
409 Buffer
410 Buf_Init (size)
411 int size; /* Initial size for the buffer */
412 {
413 Buffer bp; /* New Buffer */
414
415 bp = (Buffer)emalloc(sizeof(*bp));
416
417 if (size <= 0) {
418 size = BUF_DEF_SIZE;
419 }
420 bp->left = bp->size = size;
421 bp->buffer = (Byte *)emalloc(size);
422 bp->inPtr = bp->outPtr = bp->buffer;
423 *bp->inPtr = 0;
424
425 return (bp);
426 }
427
428 /*-
430 *-----------------------------------------------------------------------
431 * Buf_Destroy --
432 * Nuke a buffer and all its resources.
433 *
434 * Results:
435 * None.
436 *
437 * Side Effects:
438 * The buffer is freed.
439 *
440 *-----------------------------------------------------------------------
441 */
442 void
443 Buf_Destroy (buf, freeData)
444 Buffer buf; /* Buffer to destroy */
445 Boolean freeData; /* TRUE if the data should be destroyed as well */
446 {
447
448 if (freeData) {
449 free ((char *)buf->buffer);
450 }
451 free ((char *)buf);
452 }
453
454 /*-
456 *-----------------------------------------------------------------------
457 * Buf_ReplaceLastByte --
458 * Replace the last byte in a buffer.
459 *
460 * Results:
461 * None.
462 *
463 * Side Effects:
464 * If the buffer was empty intially, then a new byte will be added.
465 * Otherwise, the last byte is overwritten.
466 *
467 *-----------------------------------------------------------------------
468 */
469 void
470 Buf_ReplaceLastByte (buf, byte)
471 Buffer buf; /* buffer to augment */
472 Byte byte; /* byte to be written */
473 {
474 if (buf->inPtr == buf->outPtr)
475 Buf_AddByte(buf, byte);
476 else
477 *(buf->inPtr - 1) = byte;
478 }
479