2 * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved.
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
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.
19 #if defined (USE_EXP_BUF) || defined (USE_GEN_BUF)
21 * .../c-lib/src/exp-buf.c - buffer routines for the buffer structure
24 * --------- ----------
25 * | ExpBuf |<------>| ExpBuf |<------> ...ExpBufs
27 * ---------- | ---------- |
39 * | dataStart |-----------
40 * | dataEnd |-------- |
44 * | blkStart |=====|=|==|==>--------------------------
45 * | blkEnd |--- | | | | | (each line
46 * -------------- | | | | | | reps a byte
47 * | | | |-->| - - - - - - - - - - - -| diff in addr)
52 * | | | - - - - - - - - - - - -|
53 * | |----->|(one byte after last valid data byte)
55 * | --------------------------
56 * |-----------> (one byte after last byte in data blk)
59 * readError - set to non-zero to indicate attempt to read past end of
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.
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)
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)
89 * Copyright (C) 1992 Michael Sample and the University of British Columbia
91 * This library is free software; you can redistribute it and/or
92 * modify it provided that this copyright/license information is retained
95 * If you modify this file, you must clearly indicate your changes.
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.
101 * $Header: /cvs/Darwin/src/live/Security/SecuritySNACCRuntime/c-lib/src/exp-buf.c,v 1.1.1.1 2001/05/18 23:14:08 mb Exp $
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
106 * Revision 1.2 2001/05/05 00:59:25 rmurphy
107 * Adding darwin license headers
109 * Revision 1.1.1.1 1999/03/16 18:06:32 aram
110 * Originals from SMIME Free Library.
112 * Revision 1.2 1995/07/27 09:05:29 rj
113 * merged type table routines and code used by its gen-bufs.
115 * changed `_' to `-' in file names.
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.
122 #include "asn-config.h"
127 /* default buffer data block size (used when allocating) */
128 unsigned long expBufDataBlkSizeG
= 1024;
131 #if defined (DEBUG) || defined (USE_GEN_BUF) /* otherwise macros */
136 * casts are used to overcome void * - ExpBuf * conflict
137 * be careful if you modify param lists etc.
139 static struct GenBuf expBufOpsG
=
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
,
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
166 PutExpBufInGenBuf
PARAMS ((eb
, gb
),
170 *gb
= expBufOpsG
; /* structure assignemnt */
171 gb
->bufInfo
= &gb
->spare
; /* handle to expbuf */
173 } /* PutExpBufInGenBuf */
176 * sets the size of the data block to attach to
177 * an ExpBuf when allocating a new one
180 ExpBufInit
PARAMS ((dataBlkSize
),
181 unsigned long dataBlkSize
)
183 expBufDataBlkSizeG
= dataBlkSize
;
187 * Allocates and returns an uninitialized ExpBuf with
188 * no a data attached.
193 return (ExpBuf
*)malloc (sizeof (ExpBuf
));
197 ExpBufFreeBuf
PARAMS ((ptr
),
206 return (char*)malloc (expBufDataBlkSizeG
);
210 ExpBufFreeData
PARAMS ((ptr
),
217 ExpBufFreeBufAndData
PARAMS ((b
),
220 ExpBufFreeData ((b
)->blkStart
);
222 } /* ExpBufFreeBufAndData */
225 ExpBufNext
PARAMS ((b
),
232 ExpBufPrev
PARAMS ((b
),
239 ExpBufReadError
PARAMS ((b
),
242 return (*b
)->readError
;
243 } /* ExpBufReadError */
246 ExpBufWriteError
PARAMS ((b
),
249 return (*b
)->writeError
;
250 } /* ExpBufWriteError */
253 * set curr ptr used in reads to the first byte
257 ExpBufResetInReadMode
PARAMS ((b
),
260 b
->curr
= b
->dataStart
;
262 b
->writeError
= 1; /* catch wrong mode errors */
266 * sets dataStart to end of buffer
267 * so following writes (backward)
268 * over-write any existing data associated with
272 ExpBufResetInWriteRvsMode
PARAMS ((b
),
275 b
->dataEnd
= b
->dataStart
= b
->blkEnd
;
277 b
->readError
= 1; /* catch wrong mode errors */
282 * returns true if no more data can be read from
283 * the given buffer. only valid when buffer in read (fwd)
287 ExpBufAtEod
PARAMS ((b
),
290 return b
->curr
== b
->dataEnd
;
295 * returns true if no more reverse writes can be done
296 * to the buffer. Only valid when buffers in reverse
300 ExpBufFull
PARAMS ((b
),
303 return (b
)->dataStart
== (b
)->blkStart
;
308 * returns true if the given buffer has no
309 * valid data in it's data block
312 ExpBufHasNoData
PARAMS ((b
),
315 return b
->dataStart
== b
->dataEnd
;
320 * returns the number of valid data bytes in the
321 * given buffer's data block
324 ExpBufDataSize
PARAMS ((b
),
327 return b
->dataEnd
- b
->dataStart
;
331 * returns size of data block that is attached to
335 ExpBufDataBlkSize
PARAMS ((b
),
338 return b
->blkEnd
- b
->blkStart
;
342 * returns a ptr the beginning of the valid data of
344 * returns NULL is there is no valid data.
347 ExpBufDataPtr
PARAMS ((b
),
350 if (ExpBufHasNoData (b
))
356 #endif /* DEBUG || USE_EXP_BUF */
360 * returns last ExpBuf in a list of bufs.
361 * The given buf can be any buf in the list.
364 ExpBufListLastBuf
PARAMS ((b
),
367 for (; b
->next
!= NULL
; b
= b
->next
)
373 * returns first buf in a list of bufs .
374 * The given buf can be any buf in the list
377 ExpBufListFirstBuf
PARAMS ((b
),
380 for (; b
->prev
!= NULL
; b
= b
->prev
)
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.
392 ExpBufAllocBufAndData()
396 retVal
= ExpBufAllocBuf();
401 retVal
->readError
= 0;
402 retVal
->writeError
= 0;
403 retVal
->blkStart
= ExpBufAllocData();
405 if (retVal
->blkStart
== NULL
)
407 ExpBufFreeBuf (retVal
);
413 retVal
->curr
= retVal
->blkEnd
= retVal
->dataStart
= retVal
->dataEnd
=
414 retVal
->blkStart
+ expBufDataBlkSizeG
;
417 } /* ExpBufAllocBufAndData */
421 * Frees ExpBuf's and associated data blocks after
422 * after (next ptr) and including the given buffer, b.
425 ExpBufFreeBufAndDataList
PARAMS ((b
),
433 ExpBufFreeBufAndData (b
);
436 } /* ExpBufFreeBufAndDataList */
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
445 ExpBufInstallDataInBuf
PARAMS ((buf
, data
, len
),
448 unsigned long int len
)
452 buf
->blkStart
= buf
->dataStart
= buf
->curr
= data
;
455 buf
->blkEnd
= buf
->dataEnd
= data
+ len
;
456 } /* ExpBufInstallDataInBuf */
460 /* Buf reading and writing routines follow */
463 * returns the next byte to be read without
464 * advancing the pointer. No check for end of
465 * data - this is lame
468 ExpBufPeekByte
PARAMS ((b
),
471 if ((*b
)->curr
== (*b
)->dataEnd
)
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).
485 * Does not change the buffer
487 * if the value returned in the len param is zero or the
488 * returned char * is NULL then at end of data.
492 ExpBufPeekSeg
PARAMS ((b
, len
),
494 unsigned long int *len
)
498 if (ExpBufAtEod (*b
))
504 /* check for "buffer fault" and adjust "peeked" len */
505 if (((*b
)->dataEnd
- (*b
)->curr
) <= *len
)
510 } /* ExpBufPeekSeg */
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.
519 ExpBufPeekCopy
PARAMS ((dst
, b
, len
),
522 unsigned long int len
)
524 unsigned long int gotLen
;
532 while (1) /* optimize std path - eg only one ExpBufGetPeekSeg needed */
534 srcPtr
= ExpBufPeekSeg (b
, &gotLen
);
535 memcpy (dst
+ totalGotLen
, srcPtr
, gotLen
);
537 totalGotLen
+= gotLen
;
539 if ((totalGotLen
>= len
) || ((*b
)->next
== NULL
))
545 if (gotLen
== 0) /* eod */
553 /* get next buffer with valid data */
554 while (((*b
)->next
!= NULL
) && ExpBufHasNoData (*b
))
557 /* reset current pointer to beggining of data if nec */
558 (*b
)->curr
= (*b
)->dataStart
;
560 gotLen
= len
- totalGotLen
;
565 } /* ExpBufPeekCopy */
570 * copy the next len chars in the buffer to the given
571 * dst char string. The curr ptr in the buffer is advanced
575 ExpBufCopy
PARAMS ((dst
, b
, len
),
578 unsigned long int len
)
580 unsigned long int gotLen
;
585 while (1) /* optimize std path - eg only one ExpBufGetSeg needed */
587 srcPtr
= ExpBufGetSeg (b
, &gotLen
);
588 memcpy (dst
+ totalGotLen
, srcPtr
, gotLen
);
590 totalGotLen
+= gotLen
;
592 if (totalGotLen
>= len
)
595 if (gotLen
== 0) /* eod */
601 gotLen
= len
- totalGotLen
;
610 * advance the curr ptr in the given buffer over the next
614 ExpBufSkip
PARAMS ((b
, len
),
616 unsigned long int len
)
618 unsigned long int lenRemaining
;
621 while ((len
> 0) && ExpBufGetSeg (b
, &lenRemaining
))
625 if (lenRemaining
== 0)
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.
645 * if the value returned in the len param is zero or the
646 * returned char * is NULL then at end of data (eod)
651 ExpBufGetSeg
PARAMS ((b
, len
),
653 unsigned long int *len
)
658 if (ExpBufAtEod (*b
))
664 bytesLeft
= (*b
)->dataEnd
- (*b
)->curr
;
667 /* check for "buffer fault" */
668 if (bytesLeft
<= *len
)
672 if ((*b
)->next
!= NULL
)
676 /* get next buffer with valid data */
677 while (((*b
)->next
!= NULL
) && ExpBufHasNoData (*b
))
680 /* reset current pointer to beggining of data if nec */
681 (*b
)->curr
= (*b
)->dataStart
;
697 * Copies len bytes from the data pointer into the given buffer
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
703 * changes *b to pt to the new "prev" buffer if the current one
704 * has been totally filled
705 * Rvs is for REVERSE!
707 * modifies the dataStart pointer to reflect the new data
711 ExpBufPutSegRvs
PARAMS ((b
, data
, len
),
714 unsigned long int len
)
725 bytesLeft
= buf
->dataStart
- buf
->blkStart
;
726 dataPtr
= data
+ len
; /* pts to end of data to be written */
728 /* optimize fast path */
732 if (bytesLeft
> len
) /* enough room in this buffer for write */
734 buf
->dataStart
-= len
;
735 memcpy (buf
->dataStart
, data
, len
);
736 break; /* this is the normal exit from this loop */
741 * going to fill this buffer completely,
742 * so alloc other one (only if one is not
745 dataPtr
= dataPtr
- bytesLeft
;
746 buf
->dataStart
= buf
->blkStart
;
747 memcpy (buf
->dataStart
, dataPtr
, bytesLeft
);
751 if (buf
->prev
== NULL
)
753 /* alloc & insert new buf at head of buffer list */
754 buf
= ExpBufAllocBufAndData();
758 (*b
)->writeError
= 1;
768 *b
= buf
; /* update head of list */
770 bytesLeft
= buf
->dataStart
- buf
->blkStart
;
777 } /* ExpBufPutSegRvs */
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)
787 ExpBufGetByte
PARAMS ((b
),
790 unsigned char retVal
;
793 if (ExpBufAtEod (*b
))
796 return (unsigned char)0;
799 retVal
= *(*b
)->curr
++;
801 /* "buffer fault" - if end of this buf, go on to next, if any */
802 if (ExpBufAtEod (*b
) && ((*b
)->next
!= NULL
))
806 /* get next buffer with valid data */
807 while (((*b
)->next
!= NULL
) && ExpBufHasNoData (*b
))
810 /* reset current pointer to beggining of data if nec */
811 (*b
)->curr
= (*b
)->dataStart
;
816 } /* ExpBufGetByte */
820 * Puts a single octet into the buffer
822 * allocates new buffers as nec - may change
823 * (*b) to new buffer since writing backwards
826 ExpBufPutByteRvs
PARAMS ((b
, byte
),
832 if ((*b
)->writeError
)
835 *(--(*b
)->dataStart
) = byte
;
838 * check if buffer is full and alloc new one if nec
839 * and insert it before this one since writing backwards
843 if ((*b
)->prev
== NULL
)
846 * no prev buf so alloc & insert
847 * new buf as head of buffer list
849 new = ExpBufAllocBufAndData();
852 (*b
)->writeError
= 1;
863 ExpBufResetInWriteRvsMode (*b
);
867 } /* ExpBufPutByteRvs */
871 ExpBufCopyToFile
PARAMS ((b
, f
),
877 b
= ExpBufListFirstBuf (b
);
879 for ( ; b
!= NULL
; b
= ExpBufNext (b
))
881 writeLen
= fwrite (ExpBufDataPtr (b
), sizeof (char), ExpBufDataSize (b
), f
);
883 if (writeLen
!= ExpBufDataSize (b
))
884 fprintf (stderr
, "ExpBufCopyToFile: error during writing\n");
888 #else /* !USE_EXP_BUF */
896 #endif /* USE_EXP_BUF */