BZip2Stream.st
author Stefan Vogel <sv@exept.de>
Tue, 06 May 2003 18:19:20 +0200
changeset 1195 9d887847d1b6
parent 1193 7688148ec90c
child 1196 bba6d37ed88b
permissions -rw-r--r--
Add BZipStream and ZipStream

"{ Package: 'stx:libbasic2' }"

CompressionStream subclass:#BZipStream
	instanceVariableNames:''
	classVariableNames:''
	poolDictionaries:''
	category:'System-Compress'
!

!BZipStream primitiveDefinitions!
%{

/*
 * includes, defines, structure definitions
 * and typedefs come here.
 */

#include "bzlib/bzlib.h"

typedef enum {
	  e_opmode_unspecified          /* processing done */
	, e_opmode_deflate              /* running deflate */
	, e_opmode_inflate              /* running inflate */
} e_opmode;

typedef struct {
	bz_stream       stream;         /* pointer to the external in -stream */
	char *          in_ref;         /* size    of the external in -stream */
	char *          out_ref;        /* pointer to the external out-stream */
	unsigned int    out_total;      /* size    of the external out-stream */

	e_opmode        op_mode;        /* current operational mode */
} zstream_s;

%}
! !


!BZipStream methodsFor:'low level'!

zclose
    "low level close of the zip stream
    "
%{
    OBJ _zstreamObj = __INST( zstream );

    if( _zstreamObj != nil )
    {
	zstream_s * _zstream = (zstream_s *) __externalBytesAddress( _zstreamObj );

	__INST(zstream) = nil;

	if( _zstream->stream.state != NULL )
	{
	    if( _zstream->op_mode == e_opmode_inflate )
		BZ2_bzDecompressEnd( & _zstream->stream );
	    else
		BZ2_bzCompressEnd( & _zstream->stream );
	}
	free( _zstream );
    }
%}.
!

zdeflate
    "low level - deflate
    "
    |errorNo|

    errorNo := nil.

%{
    OBJ _zstreamObj = __INST( zstream );

    if( _zstreamObj != nil )
    {
	int          _errorNo, _action;
	unsigned int _bfsize;
	zstream_s *  _zstream = (zstream_s *) __externalBytesAddress( _zstreamObj );

	if( _zstream->op_mode != e_opmode_deflate )
	    RETURN( nil );

	_bfsize = _zstream->out_total;

	if( _zstream->stream.state == NULL )
	{
	    _zstream->op_mode = e_opmode_unspecified;
	    RETURN( nil );
	}
	_action = (__INST(hitEOF) == true) ? BZ_FINISH : BZ_RUN;        

	_zstream->stream.avail_out = _bfsize;
	_zstream->stream.next_out  = _zstream->out_ref;
        
	_errorNo = BZ2_bzCompress( & _zstream->stream, _action );

	if( _errorNo == BZ_STREAM_END )
	{
	    _zstream->stream.avail_in = 0;
	    _zstream->stream.next_in  = NULL;
	    _errorNo = BZ2_bzCompressEnd( & _zstream->stream );
	}

	if(   (_errorNo == BZ_OK)
	   || (_errorNo == BZ_RUN_OK)
	   || (_errorNo == BZ_FINISH_OK)
	  )
	{
	    if(   (_zstream->stream.avail_out != _bfsize)
	       || (_zstream->stream.avail_in  != 0)
	      )
	      RETURN( true );

	    RETURN( false );
	}
	errorNo = __MKSMALLINT( _errorNo );
    }
%}.
    errorNo ifNil:[
	zstream ifNil:[self errorNotOpen].
	self invalidArguments.
    ].
    self zerror:errorNo.
!

zdeflateInit
    "low level - open for reading
    "
    |errorNo blockSize100k workFactor|

    errorNo       := nil.
    blockSize100k := BlockSize.
    workFactor    := 30.
%{
    OBJ _zstreamObj = __INST( zstream );

    if( (_zstreamObj != nil) && __bothSmallInteger(blockSize100k, workFactor) )
    {
	int         _errorNo;
	zstream_s * _zstream = (zstream_s *) __externalBytesAddress( _zstreamObj );

	_zstream->op_mode = e_opmode_deflate;

	_errorNo = BZ2_bzCompressInit( & _zstream->stream
				     , __intVal( blockSize100k ), 0, __intVal( workFactor ) );

	if( _errorNo == BZ_OK )
	    RETURN( self );

	errorNo = __MKSMALLINT( _errorNo );
    }
%}.
    errorNo ifNil:[
	zstream ifNil:[ self errorNotOpen ].
	self invalidArguments .
    ].
    self zerror:errorNo.
!

zget_avail_out
    "low level - get the number of available out bytes
    "
