Ejemplo n.º 1
0
size_t up_unpack_step( void* outbuf_ptr, size_t outbuf_size, size_t* data_left ) {
  lib_zstream_unpack.next_out = outbuf_ptr;
  lib_zstream_unpack.avail_out = outbuf_size;

  int result;
  size_t input_size = lib_zstream_unpack.avail_in;
  result = z_inflate( &lib_zstream_unpack, Z_NO_FLUSH );

  switch (result) {
    case Z_OK:
    case Z_STREAM_END:
      lib_unpack_left -= input_size - lib_zstream_unpack.avail_in;
      if (data_left != NULL) { *data_left = lib_zstream_unpack.avail_in; }
      return outbuf_size - lib_zstream_unpack.avail_out;
    break;

    default:
      lib_error = result;
      return 0;
  }
}
Ejemplo n.º 2
0
bool ON_UncompressStream::End()
{
  if ( 0 == m_implementation )
  {
    ErrorHandler();
    return false;
  }
  
  struct ON_ZlibImplementation* imp = (struct ON_ZlibImplementation*)m_implementation;
  z_stream& strm = imp->m_strm;
  if ( 0 != strm.avail_in || 0 != strm.next_in )
  {
    // strm.avail_in is always zero when we leave an ON_UncompressStream function.
    ErrorHandler();
    return false;
  }

  const ON__UINT32 sizeof_out_buffer = (ON__UINT32)(sizeof(imp->m_zlib_out_buffer));
  void* out_buffer = imp->m_zlib_out_buffer;
  int zrc = Z_OK;
  bool rc = false;
  ON__UINT32 inflate_output_count;

  // counter prevents infinte loops if there is a bug in zlib return codes.
  for( int counter = 512; counter > 0; counter-- )
  {
    // provide storage for compressed stream output
    strm.avail_in = 0;
    strm.next_in = 0;
    strm.next_out  = (z_Bytef*)out_buffer;
    strm.avail_out = sizeof_out_buffer;

    // finish compression calculation
    zrc = z_inflate( &strm, Z_FINISH ); 
    if ( zrc < 0 ) 
    {
      // Something went haywire - bail out.
      ErrorHandler();
      rc = false;
      break;
    }

    inflate_output_count = sizeof_out_buffer - strm.avail_out;
    if ( inflate_output_count > 0 ) 
    {
      // The last call to inflate created uncompressed output.  
      // Send the output to the uncompressed stream handler.

      // Calculate the updated crc and size before we call
      // the output handler because someday sombody will
      // decide it's a good idea to modify the values
      // in the buffer argument.
      ON__UINT32 out_crc1 = ON_CRC32( m_out_crc, inflate_output_count, out_buffer);
      ON__UINT64 out_size1 = m_out_size + inflate_output_count;
      
      rc = (0 != m_out_callback_function)
          ? m_out_callback_function( m_out_callback_context, inflate_output_count, out_buffer )
          : Out( m_out_callback_context, inflate_output_count, out_buffer );
      if ( !rc )
        break;

      // Update compressed stream crc and size
      m_out_crc = out_crc1;
      m_out_size = out_size1;
      counter = 512; // created output - reset counter that detects stalls
    }

    if ( Z_STREAM_END == zrc )
    {
      // no input left, all pending compressing is finished,
      // and all compressed output has been returned.
      rc = true;
      break;
    }
  }

  strm.avail_in = 0;
  strm.next_in = 0;
  strm.next_out  = 0;
  strm.avail_out = 0;

  inflateEnd(&strm);

  onfree(m_implementation);
  m_implementation = 0;

  return rc;
}
Ejemplo n.º 3
0
bool ON_UncompressStream::In( ON__UINT64 size, const void* compressed_buffer )
{
  if ( size <= 0 )
    return true;

  if ( 0 == m_implementation )
  {
    ErrorHandler();
    return false;
  }

  if ( 0 == compressed_buffer )
  {
    ErrorHandler();
    return false;
  }
  
  struct ON_ZlibImplementation* imp = (struct ON_ZlibImplementation*)m_implementation;
  z_stream& strm = imp->m_strm;
  if ( 0 != strm.avail_in || 0 != strm.next_in )
  {
    // strm.avail_in is always zero when we leave an ON_UncompressStream function.
    ErrorHandler();
    return false;
  }

  const ON__UINT32 sizeof_out_buffer = (ON__UINT32)(sizeof(imp->m_zlib_out_buffer));
  void* out_buffer = imp->m_zlib_out_buffer;
  int zrc = Z_OK;
  const ON__UINT64 max_sz = 0x7FFFFFF0;
  bool rc = false;
  ON__UINT32 inflate_output_count;

  // counter prevents infinte loops if there is a bug in zlib return codes.
  for( int counter = 512; counter > 0; counter-- )
  {
    // Call zlib's inflate function.  It can process
    // more compressed input from strm.next_in[], create more
    // uncompressed output in strm.next_out[], or do both.

    // provide storage for uncompressed stream output
    strm.next_out  = (z_Bytef*)out_buffer;
    strm.avail_out = sizeof_out_buffer;

    if ( strm.avail_in <= 0 )
    {
      if ( size <= 0 )
      {
        // finshed with compressed input
        break;
      }
      // submit a portion of compressed_buffer to zlib
      ON__UINT64 sz = (size > max_sz) ? max_sz : size;
      m_in_size += sz;
      m_in_crc = ON_CRC32(m_in_crc,(size_t)sz,compressed_buffer); // (size_t) cast is safe because sz <= max_sz = 0x7FFFFFF0
      strm.next_in = (z_Bytef*)compressed_buffer;
      strm.avail_in = (ON__UINT32)sz;
      compressed_buffer = ((const unsigned char*)compressed_buffer) + sz;
      size -= sz;
      counter = 512; // added input - reset the counter that detects stalls
    }

    // calculate compression
    ON__UINT32 avail_in0 = strm.avail_in;
    ON__UINT32 avail_out0 = strm.avail_out;
    zrc = z_inflate( &strm, Z_NO_FLUSH ); 
    if ( zrc < 0 ) 
    {
      // Something went haywire - bail out.
      ErrorHandler();
      rc = false;
      break;
    }
    if ( strm.avail_in < avail_in0 || strm.avail_out > avail_out0 )
    {
      // zlib did something
      rc = true; 
    }    

    inflate_output_count = sizeof_out_buffer - strm.avail_out;
    if ( inflate_output_count > 0 ) 
    {
      // The last call to inflate created uncompressed output.  
      // Send the output to the uncompressed stream handler.

      // Calculate the updated crc and size before we call
      // the output handler because someday sombody will
      // decide it's a good idea to modify the values
      // in the buffer argument.
      ON__UINT32 out_crc1 = ON_CRC32( m_out_crc, inflate_output_count, out_buffer);
      ON__UINT64 out_size1 = m_out_size + inflate_output_count;
      
      rc = (0 != m_out_callback_function)
          ? m_out_callback_function( m_out_callback_context, inflate_output_count, out_buffer )
          : Out( m_out_callback_context, inflate_output_count, out_buffer );
      if ( !rc )
        break;

      // Update compressed stream crc and size
      m_out_crc = out_crc1;
      m_out_size = out_size1;
      counter = 512; // created output - reset counter that detects stalls
    }

    if ( size <= 0 && strm.avail_in <= 0 )
    {
      // no input left
      break;
    }
  }

  strm.avail_in = 0;
  strm.next_in = 0;
  strm.next_out  = 0;
  strm.avail_out = 0;

  return rc;
}
Ejemplo n.º 4
0
bool ON_BinaryArchive::ReadInflate(
        size_t sizeof___outbuffer,  // sizeof uncompressed data
        void* out___buffer          // buffer for uncompressed data
        )
{
  const size_t max_avail = 0x7FFFFFF0; // See max_avail comment in ON_BinaryArchive::WriteInflate

  size_t sizeof__inbuffer = 0;
  void* in___buffer = 0;
  bool rc = false;

  // read compressed buffer from 3dm archive
  bool bValidCompressedBuffer = false;
  {
    ON__UINT32 tcode = 0;
    ON__INT64  big_value = 0;
    rc = BeginRead3dmBigChunk(&tcode,&big_value );
    if (!rc)
    {
      if ( 0 != out___buffer && sizeof___outbuffer > 0 )
        memset(out___buffer,0,sizeof___outbuffer);
      return false;
    }
    if (   tcode == TCODE_ANONYMOUS_CHUNK 
        && big_value > 4 
        && sizeof___outbuffer > 0 
        && 0 != out___buffer )
    {
      // read compressed buffer from the archive
      sizeof__inbuffer = (size_t)(big_value-4); // the last 4 bytes in this chunk are a 32 bit crc
      in___buffer = onmalloc(sizeof__inbuffer);
      if ( !in___buffer )
      {
        rc = false;
      }
      else
      {
        rc = ReadByte( sizeof__inbuffer, in___buffer );
      }
    }
    else
    {
      // Either I have the wrong chunk, or the input
      // parameters are bogus. 
      rc = false;
    }
    int c0 = m_bad_CRC_count;
    if ( !EndRead3dmChunk() )
    {
      rc = false;
    }
    bValidCompressedBuffer = ( m_bad_CRC_count > c0 )
                           ? false
                           : rc;
  }

  if ( !bValidCompressedBuffer && 0 != out___buffer && sizeof___outbuffer > 0 )
  {
    // Decompression will fail, but we might get something valid
    // at the start if the data flaw was near the end of the buffer.
    memset(out___buffer,0,sizeof___outbuffer);
  }

  if ( !rc )
  {
    if ( in___buffer )
    {
      onfree(in___buffer);
      in___buffer = 0;
    }
    return false;
  }

  int zrc = -1;

  // set up zlib in buffer
  unsigned char* my_next_in = (unsigned char*)in___buffer;
  size_t my_avail_in = sizeof__inbuffer;

  size_t d = my_avail_in;
  if ( d > max_avail )
    d = max_avail;
  m_zlib.strm.next_in  = my_next_in;
  m_zlib.strm.avail_in = (unsigned int)d;
  my_next_in  += d;
  my_avail_in -= d;

  // set up zlib out buffer
  unsigned char* my_next_out = (unsigned char*)out___buffer;
  size_t my_avail_out = sizeof___outbuffer;

  d = my_avail_out;
  if ( d > max_avail )
    d = max_avail;
  m_zlib.strm.next_out  = my_next_out;
  m_zlib.strm.avail_out = (unsigned int)d;
  my_next_out  += d;
  my_avail_out -= d;

  // counter guards against infinte loop if there are
  // bugs in zlib return codes
  int counter = 512;
  int flush = Z_NO_FLUSH;

  while ( rc && counter > 0 )
  {
    // Call zlib's inflate function.  It can either process
    // more input from m_zlib.strm.next_in[], create more
    // uncompressed output in m_zlib.strm.next_out[], or do both.
    if ( 0 == my_avail_in && 0 == m_zlib.strm.avail_in )
    {
      // no compressed input is left - switch to finish mode
      flush = Z_FINISH;
    }
    zrc = z_inflate( &m_zlib.strm, flush );
    if ( zrc < 0 ) 
    {
      // Something went haywire - bail out.
      ON_ERROR("ON_BinaryArchive::ReadInflate - z_inflate failure");
      rc = false;
      break;
    }

    if ( Z_FINISH == flush && Z_STREAM_END == zrc )
    {
      // no input left, all pending decompression is finished,
      // and all decompressed output has been returned.
      break;
    }

    d = 0;
    if ( my_avail_in > 0 && m_zlib.strm.avail_in < max_avail )
    {
      if ( 0 == m_zlib.strm.avail_in || 0 == m_zlib.strm.next_in )
      {
        // The call to inflate() used up all the input 
        // in m_zlib.strm.next_in[].  I can feed it another chunk
        // from inbuffer[]
        d = my_avail_in;
        if ( d > max_avail )
          d = max_avail;
        m_zlib.strm.next_in  = my_next_in;
        m_zlib.strm.avail_in = (unsigned int)d; 
      }
      else
      {
        // The call to inflate() left some input in m_zlib.strm.next_in[],
        // but I can increase m_zlib.strm.avail_in.
        d =  max_avail - m_zlib.strm.avail_in;
        if ( d > my_avail_in )
          d = my_avail_in;
        m_zlib.strm.avail_in += (unsigned int)d;
      }
      my_next_in  += d;
      my_avail_in -= d;
    }

    if ( my_avail_out > 0 && m_zlib.strm.avail_out < max_avail )
    {
      // increase m_zlib.strm.next_out[] buffer
      if ( 0 == m_zlib.strm.avail_out || 0 == m_zlib.strm.next_out )
      {
        d = my_avail_out;
        if ( d > max_avail )
          d = max_avail;
        m_zlib.strm.next_out  = my_next_out;
        m_zlib.strm.avail_out = (unsigned int)d;
      }
      else
      {
        d = max_avail - m_zlib.strm.avail_out;
        if ( d > my_avail_out )
          d = my_avail_out;
        m_zlib.strm.avail_out += ((unsigned int)d);
      }
      my_next_out  += d;
      my_avail_out -= d;
    }
    else if ( 0 == d )
    {
      // no buffer changes
      counter--;
    }
  }

  if (in___buffer )
  {
    onfree(in___buffer);
    in___buffer = 0;
  }

  if ( 0 == counter )
  {
    rc = false;
  }

  return rc;
}
Ejemplo n.º 5
0
bool ON_CompressedBuffer::InflateHelper(
        ON_CompressedBufferHelper* helper,
        size_t sizeof___outbuffer,  // sizeof uncompressed data
        void* out___buffer          // buffer for uncompressed data
        ) const
{
  const size_t max_avail = 0x7FFFFFF0; // See max_avail comment in ON_CompressedBuffer::InflateHelper

  bool rc = true;

  int zrc = -1;

  // set up zlib in buffer
  unsigned char* my_next_in = (unsigned char*)m_buffer_compressed;
  size_t my_avail_in = m_sizeof_compressed;

  size_t d = my_avail_in;
  if ( d > max_avail )
    d = max_avail;

  struct ON_CompressedBufferHelper& m_zlib = *helper;

  m_zlib.strm.next_in  = my_next_in;
  m_zlib.strm.avail_in = (unsigned int)d;
  my_next_in  += d;
  my_avail_in -= d;

  // set up zlib out buffer
  unsigned char* my_next_out = (unsigned char*)out___buffer;
  size_t my_avail_out = sizeof___outbuffer;

  d = my_avail_out;
  if ( d > max_avail )
    d = max_avail;
  m_zlib.strm.next_out  = my_next_out;
  m_zlib.strm.avail_out = (unsigned int)d;
  my_next_out  += d;
  my_avail_out -= d;

  // counter guards against infinte loop if there are
  // bugs in zlib return codes
  int counter = 512;
  int flush = Z_NO_FLUSH;

  while ( rc && counter > 0 )
  {
    // Call zlib's inflate function.  It can either process
    // more input from m_zlib.strm.next_in[], create more
    // uncompressed output in m_zlib.strm.next_out[], or do both.
    if ( 0 == my_avail_in && 0 == m_zlib.strm.avail_in )
    {
      // no compressed input is left - switch to finish mode
      flush = Z_FINISH;
    }
    zrc = z_inflate( &m_zlib.strm, flush );
    if ( zrc < 0 ) 
    {
      // Something went haywire - bail out.
      ON_ERROR("ON_CompressedBuffer::InflateHelper - z_inflate failure");
      rc = false;
      break;
    }

    if ( Z_FINISH == flush && Z_STREAM_END == zrc )
    {
      // no input left, all pending decompression is finished,
      // and all decompressed output has been returned.
      break;
    }

    d = 0;
    if ( my_avail_in > 0 && m_zlib.strm.avail_in < max_avail )
    {
      if ( 0 == m_zlib.strm.avail_in || 0 == m_zlib.strm.next_in )
      {
        // The call to inflate() used up all the input 
        // in m_zlib.strm.next_in[].  I can feed it another chunk
        // from inbuffer[]
        d = my_avail_in;
        if ( d > max_avail )
          d = max_avail;
        m_zlib.strm.next_in  = my_next_in;
        m_zlib.strm.avail_in = (unsigned int)d; 
      }
      else
      {
        // The call to inflate() left some input in m_zlib.strm.next_in[],
        // but I can increase m_zlib.strm.avail_in.
        d =  max_avail - m_zlib.strm.avail_in;
        if ( d > my_avail_in )
          d = my_avail_in;
        m_zlib.strm.avail_in += (unsigned int)d;
      }
      my_next_in  += d;
      my_avail_in -= d;
    }

    if ( my_avail_out > 0 && m_zlib.strm.avail_out < max_avail )
    {
      // increase m_zlib.strm.next_out[] buffer
      if ( 0 == m_zlib.strm.avail_out || 0 == m_zlib.strm.next_out )
      {
        d = my_avail_out;
        if ( d > max_avail )
          d = max_avail;
        m_zlib.strm.next_out  = my_next_out;
        m_zlib.strm.avail_out = (unsigned int)d;
      }
      else
      {
        d = max_avail - m_zlib.strm.avail_out;
        if ( d > my_avail_out )
          d = my_avail_out;
        m_zlib.strm.avail_out += ((unsigned int)d);
      }
      my_next_out  += d;
      my_avail_out -= d;
    }
    else if ( 0 == d )
    {
      // no buffer changes
      counter--;
    }
  }

  if ( 0 == counter )
  {
    rc = false;
  }

  return rc;
}