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 >
C/C++ Source or Header  |  2014-05-19  |  6KB  |  305 lines

  1. /*
  2.  *   msgpack.c - provide "packed" file frontend
  3.  */
  4.  
  5. #include "microdot.h"
  6. #include "asyncio.h"
  7.  
  8. #define PFHSIZE MAILBFSIZE
  9.  
  10. struct pfhandle {
  11.     struct AsyncFile *file;
  12.     int offset;
  13.     int mode;
  14.     int buffpos;
  15.     int decrunchlen;
  16.     int crunchlen;
  17.     int bytesleft;
  18.     int packmode;
  19.     int buffsize;
  20.     UBYTE buffer[ PFHSIZE + 128 ];
  21. };
  22.  
  23. #define CRUNCHBITS (crunchbits[áprefs.do_packmsg - PACKMODE_INTFAST ])
  24. static ULONG crunchbits[] = {á9, 12, 15 };
  25. static UBYTE *crunchbuffer;
  26.  
  27. struct pfhandle *pf_open( struct AsyncFile *asf, int rw, int packed, int *size )
  28. {
  29.     struct pfhandle *new;
  30.  
  31.     /* Setup Crunch/Decrunch-Buffer */
  32.     if( packed && !crunchbuffer )
  33.         crunchbuffer = LibAllocPooled( miscmempool, PFHSIZE + 2048 );
  34.  
  35.     new = AllocMem( sizeof( *new ), MEMF_CLEAR | MEMF_PUBLIC );
  36.     if( !new )
  37.         return( NULL );
  38.  
  39.     new->file = asf;
  40.     new->mode = rw;
  41.     new->packmode = packed;
  42.  
  43.     if( !rw )
  44.     {
  45.         if( packed )
  46.         {
  47.             ReadAsync( asf, &new->decrunchlen, 4 );
  48. //            Printf("read decrunchlen %ld\n", new->decrunchlen );
  49.             new->buffpos = PFHSIZE + 1; /* Force fill on first read */
  50.             new->bytesleft = new->decrunchlen;
  51.             if( size )
  52.                 *size = new->decrunchlen;
  53.         }
  54.         else
  55.         {
  56.             new->bytesleft = new->decrunchlen = *size;
  57.         }
  58. //        Printf("pfopen size %ld\n", new->decrunchlen );
  59.     }
  60.     else
  61.     {
  62.         if( packed )
  63.         {
  64.             new->offset = FtellAsync( asf );
  65.             WriteAsync( asf, &new, 4 );
  66.             /* Account Decrunchlen LW */
  67.             new->crunchlen = 4;
  68.         }
  69.     }
  70.  
  71.     return( new );
  72. }
  73.  
  74. static int fillbuffer( struct pfhandle *pfh )
  75. {
  76.     struct mwheader mwh;
  77.     int rc;
  78.  
  79.     if( !pfh->bytesleft )
  80.         return( 0 );
  81.  
  82.     /*pfh->bytesleft -= 4;*/
  83.  
  84. //    Printf("fillbuffer offset %ld\n", FtellAsync( pfh->file ) );
  85.  
  86.     ReadAsync( pfh->file, &mwh, 4 );
  87.  
  88. //    Printf("fillbuffer chunksize %ld chunkreal %ld\n", mwh.chunksize, mwh.chunkreal );
  89.  
  90.     if( !mwh.chunksize )
  91.         return( 0 );
  92.     /* ungepackt */
  93.     if( !mwh.chunkreal )
  94.     {
  95.         rc = ReadAsync( pfh->file, pfh->buffer, mwh.chunksize );
  96.         if( rc != mwh.chunksize )
  97.         {
  98.             askreq( "Lesefehler: %lD statt %lD Bytes", "Weiter", rc, mwh.chunksize  );
  99.             return( 0 );
  100.         }
  101.         pfh->buffpos = 0;
  102.         pfh->bytesleft -= rc;
  103.         pfh->buffsize = rc;
  104.         return( rc );
  105.     }
  106.  
  107.     /* gepackt */
  108.     if( ( rc = ReadAsync( pfh->file, crunchbuffer, mwh.chunksize ) ) != mwh.chunksize )
  109.     {
  110.         askreq( "Lesefehler: %lD statt %lD Bytes", "Weiter", rc, mwh.chunksize  );
  111.         return( 0 );
  112.     }
  113.  
  114.     if( pfh->packmode & PIF_XPK )
  115.         rc = xpkunpack( crunchbuffer, pfh->buffer, mwh.chunksize );
  116.     else
  117.         rc = lzw_unpack( crunchbuffer, pfh->buffer );
  118.  
  119. //    Printf( "rc unpack %ld\n", rc );
  120.  
  121.     pfh->buffpos = 0;
  122.     pfh->bytesleft -= rc;
  123.     pfh->buffsize = rc;
  124.  
  125.     return( rc );
  126. }
  127.  
  128. int pf_readch( struct pfhandle *pfh )
  129. {
  130.     /* Ungepackt */
  131.     if( !pfh->packmode )
  132.     {
  133.         if( !pfh->bytesleft )
  134.             return( EOF );
  135.         pfh->bytesleft--;
  136.         return( ReadCharAsync( pfh->file ) );
  137.     }
  138.  
  139.     if( pfh->buffpos >= pfh->buffsize )
  140.     {
  141.         if( !fillbuffer( pfh ) )
  142.             return( EOF );
  143.     }
  144.     return( pfh->buffer[ápfh->buffpos++ ] );
  145. }
  146.  
  147. int pf_read( struct pfhandle *pfh, UBYTE *to, int size )
  148. {
  149.     int count = 0;
  150.     int c;
  151.  
  152.     if( !pfh->packmode )
  153.     {
  154.         size = min( size, pfh->bytesleft );
  155.         pfh->bytesleft -= size;
  156.         if( size )
  157.             return( ReadAsync( pfh->file, to, size ) );
  158.         else
  159.             return( 0 );
  160.     }
  161.  
  162.     while( size )
  163.     {
  164. /*        if( !pfh->bytesleft )
  165.             return( count );*/
  166.         c = min( size, pfh->buffsize - pfh->buffpos );
  167.         if( c > 0 )
  168.         {
  169.             CopyMem( &pfh->buffer[ápfh->buffpos ], to, c );
  170.             pfh->buffpos += c;
  171.             count += c;
  172.             to += c;
  173.             size -= c;
  174.         }
  175.         if( pfh->buffpos >= pfh->buffsize )
  176.         {
  177.             if( !fillbuffer( pfh ) )
  178.                 return( count );
  179.         }
  180.     }
  181.     return( count );
  182. }
  183.  
  184. static int writebuffer( struct pfhandle *pfh )
  185. {
  186.     struct mwheader mwh;
  187.     int bs;
  188.     int crunched = 1;
  189.  
  190. //    Printf("enter writebuffer buffpos %ld\n", pfh->buffpos );
  191.  
  192.     mwh.chunkreal = pfh->buffpos;
  193.     if( prefs.do_packmsg >= PACKMODE_XPK )
  194.         mwh.chunksize = xpkpack( pfh->buffer, crunchbuffer, pfh->buffpos );
  195.     else
  196.         mwh.chunksize = lzw_pack( pfh->buffer, crunchbuffer, pfh->buffpos, CRUNCHBITS );
  197.  
  198. //    Printf(" after pack chunksize %ld\n", mwh.chunksize );
  199.  
  200.     /* Nicht gepackt */
  201.     if( ( !mwh.chunksize ) || ( mwh.chunksize >= mwh.chunkreal && prefs.do_packmsg != PACKMODE_XPKPW ) )
  202.     {
  203.         bs = mwh.chunkreal;
  204.         mwh.chunksize = mwh.chunkreal;
  205.         mwh.chunkreal = 0;
  206.         crunched = 0;
  207.     }
  208.     else
  209.     {
  210.         bs = mwh.chunksize;
  211.     }
  212.     pfh->buffpos = 0;
  213.     if( WriteAsync( pfh->file, &mwh, 4 ) != 4 )
  214.         return( 0 );
  215.     if( WriteAsync( pfh->file, ( crunched ) ? crunchbuffer : pfh->buffer, bs ) != bs )
  216.         return( 0 );
  217.  
  218.     pfh->crunchlen += bs + 4;
  219.  
  220.     return( 1 );
  221. }
  222.  
  223. int pf_writech( struct pfhandle *pfh, int ch )
  224. {
  225.     int rc = 1;
  226.  
  227.     if( !pfh->packmode )
  228.     {
  229.         pfh->crunchlen++;
  230.         return( WriteCharAsync( pfh->file, ch ) );
  231.     }
  232.  
  233.     pfh->buffer[ápfh->buffpos++ ]á= ch;
  234.     pfh->decrunchlen++;
  235.  
  236.     if( pfh->buffpos >= PFHSIZE )
  237.         rc = writebuffer( pfh );
  238.  
  239.     return( rc );
  240. }
  241.  
  242. int pf_write( struct pfhandle *pfh, UBYTE *data, int size )
  243. {
  244.     int count = 0;
  245.     int c;
  246.  
  247.     if( !pfh->packmode )
  248.     {
  249.         count = WriteAsync( pfh->file, data, size );
  250.         pfh->crunchlen += count;
  251.     }
  252.     else
  253.     {
  254.         if( !registerinfo.serie )
  255.             return( 0 );
  256.  
  257.         /* Freie Zeichen im Buffer */
  258.         while( size )
  259.         {
  260.             c = min( size, PFHSIZE - pfh->buffpos );
  261.             if( c > 0 )
  262.             {
  263.                 CopyMem( data, &pfh->buffer[ápfh->buffpos ], c );
  264.                 pfh->buffpos += c;
  265.                 pfh->decrunchlen += c;
  266.                 count += c;
  267.                 size -= c;
  268.                 data += c;
  269.             }
  270.             if( pfh->buffpos >= PFHSIZE )
  271.                 if( !writebuffer( pfh ) ) 
  272.                     return( 0 );
  273.         }
  274.     }
  275.     return( count );
  276. }
  277.  
  278. int pf_close( struct pfhandle *pfh )
  279. {
  280.     int oldpos;
  281.  
  282.     if( pfh->packmode )
  283.     {
  284.         /* Schreiben? */
  285.         if( pfh->mode )
  286.         {
  287.             /* Flush ? */
  288.             if( pfh->buffpos )
  289.                 writebuffer( pfh );
  290.             oldpos = 0;
  291.             WriteAsync( pfh->file, &oldpos, 4 );
  292.             pfh->crunchlen += 4;
  293.             oldpos = SeekAsync( pfh->file, pfh->offset, MODE_START );
  294.             WriteAsync( pfh->file, &pfh->decrunchlen, 4 );
  295.             SeekAsync( pfh->file, oldpos, MODE_START );
  296.         }
  297.     }
  298.  
  299.     oldpos = pfh->crunchlen;
  300.  
  301.     FreeMem( pfh, sizeof( *pfh ) );
  302.  
  303.     return( oldpos );
  304. }
  305.