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