Main Page   Modules   Class Hierarchy   Compound List   File List   Compound Members   File Members   Related Pages   Examples  

misc/compress.cpp

Go to the documentation of this file.
00001 #include "compress.h"
00002 
00003 /*
00004 
00005   GLT OpenGL C++ Toolkit (LGPL)
00006   Copyright (C) 2000-2001 Nigel Stewart  
00007 
00008   Email: nigels.com@gmail.com   
00009   WWW:   http://www.nigels.com/glt/
00010 
00011   This library is free software; you can redistribute it and/or
00012   modify it under the terms of the GNU Lesser General Public
00013   License as published by the Free Software Foundation; either
00014   version 2.1 of the License, or (at your option) any later version.
00015 
00016   This library is distributed in the hope that it will be useful,
00017   but WITHOUT ANY WARRANTY; without even the implied warranty of
00018   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00019   Lesser General Public License for more details.
00020 
00021   You should have received a copy of the GNU Lesser General Public
00022   License along with this library; if not, write to the Free Software
00023   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00024 */
00025 
00026 /*
00027 
00028   Lzf compression library
00029   Copyright (c) 2000 Marc Alexander Lehmann <pcg@goof.com>
00030   An extremely fast/free compression/decompression-method
00031   http://liblzf.plan9.de/
00032 
00033   Based on ideas by Hermann Vogt, but liblzf is a total
00034   re-implementation of LZV that is not compatible to the
00035   original lzv code.
00036 
00037   This algorithm is believed to be patent-free.
00038 
00039 */
00040 
00046 #include <glt/config.h>
00047 
00048 extern "C"
00049 {
00050     #include "internal/lzf.h"
00051 }
00052 
00053 
00054 #ifdef GLT_ZLIB
00055 #include <zlib.h>
00056 #endif
00057 
00058 #include <cstdio>
00059 #include <cassert>
00060 using namespace std;
00061 
00063 
00064 // Room for zlib or bzip2
00065 
00066 #define COMPRESS_NONE   0
00067 #define COMPRESS_LIBLZF 1
00068 #define COMPRESS_ZLIB   2
00069 
00070 // Create variable-length header for compressed data
00071 
00072 bool makeHeader
00073 (
00074     string &header,
00075     const uint32 algorithm,
00076     const uint32 sizeCompressed,
00077     const uint32 sizeDecompressed,
00078     const uint32 crc32
00079 )
00080 {
00081     // 11 characters is big enough for integer 2^32 + \0
00082 
00083     char buffer[5+11+11+11+11];
00084     sprintf(buffer,"GLTZ %u %u %u %u",algorithm,sizeCompressed,sizeDecompressed,crc32);
00085     header = buffer;
00086     header += '\0';
00087 
00088     return true;
00089 }
00090 
00091 // Decode variable-length header for compressed data
00092 
00093 const byte * const getHeader
00094 (
00095     const char * const h,
00096     uint32 &algorithm,
00097     uint32 &sizeCompressed,
00098     uint32 &sizeDecompressed,
00099     uint32 &crc32
00100 )
00101 {
00102     if (h[0]=='G' && h[1]=='L' && h[2]=='T' && h[3]=='Z' && h[4]==' ')
00103     {
00104         if (sscanf(h+5,"%u %u %u %u",&algorithm,&sizeCompressed,&sizeDecompressed,&crc32)==4)
00105             return (const byte * const) h + strlen(h) + 1;
00106     }
00107 
00108     return NULL;
00109 }
00110 
00111 bool compress(string &dest,const string &src)
00112 {
00113     // Allocate a buffer for receiving the compressed data
00114 
00115     byte *buffer = new byte[src.size()];
00116     if (!buffer)
00117         return false;
00118 
00119     // Flag success
00120 
00121     bool ret = true;
00122 
00123     // Do compression
00124 
00125     unsigned int size = lzf_compress(src.data(),src.size(),buffer,src.size());
00126     
00127     // Get CRC32
00128     unsigned int crc32 = 0;
00129     
00130     #ifdef GLT_ZLIB
00131     crc32 = ::crc32(src);
00132     #endif
00133 
00134     if (size==0 || size==src.size())
00135     {
00136         // If compression fails, just copy the input buffer
00137 
00138         string header;
00139         if (makeHeader(header,COMPRESS_NONE,src.size(),src.size(),crc32))
00140             dest = header + src;
00141         else
00142             ret = false;
00143     }
00144     else
00145     {
00146         // If compression succeeds, copy the compressed buffer
00147 
00148         if (makeHeader(dest,COMPRESS_LIBLZF,size,src.size(),crc32))
00149         {
00150             size_t pos = dest.size();
00151             dest.resize(pos+size);
00152             memcpy((void *)(dest.data()+pos),buffer,size);
00153         }
00154         else
00155             ret = false;
00156     }
00157 
00158     // Exit 
00159 
00160     delete [] buffer;
00161     return ret;
00162 }
00163 
00164 bool decompress(string &dest,const string &src)
00165 {
00166     uint32 algorithm;
00167     uint32 sizeCompressed;
00168     uint32 sizeDecompressed;
00169     uint32 crc32;
00170 
00171     const byte * const pos = getHeader(src.data(),algorithm,sizeCompressed,sizeDecompressed,crc32);
00172 
00173     if (pos)
00174     {
00175         // Prepare output buffer
00176 
00177         dest.resize(sizeDecompressed);
00178 
00179         switch (algorithm)
00180         {
00181         case COMPRESS_NONE:
00182             {
00183                 // Data is not compressed, just strip off header
00184                 memcpy((void *) dest.data(),pos,sizeCompressed);
00185                 return true;
00186             }
00187 
00188         case COMPRESS_LIBLZF:
00189             {
00190                 // Data is compressed with lzf
00191                 unsigned int ret = lzf_decompress(pos,sizeCompressed,(void *) dest.data(),sizeDecompressed);
00192                 return ret==sizeDecompressed;
00193             }
00194 
00195         case COMPRESS_ZLIB:
00196             {
00197                 #ifdef GLT_ZLIB
00198                 uLongf size = sizeDecompressed;
00199                 int ok = uncompress((Bytef *) dest.data(),&size,pos,sizeCompressed);
00200                 return ok==Z_OK && size==sizeDecompressed;
00201                 #else
00202                 assert(false);
00203                 return false;
00204                 #endif
00205             }
00206         }
00207     }
00208 
00209     assert(false);
00210     return false;
00211 }
00212 
00213 bool decompress(string &dest,const void *s)
00214 {
00215     uint32 algorithm;
00216     uint32 sizeCompressed;
00217     uint32 sizeDecompressed;
00218     uint32 crc32;
00219 
00220     const byte * const pos = getHeader((const char * const) s,algorithm,sizeCompressed,sizeDecompressed,crc32);
00221 
00222     if (pos)
00223     {
00224         // Prepare output buffer
00225 
00226         dest.resize(sizeDecompressed);
00227 
00228         switch (algorithm)
00229         {
00230         case COMPRESS_NONE:
00231             {
00232                 // Data is not compressed, just strip off header
00233                 memcpy((void *) dest.data(),pos,sizeCompressed);
00234                 
00235                 #ifdef GLT_ZLIB
00236                 if (::crc32(dest)!=crc32)
00237                     return false;
00238                 #endif
00239 
00240                 return true;
00241             }
00242 
00243         case COMPRESS_LIBLZF:
00244             {
00245                 // Data is compressed with lzf
00246                 unsigned int ret = lzf_decompress(pos,sizeCompressed,(void *) dest.data(),sizeDecompressed);
00247                 
00248                 #ifdef GLT_ZLIB
00249                 if (::crc32(dest)!=crc32)
00250                     return false;
00251                 #endif
00252 
00253                 return ret==sizeDecompressed;
00254             }
00255 
00256         case COMPRESS_ZLIB:
00257             {
00258                 #ifdef GLT_ZLIB
00259                 uLongf size = sizeDecompressed;
00260                 int ok = uncompress((Bytef *) dest.data(),&size,pos,sizeCompressed);
00261 
00262                 if (::crc32(dest)!=crc32)
00263                     return false;
00264 
00265                 return ok==Z_OK && size==sizeDecompressed;
00266                 #else
00267                 assert(false);
00268                 return false;
00269                 #endif
00270             }
00271         }
00272     }
00273 
00274     assert(false);
00275     return false;
00276 }
00277 
00279 
00280 #ifdef GLT_ZLIB
00281 
00282 bool compressZLib(string &dest,const string &src,const int level)
00283 {
00284     // Allocate a buffer for receiving the compressed data
00285 
00286     byte *buffer = new byte[src.size()];
00287     if (!buffer)
00288         return false;
00289 
00290     // Flag success
00291 
00292     bool ret = true;
00293 
00294     // Do compression
00295     uLongf bufferSize = src.size();
00296     unsigned int ok = compress2(buffer,&bufferSize,(Bytef *)src.data(),src.size(),level);
00297 
00298     // Get CRC32
00299     unsigned int crc32 = 0;
00300     
00301     #ifdef GLT_ZLIB
00302     crc32 = ::crc32(src);
00303     #endif
00304 
00305     if (ok!=Z_OK)
00306     {
00307         // If compression fails, just copy the input buffer
00308 
00309         string header;
00310         if (makeHeader(header,COMPRESS_NONE,src.size(),src.size(),crc32))
00311             dest = header + src;
00312         else
00313             ret = false;
00314     }
00315     else
00316     {
00317         // If compression succeeds, copy the compressed buffer
00318 
00319         if (makeHeader(dest,COMPRESS_ZLIB,bufferSize,src.size(),crc32))
00320         {
00321             size_t pos = dest.size();
00322             dest.resize(pos+bufferSize);
00323             memcpy((void *)(dest.data()+pos),buffer,bufferSize);
00324         }
00325         else
00326             ret = false;
00327     }
00328 
00329     // Exit 
00330 
00331     delete [] buffer;
00332     return ret;
00333 }
00334 
00335 uint32 crc32(const string &data)
00336 {
00337     return crc32(crc32(0L,Z_NULL,0),(const Bytef *) data.data(),data.size());
00338 }
00339 
00340 uint32 crc32(const void *data,const uint32 bytes)
00341 {
00342     return crc32(crc32(0L,Z_NULL,0),(const Bytef *) data,bytes);
00343 }
00344 
00345 #endif
00346 
00347 

Generated on Tue Nov 5 11:11:04 2002 for GLT by doxygen1.2.18