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