📄 pgpbytefifo.c
字号:
/*
* Bytefifo.c - an infinitely-expandable FIFO structure for bytes.
*
* $Id: pgpByteFIFO.c,v 1.21 1998/09/14 20:49:13 hal Exp $
*/
#include "pgpConfig.h"
#include <stdio.h> /* For BUFSIZ */
#include <string.h>
#include "pgpDebug.h"
#include "pgpByteFIFO.h"
#include "pgpMem.h"
#include "pgpUsuals.h"
#include "pgpContext.h"
#if (BUFSIZ < 16384) && (PGP_MACINTOSH || PGP_WIN32)
#define kPGPFIFOPageSize 16384
#else
#define kPGPFIFOPageSize BUFSIZ
#endif
typedef struct ByteFifoPage {
struct ByteFifoPage *next;
PGPByte buf[kPGPFIFOPageSize-sizeof(struct ByteFifoPage *)];
DEBUG_STRUCT_CONSTRUCTOR( ByteFifoPage )
} ByteFifoPage;
struct PGPFifoContext {
PGPMemoryMgrRef memoryMgr;
ByteFifoPage *head, *tail;
PGPByte *putp;
PGPByte const *getp;
PGPSize pages;
PGPBoolean secure;
DEBUG_STRUCT_CONSTRUCTOR( PGPFifoContext )
};
static void
byteFifoInit(
PGPMemoryMgrRef memoryMgr,
PGPFifoContext * fifo,
PGPBoolean secure)
{
fifo->memoryMgr = memoryMgr;
fifo->head = 0;
fifo->tail = 0;
fifo->putp = 0;
fifo->getp = 0;
fifo->pages = 0;
fifo->secure = secure;
}
void
byteFifoFlush(PGPFifoContext *fifo)
{
ByteFifoPage *page;
while ((page = fifo->head) != 0) {
fifo->head = page->next;
pgpClearMemory( page, sizeof(page));
PGPFreeData( page );
}
fifo->tail = 0;
fifo->putp = 0;
fifo->getp = 0;
fifo->pages = 0;
}
PGPSize
byteFifoSize(PGPFifoContext const *fifo)
{
PGPSize space;
if (!fifo->pages)
return 0;
space = (fifo->putp - fifo->tail->buf) +
(fifo->head->buf + sizeof(fifo->head->buf) - fifo->getp);
space += (fifo->pages-1) * sizeof(fifo->head->buf);
return space - sizeof(fifo->head->buf);
}
PGPFifoContext *
byteFifoCreate( PGPContextRef context )
{
PGPFifoContext *fifo;
PGPMemoryMgrRef memoryMgr = PGPGetContextMemoryMgr( context );
fifo = (PGPFifoContext *)
PGPNewData( memoryMgr, sizeof(*fifo), 0);
if (fifo)
{
byteFifoInit( memoryMgr, fifo, FALSE);
}
return fifo;
}
PGPFifoContext *
byteFifoCreateSecure( PGPContextRef context )
{
PGPFifoContext *fifo;
PGPMemoryMgrRef memoryMgr = PGPGetContextMemoryMgr( context );
fifo = (PGPFifoContext *)
PGPNewData( memoryMgr, sizeof(*fifo), 0);
if (fifo)
{
byteFifoInit( memoryMgr, fifo, TRUE);
}
return fifo;
}
void
byteFifoDestroy(PGPFifoContext *fifo)
{
byteFifoFlush(fifo);
PGPFreeData( fifo );
}
PGPByte *
byteFifoGetSpace(PGPFifoContext *fifo, PGPSize *len)
{
PGPSize avail;
ByteFifoPage *page;
if (fifo->head) {
pgpAssert(fifo->putp);
avail = fifo->tail->buf + sizeof(fifo->tail->buf) - fifo->putp;
if (avail) {
*len = avail;
return fifo->putp;
}
}
if (fifo->secure) {
page = (ByteFifoPage *)
PGPNewSecureData( fifo->memoryMgr, sizeof(ByteFifoPage), 0);
} else {
page = (ByteFifoPage *)
PGPNewData( fifo->memoryMgr, sizeof(ByteFifoPage), 0);
}
if (!page) { /* Out of memory */
*len = 0;
return 0;
}
fifo->pages++;
if (fifo->head) {
pgpAssert(fifo->pages > 1);
fifo->tail->next = page;
} else {
pgpAssert(fifo->pages == 1);
fifo->head = page;
fifo->getp = page->buf;
}
fifo->tail = page;
page->next = 0;
*len = sizeof(fifo->head->buf);
return fifo->putp = page->buf;
}
void
byteFifoSkipSpace(PGPFifoContext *fifo, PGPSize len)
{
if (!len)
return;
pgpAssert(fifo->head);
pgpAssert(fifo->putp);
pgpAssert(len <= (PGPSize)(fifo->tail->buf + sizeof(fifo->tail->buf)
- fifo->putp));
fifo->putp += len;
}
PGPByte const *
byteFifoPeek(PGPFifoContext *fifo, PGPSize *len)
{
if (!fifo->head) {
*len = 0;
return 0; /* No bytes available */
}
pgpAssert(fifo->getp);
/* Head and tail on same page? */
if (fifo->tail == fifo->head)
*len = fifo->putp - fifo->getp;
else
*len = fifo->head->buf + sizeof(fifo->head->buf) - fifo->getp;
return *len ? fifo->getp : 0;
}
void
byteFifoSeek(PGPFifoContext *fifo, PGPSize len)
{
ByteFifoPage *page;
if (!len)
return;
pgpAssert(fifo->head);
pgpAssert(len <= (PGPSize)(fifo->head->buf + sizeof(fifo->head->buf)
- fifo->getp));
if (fifo->head == fifo->tail) {
pgpAssert(fifo->pages == 1);
pgpAssert(fifo->head->next == 0);
pgpAssert(len <= (PGPSize)(fifo->putp - fifo->getp));
if (len < (PGPSize)(fifo->putp - fifo->getp)) {
fifo->getp += len;
} else {
pgpClearMemory(fifo->head, sizeof(*fifo->head));
PGPFreeData( fifo->head);
byteFifoInit( fifo->memoryMgr, fifo, fifo->secure);
}
return;
}
pgpAssert(fifo->pages > 1);
if (len < (PGPSize)(fifo->head->buf + sizeof(fifo->head->buf)
- fifo->getp))
{
fifo->getp += len;
} else {
page = fifo->head;
fifo->head = fifo->head->next;
pgpAssert(fifo->head);
pgpClearMemory( page, sizeof(*page));
PGPFreeData( page);
fifo->pages--;
pgpAssert(fifo->pages);
fifo->getp = fifo->head->buf;
}
}
PGPSize
byteFifoWrite(PGPFifoContext *fifo, PGPByte const *buf, PGPSize len)
{
PGPSize avail;
PGPByte *ptr;
PGPSize len0 = len;
while (len) {
ptr = byteFifoGetSpace(fifo, &avail);
if (!ptr)
return len0 - len;
if (avail > len)
avail = len;
memcpy(ptr, buf, avail);
byteFifoSkipSpace(fifo, avail);
buf += avail;
len -= avail;
}
return len0;
}
PGPSize
byteFifoRead(PGPFifoContext *fifo, PGPByte *buf, PGPSize len)
{
PGPSize avail;
PGPByte const *ptr;
PGPSize len0 = len;
while (len) {
ptr = byteFifoPeek (fifo, &avail);
if (!ptr)
return len0 - len;
if (avail > len)
avail = len;
memcpy (buf, ptr, avail);
buf += avail;
len -= avail;
byteFifoSeek (fifo, avail);
}
return len0;
}
#if UNITTEST
/* Test driver */
#include <stdio.h>
static void
byteFifoDump(PGPFifoContext *fifo)
{
PGPByte const *ptr;
PGPSize avail;
while ((ptr = byteFifoPeek(fifo, &avail)) != 0) {
fwrite(ptr, 1, avail, stdout);
byteFifoSeek(fifo, avail);
}
}
int
main(int argc, char **argv)
{
PGPFifoContext fifo;
PGPByte const c = ' ';
int i, j;
byteFifoInit(&fifo);
for (i = 1; i < argc; i++) {
for (j = 1; j <= i; j++) {
byteFifoWrite(&fifo, argv[j], strlen(argv[j]));
if (i != j)
byteFifoWrite(&fifo, &c, 1);
}
printf("argv[1..%d] = (%lu) \"", i, byteFifoSize(&fifo));
byteFifoDump(&fifo);
puts("\"");
}
return 0;
}
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -