📄 exp_buf.c
字号:
/* * puts the given data in a buffer and sets it up for reading * the data. This results in a "full" buffer with a data * blk size of given data's len */voidExpBufInstallDataInBuf PARAMS( ( buf, data, len),ExpBuf* buf _AND_char* data _AND_unsigned long int len){ buf->readError = 0; buf->writeError = 0; buf->blkStart = buf->dataStart = buf->curr = data; buf->next = NULL; buf->prev = NULL; buf->blkEnd = buf->dataEnd = data + len;} /* ExpBufInstallDataInBuf *//* Buf reading and writing routines follow *//* READ * returns the next byte to be read without * advancing the pointer. No check for end of * data - this is lame */unsigned charExpBufPeekByte PARAMS( (b),ExpBuf** b){ if ((*b)->curr == (*b)->dataEnd) (*b)->readError = 1; return(*(*b)->curr);} /* ExpBufPeek *//* READ * copy the next len chars in the buffer to the given * dst char string. The curr ptr in the buffer is advanced * appropriately */intExpBufCopy PARAMS( (dst, b, len),char* dst _AND_ExpBuf** b _AND_unsigned long int len){ unsigned long int gotLen; int totalGotLen = 0; char* srcPtr; gotLen = len; while (1) /* optimize std path - eg only one ExpBufGetSeg needed */ { srcPtr = ExpBufGetSeg(b, &gotLen); memcpy(dst + totalGotLen, srcPtr, gotLen); totalGotLen += gotLen; if (totalGotLen >= len) return(totalGotLen); if (gotLen == 0) /* eod */ { (*b)->readError = 1; return(totalGotLen); } gotLen = len - totalGotLen; } /* not reached */} /* ExpBufCopy *//* * advance the curr ptr in the given buffer over the next * len bytes */voidExpBufSkip PARAMS( (b, len),ExpBuf** b _AND_unsigned long int len){ unsigned long int lenRemaining; lenRemaining = len; while ((len > 0) && ExpBufGetSeg(b, &lenRemaining)) { len -= lenRemaining; if (lenRemaining == 0) { (*b)->readError = 1; return; } lenRemaining = len; }} /* ExpBufSkip *//* READ * returns a ptr to the next "len" bytes (contiguous). * if "len" is greater than the available contiguous bytes * len is set the the number of contig. bytes the returned * ptr references. Subsequent call to ExpBufGetSeg or other ExpBufGet * routines will return ptrs to the following bytes (ie curr is advanced). * Changes *b to pt to the next buffer and sets curr for the * that buffer to dataStart if the current one has been totally read. * * if the value returned in the len param is zero or the * returned char* is NULL then at end of data (eod) * */char*ExpBufGetSeg PARAMS( (b, len),ExpBuf** b _AND_unsigned long int* len){ int bytesLeft; char* retVal; if (ExpBufAtEod(*b)) { *len = 0; return(NULL); } bytesLeft = (*b)->dataEnd - (*b)->curr; retVal = (*b)->curr; /* check for "buffer fault" */ if ( bytesLeft <= *len) { *len = bytesLeft; if ((*b)->next != NULL) { *b = (*b)->next; /* get next buffer with valid data */ while ( ((*b)->next != NULL) && ExpBufHasNoData(*b) ) *b = (*b)->next; /* reset current pointer to beggining of data if nec */ (*b)->curr = (*b)->dataStart; } else (*b)->curr += *len; } else (*b)->curr += *len; return(retVal); } /* ExpBufGetSeg *//* * WRITE * Copies len bytes from the data pointer into the given buffer * * FILLS EXP_BUFFERS BACKWARDS! from the end of the data to the beginning * LINKS BUFFERS BACKWARDS! if a buf is full it allocs another an * puts it at the HEAD of the buffer list * * changes *b to pt to the new "prev" buffer if the current one * has been totally filled * Rvs is for REVERSE! * * modifies the dataStart pointer to reflect the new data */voidExpBufPutSegRvs PARAMS( (b, data, len),ExpBuf** b _AND_char* data _AND_unsigned long int len){ int bytesLeft; ExpBuf* buf; char* dataPtr; buf = *b; if (buf->writeError) return; bytesLeft = buf->dataStart - buf->blkStart; dataPtr = data + len; /* pts to end of data to be written */ /* optimize fast path */ do { if (bytesLeft > len) /* enough room in this buffer for write */ { buf->dataStart -= len; memcpy(buf->dataStart, data, len); break; /* this is the normal exit from this loop */ } else { /* * going to fill this buffer completely, * so alloc other one (only if one is not * already linked in) */ dataPtr = dataPtr - bytesLeft; buf->dataStart = buf->blkStart; memcpy(buf->dataStart, dataPtr, bytesLeft); len -= bytesLeft; if (buf->prev == NULL) { /* alloc & insert new buf at head of buffer list */ buf = ExpBufAllocBufAndData(); if (buf == NULL) { (*b)->writeError = 1; return; } buf->next = *b; (*b)->prev = buf; } else buf = buf->prev; *b = buf; /* update head of list */ bytesLeft = buf->dataStart - buf->blkStart; } } while (1); /* not reached */} /* ExpBufPutSegRvs *//* * returns the next byte and advances the curr ptr by one. * sets the readError flag if there is no byte to read * (ie at end of data) */unsigned charExpBufGetByte PARAMS( (b),ExpBuf** b){ unsigned char retVal; if (ExpBufAtEod(*b)) { (*b)->readError = 1; return((unsigned char)0); } retVal = *(*b)->curr++; /* "buffer fault" - if end of this buf, go on to next, if any */ if ( ExpBufAtEod(*b) && ((*b)->next != NULL)) { *b = (*b)->next; /* get next buffer with valid data */ while ( ((*b)->next != NULL) && ExpBufHasNoData(*b) ) *b = (*b)->next; /* reset current pointer to beggining of data if nec */ (*b)->curr = (*b)->dataStart; } return(retVal); } /* ExpBufGetByte *//* WRITE * Puts a single octet into the buffer * writes in reverse. * allocates new buffers as nec - may change * (*b) to new buffer since writing backwards */voidExpBufPutByteRvs PARAMS( (b, byte),ExpBuf** b _AND_unsigned char byte){ ExpBuf* new; if ((*b)->writeError) return; *(--(*b)->dataStart) = byte; /* * check if buffer is full and alloc new one if nec * and insert it before this one since writing backwards */ if (ExpBufFull(*b)) { if ((*b)->prev == NULL) { /* * no prev buf so alloc & insert * new buf as head of buffer list */ new = ExpBufAllocBufAndData(); if (new == NULL) { (*b)->writeError = 1; return; } new->next = *b; (*b)->prev = new; *b = new; } else { (*b) = (*b)->prev; ExpBufResetInWriteRvsMode(*b); } }} /* ExpBufPutByteRvs */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -