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