📄 pgpbufmod.c
字号:
/*
* pgpBufMod.c -- A Buffering Module; buffer until the first sizeAdvise
*
* Written by: Derek Atkins <warlord@MIT.EDU>
*
* $Id: pgpBufMod.c,v 1.26 1997/12/12 01:14:14 heller Exp $
*/
#include "pgpConfig.h"
#include "pgpMem.h"
#include <stdio.h>
#include <string.h>
#include "pgpDebug.h"
#include "pgpAnnotate.h"
#include "pgpFIFO.h"
#include "pgpMem.h"
#include "pgpErrors.h"
#include "pgpPipeline.h"
#include "pgpContext.h"
#include "pgpBufMod.h"
#define kPGPBufModCmdArgSize 4096
/*
* This is a magic number for use within this module. It is used to
* make sure the passed-in module is a member of this type. Just a
* little extra sanity-checking.
*
* You should set this value to some "random" 32-bit number.
*/
#define BUFMODMAGIC 0xb3ffe43d
typedef struct BufModContext
{
PGPPipeline pipe;
PGPFifoDesc const *fd;
PGPFifoContext *fifo;
PGPFifoContext *ann; /* Fifo to hold the saved annotations */
PGPPipeline *tail;
PGPByte cmdarg[kPGPBufModCmdArgSize];
unsigned cmdlen;
int scope_depth;
PGPByte writing;
DEBUG_STRUCT_CONSTRUCTOR( BufModContext )
} BufModContext;
/*
* Buffer a command at the current spot in the data stream. This is only
* called when ctx->buffering is true. What it does is find the delta
* of this command in the data fifo from the last command in order to replay
* the commands at the proper place. It saves off context->written as
* the offset and then resets the value to 0.
*
* The return value is 0 on success or an error code.
*
* Command Byte Syntax: <arglen><arg>
*/
static PGPError
bufferCommand (BufModContext *ctx, const PGPByte *arg, unsigned arglen)
{
/* Make sure the command argument fits the buffer size */
if (arglen > sizeof (ctx->cmdarg))
return kPGPError_BadParams;
if (pgpFifoWrite (ctx->fd, ctx->ann, (PGPByte *)&arglen,
sizeof (arglen)) != sizeof (arglen))
return kPGPError_OutOfMemory;
if (pgpFifoWrite (ctx->fd, ctx->ann, arg, arglen) != arglen)
return kPGPError_OutOfMemory;
return( kPGPError_NoErr );
}
/* Buffer up an annotation */
static PGPError
bufferAnnotation (BufModContext *ctx, PGPPipeline *origin, int type,
PGPByte const *string, size_t size)
{
PGPByte *arg, *argp;
PGPError retval;
PGPContextRef cdkContext;
pgpAssertAddrValid( origin, PGPPipeline );
cdkContext = origin->cdkContext;
arg = argp = (PGPByte *)
pgpContextMemAlloc( cdkContext, sizeof (origin) + sizeof (type) +
size + sizeof (size), 0);
if (!arg)
return kPGPError_OutOfMemory;
memcpy (argp, (PGPByte *)&origin, sizeof (origin));
argp += sizeof (origin);
memcpy (argp, (PGPByte *)&type, sizeof (type));
argp += sizeof (type);
memcpy (argp, (PGPByte *)&size, sizeof (size));
argp += sizeof (size);
memcpy (argp, string, size);
argp += size;
retval = bufferCommand (ctx, arg, argp-arg);
pgpContextMemFree( cdkContext, arg);
return retval;
}
static PGPError
parseAnnotation (BufModContext *ctx)
{
PGPPipeline *origin;
int type;
size_t size;
PGPByte *string, *argp = ctx->cmdarg;
PGPError retval;
PGPContextRef cdkContext = ctx->pipe.cdkContext;
pgpAssert (ctx->cmdlen >= sizeof (origin) + sizeof (type) +
sizeof (size));
pgpCopyMemory ( argp, (PGPByte *)&origin, sizeof (origin));
argp += sizeof (origin);
pgpCopyMemory ( argp, (PGPByte *)&type, sizeof (type));
argp += sizeof (type);
pgpCopyMemory ( argp, (PGPByte *)&size, sizeof (size));
argp += sizeof (size);
/* make sure we have the right number of bytes remaining */
pgpAssert (ctx->cmdlen - size == (unsigned)(argp - ctx->cmdarg));
string = (PGPByte *)pgpContextMemAlloc( cdkContext, size, 0);
if (string == NULL)
return kPGPError_OutOfMemory;
pgpCopyMemory (argp, string, size);
retval = ctx->tail->annotate (ctx->tail, origin, type, string, size);
pgpContextMemFree( cdkContext, string);
return retval;
}
/* <len><cmd> */
static PGPError
flushCommands (BufModContext *ctx)
{
PGPError error;
unsigned cmdlen = pgpFifoSize (ctx->fd, ctx->ann);
do {
if (ctx->cmdlen) {
error = parseAnnotation (ctx);
if (error)
return error;
ctx->cmdlen = 0;
}
if (cmdlen) {
if (pgpFifoRead (ctx->fd, ctx->ann,
(PGPByte *)&ctx->cmdlen,
sizeof (ctx->cmdlen)) !=
sizeof (ctx->cmdlen))
return kPGPError_FIFOReadError;
cmdlen -= sizeof (ctx->cmdlen);
if (pgpFifoRead (ctx->fd, ctx->ann, ctx->cmdarg,
ctx->cmdlen) != ctx->cmdlen)
return kPGPError_FIFOReadError;
cmdlen -= ctx->cmdlen;
}
} while (ctx->cmdlen);
return( kPGPError_NoErr );
}
static PGPError
DoFlush (BufModContext *context)
{
PGPError error = kPGPError_NoErr;
PGPByte const *ptr;
size_t retlen;
PGPSize len;
/* first, flush out any commands */
error = flushCommands (context);
if (error)
return error;
ptr = pgpFifoPeek (context->fd, context->fifo, &len);
while (len) {
retlen = context->tail->write (context->tail,
ptr, len, &error);
pgpFifoSeek (context->fd, context->fifo, retlen);
if (error)
return error;
ptr = pgpFifoPeek (context->fd, context->fifo, &len);
}
return error;
}
static PGPError
Flush (PGPPipeline *myself)
{
BufModContext *context;
PGPError error;
pgpAssert (myself);
pgpAssert (myself->magic == BUFMODMAGIC);
context = (BufModContext *)myself->priv;
pgpAssert (context);
pgpAssert (context->tail);
if (!context->writing)
return kPGPError_LazyProgrammer; /* XXX */
error = DoFlush (context);
if (error)
return error;
return context->tail->flush (context->tail);
}
static size_t
Write (PGPPipeline *myself, PGPByte const *buf, size_t size, PGPError *error)
{
BufModContext *context;
pgpAssert (myself);
pgpAssert (myself->magic == BUFMODMAGIC);
pgpAssert (error);
context = (BufModContext *)myself->priv;
pgpAssert (context);
pgpAssert (context->tail);
if (!context->writing) {
*error = kPGPError_NoErr;
return pgpFifoWrite (context->fd, context->fifo, buf, size);
}
*error = DoFlush (context);
if (*error)
return 0;
return context->tail->write (context->tail, buf, size, error);
}
static PGPError
Annotate (PGPPipeline *myself, PGPPipeline *origin, int type,
PGPByte const *string, size_t size)
{
BufModContext *context;
PGPError error;
pgpAssert (myself);
pgpAssert (myself->magic == BUFMODMAGIC);
context = (BufModContext *)myself->priv;
pgpAssert (context);
pgpAssert (context->tail);
if (!context->writing) {
/* Make sure there isn't any data buffered! */
pgpAssert (!pgpFifoSize (context->fd, context->fifo));
error = bufferAnnotation (context, origin, type, string, size);
} else
error = context->tail->annotate (context->tail, origin, type,
string, size);
if (!error)
PGP_SCOPE_DEPTH_UPDATE(context->scope_depth, type);
pgpAssert(context->scope_depth != -1);
return error;
}
static PGPError
SizeAdvise (PGPPipeline *myself, unsigned long bytes)
{
BufModContext *context;
PGPError error;
pgpAssert (myself);
pgpAssert (myself->magic == BUFMODMAGIC);
context = (BufModContext *)myself->priv;
pgpAssert (context);
pgpAssert (context->tail);
context->writing = 1;
error = DoFlush (context);
if (error)
return error;
return context->tail->sizeAdvise (context->tail, bytes);
}
static PGPError
Teardown (PGPPipeline *myself)
{
BufModContext *context;
PGPContextRef cdkContext;
pgpAssertAddrValid( myself, PGPPipeline );
cdkContext = myself->cdkContext;
pgpAssert (myself);
pgpAssert (myself->magic == BUFMODMAGIC);
context = (BufModContext *)myself->priv;
pgpAssert (context);
if (context->tail)
context->tail->teardown (context->tail);
pgpFifoDestroy (context->fd, context->ann);
pgpFifoDestroy (context->fd, context->fifo);
pgpClearMemory (context, sizeof (*context));
pgpContextMemFree( cdkContext, context);
return kPGPError_NoErr;
}
PGPPipeline **
pgpBufferModCreate (
PGPContextRef cdkContext,
PGPPipeline **head,
PGPFifoDesc const *fd)
{
PGPPipeline *mod;
BufModContext *context;
PGPFifoContext *fifo, *ann;
if (!head || !fd)
return NULL;
context = (BufModContext *)pgpContextMemAlloc( cdkContext,
sizeof (*context), kPGPMemoryMgrFlags_Clear );
if (!context)
return NULL;
mod = &context->pipe;
fifo = pgpFifoCreate (cdkContext, fd);
if (!fifo) {
pgpContextMemFree( cdkContext, context);
return NULL;
}
ann = pgpFifoCreate (cdkContext, fd);
if (!ann) {
pgpFifoDestroy (fd, fifo);
pgpContextMemFree( cdkContext, context);
return NULL;
}
mod->magic = BUFMODMAGIC;
mod->write = Write;
mod->flush = Flush;
mod->sizeAdvise = SizeAdvise;
mod->annotate = Annotate;
mod->teardown = Teardown;
mod->name = "Buffer Module";
mod->priv = context;
mod->cdkContext = cdkContext;
context->fd = fd;
context->fifo = fifo;
context->ann = ann;
context->tail = *head;
*head = mod;
return &context->tail;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -