summaryrefslogtreecommitdiff
path: root/src/H5Zdeflate.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/H5Zdeflate.c')
-rw-r--r--src/H5Zdeflate.c206
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 */
+