///////////////////////////////////////////////////////////////////////////// // Creation 23/12/2003 // // // BZ2IFACE.C // ---------- // // // Sylvain MARECHAL - sylvain.marechal1@libertysurf.fr ///////////////////////////////////////////////////////////////////////////// // // Simple wrapper to bz2 // ///////////////////////////////////////////////////////////////////////////// #include #include "bzlib.h" #include "bz2iface.h" // Private structure typedef struct _tagBz2IfaceInternal { bz_stream bzStream; // The bz2 (compression/decompression) stream PfBz2IfWrite writeCallback; // Callback called when data available void * userData; // User data int nCompression; // 0, decompression, 1->9 compression char Buffer[20480]; // Intermediate Buffer } Bz2IfaceInternal; ///////////////////////////////////////////////////////////////////////////// // // BZ2IFCREATE ///////////////////////////////////////////////////////////////////////////// // // DESCRIPTION // --Bz2IfCreate-- // // Creation of a bz2if object used to compress or decompress data // // ARGUMENTS // Argument1: int nCompression 0, decompression, 1->9, compression // Argument2: PfBz2IfWrite writeCallback called : // -when compressed data (case nCompression = 1->9) is available // -when uncompressed data (case nCompression = 0) is available // Argument3: void * userData // RETOUR/RESULTAT // Bz2Iface * // REMARQUE // Rev 23/12/2003 ////////////////////////////////////////////////////////////////////////////// Bz2Iface * Bz2IfCreate( int nCompression, PfBz2IfWrite writeCallback, void * userData ) { Bz2IfaceInternal * pbz2if; if( ! writeCallback ) return writeCallback; pbz2if = (Bz2Iface *)calloc( 1, sizeof(Bz2IfaceInternal) ); if( ! pbz2if ) return pbz2if; // Corrects eventually the parameter if( nCompression < 0 ) nCompression = 0; if( nCompression > 9 ) nCompression = 9; // Init struct pbz2if->writeCallback = writeCallback; pbz2if->userData = userData; pbz2if->nCompression = nCompression; // Compression or decompression init if( nCompression > 0) { // Compression init if( BZ2_bzCompressInit ( &(pbz2if->bzStream), nCompression, 0, 0 ) != BZ_OK ) { free( pbz2if ); return NULL; } } else { int verbosity = 0, small = 0; // Decompression init if( BZ2_bzDecompressInit ( &(pbz2if->bzStream), verbosity, small ) != BZ_OK ) { free( pbz2if ); return NULL; } } return pbz2if; } ///////////////////////////////////////////////////////////////////////////// // // BZ2IFDESTROY ///////////////////////////////////////////////////////////////////////////// // // DESCRIPTION // --Bz2IfDestroy-- // // Destroy the bz2if object // // ARGUMENTS // Argument1: Bz2Iface * pbz2ifexternal // RETOUR/RESULTAT // int // REMARQUE // Rev 23/12/2003 ////////////////////////////////////////////////////////////////////////////// int Bz2IfDestroy( Bz2Iface * pbz2ifexternal ) { Bz2IfaceInternal * pbz2if = (Bz2IfaceInternal *)pbz2ifexternal; if( ! pbz2if ) return -1; if( pbz2if->nCompression ) { BZ2_bzCompressEnd( &(pbz2if->bzStream) ); } else { BZ2_bzDecompressEnd( &(pbz2if->bzStream) ); } free( pbz2if ); return 0; } ///////////////////////////////////////////////////////////////////////////// // // BZ2IFGETDATA ///////////////////////////////////////////////////////////////////////////// // // DESCRIPTION // --Bz2IfGetData-- // // Retrieve user data // // ARGUMENTS // Argument1: Bz2Iface * pbz2ifexternal // RETOUR/RESULTAT // void * // REMARQUE // Rev 23/12/2003 ////////////////////////////////////////////////////////////////////////////// void * Bz2IfGetData( Bz2Iface * pbz2ifexternal ) { Bz2IfaceInternal * pbz2if = (Bz2IfaceInternal *)pbz2ifexternal; if( ! pbz2if ) return pbz2if; return pbz2if->userData; } ///////////////////////////////////////////////////////////////////////////// // // BZ2IFSETDATA ///////////////////////////////////////////////////////////////////////////// // // DESCRIPTION // --Bz2IfSetData-- // // Set user data // // ARGUMENTS // Argument1: Bz2Iface * pbz2ifexternal // Argument2: void * userData // RETOUR/RESULTAT // void // REMARQUE // Rev 23/12/2003 ////////////////////////////////////////////////////////////////////////////// void Bz2IfSetData( Bz2Iface * pbz2ifexternal, void * userData ) { Bz2IfaceInternal * pbz2if = (Bz2IfaceInternal *)pbz2ifexternal; if( ! pbz2if ) return; pbz2if->userData = userData; } ///////////////////////////////////////////////////////////////////////////// // // BZ2IFWRITEINTERNAL ///////////////////////////////////////////////////////////////////////////// // // DESCRIPTION // --bz2ifWriteInternal-- // // Compress data. // Internal usage only // Adataption from the BZ2_bzWrite() function // // ARGUMENTS // Argument1: Bz2IfaceInternal * pbz2if // Argument2: void*buf // Argument3: int len // RETOUR/RESULTAT // static int // REMARQUE // Rev 23/12/2003 ////////////////////////////////////////////////////////////////////////////// static int bz2ifWriteInternal(Bz2IfaceInternal * pbz2if,void*buf, int len ) { int n, n2, ret; if (len == 0) return 0; pbz2if->bzStream.avail_in = len; pbz2if->bzStream.next_in = buf; while (1) { pbz2if->bzStream.avail_out = BZ_MAX_UNUSED; pbz2if->bzStream.next_out = pbz2if->Buffer; ret = BZ2_bzCompress ( &(pbz2if->bzStream), BZ_RUN ); if (ret != BZ_RUN_OK) { return -1; } if (pbz2if->bzStream.avail_out < BZ_MAX_UNUSED) { n = BZ_MAX_UNUSED - pbz2if->bzStream.avail_out; // User callback n2 = pbz2if->writeCallback( pbz2if->userData, pbz2if->Buffer, n ); if (n != n2 ) { return -1; } } if (pbz2if->bzStream.avail_in == 0) { return 0; } } return 0; } ///////////////////////////////////////////////////////////////////////////// // // BZ2IFWRITECLOSEINTERNAL ///////////////////////////////////////////////////////////////////////////// // // DESCRIPTION // --bz2ifWriteCloseInternal-- // // Ends the process of compression // Internal usage only // Adataption from the BZ2_bzWriteClose64() function // // ARGUMENTS // Argument1: Bz2IfaceInternal * pbz2if // RETOUR/RESULTAT // static int // REMARQUE // Rev 23/12/2003 ////////////////////////////////////////////////////////////////////////////// static int bz2ifWriteCloseInternal( Bz2IfaceInternal * pbz2if ) { int n, n2, ret; while (1) { pbz2if->bzStream.avail_out = BZ_MAX_UNUSED; pbz2if->bzStream.next_out = pbz2if->Buffer; ret = BZ2_bzCompress ( &(pbz2if->bzStream), BZ_FINISH ); if (ret != BZ_FINISH_OK && ret != BZ_STREAM_END) { return -1; } if (pbz2if->bzStream.avail_out < BZ_MAX_UNUSED) { n = BZ_MAX_UNUSED - pbz2if->bzStream.avail_out; // User callback n2 = pbz2if->writeCallback( pbz2if->userData, pbz2if->Buffer, n ); if (n != n2 ) { return -1; } } if (ret == BZ_STREAM_END) break; } return 0; } ///////////////////////////////////////////////////////////////////////////// // // BZ2IFREADINTERNAL ///////////////////////////////////////////////////////////////////////////// // // DESCRIPTION // --bz2ifReadInternal-- // // uncompresses the data // Internal usage only // // ARGUMENTS // Argument1: Bz2IfaceInternal * pbz2if // Argument2: void*bufToDecompress // Argument3: int lenToDecompress // RETOUR/RESULTAT // static int // REMARQUE // Rev 23/12/2003 ////////////////////////////////////////////////////////////////////////////// static int bz2ifReadInternal(Bz2IfaceInternal * pbz2if,void*bufToDecompress, int lenToDecompress ) { int n2, n3, ret; if (pbz2if->bzStream.avail_in != 0 ) { printf( "pbz2if->bzStream.avail_in != 0\n" ); } // Buffer where uncompressed data goes pbz2if->bzStream.avail_out = sizeof(pbz2if->Buffer); pbz2if->bzStream.next_out = pbz2if->Buffer; // Compressed data given as argument pbz2if->bzStream.avail_in = lenToDecompress; pbz2if->bzStream.next_in = bufToDecompress; while (1) { if (pbz2if->bzStream.avail_in == 0 ) { // bufToDecompress is consumed (lenToDecompress bytes consumed) return 0; } ret = BZ2_bzDecompress ( &(pbz2if->bzStream) ); if (ret != BZ_OK && ret != BZ_STREAM_END) { //BZ_SETERR(ret) return -1; } // End of stream ? if (ret == BZ_STREAM_END) { // BZ_SETERR(BZ_STREAM_END); // User callback n3 = sizeof(pbz2if->Buffer) - pbz2if->bzStream.avail_out; n2 = pbz2if->writeCallback( pbz2if->userData, pbz2if->Buffer, n3 ); if (n3 != n2 ) { return -1; } // User callback (indicates end) pbz2if->writeCallback( pbz2if->userData, NULL, 0 ); return 0; } // Call the callback with the uncompressed data if there is some n3 = sizeof(pbz2if->Buffer) - pbz2if->bzStream.avail_out; if( n3 ) { n2 = pbz2if->writeCallback( pbz2if->userData, pbz2if->Buffer, n3 ); if (n3 != n2 ) { return -1; } pbz2if->bzStream.avail_out = sizeof(pbz2if->Buffer); pbz2if->bzStream.next_out = pbz2if->Buffer; } } return 0; /*not reached*/ } ///////////////////////////////////////////////////////////////////////////// // // BZ2IFWRITE ///////////////////////////////////////////////////////////////////////////// // // DESCRIPTION // --Bz2IfWrite-- // // Compress or uncompress the data. // The writeCallback() is called when data can be written // // In case of compression, user should call Bz2IfWrite() // with pData=NULl and cbData=0 to indicate the end of the data stream // // In case of decompression, the callback writeCallback() is called // with pData=NULl and cbData=0 to indicate that all data has been // uncompressed // // ARGUMENTS // Argument1: Bz2Iface * pbz2ifexternal // Argument2: char * pData // Argument3: int cbData // RETOUR/RESULTAT // int // REMARQUE // Rev 23/12/2003 ////////////////////////////////////////////////////////////////////////////// int Bz2IfWrite( Bz2Iface * pbz2ifexternal, char * pData, int cbData ) { Bz2IfaceInternal * pbz2if = (Bz2IfaceInternal *)pbz2ifexternal; if( ! pbz2if ) return -1; if( pbz2if->nCompression ) { if( pData == NULL && cbData == 0 ) { return bz2ifWriteCloseInternal( pbz2if ); } return bz2ifWriteInternal( pbz2if, pData, cbData ); } else { if( pData == NULL && cbData == 0 ) { return 0; } return bz2ifReadInternal( pbz2if, pData, cbData ); } return -1; }