diff options
Diffstat (limited to 'src/H5Zdeflate.c')
-rw-r--r-- | src/H5Zdeflate.c | 206 |
1 files changed, 206 insertions, 0 deletions
diff --git a/src/H5Zdeflate.c b/src/H5Zdeflate.c new file mode 100644 index 0000000..34fdfec --- /dev/null +++ b/src/H5Zdeflate.c @@ -0,0 +1,206 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by The HDF Group. * + * Copyright by the Board of Trustees of the University of Illinois. * + * All rights reserved. * + * * + * This file is part of HDF5. The full HDF5 copyright notice, including * + * terms governing use, modification, and redistribution, is contained in * + * the COPYING file, which can be found at the root of the source code * + * distribution tree, or in https://support.hdfgroup.org/ftp/HDF5/releases. * + * If you do not have access to either file, you may request a copy from * + * help@hdfgroup.org. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/* + * Programmer: Robb Matzke <matzke@llnl.gov> + * Friday, August 27, 1999 + */ + +#include "H5Zmodule.h" /* This source code file is part of the H5Z module */ + + +#include "H5private.h" /* Generic Functions */ +#include "H5Eprivate.h" /* Error handling */ +#include "H5MMprivate.h" /* Memory management */ +#include "H5Zpkg.h" /* Data filters */ + +#ifdef H5_HAVE_FILTER_DEFLATE + +#if defined(H5_HAVE_ZLIB_H) && !defined(H5_ZLIB_HEADER) +# define H5_ZLIB_HEADER "zlib.h" +#endif +#if defined(H5_ZLIB_HEADER) +# include H5_ZLIB_HEADER /* "zlib.h" */ +#endif + +/* Local function prototypes */ +static size_t H5Z_filter_deflate (unsigned flags, size_t cd_nelmts, + const unsigned cd_values[], size_t nbytes, size_t *buf_size, void **buf); + +/* This message derives from H5Z */ +const H5Z_class2_t H5Z_DEFLATE[1] = {{ + H5Z_CLASS_T_VERS, /* H5Z_class_t version */ + H5Z_FILTER_DEFLATE, /* Filter id number */ + 1, /* encoder_present flag (set to true) */ + 1, /* decoder_present flag (set to true) */ + "deflate", /* Filter name for debugging */ + NULL, /* The "can apply" callback */ + NULL, /* The "set local" callback */ + H5Z_filter_deflate, /* The actual filter function */ +}}; + +#define H5Z_DEFLATE_SIZE_ADJUST(s) (HDceil(((double)(s)) * (double)1.001f) + 12) + + +/*------------------------------------------------------------------------- + * Function: H5Z_filter_deflate + * + * Purpose: Implement an I/O filter around the 'deflate' algorithm in + * libz + * + * Return: Success: Size of buffer filtered + * Failure: 0 + * + * Programmer: Robb Matzke + * Thursday, April 16, 1998 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static size_t +H5Z_filter_deflate (unsigned flags, size_t cd_nelmts, + const unsigned cd_values[], size_t nbytes, + size_t *buf_size, void **buf) +{ + void *outbuf = NULL; /* Pointer to new buffer */ + int status; /* Status from zlib operation */ + size_t ret_value = 0; /* Return value */ + + FUNC_ENTER_NOAPI(0) + + /* Sanity check */ + HDassert(*buf_size > 0); + HDassert(buf); + HDassert(*buf); + + /* Check arguments */ + if (cd_nelmts!=1 || cd_values[0]>9) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, 0, "invalid deflate aggression level") + + if (flags & H5Z_FLAG_REVERSE) { + /* Input; uncompress */ + z_stream z_strm; /* zlib parameters */ + size_t nalloc = *buf_size; /* Number of bytes for output (compressed) buffer */ + + /* Allocate space for the compressed buffer */ + if (NULL==(outbuf = H5MM_malloc(nalloc))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, 0, "memory allocation failed for deflate uncompression") + + /* Set the uncompression parameters */ + HDmemset(&z_strm, 0, sizeof(z_strm)); + z_strm.next_in = (Bytef *)*buf; + H5_CHECKED_ASSIGN(z_strm.avail_in, unsigned, nbytes, size_t); + z_strm.next_out = (Bytef *)outbuf; + H5_CHECKED_ASSIGN(z_strm.avail_out, unsigned, nalloc, size_t); + + /* Initialize the uncompression routines */ + if (Z_OK!=inflateInit(&z_strm)) + HGOTO_ERROR(H5E_PLINE, H5E_CANTINIT, 0, "inflateInit() failed") + + /* Loop to uncompress the buffer */ + do { + /* Uncompress some data */ + status = inflate(&z_strm, Z_SYNC_FLUSH); + + /* Check if we are done uncompressing data */ + if (Z_STREAM_END==status) + break; /*done*/ + + /* Check for error */ + if (Z_OK!=status) { + (void)inflateEnd(&z_strm); + HGOTO_ERROR(H5E_PLINE, H5E_CANTINIT, 0, "inflate() failed") + } + else { + /* If we're not done and just ran out of buffer space, get more */ + if(0 == z_strm.avail_out) { + void *new_outbuf; /* Pointer to new output buffer */ + + /* Allocate a buffer twice as big */ + nalloc *= 2; + if(NULL == (new_outbuf = H5MM_realloc(outbuf, nalloc))) { + (void)inflateEnd(&z_strm); + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, 0, "memory allocation failed for deflate uncompression") + } /* end if */ + outbuf = new_outbuf; + + /* Update pointers to buffer for next set of uncompressed data */ + z_strm.next_out = (unsigned char*)outbuf + z_strm.total_out; + z_strm.avail_out = (uInt)(nalloc - z_strm.total_out); + } /* end if */ + } /* end else */ + } while(status==Z_OK); + + /* Free the input buffer */ + H5MM_xfree(*buf); + + /* Set return values */ + *buf = outbuf; + outbuf = NULL; + *buf_size = nalloc; + ret_value = z_strm.total_out; + + /* Finish uncompressing the stream */ + (void)inflateEnd(&z_strm); + } /* end if */ + else { + /* + * Output; compress but fail if the result would be larger than the + * input. The library doesn't provide in-place compression, so we + * must allocate a separate buffer for the result. + */ + const Bytef *z_src = (const Bytef*)(*buf); + Bytef *z_dst; /*destination buffer */ + uLongf z_dst_nbytes = (uLongf)H5Z_DEFLATE_SIZE_ADJUST(nbytes); + uLong z_src_nbytes = (uLong)nbytes; + int aggression; /* Compression aggression setting */ + + /* Set the compression aggression level */ + H5_CHECKED_ASSIGN(aggression, int, cd_values[0], unsigned); + + /* Allocate output (compressed) buffer */ + if(NULL == (outbuf = H5MM_malloc(z_dst_nbytes))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, 0, "unable to allocate deflate destination buffer") + z_dst = (Bytef *)outbuf; + + /* Perform compression from the source to the destination buffer */ + status = compress2(z_dst, &z_dst_nbytes, z_src, z_src_nbytes, aggression); + + /* Check for various zlib errors */ + if(Z_BUF_ERROR == status) + HGOTO_ERROR(H5E_PLINE, H5E_CANTINIT, 0, "overflow") + else if(Z_MEM_ERROR == status) + HGOTO_ERROR(H5E_PLINE, H5E_CANTINIT, 0, "deflate memory error") + else if(Z_OK != status) + HGOTO_ERROR(H5E_PLINE, H5E_CANTINIT, 0, "other deflate error") + /* Successfully uncompressed the buffer */ + else { + /* Free the input buffer */ + H5MM_xfree(*buf); + + /* Set return values */ + *buf = outbuf; + outbuf = NULL; + *buf_size = nbytes; + ret_value = z_dst_nbytes; + } /* end else */ + } /* end else */ + +done: + if(outbuf) + H5MM_xfree(outbuf); + FUNC_LEAVE_NOAPI(ret_value) +} +#endif /* H5_HAVE_FILTER_DEFLATE */ + |