Commit | Line | Data |
---|---|---|
15637ed4 RG |
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 | \f | |
109 | /*- | |
110 | *----------------------------------------------------------------------- | |
111 | * Buf_AddBytes -- | |
112 | * Add a number of bytes to the buffer. | |
113 | * | |
114 | * Results: | |
115 | * None. | |
116 | * | |
117 | * Side Effects: | |
118 | * Guess what? | |
119 | * | |
120 | *----------------------------------------------------------------------- | |
121 | */ | |
122 | void | |
123 | Buf_AddBytes (bp, numBytes, bytesPtr) | |
124 | register Buffer bp; | |
125 | int numBytes; | |
126 | Byte *bytesPtr; | |
127 | { | |
128 | ||
129 | BufExpand (bp, numBytes); | |
130 | ||
131 | bcopy (bytesPtr, bp->inPtr, numBytes); | |
132 | bp->inPtr += numBytes; | |
133 | bp->left -= numBytes; | |
134 | ||
135 | /* | |
136 | * Null-terminate | |
137 | */ | |
138 | *bp->inPtr = 0; | |
139 | } | |
140 | \f | |
141 | /*- | |
142 | *----------------------------------------------------------------------- | |
143 | * Buf_UngetByte -- | |
144 | * Place the byte back at the beginning of the buffer. | |
145 | * | |
146 | * Results: | |
147 | * SUCCESS if the byte was added ok. FAILURE if not. | |
148 | * | |
149 | * Side Effects: | |
150 | * The byte is stuffed in the buffer and outPtr is decremented. | |
151 | * | |
152 | *----------------------------------------------------------------------- | |
153 | */ | |
154 | void | |
155 | Buf_UngetByte (bp, byte) | |
156 | register Buffer bp; | |
157 | Byte byte; | |
158 | { | |
159 | ||
160 | if (bp->outPtr != bp->buffer) { | |
161 | bp->outPtr--; | |
162 | *bp->outPtr = byte; | |
163 | } else if (bp->outPtr == bp->inPtr) { | |
164 | *bp->inPtr = byte; | |
165 | bp->inPtr++; | |
166 | bp->left--; | |
167 | *bp->inPtr = 0; | |
168 | } else { | |
169 | /* | |
170 | * Yech. have to expand the buffer to stuff this thing in. | |
171 | * We use a different expansion constant because people don't | |
172 | * usually push back many bytes when they're doing it a byte at | |
173 | * a time... | |
174 | */ | |
175 | int numBytes = bp->inPtr - bp->outPtr; | |
176 | Byte *newBuf; | |
177 | ||
178 | newBuf = (Byte *)emalloc(bp->size + BUF_UNGET_INC); | |
179 | bcopy ((char *)bp->outPtr, | |
180 | (char *)(newBuf+BUF_UNGET_INC), numBytes+1); | |
181 | bp->outPtr = newBuf + BUF_UNGET_INC; | |
182 | bp->inPtr = bp->outPtr + numBytes; | |
183 | free ((char *)bp->buffer); | |
184 | bp->buffer = newBuf; | |
185 | bp->size += BUF_UNGET_INC; | |
186 | bp->left = bp->size - (bp->inPtr - bp->buffer); | |
187 | bp->outPtr -= 1; | |
188 | *bp->outPtr = byte; | |
189 | } | |
190 | } | |
191 | \f | |
192 | /*- | |
193 | *----------------------------------------------------------------------- | |
194 | * Buf_UngetBytes -- | |
195 | * Push back a series of bytes at the beginning of the buffer. | |
196 | * | |
197 | * Results: | |
198 | * None. | |
199 | * | |
200 | * Side Effects: | |
201 | * outPtr is decremented and the bytes copied into the buffer. | |
202 | * | |
203 | *----------------------------------------------------------------------- | |
204 | */ | |
205 | void | |
206 | Buf_UngetBytes (bp, numBytes, bytesPtr) | |
207 | register Buffer bp; | |
208 | int numBytes; | |
209 | Byte *bytesPtr; | |
210 | { | |
211 | ||
212 | if (bp->outPtr - bp->buffer >= numBytes) { | |
213 | bp->outPtr -= numBytes; | |
214 | bcopy (bytesPtr, bp->outPtr, numBytes); | |
215 | } else if (bp->outPtr == bp->inPtr) { | |
216 | Buf_AddBytes (bp, numBytes, bytesPtr); | |
217 | } else { | |
218 | int curNumBytes = bp->inPtr - bp->outPtr; | |
219 | Byte *newBuf; | |
220 | int newBytes = max(numBytes,BUF_UNGET_INC); | |
221 | ||
222 | newBuf = (Byte *)emalloc (bp->size + newBytes); | |
223 | bcopy((char *)bp->outPtr, (char *)(newBuf+newBytes), curNumBytes+1); | |
224 | bp->outPtr = newBuf + newBytes; | |
225 | bp->inPtr = bp->outPtr + curNumBytes; | |
226 | free ((char *)bp->buffer); | |
227 | bp->buffer = newBuf; | |
228 | bp->size += newBytes; | |
229 | bp->left = bp->size - (bp->inPtr - bp->buffer); | |
230 | bp->outPtr -= numBytes; | |
231 | bcopy ((char *)bytesPtr, (char *)bp->outPtr, numBytes); | |
232 | } | |
233 | } | |
234 | \f | |
235 | /*- | |
236 | *----------------------------------------------------------------------- | |
237 | * Buf_GetByte -- | |
238 | * Return the next byte from the buffer. Actually returns an integer. | |
239 | * | |
240 | * Results: | |
241 | * Returns BUF_ERROR if there's no byte in the buffer, or the byte | |
242 | * itself if there is one. | |
243 | * | |
244 | * Side Effects: | |
245 | * outPtr is incremented and both outPtr and inPtr will be reset if | |
246 | * the buffer is emptied. | |
247 | * | |
248 | *----------------------------------------------------------------------- | |
249 | */ | |
250 | int | |
251 | Buf_GetByte (bp) | |
252 | register Buffer bp; | |
253 | { | |
254 | int res; | |
255 | ||
256 | if (bp->inPtr == bp->outPtr) { | |
257 | return (BUF_ERROR); | |
258 | } else { | |
259 | res = (int) *bp->outPtr; | |
260 | bp->outPtr += 1; | |
261 | if (bp->outPtr == bp->inPtr) { | |
262 | bp->outPtr = bp->inPtr = bp->buffer; | |
263 | bp->left = bp->size; | |
264 | *bp->inPtr = 0; | |
265 | } | |
266 | return (res); | |
267 | } | |
268 | } | |
269 | \f | |
270 | /*- | |
271 | *----------------------------------------------------------------------- | |
272 | * Buf_GetBytes -- | |
273 | * Extract a number of bytes from the buffer. | |
274 | * | |
275 | * Results: | |
276 | * The number of bytes gotten. | |
277 | * | |
278 | * Side Effects: | |
279 | * The passed array is overwritten. | |
280 | * | |
281 | *----------------------------------------------------------------------- | |
282 | */ | |
283 | int | |
284 | Buf_GetBytes (bp, numBytes, bytesPtr) | |
285 | register Buffer bp; | |
286 | int numBytes; | |
287 | Byte *bytesPtr; | |
288 | { | |
289 | ||
290 | if (bp->inPtr - bp->outPtr < numBytes) { | |
291 | numBytes = bp->inPtr - bp->outPtr; | |
292 | } | |
293 | bcopy (bp->outPtr, bytesPtr, numBytes); | |
294 | bp->outPtr += numBytes; | |
295 | ||
296 | if (bp->outPtr == bp->inPtr) { | |
297 | bp->outPtr = bp->inPtr = bp->buffer; | |
298 | bp->left = bp->size; | |
299 | *bp->inPtr = 0; | |
300 | } | |
301 | return (numBytes); | |
302 | } | |
303 | \f | |
304 | /*- | |
305 | *----------------------------------------------------------------------- | |
306 | * Buf_GetAll -- | |
307 | * Get all the available data at once. | |
308 | * | |
309 | * Results: | |
310 | * A pointer to the data and the number of bytes available. | |
311 | * | |
312 | * Side Effects: | |
313 | * None. | |
314 | * | |
315 | *----------------------------------------------------------------------- | |
316 | */ | |
317 | Byte * | |
318 | Buf_GetAll (bp, numBytesPtr) | |
319 | register Buffer bp; | |
320 | int *numBytesPtr; | |
321 | { | |
322 | ||
323 | if (numBytesPtr != (int *)NULL) { | |
324 | *numBytesPtr = bp->inPtr - bp->outPtr; | |
325 | } | |
326 | ||
327 | return (bp->outPtr); | |
328 | } | |
329 | \f | |
330 | /*- | |
331 | *----------------------------------------------------------------------- | |
332 | * Buf_Discard -- | |
333 | * Throw away bytes in a buffer. | |
334 | * | |
335 | * Results: | |
336 | * None. | |
337 | * | |
338 | * Side Effects: | |
339 | * The bytes are discarded. | |
340 | * | |
341 | *----------------------------------------------------------------------- | |
342 | */ | |
343 | void | |
344 | Buf_Discard (bp, numBytes) | |
345 | register Buffer bp; | |
346 | int numBytes; | |
347 | { | |
348 | ||
349 | if (bp->inPtr - bp->outPtr <= numBytes) { | |
350 | bp->inPtr = bp->outPtr = bp->buffer; | |
351 | bp->left = bp->size; | |
352 | *bp->inPtr = 0; | |
353 | } else { | |
354 | bp->outPtr += numBytes; | |
355 | } | |
356 | } | |
357 | \f | |
358 | /*- | |
359 | *----------------------------------------------------------------------- | |
360 | * Buf_Size -- | |
361 | * Returns the number of bytes in the given buffer. Doesn't include | |
362 | * the null-terminating byte. | |
363 | * | |
364 | * Results: | |
365 | * The number of bytes. | |
366 | * | |
367 | * Side Effects: | |
368 | * None. | |
369 | * | |
370 | *----------------------------------------------------------------------- | |
371 | */ | |
372 | int | |
373 | Buf_Size (buf) | |
374 | Buffer buf; | |
375 | { | |
376 | return (buf->inPtr - buf->outPtr); | |
377 | } | |
378 | \f | |
379 | /*- | |
380 | *----------------------------------------------------------------------- | |
381 | * Buf_Init -- | |
382 | * Initialize a buffer. If no initial size is given, a reasonable | |
383 | * default is used. | |
384 | * | |
385 | * Results: | |
386 | * A buffer to be given to other functions in this library. | |
387 | * | |
388 | * Side Effects: | |
389 | * The buffer is created, the space allocated and pointers | |
390 | * initialized. | |
391 | * | |
392 | *----------------------------------------------------------------------- | |
393 | */ | |
394 | Buffer | |
395 | Buf_Init (size) | |
396 | int size; /* Initial size for the buffer */ | |
397 | { | |
398 | Buffer bp; /* New Buffer */ | |
399 | ||
400 | bp = (Buffer)emalloc(sizeof(*bp)); | |
401 | ||
402 | if (size <= 0) { | |
403 | size = BUF_DEF_SIZE; | |
404 | } | |
405 | bp->left = bp->size = size; | |
406 | bp->buffer = (Byte *)emalloc(size); | |
407 | bp->inPtr = bp->outPtr = bp->buffer; | |
408 | *bp->inPtr = 0; | |
409 | ||
410 | return (bp); | |
411 | } | |
412 | \f | |
413 | /*- | |
414 | *----------------------------------------------------------------------- | |
415 | * Buf_Destroy -- | |
416 | * Nuke a buffer and all its resources. | |
417 | * | |
418 | * Results: | |
419 | * None. | |
420 | * | |
421 | * Side Effects: | |
422 | * The buffer is freed. | |
423 | * | |
424 | *----------------------------------------------------------------------- | |
425 | */ | |
426 | void | |
427 | Buf_Destroy (buf, freeData) | |
428 | Buffer buf; /* Buffer to destroy */ | |
429 | Boolean freeData; /* TRUE if the data should be destroyed as well */ | |
430 | { | |
431 | ||
432 | if (freeData) { | |
433 | free ((char *)buf->buffer); | |
434 | } | |
435 | free ((char *)buf); | |
436 | } |