%{
    OBJ _zstreamObj = __INST( zstream );

    if( _zstreamObj != nil )
    {
	unsigned int _count;
	zstream_s *  _zstream = (zstream_s *) __externalBytesAddress( _zstreamObj );

	_count = _zstream->out_total - _zstream->stream.avail_out;

	RETURN( __MKSMALLINT (_count) );
    }
%}.
    self errorNotOpen.
!

zinflate
    "low level - inflate
    "
    |errorNo|

    errorNo := nil.
%{
    OBJ _zstreamObj = __INST( zstream );

    if( _zstreamObj != nil )
    {
	int         _errorNo, _count;
	zstream_s * _zstream;

	_zstream = (zstream_s *) __externalBytesAddress( _zstreamObj );

	if( _zstream->op_mode != e_opmode_inflate )
	    RETURN( nil );

	if( _zstream->stream.state == NULL )
	{
	    _zstream->op_mode = e_opmode_unspecified;
	    RETURN( nil );
	}
	if( _zstream->stream.avail_in == 0 )
	    RETURN( __MKSMALLINT (0) );

	_zstream->stream.avail_out = _zstream->out_total;
	_zstream->stream.next_out  = _zstream->out_ref;

	_errorNo = BZ2_bzDecompress( & _zstream->stream );

	if( _errorNo == BZ_STREAM_END )
	    _errorNo = BZ2_bzDecompressEnd( & _zstream->stream );

	if( _errorNo == BZ_OK )
	{
	    _count = _zstream->out_total - _zstream->stream.avail_out;

	    RETURN( __MKSMALLINT (_count) );
	}
	errorNo = __MKSMALLINT( _errorNo );
    }
%}.
    errorNo ifNil:[ self errorNotOpen ].
    self zerror:errorNo.
!

zinflateInit
    "low level - inflateInit
    "
    |errorNo|

    errorNo := nil.

%{
    OBJ _zstreamObj = __INST( zstream );

    if( _zstreamObj != nil )
    {
	int         _errorNo;
	zstream_s * _zstream = (zstream_s *) __externalBytesAddress( _zstreamObj );

	_zstream->op_mode = e_opmode_inflate;
	_errorNo = BZ2_bzDecompressInit( & _zstream->stream, 0, 1 );

	if( _errorNo == BZ_OK )
	    RETURN( self );

	_zstream->stream.avail_in = 0;
	errorNo = __MKSMALLINT( _errorNo );
    }
%}.
    errorNo ifNil:[ self errorNotOpen ].
    self zerror:errorNo.
!

zopen
    "low level - opens the zip stream
    "
    |outTotal|

    outTotal := outputBytes size.
%{
    zstream_s * _zstream = (zstream_s *) malloc( sizeof(zstream_s) );

    if( _zstream )
    {
	OBJ     _zobj   = __MKEXTERNALADDRESS( _zstream );
	OBJ     _outObj = __INST( outputBytes );
	OBJ     _inpObj = __INST( inputBytes  );

	_zstream->in_ref           = (char *) __externalBytesAddress( _inpObj );
	_zstream->stream.next_in   = NULL;
	_zstream->stream.avail_in  = 0;
	_zstream->stream.total_in_lo32  = 0;
	_zstream->stream.total_in_hi32  = 0;

	_zstream->out_total        = __intVal( outTotal );
	_zstream->out_ref          = (char *) __externalBytesAddress( _outObj );
	_zstream->stream.next_out  = _zstream->out_ref;
	_zstream->stream.avail_out = _zstream->out_total;

	_zstream->stream.total_out_lo32 = 0;
	_zstream->stream.total_out_hi32 = 0;

	_zstream->stream.bzalloc   = 0;
	_zstream->stream.bzfree    = 0;
	_zstream->stream.opaque    = 0;

	_zstream->op_mode          = e_opmode_unspecified;

	__INST (zstream) = _zobj;
	__STORE(self, _zobj);
    }
%}.
!

zset_avail_in:count
    "set the 'avail_in'
    "
%{
    OBJ _zstreamObj = __INST( zstream );

    if( (_zstreamObj != nil) && __isSmallInteger(count) )
    {
	int         _count;
	zstream_s * _zstream = (zstream_s *) __externalBytesAddress( _zstreamObj );

	if( (_count = __intVal( count )) > 0 )
	{
	    char * _in_ref = _zstream->in_ref;

	    _zstream->stream.avail_in = _count;
	    _zstream->stream.next_in  = _in_ref;
	} else {
	    _zstream->stream.avail_in = 0;
	    _zstream->stream.next_in  = NULL;
	}
	RETURN( self );
    }
%}.
    zstream ifNil:[ self errorNotOpen ].
    self invalidArguments.
! !

!BZipStream class methodsFor:'documentation'!

version
    ^ '$Header: /cvs/stx/stx/libbasic2/BZip2Stream.st,v 1.5 2003-05-06 16:19:20 stefan Exp $'
! !