home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
back2roots/padua
/
padua.7z
/
padua
/
ftp.vapor.com
/
microdot-1
/
md1_src_02.lzx
/
msgpack.c
< prev
next >
Wrap
C/C++ Source or Header
|
2014-05-19
|
6KB
|
305 lines
/*
* msgpack.c - provide "packed" file frontend
*/
#include "microdot.h"
#include "asyncio.h"
#define PFHSIZE MAILBFSIZE
struct pfhandle {
struct AsyncFile *file;
int offset;
int mode;
int buffpos;
int decrunchlen;
int crunchlen;
int bytesleft;
int packmode;
int buffsize;
UBYTE buffer[ PFHSIZE + 128 ];
};
#define CRUNCHBITS (crunchbits[áprefs.do_packmsg - PACKMODE_INTFAST ])
static ULONG crunchbits[] = {á9, 12, 15 };
static UBYTE *crunchbuffer;
struct pfhandle *pf_open( struct AsyncFile *asf, int rw, int packed, int *size )
{
struct pfhandle *new;
/* Setup Crunch/Decrunch-Buffer */
if( packed && !crunchbuffer )
crunchbuffer = LibAllocPooled( miscmempool, PFHSIZE + 2048 );
new = AllocMem( sizeof( *new ), MEMF_CLEAR | MEMF_PUBLIC );
if( !new )
return( NULL );
new->file = asf;
new->mode = rw;
new->packmode = packed;
if( !rw )
{
if( packed )
{
ReadAsync( asf, &new->decrunchlen, 4 );
// Printf("read decrunchlen %ld\n", new->decrunchlen );
new->buffpos = PFHSIZE + 1; /* Force fill on first read */
new->bytesleft = new->decrunchlen;
if( size )
*size = new->decrunchlen;
}
else
{
new->bytesleft = new->decrunchlen = *size;
}
// Printf("pfopen size %ld\n", new->decrunchlen );
}
else
{
if( packed )
{
new->offset = FtellAsync( asf );
WriteAsync( asf, &new, 4 );
/* Account Decrunchlen LW */
new->crunchlen = 4;
}
}
return( new );
}
static int fillbuffer( struct pfhandle *pfh )
{
struct mwheader mwh;
int rc;
if( !pfh->bytesleft )
return( 0 );
/*pfh->bytesleft -= 4;*/
// Printf("fillbuffer offset %ld\n", FtellAsync( pfh->file ) );
ReadAsync( pfh->file, &mwh, 4 );
// Printf("fillbuffer chunksize %ld chunkreal %ld\n", mwh.chunksize, mwh.chunkreal );
if( !mwh.chunksize )
return( 0 );
/* ungepackt */
if( !mwh.chunkreal )
{
rc = ReadAsync( pfh->file, pfh->buffer, mwh.chunksize );
if( rc != mwh.chunksize )
{
askreq( "Lesefehler: %lD statt %lD Bytes", "Weiter", rc, mwh.chunksize );
return( 0 );
}
pfh->buffpos = 0;
pfh->bytesleft -= rc;
pfh->buffsize = rc;
return( rc );
}
/* gepackt */
if( ( rc = ReadAsync( pfh->file, crunchbuffer, mwh.chunksize ) ) != mwh.chunksize )
{
askreq( "Lesefehler: %lD statt %lD Bytes", "Weiter", rc, mwh.chunksize );
return( 0 );
}
if( pfh->packmode & PIF_XPK )
rc = xpkunpack( crunchbuffer, pfh->buffer, mwh.chunksize );
else
rc = lzw_unpack( crunchbuffer, pfh->buffer );
// Printf( "rc unpack %ld\n", rc );
pfh->buffpos = 0;
pfh->bytesleft -= rc;
pfh->buffsize = rc;
return( rc );
}
int pf_readch( struct pfhandle *pfh )
{
/* Ungepackt */
if( !pfh->packmode )
{
if( !pfh->bytesleft )
return( EOF );
pfh->bytesleft--;
return( ReadCharAsync( pfh->file ) );
}
if( pfh->buffpos >= pfh->buffsize )
{
if( !fillbuffer( pfh ) )
return( EOF );
}
return( pfh->buffer[ápfh->buffpos++ ] );
}
int pf_read( struct pfhandle *pfh, UBYTE *to, int size )
{
int count = 0;
int c;
if( !pfh->packmode )
{
size = min( size, pfh->bytesleft );
pfh->bytesleft -= size;
if( size )
return( ReadAsync( pfh->file, to, size ) );
else
return( 0 );
}
while( size )
{
/* if( !pfh->bytesleft )
return( count );*/
c = min( size, pfh->buffsize - pfh->buffpos );
if( c > 0 )
{
CopyMem( &pfh->buffer[ápfh->buffpos ], to, c );
pfh->buffpos += c;
count += c;
to += c;
size -= c;
}
if( pfh->buffpos >= pfh->buffsize )
{
if( !fillbuffer( pfh ) )
return( count );
}
}
return( count );
}
static int writebuffer( struct pfhandle *pfh )
{
struct mwheader mwh;
int bs;
int crunched = 1;
// Printf("enter writebuffer buffpos %ld\n", pfh->buffpos );
mwh.chunkreal = pfh->buffpos;
if( prefs.do_packmsg >= PACKMODE_XPK )
mwh.chunksize = xpkpack( pfh->buffer, crunchbuffer, pfh->buffpos );
else
mwh.chunksize = lzw_pack( pfh->buffer, crunchbuffer, pfh->buffpos, CRUNCHBITS );
// Printf(" after pack chunksize %ld\n", mwh.chunksize );
/* Nicht gepackt */
if( ( !mwh.chunksize ) || ( mwh.chunksize >= mwh.chunkreal && prefs.do_packmsg != PACKMODE_XPKPW ) )
{
bs = mwh.chunkreal;
mwh.chunksize = mwh.chunkreal;
mwh.chunkreal = 0;
crunched = 0;
}
else
{
bs = mwh.chunksize;
}
pfh->buffpos = 0;
if( WriteAsync( pfh->file, &mwh, 4 ) != 4 )
return( 0 );
if( WriteAsync( pfh->file, ( crunched ) ? crunchbuffer : pfh->buffer, bs ) != bs )
return( 0 );
pfh->crunchlen += bs + 4;
return( 1 );
}
int pf_writech( struct pfhandle *pfh, int ch )
{
int rc = 1;
if( !pfh->packmode )
{
pfh->crunchlen++;
return( WriteCharAsync( pfh->file, ch ) );
}
pfh->buffer[ápfh->buffpos++ ]á= ch;
pfh->decrunchlen++;
if( pfh->buffpos >= PFHSIZE )
rc = writebuffer( pfh );
return( rc );
}
int pf_write( struct pfhandle *pfh, UBYTE *data, int size )
{
int count = 0;
int c;
if( !pfh->packmode )
{
count = WriteAsync( pfh->file, data, size );
pfh->crunchlen += count;
}
else
{
if( !registerinfo.serie )
return( 0 );
/* Freie Zeichen im Buffer */
while( size )
{
c = min( size, PFHSIZE - pfh->buffpos );
if( c > 0 )
{
CopyMem( data, &pfh->buffer[ápfh->buffpos ], c );
pfh->buffpos += c;
pfh->decrunchlen += c;
count += c;
size -= c;
data += c;
}
if( pfh->buffpos >= PFHSIZE )
if( !writebuffer( pfh ) )
return( 0 );
}
}
return( count );
}
int pf_close( struct pfhandle *pfh )
{
int oldpos;
if( pfh->packmode )
{
/* Schreiben? */
if( pfh->mode )
{
/* Flush ? */
if( pfh->buffpos )
writebuffer( pfh );
oldpos = 0;
WriteAsync( pfh->file, &oldpos, 4 );
pfh->crunchlen += 4;
oldpos = SeekAsync( pfh->file, pfh->offset, MODE_START );
WriteAsync( pfh->file, &pfh->decrunchlen, 4 );
SeekAsync( pfh->file, oldpos, MODE_START );
}
}
oldpos = pfh->crunchlen;
FreeMem( pfh, sizeof( *pfh ) );
return( oldpos );
}