Main Page   Class Hierarchy   Compound List   File List   Compound Members   File Members  

ZLib.cpp

Go to the documentation of this file.
00001 /*
00002 This product contains certain software code or other information
00003 ("AT&T Software") proprietary to AT&T Corp. ("AT&T").  The AT&T
00004 Software is provided to you "AS IS".  YOU ASSUME TOTAL RESPONSIBILITY
00005 AND RISK FOR USE OF THE AT&T SOFTWARE.  AT&T DOES NOT MAKE, AND
00006 EXPRESSLY DISCLAIMS, ANY EXPRESS OR IMPLIED WARRANTIES OF ANY KIND
00007 WHATSOEVER, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
00008 MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, WARRANTIES OF
00009 TITLE OR NON-INFRINGEMENT OF ANY INTELLECTUAL PROPERTY RIGHTS, ANY
00010 WARRANTIES ARISING BY USAGE OF TRADE, COURSE OF DEALING OR COURSE OF
00011 PERFORMANCE, OR ANY WARRANTY THAT THE AT&T SOFTWARE IS "ERROR FREE" OR
00012 WILL MEET YOUR REQUIREMENTS.
00013 
00014 Unless you accept a license to use the AT&T Software, you shall not
00015 reverse compile, disassemble or otherwise reverse engineer this
00016 product to ascertain the source code for any AT&T Software.
00017 
00018 (c) AT&T Corp. All rights reserved.  AT&T is a registered trademark of AT&T Corp.
00019 
00020 ***********************************************************************
00021 
00022 History:
00023 
00024       24/11/99  - initial release by Hartmut Liefke, liefke@seas.upenn.edu
00025                                      Dan Suciu,      suciu@research.att.com
00026 */
00027 
00028 //**************************************************************************
00029 //**************************************************************************
00030 
00031 // This module contains the interface to the ZLIB (either gzip or bzip)
00032 // libary
00033 
00034 #include <stdio.h>
00035 #include <string.h>
00036 #include <stdlib.h>
00037 
00038 #ifdef USE_BZIP
00039 #include <bzlib.h>
00040 #else
00041 #include <zlib.h>
00042 #endif
00043 
00044 #include "Compress.hpp"
00045 #include "MemStreamer.hpp"
00046 #include "Input.hpp"
00047 #include "Output.hpp"
00048 
00049 #ifdef XMILL
00050 extern unsigned char zlib_compressidx;
00051 #endif
00052 
00053 //************************************************************************
00054 
00055 #ifdef ZALLOC_COUNT
00056 unsigned long allocsize=0;
00057 #endif
00058 
00059 // Function zalloc is called by the zlib library to allocate memory
00060 
00061 #ifdef USE_BZIP
00062 void *zalloc(void *opaque,int items,int size)
00063 #else
00064 void *zalloc(void *opaque,unsigned items,unsigned size)
00065 #endif
00066 {
00067 #ifdef ZALLOC_COUNT
00068    void *ptr=malloc(items*size+4);
00069 #else
00070    void *ptr=malloc(items*size);
00071 #endif
00072    if(ptr==NULL)
00073       ExitNoMem();
00074 
00075 //   printf("zalloc : %lu * %lu ==> %lX\n",items,size,ptr);
00076 
00077 #ifdef ZALLOC_COUNT
00078    allocsize+=size;
00079    *(unsigned *)ptr=size;
00080    return (void *)(((char *)ptr)+4);
00081 #else
00082    return (void *)ptr;
00083 #endif
00084 }
00085 
00086 // Function zfree is called by the zlib library to release memory
00087 
00088 void zfree(void *opaque,void *ptr)
00089 {
00090 #ifdef ZALLOC_COUNT
00091    allocsize-=*((unsigned *)ptr-1);
00092    free((char *)ptr-4);
00093 #else
00094    free((char *)ptr);
00095 #endif
00096 }
00097 
00098 //******************************************************************
00099 //******************************************************************
00100 
00101 // The compressor part
00102 
00103 #ifdef XMILL
00104 
00105 Compressor::Compressor(Output *myoutput)
00106    // The constructor
00107 {
00108 #ifdef USE_BZIP
00109    state.bzalloc=zalloc;
00110    state.bzfree=zfree;
00111 #else
00112    state.zalloc=zalloc;
00113    state.zfree=zfree;
00114 #endif
00115 
00116    isinitialized=0;
00117 
00118    output=myoutput;
00119 };
00120 
00121 Compressor::~Compressor()
00122    // The deconstructor
00123 {
00124    if(isinitialized)
00125       // We finish compression, if there has been some data in the queue
00126    {
00127 #ifdef USE_BZIP
00128       bzCompressEnd(&state);
00129 #else
00130       deflateEnd(&state);
00131 #endif
00132 
00133 //      deflateReset(&state);
00134       isinitialized=0;
00135    }
00136 }
00137 
00138 void Compressor::CompressMemStream(MemStreamer *memstream)
00139    // Reads the data from 'memstream' and sends
00140    // it to the compressor
00141 {
00142    MemStreamBlock *curblock=memstream->GetFirstBlock();
00143    char           first=1;
00144    int            saveavail;
00145 
00146    // Any data there? 
00147    if(memstream->GetSize()==0)
00148       return;
00149 
00150 #ifdef USE_BZIP
00151    state.next_out=(char *)output->GetBufPtr((int *)&state.avail_out);
00152    state.next_in=(char *)curblock->data;
00153 #else
00154    state.next_out=(unsigned char *)output->GetBufPtr((int *)&state.avail_out);
00155    state.next_in=(unsigned char *)curblock->data;
00156 #endif
00157 
00158    // If there is no space in the output buffer, we need to flush
00159    if(state.avail_out==0)
00160    {
00161       // If the output buffer is full, we flush
00162       output->Flush();
00163 
00164       // We get the next piece of output buffer that will be filled up
00165 #ifdef USE_BZIP
00166       state.next_out=(char *)output->GetBufPtr((int *)&state.avail_out);
00167 #else
00168       state.next_out=(unsigned char *)output->GetBufPtr((int *)&state.avail_out);
00169 #endif
00170    }
00171 
00172 //   state.avail_in=curblock->cursize;
00173 
00174    // If we haven't initialized yet, we do that now
00175    if(isinitialized==0)
00176    {
00177 #ifdef USE_BZIP
00178       if(bzCompressInit(&state,7,0,0)!=BZ_OK)
00179 #else
00180       if(deflateInit(&state,zlib_compressidx)!=Z_OK)
00181 #endif
00182       {
00183          Error("Error while compressing container!");
00184          Exit();
00185       }
00186       state.total_out=0;
00187       state.total_in=0;
00188 
00189       isinitialized=1;
00190    }
00191 
00192    do
00193    {
00194       // Let's the input block to 'curblock'
00195 #ifdef USE_BZIP
00196       state.next_in=(char *)curblock->data;
00197 #else
00198       state.next_in=(unsigned char *)curblock->data;
00199 #endif
00200       state.avail_in=curblock->cursize;
00201 
00202       // As long as we still have data in the input block, we continue
00203       while(state.avail_in>0)
00204       {
00205          saveavail=state.avail_out;
00206 
00207 #ifdef USE_BZIP
00208          if(bzCompress(&state,BZ_RUN)!=BZ_RUN_OK)
00209 #else
00210          if(deflate(&state,Z_NO_FLUSH)!=Z_OK)
00211 #endif
00212          {
00213             Error("Error while compressing container!");
00214             Exit();
00215          }
00216 
00217          // We tell the output stream that 'saveavail-state.avail_out' bytes
00218          // are now ready for output
00219          output->SaveBytes(saveavail-state.avail_out);
00220 
00221          if((state.avail_in==0)&&(state.avail_out>0))
00222             // Is the input buffer is empty ? ==> We go to next block
00223             break;
00224 
00225          // If the output buffer is full, we flush
00226          output->Flush();
00227 
00228          // We get the next piece of output buffer that will be filled up
00229 #ifdef USE_BZIP
00230          state.next_out=(char *)output->GetBufPtr((int *)&state.avail_out);
00231 #else
00232          state.next_out=(unsigned char *)output->GetBufPtr((int *)&state.avail_out);
00233 #endif
00234       }
00235 
00236       // There is no more input data available ==> We go to next block in MemStreamer
00237       curblock=curblock->next;
00238    }
00239    while(curblock!=NULL);
00240 }
00241 
00242 void Compressor::CompressData(unsigned char *ptr,unsigned len)
00243    // Compresses the data at position 'ptr' of length 'len'
00244 {
00245    int            saveavail;
00246 
00247    // Let's get some space in the output buffer
00248 #ifdef USE_BZIP
00249    state.next_out=output->GetBufPtr((int *)&state.avail_out);
00250    state.next_in=(char *)ptr;
00251 #else
00252    state.next_out=(unsigned char *)output->GetBufPtr((int *)&state.avail_out);
00253    state.next_in=ptr;
00254 #endif
00255 
00256    state.avail_in=len;
00257 
00258    // If we haven't initialized the compressor yet, then let's do it now
00259    if(isinitialized==0)
00260    {
00261 #ifdef USE_BZIP
00262       if(bzCompressInit(&state,7,0,0)!=BZ_OK)
00263 #else
00264       if(deflateInit(&state,zlib_compressidx)!=Z_OK)
00265 #endif
00266       {
00267          Error("Error while compressing container!");
00268          Exit();
00269       }
00270       state.total_out=0;
00271       state.total_in=0;
00272       isinitialized=1;
00273    }
00274 
00275    do
00276    {
00277       saveavail=state.avail_out;
00278 
00279       // The actual compression
00280 #ifdef USE_BZIP
00281       if(bzCompress(&state,BZ_RUN)!=BZ_RUN_OK)
00282 #else
00283       if(deflate(&state,Z_NO_FLUSH)!=Z_OK)
00284 #endif
00285       {
00286          Error("Error while compressing container!");
00287          Exit();
00288       }
00289       output->SaveBytes(saveavail-state.avail_out);
00290          // We tell the output stream that 'saveavail-state.avail_out' bytes
00291          // are now ready for output
00292 
00293       if((state.avail_in==0)&&(state.avail_out>0))
00294          // Is the input buffer is empty ? ==> We go to next block
00295          break;
00296 
00297       // If the output buffer is full, we flush
00298       output->Flush();
00299 
00300       // We get the next piece of output buffer that will be filled up
00301 #ifdef USE_BZIP
00302       state.next_out=output->GetBufPtr((int *)&state.avail_out);
00303 #else
00304       state.next_out=(unsigned char *)output->GetBufPtr((int *)&state.avail_out);
00305 #endif
00306    }
00307    while(1);
00308 }
00309 
00310 void Compressor::FinishCompress(unsigned long *uncompressedsize,unsigned long *compressedsize)
00311    // Finishes the compression and stores the input data size and
00312    // the output data size in 'uncompressedsize' and 'compressedsize'
00313 {
00314    char err;
00315    int   saveavail;
00316 
00317    do
00318    {
00319       // Let's get more space in the output buffer
00320 #ifdef USE_BZIP
00321       state.next_out=output->GetBufPtr((int *)&state.avail_out);
00322 #else
00323       state.next_out=(unsigned char *)output->GetBufPtr((int *)&state.avail_out);
00324 #endif
00325 
00326       saveavail=state.avail_out;
00327 
00328 #ifdef USE_BZIP
00329       err=bzCompress(&state,BZ_FINISH);
00330 #else
00331       err=deflate(&state,Z_FINISH);
00332 #endif
00333 
00334       output->SaveBytes(saveavail-state.avail_out);
00335 
00336 #ifdef USE_BZIP
00337       if(err==BZ_STREAM_END)
00338          break;
00339       if(err!=BZ_FINISH_OK)
00340 #else
00341       if(err==Z_STREAM_END)
00342          break;
00343       if(err!=Z_OK)
00344 #endif
00345       {
00346          Error("Error while compressing container!");
00347          Exit();
00348       }
00349 
00350       // Z_OK means that the output buffer is full ! ==> We flush
00351       output->Flush();
00352    }
00353    while(1);
00354 
00355    // Let's store the input and output size
00356    if(uncompressedsize!=NULL) *uncompressedsize =state.total_in;
00357    if(compressedsize!=NULL)   *compressedsize   =state.total_out;
00358 
00359    state.total_out=0;
00360    state.total_in=0;
00361 
00362    // Finally, we release the internal memory
00363 #ifdef USE_BZIP
00364    if(bzCompressEnd(&state)!=BZ_OK)
00365 #else
00366    if(deflateReset(&state)!=Z_OK)
00367 #endif
00368    {  
00369       Error("Error while compressing container!");
00370       Exit();
00371    }
00372 #ifdef USE_BZIP
00373    // bzip must be reinitialized
00374    isinitialized=0;
00375 #endif
00376 }
00377 
00378 #endif // XMILL
00379 
00380 //******************************************************************************
00381 //******************************************************************************
00382 //******************************************************************************
00383 //******************************************************************************
00384 
00385 #ifdef XDEMILL
00386 
00387 char Uncompressor::Uncompress(Input *input,unsigned char *dataptr,unsigned long *len)
00388    // Decompresses the data from 'input' and stores
00389    // the result in 'dataptr'. It decompresses at most *len
00390    // bytes. Afterwards, '*len' is set to the actual number
00391    // of bytes uncompressed.
00392    // The function returns 1, if output buffer is full and
00393    // there is more data to read. Otherwise, the function returns 0.
00394 {
00395    // We haven't initialized the object yet, we do that now
00396    if(isinitialized==0)
00397    {
00398 #ifdef USE_BZIP
00399       state.bzalloc=zalloc;
00400       state.bzfree=zfree;
00401 #else
00402       state.zalloc=zalloc;
00403       state.zfree=zfree;
00404 #endif
00405 
00406 #ifdef USE_BZIP
00407       if(bzDecompressInit(&state,0,0)!=BZ_OK)
00408 #else
00409       if(inflateInit(&state)!=Z_OK)
00410 #endif
00411       {
00412          Error("Error while compressing container!");
00413          Exit();
00414       }
00415 
00416       isinitialized=1;
00417    }
00418 
00419    int   save_in;
00420 
00421 #ifdef USE_BZIP
00422    state.next_out=(char *)dataptr;
00423 #else
00424    state.next_out=(unsigned char *)dataptr;
00425 #endif
00426 
00427    // Let's remember how much space we have in the output ...
00428    state.avail_out=*len;
00429 
00430    // ... and we get the piece of data from the input
00431    state.avail_in=input->GetCurBlockPtr((char **)&(state.next_in));
00432 
00433    do
00434    {
00435       // We save the amount of input data that is available
00436       // This will be used to compute how much input data was
00437       // decompressed
00438       save_in=state.avail_in;
00439 
00440       // The actual decompression
00441 #ifdef USE_BZIP
00442       switch(bzDecompress(&state))
00443 #else
00444       switch(inflate(&state,Z_NO_FLUSH))
00445 #endif
00446       {
00447          // Did we finish completely?
00448 #ifdef USE_BZIP
00449       case BZ_STREAM_END:
00450 #else
00451       case Z_STREAM_END:
00452 #endif
00453          // We skip over the amount of data that was decompressed
00454          input->SkipData(save_in-state.avail_in);
00455 
00456          // Let's store the overall amount of "decompressed" data.
00457          *len=state.total_out;
00458 
00459          // Let's finish the decompression entirely
00460 #ifdef USE_BZIP
00461          if(bzDecompressEnd(&state)!=BZ_OK)
00462 #else
00463          if(inflateReset(&state)!=Z_OK)
00464 #endif
00465          {
00466             Error("Error while compressing container!");
00467             Exit();
00468          }
00469 #ifdef USE_BZIP
00470          // Only for BZIP, we need to reinitialize
00471          isinitialized=0;
00472 #endif
00473          return 0;   // We reached the end
00474 
00475          
00476 #ifdef USE_BZIP
00477       case BZ_OK:
00478 #else
00479       case Z_OK:
00480 #endif
00481          // Did we do the decompression correctly?
00482          // => Let's go to the next piece of data
00483          break;
00484 
00485       default:
00486          // In all other cases, we have an error
00487          Error("Error while uncompressing container!");
00488          Exit();
00489       }
00490 
00491       // Skip the input data that was decompressed
00492       input->SkipData(save_in-state.avail_in);
00493 
00494       if(state.avail_out==0)  // Output buffer is full
00495          return 1;
00496 
00497 //      if(state.avail_in>0) // Something is wrong !
00498 //         return -1;
00499 
00500       // Let's get the next input data block
00501       input->RefillAndGetCurBlockPtr((char **)&(state.next_in),(int *)&(state.avail_in));
00502    }
00503    while(1);
00504 }
00505 
00506 #endif // XDEMILL

Generated on Sat Oct 13 16:08:42 2001 for XMILL by doxygen1.2.11.1 written by Dimitri van Heesch, © 1997-2001