buf.c revision 1.2 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[] = "from: @(#)buf.c 5.5 (Berkeley) 12/28/90";*/
41 static char rcsid[] = "$Id: buf.c,v 1.2 1993/08/01 18:11:55 mycroft Exp $";
42 #endif /* not lint */
43
44 /*-
45 * buf.c --
46 * Functions for automatically-expanded buffers.
47 */
48
49 #include "sprite.h"
50 #include "buf.h"
51
52 #ifndef max
53 #define max(a,b) ((a) > (b) ? (a) : (b))
54 #endif
55
56 /*
57 * BufExpand --
58 * Expand the given buffer to hold the given number of additional
59 * bytes.
60 * Makes sure there's room for an extra NULL byte at the end of the
61 * buffer in case it holds a string.
62 */
63 #define BufExpand(bp,nb) \
64 if (bp->left < (nb)+1) {\
65 int newSize = (bp)->size + max((nb)+1,BUF_ADD_INC); \
66 Byte *newBuf = (Byte *) realloc((bp)->buffer, newSize); \
67 \
68 (bp)->inPtr = newBuf + ((bp)->inPtr - (bp)->buffer); \
69 (bp)->outPtr = newBuf + ((bp)->outPtr - (bp)->buffer);\
70 (bp)->buffer = newBuf;\
71 (bp)->size = newSize;\
72 (bp)->left = newSize - ((bp)->inPtr - (bp)->buffer);\
73 }
74
75 #define BUF_DEF_SIZE 256 /* Default buffer size */
76 #define BUF_ADD_INC 256 /* Expansion increment when Adding */
77 #define BUF_UNGET_INC 16 /* Expansion increment when Ungetting */
78
79 /*-
80 *-----------------------------------------------------------------------
81 * Buf_OvAddByte --
82 * Add a single byte to the buffer. left is zero or negative.
83 *
84 * Results:
85 * None.
86 *
87 * Side Effects:
88 * The buffer may be expanded.
89 *
90 *-----------------------------------------------------------------------
91 */
92 void
93 Buf_OvAddByte (bp, byte)
94 register Buffer bp;
95 Byte byte;
96 {
97
98 bp->left = 0;
99 BufExpand (bp, 1);
100
101 *bp->inPtr++ = byte;
102 bp->left--;
103
104 /*
105 * Null-terminate
106 */
107 *bp->inPtr = 0;
108 }
109
110 /*-
112 *-----------------------------------------------------------------------
113 * Buf_AddBytes --
114 * Add a number of bytes to the buffer.
115 *
116 * Results:
117 * None.
118 *
119 * Side Effects:
120 * Guess what?
121 *
122 *-----------------------------------------------------------------------
123 */
124 void
125 Buf_AddBytes (bp, numBytes, bytesPtr)
126 register Buffer bp;
127 int numBytes;
128 Byte *bytesPtr;
129 {
130
131 BufExpand (bp, numBytes);
132
133 bcopy (bytesPtr, bp->inPtr, numBytes);
134 bp->inPtr += numBytes;
135 bp->left -= numBytes;
136
137 /*
138 * Null-terminate
139 */
140 *bp->inPtr = 0;
141 }
142
143 /*-
145 *-----------------------------------------------------------------------
146 * Buf_UngetByte --
147 * Place the byte back at the beginning of the buffer.
148 *
149 * Results:
150 * SUCCESS if the byte was added ok. FAILURE if not.
151 *
152 * Side Effects:
153 * The byte is stuffed in the buffer and outPtr is decremented.
154 *
155 *-----------------------------------------------------------------------
156 */
157 void
158 Buf_UngetByte (bp, byte)
159 register Buffer bp;
160 Byte byte;
161 {
162
163 if (bp->outPtr != bp->buffer) {
164 bp->outPtr--;
165 *bp->outPtr = byte;
166 } else if (bp->outPtr == bp->inPtr) {
167 *bp->inPtr = byte;
168 bp->inPtr++;
169 bp->left--;
170 *bp->inPtr = 0;
171 } else {
172 /*
173 * Yech. have to expand the buffer to stuff this thing in.
174 * We use a different expansion constant because people don't
175 * usually push back many bytes when they're doing it a byte at
176 * a time...
177 */
178 int numBytes = bp->inPtr - bp->outPtr;
179 Byte *newBuf;
180
181 newBuf = (Byte *)emalloc(bp->size + BUF_UNGET_INC);
182 bcopy ((char *)bp->outPtr,
183 (char *)(newBuf+BUF_UNGET_INC), 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 bcopy (bytesPtr, bp->outPtr, 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 bcopy((char *)bp->outPtr, (char *)(newBuf+newBytes), 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 bcopy ((char *)bytesPtr, (char *)bp->outPtr, 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 bcopy (bp->outPtr, bytesPtr, 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