]>
Commit | Line | Data |
---|---|---|
bac41a7b A |
1 | /* |
2 | * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. | |
3 | * | |
4 | * The contents of this file constitute Original Code as defined in and are | |
5 | * subject to the Apple Public Source License Version 1.2 (the 'License'). | |
6 | * You may not use this file except in compliance with the License. Please obtain | |
7 | * a copy of the License at http://www.apple.com/publicsource and read it before | |
8 | * using this file. | |
9 | * | |
10 | * This Original Code and all software distributed under the License are | |
11 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS | |
12 | * OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT | |
13 | * LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR | |
14 | * PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the | |
15 | * specific language governing rights and limitations under the License. | |
16 | */ | |
17 | ||
18 | ||
19 | #if defined (USE_EXP_BUF) || defined (USE_GEN_BUF) | |
20 | /* | |
21 | * .../c-lib/src/exp-buf.c - buffer routines for the buffer structure | |
22 | * | |
23 | * | |
24 | * --------- ---------- | |
25 | * | ExpBuf |<------>| ExpBuf |<------> ...ExpBufs | |
26 | * | |--- | |--- | |
27 | * ---------- | ---------- | | |
28 | * V V | |
29 | * -------- -------- | |
30 | * | DATA | | DATA | | |
31 | * | BLK | | BLK | | |
32 | * -------- -------- | |
33 | * | |
34 | * | |
35 | * ExpBuf | |
36 | * -------------- | |
37 | * | readError | | |
38 | * | writeError | | |
39 | * | dataStart |----------- | |
40 | * | dataEnd |-------- | | |
41 | * | curr |------ | | | |
42 | * | next | | | | | |
43 | * | prev | | | | data | |
44 | * | blkStart |=====|=|==|==>-------------------------- | |
45 | * | blkEnd |--- | | | | | (each line | |
46 | * -------------- | | | | | | reps a byte | |
47 | * | | | |-->| - - - - - - - - - - - -| diff in addr) | |
48 | * | | | | valid | | |
49 | * | |-|----->| | | |
50 | * | | | data | | |
51 | * | | | | | |
52 | * | | | - - - - - - - - - - - -| | |
53 | * | |----->|(one byte after last valid data byte) | |
54 | * | | | | |
55 | * | -------------------------- | |
56 | * |-----------> (one byte after last byte in data blk) | |
57 | * | |
58 | * | |
59 | * readError - set to non-zero to indicate attempt to read past end of | |
60 | * of data | |
61 | * writeError- set to non-zero to indicate write error. | |
62 | * Set if Alloc of new buf fails | |
63 | * dataStart - pts to first VALID data byte ie *dataStart is first byte | |
64 | * dataEnd - pts to byte AFTER last VALID byte *dataEnd is not in the data | |
65 | * but *(dataEnd -1) is in the data | |
66 | * curr - used for current read ptr - points to next byte to be read | |
67 | * so *curr is the next byte to be read. | |
68 | * next - pts to next BUF in list, NULL for last BUF in list | |
69 | * prev - pts to prev BUF in list, NULL for first BUF in list | |
70 | * blkStart - pts to start of the data blk. *blkStart is first byte | |
71 | * in the buffer's data blk. | |
72 | * blkEnd - pts to byte AFTER last writable byte of the dataBlk. | |
73 | * *(blkEnd-1) is the last byte in the buffer's data blk. | |
74 | * | |
75 | * NOTES: | |
76 | * - dataEnd is currently always the same as blkEnd | |
77 | * - at End Of Data (EOD) (no more data to be read) | |
78 | * if (curr == dataEnd) | |
79 | * - buffer has no valid data if (dataStart == dataEnd) | |
80 | * - number of valid data bytes = (dataEnd - dataStart) | |
81 | * - size of the data block = (blkEnd - blkStart) | |
82 | * | |
83 | * - the write reverse routines modify dataStart | |
84 | * - the read routines modify the curr ptr. | |
85 | * - there are no 'forward' write routines at the moment | |
86 | * (if there were they would adjust dataEnd) | |
87 | * | |
88 | * | |
89 | * Copyright (C) 1992 Michael Sample and the University of British Columbia | |
90 | * | |
91 | * This library is free software; you can redistribute it and/or | |
92 | * modify it provided that this copyright/license information is retained | |
93 | * in original form. | |
94 | * | |
95 | * If you modify this file, you must clearly indicate your changes. | |
96 | * | |
97 | * This source code is distributed in the hope that it will be | |
98 | * useful, but WITHOUT ANY WARRANTY; without even the implied warranty | |
99 | * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | |
100 | * | |
a66d0d4a | 101 | * $Header: /cvs/root/Security/SecuritySNACCRuntime/c-lib/src/Attic/exp-buf.c,v 1.1.1.1 2001/05/18 23:14:08 mb Exp $ |
bac41a7b A |
102 | * $Log: exp-buf.c,v $ |
103 | * Revision 1.1.1.1 2001/05/18 23:14:08 mb | |
104 | * Move from private repository to open source repository | |
105 | * | |
106 | * Revision 1.2 2001/05/05 00:59:25 rmurphy | |
107 | * Adding darwin license headers | |
108 | * | |
109 | * Revision 1.1.1.1 1999/03/16 18:06:32 aram | |
110 | * Originals from SMIME Free Library. | |
111 | * | |
112 | * Revision 1.2 1995/07/27 09:05:29 rj | |
113 | * merged type table routines and code used by its gen-bufs. | |
114 | * | |
115 | * changed `_' to `-' in file names. | |
116 | * | |
117 | * Revision 1.1 1994/08/28 09:46:05 rj | |
118 | * first check-in. for a list of changes to the snacc-1.1 distribution please refer to the ChangeLog. | |
119 | * | |
120 | */ | |
121 | ||
122 | #include "asn-config.h" | |
123 | #include "gen-buf.h" | |
124 | #include "exp-buf.h" | |
125 | ||
126 | ||
127 | /* default buffer data block size (used when allocating) */ | |
128 | unsigned long expBufDataBlkSizeG = 1024; | |
129 | ||
130 | ||
131 | #if defined (DEBUG) || defined (USE_GEN_BUF) /* otherwise macros */ | |
132 | ||
133 | #ifdef USE_GEN_BUF | |
134 | ||
135 | /* | |
136 | * casts are used to overcome void * - ExpBuf * conflict | |
137 | * be careful if you modify param lists etc. | |
138 | */ | |
139 | static struct GenBuf expBufOpsG = | |
140 | { | |
141 | (BufGetByteFcn) ExpBufGetByte, | |
142 | (BufGetSegFcn) ExpBufGetSeg, | |
143 | (BufCopyFcn) ExpBufCopy, | |
144 | (BufSkipFcn) ExpBufSkip, | |
145 | (BufPeekByteFcn) ExpBufPeekByte, | |
146 | (BufPeekSegFcn) ExpBufPeekSeg, | |
147 | (BufPeekCopyFcn) ExpBufPeekCopy, | |
148 | (BufPutByteRvsFcn) ExpBufPutByteRvs, | |
149 | (BufPutSegRvsFcn) ExpBufPutSegRvs, | |
150 | (BufReadErrorFcn) ExpBufReadError, | |
151 | (BufWriteErrorFcn) ExpBufWriteError, | |
152 | NULL, | |
153 | NULL | |
154 | }; | |
155 | ||
156 | #endif | |
157 | ||
158 | /* | |
159 | * remember: ExpBufs are used via a handle (double ptr) | |
160 | * in the standardized buffer routines. This allows | |
161 | * the 'current' expbuf in the list of expbuf to be the arg. | |
162 | * The list is doubly linked so you can always find | |
163 | * the head or tail given any expbuf in the list | |
164 | */ | |
165 | void | |
166 | PutExpBufInGenBuf PARAMS ((eb, gb), | |
167 | ExpBuf *eb _AND_ | |
168 | GenBuf *gb) | |
169 | { | |
170 | *gb = expBufOpsG; /* structure assignemnt */ | |
171 | gb->bufInfo = &gb->spare; /* handle to expbuf */ | |
172 | gb->spare = eb; | |
173 | } /* PutExpBufInGenBuf */ | |
174 | ||
175 | /* | |
176 | * sets the size of the data block to attach to | |
177 | * an ExpBuf when allocating a new one | |
178 | */ | |
179 | void | |
180 | ExpBufInit PARAMS ((dataBlkSize), | |
181 | unsigned long dataBlkSize) | |
182 | { | |
183 | expBufDataBlkSizeG = dataBlkSize; | |
184 | } /* InitBuffers */ | |
185 | ||
186 | /* | |
187 | * Allocates and returns an uninitialized ExpBuf with | |
188 | * no a data attached. | |
189 | */ | |
190 | ExpBuf* | |
191 | ExpBufAllocBuf() | |
192 | { | |
193 | return (ExpBuf*)malloc (sizeof (ExpBuf)); | |
194 | } | |
195 | ||
196 | void | |
197 | ExpBufFreeBuf PARAMS ((ptr), | |
198 | ExpBuf *ptr) | |
199 | { | |
200 | free (ptr); | |
201 | } | |
202 | ||
203 | char* | |
204 | ExpBufAllocData() | |
205 | { | |
206 | return (char*)malloc (expBufDataBlkSizeG); | |
207 | } | |
208 | ||
209 | void | |
210 | ExpBufFreeData PARAMS ((ptr), | |
211 | char *ptr) | |
212 | { | |
213 | free (ptr); | |
214 | } | |
215 | ||
216 | void | |
217 | ExpBufFreeBufAndData PARAMS ((b), | |
218 | ExpBuf *b) | |
219 | { | |
220 | ExpBufFreeData ((b)->blkStart); | |
221 | ExpBufFreeBuf (b); | |
222 | } /* ExpBufFreeBufAndData */ | |
223 | ||
224 | ExpBuf* | |
225 | ExpBufNext PARAMS ((b), | |
226 | ExpBuf *b) | |
227 | { | |
228 | return b->next; | |
229 | } | |
230 | ||
231 | ExpBuf* | |
232 | ExpBufPrev PARAMS ((b), | |
233 | ExpBuf *b) | |
234 | { | |
235 | return b->prev; | |
236 | } | |
237 | ||
238 | int | |
239 | ExpBufReadError PARAMS ((b), | |
240 | ExpBuf **b) | |
241 | { | |
242 | return (*b)->readError; | |
243 | } /* ExpBufReadError */ | |
244 | ||
245 | int | |
246 | ExpBufWriteError PARAMS ((b), | |
247 | ExpBuf **b) | |
248 | { | |
249 | return (*b)->writeError; | |
250 | } /* ExpBufWriteError */ | |
251 | ||
252 | /* | |
253 | * set curr ptr used in reads to the first byte | |
254 | * to be read | |
255 | */ | |
256 | void | |
257 | ExpBufResetInReadMode PARAMS ((b), | |
258 | ExpBuf *b) | |
259 | { | |
260 | b->curr = b->dataStart; | |
261 | b->readError = 0; | |
262 | b->writeError = 1; /* catch wrong mode errors */ | |
263 | } | |
264 | ||
265 | /* | |
266 | * sets dataStart to end of buffer | |
267 | * so following writes (backward) | |
268 | * over-write any existing data associated with | |
269 | * the buffer | |
270 | */ | |
271 | void | |
272 | ExpBufResetInWriteRvsMode PARAMS ((b), | |
273 | ExpBuf *b) | |
274 | { | |
275 | b->dataEnd = b->dataStart = b->blkEnd; | |
276 | b->writeError = 0; | |
277 | b->readError = 1; /* catch wrong mode errors */ | |
278 | } | |
279 | ||
280 | ||
281 | /* | |
282 | * returns true if no more data can be read from | |
283 | * the given buffer. only valid when buffer in read (fwd) | |
284 | * mode. | |
285 | */ | |
286 | int | |
287 | ExpBufAtEod PARAMS ((b), | |
288 | ExpBuf *b) | |
289 | { | |
290 | return b->curr == b->dataEnd; | |
291 | } | |
292 | ||
293 | ||
294 | /* | |
295 | * returns true if no more reverse writes can be done | |
296 | * to the buffer. Only valid when buffers in reverse | |
297 | * write mode | |
298 | */ | |
299 | int | |
300 | ExpBufFull PARAMS ((b), | |
301 | ExpBuf *b) | |
302 | { | |
303 | return (b)->dataStart == (b)->blkStart; | |
304 | } | |
305 | ||
306 | ||
307 | /* | |
308 | * returns true if the given buffer has no | |
309 | * valid data in it's data block | |
310 | */ | |
311 | int | |
312 | ExpBufHasNoData PARAMS ((b), | |
313 | ExpBuf *b) | |
314 | { | |
315 | return b->dataStart == b->dataEnd; | |
316 | } | |
317 | ||
318 | ||
319 | /* | |
320 | * returns the number of valid data bytes in the | |
321 | * given buffer's data block | |
322 | */ | |
323 | unsigned long | |
324 | ExpBufDataSize PARAMS ((b), | |
325 | ExpBuf *b) | |
326 | { | |
327 | return b->dataEnd - b->dataStart; | |
328 | } | |
329 | ||
330 | /* | |
331 | * returns size of data block that is attached to | |
332 | * the given buffer. | |
333 | */ | |
334 | unsigned long | |
335 | ExpBufDataBlkSize PARAMS ((b), | |
336 | ExpBuf *b) | |
337 | { | |
338 | return b->blkEnd - b->blkStart; | |
339 | } | |
340 | ||
341 | /* | |
342 | * returns a ptr the beginning of the valid data of | |
343 | * the given buffer. | |
344 | * returns NULL is there is no valid data. | |
345 | */ | |
346 | char* | |
347 | ExpBufDataPtr PARAMS ((b), | |
348 | ExpBuf *b) | |
349 | { | |
350 | if (ExpBufHasNoData (b)) | |
351 | return NULL; | |
352 | else | |
353 | return b->dataStart; | |
354 | } | |
355 | ||
356 | #endif /* DEBUG || USE_EXP_BUF */ | |
357 | ||
358 | ||
359 | /* | |
360 | * returns last ExpBuf in a list of bufs. | |
361 | * The given buf can be any buf in the list. | |
362 | */ | |
363 | ExpBuf* | |
364 | ExpBufListLastBuf PARAMS ((b), | |
365 | ExpBuf *b) | |
366 | { | |
367 | for (; b->next != NULL; b = b->next) | |
368 | ; | |
369 | return b; | |
370 | } | |
371 | ||
372 | /* | |
373 | * returns first buf in a list of bufs . | |
374 | * The given buf can be any buf in the list | |
375 | */ | |
376 | ExpBuf* | |
377 | ExpBufListFirstBuf PARAMS ((b), | |
378 | ExpBuf *b) | |
379 | { | |
380 | for (; b->prev != NULL; b = b->prev) | |
381 | ; | |
382 | return b; | |
383 | } | |
384 | ||
385 | /* | |
386 | * Allocates a Buf and allocates an attaches a | |
387 | * data block of expBufDataBlkSizeG to that buffer. | |
388 | * sets up the blk for writing in that the data start | |
389 | * and data end point to the byte after the data blk. | |
390 | */ | |
391 | ExpBuf* | |
392 | ExpBufAllocBufAndData() | |
393 | { | |
394 | ExpBuf *retVal; | |
395 | ||
396 | retVal = ExpBufAllocBuf(); | |
397 | ||
398 | if (retVal == NULL) | |
399 | return NULL; | |
400 | ||
401 | retVal->readError = 0; | |
402 | retVal->writeError = 0; | |
403 | retVal->blkStart = ExpBufAllocData(); | |
404 | ||
405 | if (retVal->blkStart == NULL) | |
406 | { | |
407 | ExpBufFreeBuf (retVal); | |
408 | return NULL; | |
409 | } | |
410 | ||
411 | retVal->next = NULL; | |
412 | retVal->prev = NULL; | |
413 | retVal->curr = retVal->blkEnd = retVal->dataStart = retVal->dataEnd = | |
414 | retVal->blkStart + expBufDataBlkSizeG; | |
415 | ||
416 | return retVal; | |
417 | } /* ExpBufAllocBufAndData */ | |
418 | ||
419 | ||
420 | /* | |
421 | * Frees ExpBuf's and associated data blocks after | |
422 | * after (next ptr) and including the given buffer, b. | |
423 | */ | |
424 | void | |
425 | ExpBufFreeBufAndDataList PARAMS ((b), | |
426 | ExpBuf *b) | |
427 | { | |
428 | ExpBuf *tmp; | |
429 | ||
430 | for (; b != NULL;) | |
431 | { | |
432 | tmp = b->next; | |
433 | ExpBufFreeBufAndData (b); | |
434 | b = tmp; | |
435 | } | |
436 | } /* ExpBufFreeBufAndDataList */ | |
437 | ||
438 | ||
439 | /* | |
440 | * puts the given data in a buffer and sets it up for reading | |
441 | * the data. This results in a "full" buffer with a data | |
442 | * blk size of given data's len | |
443 | */ | |
444 | void | |
445 | ExpBufInstallDataInBuf PARAMS ((buf, data, len), | |
446 | ExpBuf *buf _AND_ | |
447 | char *data _AND_ | |
448 | unsigned long int len) | |
449 | { | |
450 | buf->readError = 0; | |
451 | buf->writeError = 0; | |
452 | buf->blkStart = buf->dataStart = buf->curr = data; | |
453 | buf->next = NULL; | |
454 | buf->prev = NULL; | |
455 | buf->blkEnd = buf->dataEnd = data + len; | |
456 | } /* ExpBufInstallDataInBuf */ | |
457 | ||
458 | ||
459 | ||
460 | /* Buf reading and writing routines follow */ | |
461 | ||
462 | /* READ | |
463 | * returns the next byte to be read without | |
464 | * advancing the pointer. No check for end of | |
465 | * data - this is lame | |
466 | */ | |
467 | unsigned char | |
468 | ExpBufPeekByte PARAMS ((b), | |
469 | ExpBuf **b) | |
470 | { | |
471 | if ((*b)->curr == (*b)->dataEnd) | |
472 | (*b)->readError = 1; | |
473 | return *(*b)->curr; | |
474 | } /* ExpBufPeek */ | |
475 | ||
476 | #if TTBL | |
477 | ||
478 | /* READ | |
479 | * returns a ptr to the next "len" bytes (contiguous). | |
480 | * if "len" is greater than the available contiguous bytes | |
481 | * len is set the the number of contig. bytes the returned | |
482 | * ptr references. The next call to ExpBufGetSeg or other ExpBufGet | |
483 | * routines will return a ptrsto the SAME bytes (ie curr is NOT advanced). | |
484 | * | |
485 | * Does not change the buffer | |
486 | * | |
487 | * if the value returned in the len param is zero or the | |
488 | * returned char * is NULL then at end of data. | |
489 | * | |
490 | */ | |
491 | char* | |
492 | ExpBufPeekSeg PARAMS ((b, len), | |
493 | ExpBuf **b _AND_ | |
494 | unsigned long int *len) | |
495 | { | |
496 | int bytesLeft; | |
497 | ||
498 | if (ExpBufAtEod (*b)) | |
499 | { | |
500 | *len = 0; | |
501 | return NULL; | |
502 | } | |
503 | ||
504 | /* check for "buffer fault" and adjust "peeked" len */ | |
505 | if (((*b)->dataEnd - (*b)->curr) <= *len) | |
506 | *len = bytesLeft; | |
507 | ||
508 | return (*b)->curr; | |
509 | ||
510 | } /* ExpBufPeekSeg */ | |
511 | ||
512 | ||
513 | /* READ | |
514 | * copy the next len chars in the buffer to the given | |
515 | * dst char string. The curr ptr in the buffer is | |
516 | * NOT advanced so the next read will get the same bytes. | |
517 | */ | |
518 | int | |
519 | ExpBufPeekCopy PARAMS ((dst, b, len), | |
520 | char *dst _AND_ | |
521 | ExpBuf **b _AND_ | |
522 | unsigned long int len) | |
523 | { | |
524 | unsigned long int gotLen; | |
525 | int totalGotLen = 0; | |
526 | char *srcPtr; | |
527 | ExpBuf *origBuf; | |
528 | ||
529 | origBuf = *b; | |
530 | ||
531 | gotLen = len; | |
532 | while (1) /* optimize std path - eg only one ExpBufGetPeekSeg needed */ | |
533 | { | |
534 | srcPtr = ExpBufPeekSeg (b, &gotLen); | |
535 | memcpy (dst + totalGotLen, srcPtr, gotLen); | |
536 | ||
537 | totalGotLen += gotLen; | |
538 | ||
539 | if ((totalGotLen >= len) || ((*b)->next == NULL)) | |
540 | { | |
541 | *b = origBuf; | |
542 | return totalGotLen; | |
543 | } | |
544 | ||
545 | if (gotLen == 0) /* eod */ | |
546 | { | |
547 | (*b)->readError = 1; | |
548 | *b = origBuf; | |
549 | return totalGotLen; | |
550 | } | |
551 | ||
552 | *b = (*b)->next; | |
553 | /* get next buffer with valid data */ | |
554 | while (((*b)->next != NULL) && ExpBufHasNoData (*b)) | |
555 | *b = (*b)->next; | |
556 | ||
557 | /* reset current pointer to beggining of data if nec */ | |
558 | (*b)->curr = (*b)->dataStart; | |
559 | ||
560 | gotLen = len - totalGotLen; | |
561 | } | |
562 | ||
563 | /* not reached */ | |
564 | ||
565 | } /* ExpBufPeekCopy */ | |
566 | ||
567 | #endif /* TTBL */ | |
568 | ||
569 | /* READ | |
570 | * copy the next len chars in the buffer to the given | |
571 | * dst char string. The curr ptr in the buffer is advanced | |
572 | * appropriately | |
573 | */ | |
574 | int | |
575 | ExpBufCopy PARAMS ((dst, b, len), | |
576 | char *dst _AND_ | |
577 | ExpBuf **b _AND_ | |
578 | unsigned long int len) | |
579 | { | |
580 | unsigned long int gotLen; | |
581 | int totalGotLen = 0; | |
582 | char *srcPtr; | |
583 | ||
584 | gotLen = len; | |
585 | while (1) /* optimize std path - eg only one ExpBufGetSeg needed */ | |
586 | { | |
587 | srcPtr = ExpBufGetSeg (b, &gotLen); | |
588 | memcpy (dst + totalGotLen, srcPtr, gotLen); | |
589 | ||
590 | totalGotLen += gotLen; | |
591 | ||
592 | if (totalGotLen >= len) | |
593 | return totalGotLen; | |
594 | ||
595 | if (gotLen == 0) /* eod */ | |
596 | { | |
597 | (*b)->readError = 1; | |
598 | return totalGotLen; | |
599 | } | |
600 | ||
601 | gotLen = len - totalGotLen; | |
602 | } | |
603 | ||
604 | /* not reached */ | |
605 | ||
606 | } /* ExpBufCopy */ | |
607 | ||
608 | ||
609 | /* | |
610 | * advance the curr ptr in the given buffer over the next | |
611 | * len bytes | |
612 | */ | |
613 | void | |
614 | ExpBufSkip PARAMS ((b, len), | |
615 | ExpBuf **b _AND_ | |
616 | unsigned long int len) | |
617 | { | |
618 | unsigned long int lenRemaining; | |
619 | ||
620 | lenRemaining = len; | |
621 | while ((len > 0) && ExpBufGetSeg (b, &lenRemaining)) | |
622 | { | |
623 | len -= lenRemaining; | |
624 | ||
625 | if (lenRemaining == 0) | |
626 | { | |
627 | (*b)->readError = 1; | |
628 | return; | |
629 | } | |
630 | ||
631 | lenRemaining = len; | |
632 | } | |
633 | } /* ExpBufSkip */ | |
634 | ||
635 | ||
636 | /* READ | |
637 | * returns a ptr to the next "len" bytes (contiguous). | |
638 | * if "len" is greater than the available contiguous bytes | |
639 | * len is set the the number of contig. bytes the returned | |
640 | * ptr references. Subsequent call to ExpBufGetSeg or other ExpBufGet | |
641 | * routines will return ptrs to the following bytes (ie curr is advanced). | |
642 | * Changes *b to pt to the next buffer and sets curr for the | |
643 | * that buffer to dataStart if the current one has been totally read. | |
644 | * | |
645 | * if the value returned in the len param is zero or the | |
646 | * returned char * is NULL then at end of data (eod) | |
647 | * | |
648 | */ | |
649 | ||
650 | char* | |
651 | ExpBufGetSeg PARAMS ((b, len), | |
652 | ExpBuf **b _AND_ | |
653 | unsigned long int *len) | |
654 | { | |
655 | int bytesLeft; | |
656 | char *retVal; | |
657 | ||
658 | if (ExpBufAtEod (*b)) | |
659 | { | |
660 | *len = 0; | |
661 | return NULL; | |
662 | } | |
663 | ||
664 | bytesLeft = (*b)->dataEnd - (*b)->curr; | |
665 | retVal = (*b)->curr; | |
666 | ||
667 | /* check for "buffer fault" */ | |
668 | if (bytesLeft <= *len) | |
669 | { | |
670 | *len = bytesLeft; | |
671 | ||
672 | if ((*b)->next != NULL) | |
673 | { | |
674 | *b = (*b)->next; | |
675 | ||
676 | /* get next buffer with valid data */ | |
677 | while (((*b)->next != NULL) && ExpBufHasNoData (*b)) | |
678 | *b = (*b)->next; | |
679 | ||
680 | /* reset current pointer to beggining of data if nec */ | |
681 | (*b)->curr = (*b)->dataStart; | |
682 | } | |
683 | else | |
684 | (*b)->curr += *len; | |
685 | } | |
686 | else | |
687 | (*b)->curr += *len; | |
688 | ||
689 | return retVal; | |
690 | ||
691 | } /* ExpBufGetSeg */ | |
692 | ||
693 | ||
694 | ||
695 | /* | |
696 | * WRITE | |
697 | * Copies len bytes from the data pointer into the given buffer | |
698 | * | |
699 | * FILLS EXP_BUFFERS BACKWARDS! from the end of the data to the beginning | |
700 | * LINKS BUFFERS BACKWARDS! if a buf is full it allocs another an | |
701 | * puts it at the HEAD of the buffer list | |
702 | * | |
703 | * changes *b to pt to the new "prev" buffer if the current one | |
704 | * has been totally filled | |
705 | * Rvs is for REVERSE! | |
706 | * | |
707 | * modifies the dataStart pointer to reflect the new data | |
708 | */ | |
709 | ||
710 | void | |
711 | ExpBufPutSegRvs PARAMS ((b, data, len), | |
712 | ExpBuf **b _AND_ | |
713 | char *data _AND_ | |
714 | unsigned long int len) | |
715 | { | |
716 | int bytesLeft; | |
717 | ExpBuf *buf; | |
718 | char *dataPtr; | |
719 | ||
720 | buf = *b; | |
721 | ||
722 | if (buf->writeError) | |
723 | return; | |
724 | ||
725 | bytesLeft = buf->dataStart - buf->blkStart; | |
726 | dataPtr = data + len; /* pts to end of data to be written */ | |
727 | ||
728 | /* optimize fast path */ | |
729 | ||
730 | do | |
731 | { | |
732 | if (bytesLeft > len) /* enough room in this buffer for write */ | |
733 | { | |
734 | buf->dataStart -= len; | |
735 | memcpy (buf->dataStart, data, len); | |
736 | break; /* this is the normal exit from this loop */ | |
737 | } | |
738 | else | |
739 | { | |
740 | /* | |
741 | * going to fill this buffer completely, | |
742 | * so alloc other one (only if one is not | |
743 | * already linked in) | |
744 | */ | |
745 | dataPtr = dataPtr - bytesLeft; | |
746 | buf->dataStart = buf->blkStart; | |
747 | memcpy (buf->dataStart, dataPtr, bytesLeft); | |
748 | ||
749 | len -= bytesLeft; | |
750 | ||
751 | if (buf->prev == NULL) | |
752 | { | |
753 | /* alloc & insert new buf at head of buffer list */ | |
754 | buf = ExpBufAllocBufAndData(); | |
755 | ||
756 | if (buf == NULL) | |
757 | { | |
758 | (*b)->writeError = 1; | |
759 | return; | |
760 | } | |
761 | ||
762 | buf->next = *b; | |
763 | (*b)->prev = buf; | |
764 | } | |
765 | else | |
766 | buf = buf->prev; | |
767 | ||
768 | *b = buf; /* update head of list */ | |
769 | ||
770 | bytesLeft = buf->dataStart - buf->blkStart; | |
771 | } | |
772 | } | |
773 | while (1); | |
774 | ||
775 | /* not reached */ | |
776 | ||
777 | } /* ExpBufPutSegRvs */ | |
778 | ||
779 | ||
780 | ||
781 | /* | |
782 | * returns the next byte and advances the curr ptr by one. | |
783 | * sets the readError flag if there is no byte to read | |
784 | * (ie at end of data) | |
785 | */ | |
786 | unsigned char | |
787 | ExpBufGetByte PARAMS ((b), | |
788 | ExpBuf **b) | |
789 | { | |
790 | unsigned char retVal; | |
791 | ||
792 | ||
793 | if (ExpBufAtEod (*b)) | |
794 | { | |
795 | (*b)->readError = 1; | |
796 | return (unsigned char)0; | |
797 | } | |
798 | ||
799 | retVal = *(*b)->curr++; | |
800 | ||
801 | /* "buffer fault" - if end of this buf, go on to next, if any */ | |
802 | if (ExpBufAtEod (*b) && ((*b)->next != NULL)) | |
803 | { | |
804 | *b = (*b)->next; | |
805 | ||
806 | /* get next buffer with valid data */ | |
807 | while (((*b)->next != NULL) && ExpBufHasNoData (*b)) | |
808 | *b = (*b)->next; | |
809 | ||
810 | /* reset current pointer to beggining of data if nec */ | |
811 | (*b)->curr = (*b)->dataStart; | |
812 | } | |
813 | ||
814 | return retVal; | |
815 | ||
816 | } /* ExpBufGetByte */ | |
817 | ||
818 | ||
819 | /* WRITE | |
820 | * Puts a single octet into the buffer | |
821 | * writes in reverse. | |
822 | * allocates new buffers as nec - may change | |
823 | * (*b) to new buffer since writing backwards | |
824 | */ | |
825 | void | |
826 | ExpBufPutByteRvs PARAMS ((b, byte), | |
827 | ExpBuf **b _AND_ | |
828 | unsigned char byte) | |
829 | { | |
830 | ExpBuf *new; | |
831 | ||
832 | if ((*b)->writeError) | |
833 | return; | |
834 | ||
835 | *(--(*b)->dataStart) = byte; | |
836 | ||
837 | /* | |
838 | * check if buffer is full and alloc new one if nec | |
839 | * and insert it before this one since writing backwards | |
840 | */ | |
841 | if (ExpBufFull (*b)) | |
842 | { | |
843 | if ((*b)->prev == NULL) | |
844 | { | |
845 | /* | |
846 | * no prev buf so alloc & insert | |
847 | * new buf as head of buffer list | |
848 | */ | |
849 | new = ExpBufAllocBufAndData(); | |
850 | if (new == NULL) | |
851 | { | |
852 | (*b)->writeError = 1; | |
853 | return; | |
854 | } | |
855 | ||
856 | new->next = *b; | |
857 | (*b)->prev = new; | |
858 | *b = new; | |
859 | } | |
860 | else | |
861 | { | |
862 | (*b) = (*b)->prev; | |
863 | ExpBufResetInWriteRvsMode (*b); | |
864 | } | |
865 | ||
866 | } | |
867 | } /* ExpBufPutByteRvs */ | |
868 | ||
869 | ||
870 | void | |
871 | ExpBufCopyToFile PARAMS ((b, f), | |
872 | ExpBuf *b _AND_ | |
873 | FILE *f) | |
874 | { | |
875 | long int writeLen; | |
876 | ||
877 | b = ExpBufListFirstBuf (b); | |
878 | ||
879 | for ( ; b != NULL; b = ExpBufNext (b)) | |
880 | { | |
881 | writeLen = fwrite (ExpBufDataPtr (b), sizeof (char), ExpBufDataSize (b), f); | |
882 | ||
883 | if (writeLen != ExpBufDataSize (b)) | |
884 | fprintf (stderr, "ExpBufCopyToFile: error during writing\n"); | |
885 | } | |
886 | } | |
887 | ||
888 | #else /* !USE_EXP_BUF */ | |
889 | ||
890 | #ifdef __alpha | |
891 | static void dummy() | |
892 | { | |
893 | } | |
894 | #endif | |
895 | ||
896 | #endif /* USE_EXP_BUF */ |