00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 
00029 
00030 
00031 
00032 
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 
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 
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 
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 
00102 
00103 #ifdef XMILL
00104 
00105 Compressor::Compressor(Output *myoutput)
00106    
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    
00123 {
00124    if(isinitialized)
00125       
00126    {
00127 #ifdef USE_BZIP
00128       bzCompressEnd(&state);
00129 #else
00130       deflateEnd(&state);
00131 #endif
00132 
00133 
00134       isinitialized=0;
00135    }
00136 }
00137 
00138 void Compressor::CompressMemStream(MemStreamer *memstream)
00139    
00140    
00141 {
00142    MemStreamBlock *curblock=memstream->GetFirstBlock();
00143    char           first=1;
00144    int            saveavail;
00145 
00146    
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    
00159    if(state.avail_out==0)
00160    {
00161       
00162       output->Flush();
00163 
00164       
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 
00173 
00174    
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       
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       
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          
00218          
00219          output->SaveBytes(saveavail-state.avail_out);
00220 
00221          if((state.avail_in==0)&&(state.avail_out>0))
00222             
00223             break;
00224 
00225          
00226          output->Flush();
00227 
00228          
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       
00237       curblock=curblock->next;
00238    }
00239    while(curblock!=NULL);
00240 }
00241 
00242 void Compressor::CompressData(unsigned char *ptr,unsigned len)
00243    
00244 {
00245    int            saveavail;
00246 
00247    
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    
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       
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          
00291          
00292 
00293       if((state.avail_in==0)&&(state.avail_out>0))
00294          
00295          break;
00296 
00297       
00298       output->Flush();
00299 
00300       
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    
00312    
00313 {
00314    char err;
00315    int   saveavail;
00316 
00317    do
00318    {
00319       
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       
00351       output->Flush();
00352    }
00353    while(1);
00354 
00355    
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    
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    
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    
00389    
00390    
00391    
00392    
00393    
00394 {
00395    
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    
00428    state.avail_out=*len;
00429 
00430    
00431    state.avail_in=input->GetCurBlockPtr((char **)&(state.next_in));
00432 
00433    do
00434    {
00435       
00436       
00437       
00438       save_in=state.avail_in;
00439 
00440       
00441 #ifdef USE_BZIP
00442       switch(bzDecompress(&state))
00443 #else
00444       switch(inflate(&state,Z_NO_FLUSH))
00445 #endif
00446       {
00447          
00448 #ifdef USE_BZIP
00449       case BZ_STREAM_END:
00450 #else
00451       case Z_STREAM_END:
00452 #endif
00453          
00454          input->SkipData(save_in-state.avail_in);
00455 
00456          
00457          *len=state.total_out;
00458 
00459          
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          
00471          isinitialized=0;
00472 #endif
00473          return 0;   
00474 
00475          
00476 #ifdef USE_BZIP
00477       case BZ_OK:
00478 #else
00479       case Z_OK:
00480 #endif
00481          
00482          
00483          break;
00484 
00485       default:
00486          
00487          Error("Error while uncompressing container!");
00488          Exit();
00489       }
00490 
00491       
00492       input->SkipData(save_in-state.avail_in);
00493 
00494       if(state.avail_out==0)  
00495          return 1;
00496 
00497 
00498 
00499 
00500       
00501       input->RefillAndGetCurBlockPtr((char **)&(state.next_in),(int *)&(state.avail_in));
00502    }
00503    while(1);
00504 }
00505 
00506 #endif // XDEMILL