opennurbs_zlib.cpp
Go to the documentation of this file.
00001 /* $NoKeywords: $ */
00002 /*
00003 //
00004 // Copyright (c) 1993-2012 Robert McNeel & Associates. All rights reserved.
00005 // OpenNURBS, Rhinoceros, and Rhino3D are registered trademarks of Robert
00006 // McNeel & Associates.
00007 //
00008 // THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY.
00009 // ALL IMPLIED WARRANTIES OF FITNESS FOR ANY PARTICULAR PURPOSE AND OF
00010 // MERCHANTABILITY ARE HEREBY DISCLAIMED.
00011 //                              
00012 // For complete openNURBS copyright information see <http://www.opennurbs.org>.
00013 //
00015 */
00016 
00017 #include "pcl/surface/3rdparty/opennurbs/opennurbs.h"
00018 
00019 #if defined(ON_DLL_EXPORTS)
00020 // When compiling a Windows DLL opennurbs, we
00021 // statically link ./zlib/.../zlib....lib into
00022 // the opennurbs DLL.
00023 
00024 
00025 #define OPENNURBS_ZLIB_FILE_NAME "zlib.lib"
00026 
00028 //
00029 // OPENNURBS_ZLIB_OUTPUT_DIR is the directory containing zlib
00030 // relative to the "opennurbs" directory.  
00031 //
00032 // OPENNURBS_ZLIB_OUTPUT_DIR must not have a trailing slash
00033 //
00034 #define OPENNURBS_ZLIB_OUTPUT_ROOT_DIR "."
00035 
00036 
00037 #if defined(WIN64) && defined(_M_X64)
00038 
00039 // 64 bit Windows zlib linking instructions
00040 
00041 #if defined(NDEBUG)
00042 
00043 // release x64 libs
00044 #define OPENNURBS_CONFIGURATION_DIR "x64/Release"
00045 
00046 #else // _DEBUG
00047 
00048 // debug  x64 libs
00049 #define OPENNURBS_CONFIGURATION_DIR "x64/Debug"
00050 
00051 #endif // if NDEBUG else _DEBUG
00052 
00053 #elif defined(WIN32) && defined(_M_IX86)
00054 
00055 // 32 bit Windows zlib linking instructions
00056 
00057 #if defined(NDEBUG)
00058 
00059 // release 32 bit WIndows libs
00060 #define OPENNURBS_CONFIGURATION_DIR "Release"
00061 
00062 #else // _DEBUG
00063 
00064 // debug 32 bit WIndows libs
00065 #define OPENNURBS_CONFIGURATION_DIR "Debug"
00066 
00067 #endif // if NDEBUG else _DEBUG
00068 
00069 #endif // if WIN64 else WIN32
00070 
00071 #pragma comment(lib, "\"" OPENNURBS_ZLIB_OUTPUT_ROOT_DIR "/" OPENNURBS_CONFIGURATION_DIR "/" OPENNURBS_ZLIB_FILE_NAME "\"")
00072 
00073 #endif // ON_DLL_EXPORTS
00074 
00075 
00076 bool ON_BinaryArchive::WriteCompressedBuffer(
00077         size_t sizeof__inbuffer,  // sizeof uncompressed input data
00078         const void* inbuffer  // uncompressed input data
00079         )
00080 {
00081   size_t compressed_size = 0;
00082   bool rc = false;
00083 
00084   if ( !WriteMode() )
00085     return false;
00086   if ( sizeof__inbuffer > 0 && 0 == inbuffer )
00087     return false;
00088 
00089 
00090   // number of bytes of uncompressed data
00091 
00092   if (!WriteSize(sizeof__inbuffer))
00093     return false;
00094   if ( 0 == sizeof__inbuffer )
00095     return true;
00096 
00097   // 32 bit crc of uncompressed data
00098   const unsigned int buffer_crc = ON_CRC32( 0, sizeof__inbuffer, inbuffer );
00099   if (!WriteInt(buffer_crc))
00100     return false;
00101 
00102   unsigned char method = (sizeof__inbuffer > 128) ? 1 : 0;
00103   if ( method ) {
00104     if ( !CompressionInit() ) {
00105       CompressionEnd();
00106       method = 0;
00107     }
00108   }
00109   if ( !WriteChar(method) )
00110     return false;
00111 
00112   switch ( method )
00113   {
00114   case 0: // uncompressed
00115     rc = WriteByte(sizeof__inbuffer, inbuffer);
00116     if ( rc )
00117     {
00118       compressed_size = sizeof__inbuffer;
00119     }
00120     break;
00121 
00122   case 1: // compressed
00123     compressed_size = WriteDeflate( sizeof__inbuffer, inbuffer );
00124     rc = ( compressed_size > 0 ) ? true : false;
00125     CompressionEnd();
00126     break;
00127   }
00128 
00129 
00130   return rc;
00131 }
00132 
00133 bool ON_BinaryArchive::ReadCompressedBufferSize( size_t* sizeof__outbuffer )
00134 {
00135   return ReadSize(sizeof__outbuffer);
00136 }
00137 
00138 bool ON_BinaryArchive::ReadCompressedBuffer( // read and uncompress
00139   size_t sizeof__outbuffer,  // sizeof of uncompressed buffer to read
00140   void* outbuffer,           // uncompressed output data returned here
00141   int* bFailedCRC
00142   )
00143 {
00144   bool rc = false;
00145   unsigned int buffer_crc0 = 0;
00146   unsigned int buffer_crc1 = 0;
00147   char method = 0;
00148 
00149   if ( bFailedCRC)
00150     *bFailedCRC = false;
00151   if ( !ReadMode() )
00152     return false;
00153   if ( 0 == sizeof__outbuffer )
00154     return true;
00155   if ( 0 == outbuffer )
00156     return false;
00157 
00158   if ( !ReadInt(&buffer_crc0) ) // 32 bit crc of uncompressed buffer
00159     return false;
00160 
00161   if ( !ReadChar(&method) )
00162     return false;
00163 
00164   if ( method != 0 && method != 1 )
00165     return false;
00166 
00167   switch(method)
00168   {
00169   case 0: // uncompressed
00170     rc = ReadByte(sizeof__outbuffer, outbuffer);
00171     break;
00172   case 1: // compressed
00173     rc = CompressionInit();
00174     if (rc)
00175       rc = ReadInflate( sizeof__outbuffer, outbuffer );
00176     CompressionEnd();
00177     break;
00178   }
00179 
00180   if (rc ) 
00181   {
00182     buffer_crc1 = ON_CRC32( 0, sizeof__outbuffer, outbuffer );
00183     if ( buffer_crc1 != buffer_crc0 ) 
00184     {
00185       ON_ERROR("ON_BinaryArchive::ReadCompressedBuffer() crc error");
00186       if ( bFailedCRC )
00187         *bFailedCRC = true;
00188     }
00189   }
00190 
00191   return rc;
00192 }
00193 
00194 size_t ON_BinaryArchive::WriteDeflate( // returns number of bytes written
00195         size_t sizeof___inbuffer,  // sizeof uncompressed input data ( > 0 )
00196         const void* in___buffer     // uncompressed input data ( != NULL )
00197         )
00198 {
00199   /*
00200     In "standard" (in 2005) 32 bit code
00201     
00202       sizeof(int)     = 4 bytes, 
00203       sizeof(long)    = 4 bytes,
00204       sizeof(pointer) = 4 bytes, and
00205       sizeof(size_t)  = 4 bytes.
00206 
00207     Theoretically I don't need to use multiple input buffer
00208     chunks in case.  But I'm paranoid and I will use multiple 
00209     input chunks when sizeof_inbuffer > 2GB in order to dodge
00210     any potential zlib signed verses unsigned compare bugs or
00211     having a signed int i++ roll over to a negative number.
00212 
00213     In "standard" code that has 64 bit pointers
00214     
00215       sizeof(int)     >= 4 bytes, (it's 4 on MS VS2005) 
00216       sizeof(long)    >= 4 bytes, (it's 4 on MS VS2005)
00217       sizeof(pointer)  = 8 bytes, and
00218       sizeof(size_t)   = 8 bytes.
00219 
00220     So, I'm going to assume the ints and longs in the zlib code 
00221     are 4 bytes, but I could have sizeof_inbuffer > 4GB.
00222     This means I have to use multiple input buffer chunks.  
00223     In this case I still use multiple input chunks when 
00224     sizeof_inbuffer > 2GB in order to dodge any potential zlib
00225     signed verses unsigned compare bugs or having a signed
00226     int i++ roll over to a negative number.
00227 
00228     So, I set
00229     
00230        const size_t max_avail = (largest signed 4 byte integer - 15)
00231     
00232     and feed inflate and deflate buffers with size <= max_avail.
00233 
00234 
00235     This information below is from the zlib 1.2.3 FAQ.  
00236 
00237     32. Can zlib work with greater than 4 GB of data?
00238 
00239         Yes. inflate() and deflate() will process any amount of data correctly.
00240         Each call of inflate() or deflate() is limited to input and output chunks
00241         of the maximum value that can be stored in the compiler's "unsigned int"
00242         type, but there is no limit to the number of chunks. Note however that the
00243         strm.total_in and strm_total_out counters may be limited to 4 GB. These
00244         counters are provided as a convenience and are not used internally by
00245         inflate() or deflate(). The application can easily set up its own counters
00246         updated after each call of inflate() or deflate() to count beyond 4 GB.
00247         compress() and uncompress() may be limited to 4 GB, since they operate in a
00248         single call. gzseek() and gztell() may be limited to 4 GB depending on how
00249         zlib is compiled. See the zlibCompileFlags() function in zlib.h.
00250 
00251         The word "may" appears several times above since there is a 4 GB limit
00252         only if the compiler's "long" type is 32 bits. If the compiler's "long"
00253         type is 64 bits, then the limit is 16 exabytes.
00254   */
00255 
00256   const size_t max_avail = 0x7FFFFFF0;
00257 
00258   //  Compressed information is saved in a chunk.
00259   bool rc = BeginWrite3dmChunk(TCODE_ANONYMOUS_CHUNK,0);
00260   if ( !rc )
00261     return false;
00262 
00263   size_t out__count = 0;
00264   int zrc = Z_OK;
00265 
00266   size_t my_avail_in = sizeof___inbuffer;
00267   unsigned char* my_next_in = (unsigned char*)in___buffer;
00268 
00269   size_t d = my_avail_in;
00270   if ( d > max_avail )
00271     d = max_avail;
00272   m_zlib.strm.next_in = my_next_in;
00273   m_zlib.strm.avail_in = (unsigned int)d; 
00274   my_avail_in -= d;
00275   my_next_in  += d;
00276 
00277   m_zlib.strm.next_out = m_zlib.buffer;
00278   m_zlib.strm.avail_out = m_zlib.sizeof_x_buffer;
00279 
00280   // counter guards prevents infinte loops if there is a bug in zlib return codes.
00281   int counter = 512; 
00282   int flush = Z_NO_FLUSH;
00283 
00284   size_t deflate_output_count = 0;
00285 
00286   while( rc && counter > 0 ) 
00287   {
00288     // Call zlib's deflate function.  It can either process
00289     // more input from m_zlib.strm.next_in[], create more
00290     // compressed output in m_zlib.strm.next_out[], or do both.
00291     if ( 0 == my_avail_in && 0 == m_zlib.strm.avail_in )
00292     {
00293       // no uncompressed input is left - switch to finish mode
00294       flush = Z_FINISH;
00295     }
00296     zrc = z_deflate( &m_zlib.strm, flush ); 
00297     if ( zrc < 0 ) 
00298     {
00299       // Something went haywire - bail out.
00300       ON_ERROR("ON_BinaryArchive::WriteDeflate - z_deflate failure");
00301       rc = false;
00302       break;
00303     }
00304 
00305     deflate_output_count = m_zlib.sizeof_x_buffer - m_zlib.strm.avail_out;
00306     if ( deflate_output_count > 0 ) 
00307     {
00308       // The last call to deflate created output.  Send
00309       // this output to the archive.
00310       rc = WriteChar( deflate_output_count, m_zlib.buffer );
00311       if ( !rc )
00312         break;
00313       out__count += deflate_output_count;
00314       m_zlib.strm.next_out  = m_zlib.buffer;
00315       m_zlib.strm.avail_out = m_zlib.sizeof_x_buffer;
00316     }
00317 
00318     if ( Z_FINISH == flush && Z_STREAM_END == zrc )
00319     {
00320       // no input left, all pending compressing is finished,
00321       // and all compressed output has been returned.
00322       break;
00323     }
00324 
00325     if ( my_avail_in > 0 && m_zlib.strm.avail_in < max_avail )
00326     {
00327       // inbuffer[] had more than max_zlib_avail_in bytes in it
00328       // and I am feeding inbuffer[] to deflate in smaller chunks
00329       // that the 32 bit integers in the zlib code can handle.
00330       if ( 0 == m_zlib.strm.avail_in || 0 == m_zlib.strm.next_in )
00331       {
00332         // The call to deflate() used up all the input 
00333         // in m_zlib.strm.next_in[].  I can feed it another chunk
00334         // from inbuffer[]
00335         d = my_avail_in;
00336         if ( d > max_avail )
00337           d = max_avail;
00338         m_zlib.strm.next_in = my_next_in;
00339         m_zlib.strm.avail_in = (unsigned int)d; 
00340       }
00341       else
00342       {
00343         // The call to deflate left some input in m_zlib.strm.next_in[],
00344         // but I can increase m_zlib.strm.avail_in.
00345         d =  max_avail - m_zlib.strm.avail_in;
00346         if ( d > my_avail_in )
00347           d = my_avail_in;
00348         m_zlib.strm.avail_in += (unsigned int)d;
00349       }
00350 
00351       my_avail_in -= d;
00352       my_next_in  += d;
00353     }
00354     else if ( 0 == deflate_output_count )
00355     {
00356       // no buffer changes this time
00357       counter--;
00358     }
00359 
00360     if ( zrc != Z_OK )
00361     {
00362       break;
00363     }
00364   }
00365 
00366   if ( !EndWrite3dmChunk() )
00367   {
00368     rc = false;
00369   }
00370 
00371   if ( 0 == counter )
00372   {
00373     rc = false;
00374   }
00375 
00376   return (rc ? out__count : 0);
00377 }
00378 
00379 
00380 bool ON_BinaryArchive::ReadInflate(
00381         size_t sizeof___outbuffer,  // sizeof uncompressed data
00382         void* out___buffer          // buffer for uncompressed data
00383         )
00384 {
00385   const size_t max_avail = 0x7FFFFFF0; // See max_avail comment in ON_BinaryArchive::WriteInflate
00386 
00387   size_t sizeof__inbuffer = 0;
00388   void* in___buffer = 0;
00389   bool rc = false;
00390 
00391   // read compressed buffer from 3dm archive
00392   bool bValidCompressedBuffer = false;
00393   {
00394     ON__UINT32 tcode = 0;
00395     ON__INT64  big_value = 0;
00396     rc = BeginRead3dmBigChunk(&tcode,&big_value );
00397     if (!rc)
00398     {
00399       if ( 0 != out___buffer && sizeof___outbuffer > 0 )
00400         memset(out___buffer,0,sizeof___outbuffer);
00401       return false;
00402     }
00403     if (   tcode == TCODE_ANONYMOUS_CHUNK 
00404         && big_value > 4 
00405         && sizeof___outbuffer > 0 
00406         && 0 != out___buffer )
00407     {
00408       // read compressed buffer from the archive
00409       sizeof__inbuffer = (size_t)(big_value-4); // the last 4 bytes in this chunk are a 32 bit crc
00410       in___buffer = onmalloc(sizeof__inbuffer);
00411       if ( !in___buffer )
00412       {
00413         rc = false;
00414       }
00415       else
00416       {
00417         rc = ReadByte( sizeof__inbuffer, in___buffer );
00418       }
00419     }
00420     else
00421     {
00422       // Either I have the wrong chunk, or the input
00423       // parameters are bogus. 
00424       rc = false;
00425     }
00426     int c0 = m_bad_CRC_count;
00427     if ( !EndRead3dmChunk() )
00428     {
00429       rc = false;
00430     }
00431     bValidCompressedBuffer = ( m_bad_CRC_count > c0 )
00432                            ? false
00433                            : rc;
00434   }
00435 
00436   if ( !bValidCompressedBuffer && 0 != out___buffer && sizeof___outbuffer > 0 )
00437   {
00438     // Decompression will fail, but we might get something valid
00439     // at the start if the data flaw was near the end of the buffer.
00440     memset(out___buffer,0,sizeof___outbuffer);
00441   }
00442 
00443   if ( !rc )
00444   {
00445     if ( in___buffer )
00446     {
00447       onfree(in___buffer);
00448       in___buffer = 0;
00449     }
00450     return false;
00451   }
00452 
00453   int zrc = -1;
00454 
00455   // set up zlib in buffer
00456   unsigned char* my_next_in = (unsigned char*)in___buffer;
00457   size_t my_avail_in = sizeof__inbuffer;
00458 
00459   size_t d = my_avail_in;
00460   if ( d > max_avail )
00461     d = max_avail;
00462   m_zlib.strm.next_in  = my_next_in;
00463   m_zlib.strm.avail_in = (unsigned int)d;
00464   my_next_in  += d;
00465   my_avail_in -= d;
00466 
00467   // set up zlib out buffer
00468   unsigned char* my_next_out = (unsigned char*)out___buffer;
00469   size_t my_avail_out = sizeof___outbuffer;
00470 
00471   d = my_avail_out;
00472   if ( d > max_avail )
00473     d = max_avail;
00474   m_zlib.strm.next_out  = my_next_out;
00475   m_zlib.strm.avail_out = (unsigned int)d;
00476   my_next_out  += d;
00477   my_avail_out -= d;
00478 
00479   // counter guards against infinte loop if there are
00480   // bugs in zlib return codes
00481   int counter = 512;
00482   int flush = Z_NO_FLUSH;
00483 
00484   while ( rc && counter > 0 )
00485   {
00486     // Call zlib's inflate function.  It can either process
00487     // more input from m_zlib.strm.next_in[], create more
00488     // uncompressed output in m_zlib.strm.next_out[], or do both.
00489     if ( 0 == my_avail_in && 0 == m_zlib.strm.avail_in )
00490     {
00491       // no compressed input is left - switch to finish mode
00492       flush = Z_FINISH;
00493     }
00494     zrc = z_inflate( &m_zlib.strm, flush );
00495     if ( zrc < 0 ) 
00496     {
00497       // Something went haywire - bail out.
00498       ON_ERROR("ON_BinaryArchive::ReadInflate - z_inflate failure");
00499       rc = false;
00500       break;
00501     }
00502 
00503     if ( Z_FINISH == flush && Z_STREAM_END == zrc )
00504     {
00505       // no input left, all pending decompression is finished,
00506       // and all decompressed output has been returned.
00507       break;
00508     }
00509 
00510     d = 0;
00511     if ( my_avail_in > 0 && m_zlib.strm.avail_in < max_avail )
00512     {
00513       if ( 0 == m_zlib.strm.avail_in || 0 == m_zlib.strm.next_in )
00514       {
00515         // The call to inflate() used up all the input 
00516         // in m_zlib.strm.next_in[].  I can feed it another chunk
00517         // from inbuffer[]
00518         d = my_avail_in;
00519         if ( d > max_avail )
00520           d = max_avail;
00521         m_zlib.strm.next_in  = my_next_in;
00522         m_zlib.strm.avail_in = (unsigned int)d; 
00523       }
00524       else
00525       {
00526         // The call to inflate() left some input in m_zlib.strm.next_in[],
00527         // but I can increase m_zlib.strm.avail_in.
00528         d =  max_avail - m_zlib.strm.avail_in;
00529         if ( d > my_avail_in )
00530           d = my_avail_in;
00531         m_zlib.strm.avail_in += (unsigned int)d;
00532       }
00533       my_next_in  += d;
00534       my_avail_in -= d;
00535     }
00536 
00537     if ( my_avail_out > 0 && m_zlib.strm.avail_out < max_avail )
00538     {
00539       // increase m_zlib.strm.next_out[] buffer
00540       if ( 0 == m_zlib.strm.avail_out || 0 == m_zlib.strm.next_out )
00541       {
00542         d = my_avail_out;
00543         if ( d > max_avail )
00544           d = max_avail;
00545         m_zlib.strm.next_out  = my_next_out;
00546         m_zlib.strm.avail_out = (unsigned int)d;
00547       }
00548       else
00549       {
00550         d = max_avail - m_zlib.strm.avail_out;
00551         if ( d > my_avail_out )
00552           d = my_avail_out;
00553         m_zlib.strm.avail_out += ((unsigned int)d);
00554       }
00555       my_next_out  += d;
00556       my_avail_out -= d;
00557     }
00558     else if ( 0 == d )
00559     {
00560       // no buffer changes
00561       counter--;
00562     }
00563   }
00564 
00565   if (in___buffer )
00566   {
00567     onfree(in___buffer);
00568     in___buffer = 0;
00569   }
00570 
00571   if ( 0 == counter )
00572   {
00573     rc = false;
00574   }
00575 
00576   return rc;
00577 }
00578 
00579 bool ON_BinaryArchive::CompressionInit()
00580 {
00581   // inflateInit() and deflateInit() are in zlib 1.3.3
00582   bool rc = false;
00583   if ( WriteMode() ) {
00584     rc = ( m_zlib.mode == ON::write ) ? true : false;
00585     if ( !rc ) {
00586       CompressionEnd();
00587       if ( Z_OK == deflateInit( &m_zlib.strm, Z_BEST_COMPRESSION ) ) {
00588         m_zlib.mode = ON::write;
00589         rc = true;
00590       }
00591       else {
00592         memset(&m_zlib.strm,0,sizeof(m_zlib.strm));
00593       }
00594     }
00595   }
00596   else if ( ReadMode() ) {
00597     rc = ( m_zlib.mode == ON::read ) ? true : false;
00598     if ( !rc ) {
00599       CompressionEnd();
00600       if ( Z_OK == inflateInit( &m_zlib.strm ) ) {
00601         m_zlib.mode = ON::read;
00602         rc = true;
00603       }
00604       else {
00605         memset(&m_zlib.strm,0,sizeof(m_zlib.strm));
00606       }
00607     }
00608   }
00609   else {
00610     CompressionEnd();
00611   }
00612   return rc;
00613 }
00614 
00615 void ON_BinaryArchive::CompressionEnd()
00616 {
00617   // inflateEnd() and deflateEnd() are in zlib 1.3.3
00618   switch ( m_zlib.mode ) {
00619   case ON::read:
00620   case ON::read3dm:
00621     inflateEnd(&m_zlib.strm);
00622     break;
00623   case ON::write:
00624   case ON::write3dm:
00625     deflateEnd(&m_zlib.strm);
00626     break;
00627   default: // to quiet lint
00628     break;
00629   }
00630   memset(&m_zlib.strm,0,sizeof(m_zlib.strm));
00631   m_zlib.mode = ON::unknown_archive_mode;
00632 }
00633 
00634 
00635 
00636 struct ON_CompressedBufferHelper
00637 {
00638   int action; // 1 = compress, 2 = uncompress
00639   enum
00640   {
00641     sizeof_x_buffer = 16384
00642   };
00643   unsigned char    buffer[sizeof_x_buffer];
00644   z_stream         strm;
00645   size_t           m_buffer_compressed_capacity;
00646 };
00647 
00648 ON_CompressedBuffer::ON_CompressedBuffer()
00649                     : m_sizeof_uncompressed(0),
00650                       m_sizeof_compressed(0),
00651                       m_crc_uncompressed(0),
00652                       m_crc_compressed(0),
00653                       m_method(0),
00654                       m_sizeof_element(0),
00655                       m_buffer_compressed_capacity(0),
00656                       m_buffer_compressed(0)
00657 {
00658 }
00659 
00660 ON_CompressedBuffer::~ON_CompressedBuffer()
00661 {
00662   Destroy();
00663 }
00664 
00665 ON_CompressedBuffer::ON_CompressedBuffer(const ON_CompressedBuffer& src)
00666                     : m_sizeof_uncompressed(0),
00667                       m_sizeof_compressed(0),
00668                       m_crc_uncompressed(0),
00669                       m_crc_compressed(0),
00670                       m_method(0),
00671                       m_sizeof_element(0),
00672                       m_buffer_compressed_capacity(0),
00673                       m_buffer_compressed(0)
00674 {
00675   *this = src;
00676 }
00677 
00678 ON_CompressedBuffer& ON_CompressedBuffer::operator=(const ON_CompressedBuffer& src)
00679 {
00680   if ( this != &src )
00681   {
00682     Destroy();
00683     if( src.m_buffer_compressed && src.m_sizeof_compressed > 0 )
00684     {
00685       m_sizeof_uncompressed = src.m_sizeof_uncompressed;
00686       m_sizeof_compressed   = src.m_sizeof_compressed;
00687       m_crc_uncompressed    = src.m_crc_uncompressed;
00688       m_crc_compressed      = src.m_crc_compressed;
00689       m_method              = src.m_method;
00690       m_sizeof_element      = src.m_sizeof_element;
00691 
00692       m_buffer_compressed = onmalloc(m_sizeof_compressed);
00693       if( m_buffer_compressed )
00694       {
00695         m_buffer_compressed_capacity = m_sizeof_compressed;
00696         memcpy(m_buffer_compressed,src.m_buffer_compressed,m_sizeof_compressed);
00697       }
00698     }
00699   }
00700   return *this;
00701 }
00702 
00703 bool ON_CompressedBuffer::Write( ON_BinaryArchive& binary_archive ) const
00704 {
00705   bool rc = binary_archive.BeginWrite3dmChunk(TCODE_ANONYMOUS_CHUNK,1,0);
00706   if ( !rc )
00707     return false;
00708 
00709   for(;;)
00710   {
00711     rc = binary_archive.WriteSize(m_sizeof_uncompressed);
00712     if (!rc)
00713       break;
00714     rc = binary_archive.WriteSize((m_buffer_compressed && m_sizeof_compressed>0) ? m_sizeof_compressed : 0);
00715     if (!rc)
00716       break;
00717     rc = binary_archive.WriteInt(m_crc_uncompressed);
00718     if (!rc)
00719       break;
00720     rc = binary_archive.WriteInt(m_crc_compressed);
00721     if (!rc)
00722       break;
00723     rc = binary_archive.WriteInt(m_method);
00724     if (!rc)
00725       break;
00726     rc = binary_archive.WriteInt(m_sizeof_element);
00727     if (!rc)
00728       break;
00729     if ( m_buffer_compressed && m_sizeof_compressed > 0 )
00730     {
00731       rc = binary_archive.WriteByte(m_sizeof_compressed,m_buffer_compressed);
00732       if (!rc)
00733         break;
00734     }
00735     break;
00736   }
00737 
00738   if ( !binary_archive.EndWrite3dmChunk() )
00739     rc = false;
00740 
00741   return rc;
00742 }
00743 
00744 bool ON_CompressedBuffer::Read( ON_BinaryArchive& binary_archive )
00745 {
00746   int major_version = 0;
00747   int minor_version = 0;
00748   bool rc = binary_archive.BeginRead3dmChunk(TCODE_ANONYMOUS_CHUNK,&major_version,&minor_version);
00749   if ( !rc )
00750     return false;
00751 
00752   for(;;)
00753   {
00754     rc = ( 1 == major_version );
00755     if ( !rc ) 
00756       break;
00757     rc = binary_archive.ReadSize(&m_sizeof_uncompressed);
00758     if (!rc)
00759       break;
00760     rc = binary_archive.ReadSize(&m_sizeof_compressed);
00761     if (!rc)
00762       break;
00763     rc = binary_archive.ReadInt(&m_crc_uncompressed);
00764     if (!rc)
00765       break;
00766     rc = binary_archive.ReadInt(&m_crc_compressed);
00767     if (!rc)
00768       break;
00769     rc = binary_archive.ReadInt(&m_method);
00770     if (!rc)
00771       break;
00772     rc = binary_archive.ReadInt(&m_sizeof_element);
00773     if (!rc)
00774       break;
00775     if ( m_sizeof_compressed > 0 )
00776     {
00777       m_buffer_compressed = onmalloc(m_sizeof_compressed);
00778       if ( m_buffer_compressed )
00779       {
00780         m_buffer_compressed_capacity = m_sizeof_compressed;
00781         rc = binary_archive.ReadByte(m_sizeof_compressed,m_buffer_compressed);
00782       }
00783       else
00784       {
00785         m_sizeof_compressed =0;
00786       }
00787       if (!rc)
00788         break;
00789     }
00790 
00791     break;
00792   }
00793 
00794   if ( !binary_archive.EndRead3dmChunk() )
00795     rc = false;
00796 
00797   return rc;
00798 }
00799 
00800 void ON_CompressedBuffer::Destroy()
00801 {
00802   if ( m_buffer_compressed )
00803     onfree(m_buffer_compressed);
00804 
00805   m_sizeof_uncompressed = 0;
00806   m_sizeof_compressed   = 0;
00807   m_crc_uncompressed    = 0;
00808   m_crc_compressed      = 0;
00809   m_method              = 0;
00810   m_sizeof_element      = 0;
00811   m_buffer_compressed   = 0;
00812   m_buffer_compressed_capacity = 0;
00813 }
00814 
00815 bool ON_CompressedBuffer::Compress(
00816         size_t sizeof__inbuffer,  // sizeof uncompressed input data
00817         const void* inbuffer,     // uncompressed input data
00818         int sizeof_element
00819         )
00820 {
00821   Destroy();
00822 
00823   //size_t compressed_size = 0;
00824   bool rc = false;
00825 
00826   if ( sizeof__inbuffer > 0 && 0 == inbuffer )
00827     return false;
00828 
00829   if ( 0 == sizeof__inbuffer )
00830     return true;
00831 
00832   // number of bytes of uncompressed data
00833   m_sizeof_uncompressed = sizeof__inbuffer;
00834 
00835   ON_CompressedBufferHelper helper;
00836   memset(&helper,0,sizeof(helper));
00837   helper.action = 1;
00838 
00839   bool bToggleByteOrder = false;
00840   switch(sizeof_element)
00841   {
00842   case 2:
00843   case 4:
00844   case 8:
00845     if ( 0 == (sizeof__inbuffer%sizeof_element) )
00846     {
00847       m_sizeof_element = sizeof_element;
00848       bToggleByteOrder = (ON::big_endian == ON::Endian());
00849     }
00850     break;
00851   };
00852 
00853   if ( bToggleByteOrder ) 
00854   {
00855     ON_BinaryFile::ToggleByteOrder( 
00856       (int)(sizeof__inbuffer/m_sizeof_element), 
00857       m_sizeof_element, 
00858       inbuffer, 
00859       (void*)inbuffer
00860       );
00861   }
00862 
00863   m_method = (sizeof__inbuffer > 128) ? 1 : 0;
00864   if ( m_method ) 
00865   {
00866     if ( !CompressionInit(&helper) ) 
00867     {
00868       CompressionEnd(&helper);
00869       m_method = 0;
00870     }
00871     else
00872     {
00873       m_buffer_compressed = onmalloc(sizeof__inbuffer/4);
00874       size_t sizeof_compressed = DeflateHelper( &helper, sizeof__inbuffer, inbuffer );
00875       CompressionEnd(&helper);
00876       if ( sizeof_compressed > 0 && sizeof_compressed == m_sizeof_compressed )
00877       {
00878         rc = true;
00879         if ( 2*m_buffer_compressed_capacity > 3*m_sizeof_compressed )
00880         {
00881           // release memory we don't need
00882           m_buffer_compressed_capacity = m_sizeof_compressed;
00883           m_buffer_compressed = onrealloc(m_buffer_compressed,m_buffer_compressed_capacity);
00884         }
00885       }
00886       else
00887       {
00888         Destroy();
00889         m_method = 0;
00890       }
00891     }
00892   }
00893 
00894   if ( 0 ==  m_method )
00895   {
00896     // uncompressed
00897     m_buffer_compressed = onmalloc(sizeof__inbuffer);
00898     if ( m_buffer_compressed )
00899     {
00900       m_sizeof_compressed = sizeof__inbuffer;
00901       m_buffer_compressed_capacity = sizeof__inbuffer;
00902       memcpy(m_buffer_compressed,inbuffer,sizeof__inbuffer);
00903       rc = true;
00904     }
00905   }
00906 
00907   if ( bToggleByteOrder ) 
00908   {
00909     ON_BinaryFile::ToggleByteOrder( 
00910       (int)(sizeof__inbuffer/m_sizeof_element), 
00911       m_sizeof_element, 
00912       inbuffer, 
00913       (void*)inbuffer
00914       );
00915   }
00916 
00917   if (rc)
00918   {
00919     m_crc_uncompressed = ON_CRC32( 0, sizeof__inbuffer, inbuffer );
00920     m_crc_compressed   = ON_CRC32( 0, m_sizeof_compressed, m_buffer_compressed );
00921   }
00922 
00923   return rc;
00924 }
00925 
00926 bool ON_CompressedBuffer::Uncompress(
00927           void* outbuffer,
00928           int* bFailedCRC
00929           ) const
00930 {
00931   bool rc = false;
00932 
00933   if ( bFailedCRC)
00934     *bFailedCRC = false;
00935   if ( 0 == m_sizeof_uncompressed )
00936     return true;
00937   if ( 0 == outbuffer )
00938     return false;
00939 
00940   if ( m_method != 0 && m_method != 1 )
00941     return false;
00942 
00943   ON__UINT32 compressed_crc = ON_CRC32( 0, m_sizeof_compressed, m_buffer_compressed );
00944   if ( compressed_crc != m_crc_compressed )
00945   {
00946     // m_buffer_compressed is corrupt - let's hope the corruption
00947     // is near the end and we ge something useful from the
00948     // beginning.
00949     memset(outbuffer,0,m_sizeof_uncompressed);
00950     if ( bFailedCRC)
00951       *bFailedCRC = false;
00952   }
00953 
00954   switch(m_method)
00955   {
00956   case 0: // uncompressed
00957     if (    m_buffer_compressed
00958          && m_sizeof_uncompressed == m_sizeof_compressed
00959          )
00960     {
00961       memcpy(outbuffer,m_buffer_compressed,m_sizeof_uncompressed);
00962       rc = true;
00963     }
00964     break;
00965 
00966   case 1: // compressed
00967     {
00968       ON_CompressedBufferHelper helper;
00969       memset(&helper,0,sizeof(helper));
00970       helper.action = 2;
00971       rc = CompressionInit(&helper);
00972       if (rc)
00973       {
00974         rc = InflateHelper( &helper, m_sizeof_uncompressed, outbuffer );
00975         CompressionEnd(&helper);
00976       }
00977     }
00978     break;
00979   }
00980 
00981   switch(m_sizeof_element)
00982   {
00983   case 2:
00984   case 4:
00985   case 8:
00986     if ( 0 == (m_sizeof_uncompressed%m_sizeof_element) )
00987     {
00988       if ( ON::big_endian == ON::Endian() )
00989       {
00990         ON_BinaryFile::ToggleByteOrder( 
00991           (int)(m_sizeof_uncompressed/m_sizeof_element), 
00992           m_sizeof_element, 
00993           outbuffer, 
00994           outbuffer
00995           );
00996       }
00997     }
00998     break;
00999   };
01000 
01001 
01002   if (rc ) 
01003   {
01004     ON__UINT32 uncompressed_crc = ON_CRC32( 0, m_sizeof_uncompressed, outbuffer );
01005     if ( uncompressed_crc != m_crc_uncompressed ) 
01006     {
01007       ON_ERROR("ON_CompressedBuffer::Uncompress() crc error");
01008       if ( bFailedCRC )
01009         *bFailedCRC = true;
01010     }
01011   }
01012 
01013   return rc;
01014 }
01015 
01016 bool ON_CompressedBuffer::WriteChar( 
01017         size_t count, const void* buffer         
01018         )
01019 {
01020   bool rc = true;
01021   if ( count > 0 && buffer )
01022   {
01023     if ( count + m_sizeof_compressed > m_buffer_compressed_capacity )
01024     {
01025       size_t delta = count + m_sizeof_compressed - m_buffer_compressed_capacity;
01026       if ( delta < 2048 )
01027         delta = 2048;
01028       if ( delta < m_buffer_compressed_capacity/4 )
01029         delta = m_buffer_compressed_capacity/4;
01030       m_buffer_compressed_capacity += delta;
01031       m_buffer_compressed = onrealloc(m_buffer_compressed,m_buffer_compressed_capacity);
01032       if ( !m_buffer_compressed )
01033       {
01034         m_buffer_compressed_capacity = 0;
01035         m_sizeof_compressed = 0;
01036         return false;
01037       }
01038     }
01039     memcpy(((char*)m_buffer_compressed)+m_sizeof_compressed,buffer,count);
01040     m_sizeof_compressed += count;
01041   }
01042   else
01043   {
01044     rc = (0 == count);
01045   }
01046   return rc;
01047 }
01048 
01049 
01050 size_t ON_CompressedBuffer::DeflateHelper( // returns number of bytes written
01051         ON_CompressedBufferHelper* helper,
01052         size_t sizeof___inbuffer,  // sizeof uncompressed input data ( > 0 )
01053         const void* in___buffer     // uncompressed input data ( != NULL )
01054         )
01055 {
01056   /*
01057     In "standard" (in 2005) 32 bit code
01058     
01059       sizeof(int)     = 4 bytes, 
01060       sizeof(long)    = 4 bytes,
01061       sizeof(pointer) = 4 bytes, and
01062       sizeof(size_t)  = 4 bytes.
01063 
01064     Theoretically I don't need to use multiple input buffer
01065     chunks in case.  But I'm paranoid and I will use multiple 
01066     input chunks when sizeof_inbuffer > 2GB in order to dodge
01067     any potential zlib signed verses unsigned compare bugs or
01068     having a signed int i++ roll over to a negative number.
01069 
01070     In "standard" code that has 64 bit pointers
01071     
01072       sizeof(int)     >= 4 bytes, (it's 4 on MS VS2005) 
01073       sizeof(long)    >= 4 bytes, (it's 4 on MS VS2005)
01074       sizeof(pointer)  = 8 bytes, and
01075       sizeof(size_t)   = 8 bytes.
01076 
01077     So, I'm going to assume the ints and longs in the zlib code 
01078     are 4 bytes, but I could have sizeof_inbuffer > 4GB.
01079     This means I have to use multiple input buffer chunks.  
01080     In this case I still use multiple input chunks when 
01081     sizeof_inbuffer > 2GB in order to dodge any potential zlib
01082     signed verses unsigned compare bugs or having a signed
01083     int i++ roll over to a negative number.
01084 
01085     So, I set
01086     
01087        const size_t max_avail = (largest signed 4 byte integer - 15)
01088     
01089     and feed inflate and deflate buffers with size <= max_avail.
01090 
01091 
01092     This information below is from the zlib 1.2.3 FAQ.  
01093 
01094     32. Can zlib work with greater than 4 GB of data?
01095 
01096         Yes. inflate() and deflate() will process any amount of data correctly.
01097         Each call of inflate() or deflate() is limited to input and output chunks
01098         of the maximum value that can be stored in the compiler's "unsigned int"
01099         type, but there is no limit to the number of chunks. Note however that the
01100         strm.total_in and strm_total_out counters may be limited to 4 GB. These
01101         counters are provided as a convenience and are not used internally by
01102         inflate() or deflate(). The application can easily set up its own counters
01103         updated after each call of inflate() or deflate() to count beyond 4 GB.
01104         compress() and uncompress() may be limited to 4 GB, since they operate in a
01105         single call. gzseek() and gztell() may be limited to 4 GB depending on how
01106         zlib is compiled. See the zlibCompileFlags() function in zlib.h.
01107 
01108         The word "may" appears several times above since there is a 4 GB limit
01109         only if the compiler's "long" type is 32 bits. If the compiler's "long"
01110         type is 64 bits, then the limit is 16 exabytes.
01111   */
01112 
01113   const size_t max_avail = 0x7FFFFFF0;
01114 
01115   //  Compressed information is saved in a chunk.
01116   bool rc = true;
01117 
01118   size_t out__count = 0;
01119   int zrc = Z_OK;
01120 
01121   size_t my_avail_in = sizeof___inbuffer;
01122   unsigned char* my_next_in = (unsigned char*)in___buffer;
01123 
01124   size_t d = my_avail_in;
01125   if ( d > max_avail )
01126     d = max_avail;
01127 
01128   ON_CompressedBufferHelper& m_zlib = *helper;
01129 
01130   m_zlib.strm.next_in = my_next_in;
01131   m_zlib.strm.avail_in = (unsigned int)d; 
01132   my_avail_in -= d;
01133   my_next_in  += d;
01134 
01135   m_zlib.strm.next_out = m_zlib.buffer;
01136   m_zlib.strm.avail_out = m_zlib.sizeof_x_buffer;
01137 
01138   // counter guards prevents infinte loops if there is a bug in zlib return codes.
01139   int counter = 512; 
01140   int flush = Z_NO_FLUSH;
01141 
01142   size_t deflate_output_count = 0;
01143 
01144   while( rc && counter > 0 ) 
01145   {
01146     // Call zlib's deflate function.  It can either process
01147     // more input from m_zlib.strm.next_in[], create more
01148     // compressed output in m_zlib.strm.next_out[], or do both.
01149     if ( 0 == my_avail_in && 0 == m_zlib.strm.avail_in )
01150     {
01151       // no uncompressed input is left - switch to finish mode
01152       flush = Z_FINISH;
01153     }
01154     zrc = z_deflate( &m_zlib.strm, flush ); 
01155     if ( zrc < 0 ) 
01156     {
01157       // Something went haywire - bail out.
01158       ON_ERROR("ON_CompressedBuffer::DeflateHelper - z_deflate failure");
01159       rc = false;
01160       break;
01161     }
01162 
01163     deflate_output_count = m_zlib.sizeof_x_buffer - m_zlib.strm.avail_out;
01164     if ( deflate_output_count > 0 ) 
01165     {
01166       // The last call to deflate created output.  Send
01167       // this output to the archive.
01168       rc = WriteChar( deflate_output_count, m_zlib.buffer );
01169       if ( !rc )
01170         break;
01171       out__count += deflate_output_count;
01172       m_zlib.strm.next_out  = m_zlib.buffer;
01173       m_zlib.strm.avail_out = m_zlib.sizeof_x_buffer;
01174     }
01175 
01176     if ( Z_FINISH == flush && Z_STREAM_END == zrc )
01177     {
01178       // no input left, all pending compressing is finished,
01179       // and all compressed output has been returned.
01180       break;
01181     }
01182 
01183     if ( my_avail_in > 0 && m_zlib.strm.avail_in < max_avail )
01184     {
01185       // inbuffer[] had more than max_zlib_avail_in bytes in it
01186       // and I am feeding inbuffer[] to deflate in smaller chunks
01187       // that the 32 bit integers in the zlib code can handle.
01188       if ( 0 == m_zlib.strm.avail_in || 0 == m_zlib.strm.next_in )
01189       {
01190         // The call to deflate() used up all the input 
01191         // in m_zlib.strm.next_in[].  I can feed it another chunk
01192         // from inbuffer[]
01193         d = my_avail_in;
01194         if ( d > max_avail )
01195           d = max_avail;
01196         m_zlib.strm.next_in = my_next_in;
01197         m_zlib.strm.avail_in = (unsigned int)d; 
01198       }
01199       else
01200       {
01201         // The call to deflate left some input in m_zlib.strm.next_in[],
01202         // but I can increase m_zlib.strm.avail_in.
01203         d =  max_avail - m_zlib.strm.avail_in;
01204         if ( d > my_avail_in )
01205           d = my_avail_in;
01206         m_zlib.strm.avail_in += (unsigned int)d;
01207       }
01208 
01209       my_avail_in -= d;
01210       my_next_in  += d;
01211     }
01212     else if ( 0 == deflate_output_count )
01213     {
01214       // no buffer changes this time
01215       counter--;
01216     }
01217 
01218     if ( zrc != Z_OK )
01219     {
01220       break;
01221     }
01222   }
01223 
01224   if ( 0 == counter )
01225   {
01226     rc = false;
01227   }
01228 
01229   return (rc ? out__count : 0);
01230 }
01231 
01232 
01233 bool ON_CompressedBuffer::InflateHelper(
01234         ON_CompressedBufferHelper* helper,
01235         size_t sizeof___outbuffer,  // sizeof uncompressed data
01236         void* out___buffer          // buffer for uncompressed data
01237         ) const
01238 {
01239   const size_t max_avail = 0x7FFFFFF0; // See max_avail comment in ON_CompressedBuffer::InflateHelper
01240 
01241   bool rc = true;
01242 
01243   int zrc = -1;
01244 
01245   // set up zlib in buffer
01246   unsigned char* my_next_in = (unsigned char*)m_buffer_compressed;
01247   size_t my_avail_in = m_sizeof_compressed;
01248 
01249   size_t d = my_avail_in;
01250   if ( d > max_avail )
01251     d = max_avail;
01252 
01253   struct ON_CompressedBufferHelper& m_zlib = *helper;
01254 
01255   m_zlib.strm.next_in  = my_next_in;
01256   m_zlib.strm.avail_in = (unsigned int)d;
01257   my_next_in  += d;
01258   my_avail_in -= d;
01259 
01260   // set up zlib out buffer
01261   unsigned char* my_next_out = (unsigned char*)out___buffer;
01262   size_t my_avail_out = sizeof___outbuffer;
01263 
01264   d = my_avail_out;
01265   if ( d > max_avail )
01266     d = max_avail;
01267   m_zlib.strm.next_out  = my_next_out;
01268   m_zlib.strm.avail_out = (unsigned int)d;
01269   my_next_out  += d;
01270   my_avail_out -= d;
01271 
01272   // counter guards against infinte loop if there are
01273   // bugs in zlib return codes
01274   int counter = 512;
01275   int flush = Z_NO_FLUSH;
01276 
01277   while ( rc && counter > 0 )
01278   {
01279     // Call zlib's inflate function.  It can either process
01280     // more input from m_zlib.strm.next_in[], create more
01281     // uncompressed output in m_zlib.strm.next_out[], or do both.
01282     if ( 0 == my_avail_in && 0 == m_zlib.strm.avail_in )
01283     {
01284       // no compressed input is left - switch to finish mode
01285       flush = Z_FINISH;
01286     }
01287     zrc = z_inflate( &m_zlib.strm, flush );
01288     if ( zrc < 0 ) 
01289     {
01290       // Something went haywire - bail out.
01291       ON_ERROR("ON_CompressedBuffer::InflateHelper - z_inflate failure");
01292       rc = false;
01293       break;
01294     }
01295 
01296     if ( Z_FINISH == flush && Z_STREAM_END == zrc )
01297     {
01298       // no input left, all pending decompression is finished,
01299       // and all decompressed output has been returned.
01300       break;
01301     }
01302 
01303     d = 0;
01304     if ( my_avail_in > 0 && m_zlib.strm.avail_in < max_avail )
01305     {
01306       if ( 0 == m_zlib.strm.avail_in || 0 == m_zlib.strm.next_in )
01307       {
01308         // The call to inflate() used up all the input 
01309         // in m_zlib.strm.next_in[].  I can feed it another chunk
01310         // from inbuffer[]
01311         d = my_avail_in;
01312         if ( d > max_avail )
01313           d = max_avail;
01314         m_zlib.strm.next_in  = my_next_in;
01315         m_zlib.strm.avail_in = (unsigned int)d; 
01316       }
01317       else
01318       {
01319         // The call to inflate() left some input in m_zlib.strm.next_in[],
01320         // but I can increase m_zlib.strm.avail_in.
01321         d =  max_avail - m_zlib.strm.avail_in;
01322         if ( d > my_avail_in )
01323           d = my_avail_in;
01324         m_zlib.strm.avail_in += (unsigned int)d;
01325       }
01326       my_next_in  += d;
01327       my_avail_in -= d;
01328     }
01329 
01330     if ( my_avail_out > 0 && m_zlib.strm.avail_out < max_avail )
01331     {
01332       // increase m_zlib.strm.next_out[] buffer
01333       if ( 0 == m_zlib.strm.avail_out || 0 == m_zlib.strm.next_out )
01334       {
01335         d = my_avail_out;
01336         if ( d > max_avail )
01337           d = max_avail;
01338         m_zlib.strm.next_out  = my_next_out;
01339         m_zlib.strm.avail_out = (unsigned int)d;
01340       }
01341       else
01342       {
01343         d = max_avail - m_zlib.strm.avail_out;
01344         if ( d > my_avail_out )
01345           d = my_avail_out;
01346         m_zlib.strm.avail_out += ((unsigned int)d);
01347       }
01348       my_next_out  += d;
01349       my_avail_out -= d;
01350     }
01351     else if ( 0 == d )
01352     {
01353       // no buffer changes
01354       counter--;
01355     }
01356   }
01357 
01358   if ( 0 == counter )
01359   {
01360     rc = false;
01361   }
01362 
01363   return rc;
01364 }
01365 
01366 bool ON_CompressedBuffer::CompressionInit( struct ON_CompressedBufferHelper* helper ) const
01367 {
01368   bool rc = false;
01369 
01370   if ( helper )
01371   {
01372     // inflateInit() and deflateInit() are in zlib 1.3.3
01373     if ( 1 == helper->action ) 
01374     {
01375       // begin compression using zlib's deflate tool
01376       if ( Z_OK == deflateInit( &helper->strm, Z_BEST_COMPRESSION ) ) 
01377       {
01378         rc = true;
01379       }
01380       else 
01381       {
01382         memset(&helper->strm,0,sizeof(helper->strm));
01383         helper->action = 0;
01384       }
01385     }
01386     else if ( 2 == helper->action ) 
01387     {
01388       // begin uncompression using zlib's inflate tool
01389       if ( Z_OK == inflateInit( &helper->strm ) ) 
01390       {
01391         rc = true;
01392       }
01393       else 
01394       {
01395         memset(&helper->strm,0,sizeof(helper->strm));
01396         helper->action = 0;
01397       }
01398     }
01399   }
01400 
01401   return rc;
01402 }
01403 
01404 bool ON_CompressedBuffer::CompressionEnd( struct ON_CompressedBufferHelper* helper ) const
01405 {
01406   bool rc = false;
01407 
01408   if ( helper )
01409   {
01410     // inflateEnd() and deflateEnd() are in zlib 1.3.3
01411     if ( 1 == helper->action ) 
01412     {
01413       // finish compression
01414       deflateEnd(&helper->strm);
01415       rc = true;
01416     }
01417     else if ( 2 == helper->action )
01418     {
01419       // finish decompression
01420       inflateEnd(&helper->strm);
01421       rc = true;
01422     }
01423     memset(&helper->strm,0,sizeof(helper->strm));
01424     helper->action = 0;
01425   }
01426 
01427   return rc;
01428 }
01429 
01430 


pcl
Author(s): Open Perception
autogenerated on Wed Aug 26 2015 15:27:03