summaryrefslogtreecommitdiffstats
path: root/src/H5Z.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/H5Z.c')
-rw-r--r--src/H5Z.c501
1 files changed, 501 insertions, 0 deletions
diff --git a/src/H5Z.c b/src/H5Z.c
new file mode 100644
index 0000000..993cc5e
--- /dev/null
+++ b/src/H5Z.c
@@ -0,0 +1,501 @@
+/*
+ * Copyright (C) 1998 NCSA
+ * All rights reserved.
+ *
+ * Programmer: Robb Matzke <matzke@llnl.gov>
+ * Thursday, April 16, 1998
+ *
+ * Purpose: Functions for data compression.
+ */
+#include <H5private.h>
+#include <H5Eprivate.h>
+#include <H5MMprivate.h>
+#include <H5Oprivate.h>
+#include <H5Zprivate.h>
+
+#ifdef HAVE_ZLIB_H
+# include <zlib.h>
+#endif
+
+/* Interface initialization */
+#define PABLO_MASK H5Z_mask
+#define INTERFACE_INIT H5Z_init_interface
+static intn interface_initialize_g = FALSE;
+static herr_t H5Z_init_interface (void);
+static void H5Z_term_interface (void);
+
+/*
+ * The compression table maps compression method number to a struct that
+ * contains pointers to the compress and uncompress methods along with timing
+ * statistics.
+ */
+typedef struct H5Z_class_t {
+ char *name; /*method name for debugging */
+ H5Z_func_t compress; /*compression function */
+ H5Z_func_t uncompress; /*uncompression function */
+
+#ifdef H5Z_DEBUG
+ struct {
+ hsize_t nbytes; /*bytes compressed including overruns */
+ hsize_t over; /*bytes of overrun */
+ H5_timer_t timer; /*total compression time inc. overruns */
+ hsize_t failed; /*bytes of failure (not overruns) */
+ } comp;
+
+ struct {
+ hsize_t nbytes; /*bytes uncompressed, including overruns*/
+ hsize_t over; /*bytes of overrun */
+ H5_timer_t timer; /*total uncompression time */
+ hsize_t failed; /*bytes of failure (not overruns) */
+ } uncomp;
+#endif
+} H5Z_class_t;
+static H5Z_class_t H5Z_g[H5Z_MAXVAL+1];
+
+/* Compression and uncompression methods */
+static size_t H5Z_zlib_c (unsigned int flags, size_t __unused__ cd_size,
+ const void __unused__ *client_data,
+ size_t src_nbytes, const void *_src,
+ size_t dst_nbytes, void *dst/*out*/);
+static size_t H5Z_zlib_u (unsigned int flags, size_t __unused__ cd_size,
+ const void __unused__ *client_data,
+ size_t src_nbytes, const void *_src,
+ size_t dst_nbytes, void *dst/*out*/);
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5Z_init_interface
+ *
+ * Purpose: Initializes the data compression layer.
+ *
+ * Return: Success: SUCCEED
+ *
+ * Failure: FAIL
+ *
+ * Programmer: Robb Matzke
+ * Thursday, April 16, 1998
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5Z_init_interface (void)
+{
+ FUNC_ENTER (H5Z_init_interface, FAIL);
+
+ H5_add_exit (H5Z_term_interface);
+
+ H5Z_register (H5Z_NONE, "none", NULL, NULL);
+ H5Z_register (H5Z_DEFLATE, "deflate", H5Z_zlib_c, H5Z_zlib_u);
+
+ FUNC_LEAVE (SUCCEED);
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5Z_term_interface
+ *
+ * Purpose: Terminate the H5Z layer.
+ *
+ * Return: void
+ *
+ * Programmer: Robb Matzke
+ * Thursday, April 16, 1998
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static void
+H5Z_term_interface (void)
+{
+#ifdef H5Z_DEBUG
+ int i, nprint=0;
+ char name[16];
+
+ for (i=0; i<=H5Z_MAXVAL; i++) {
+ if (H5Z_g[i].comp.nbytes || H5Z_g[i].uncomp.nbytes) {
+ if (0==nprint++) {
+ HDfprintf (stderr, "H5Z: compression statistics accumulated "
+ "over life of library:\n");
+ HDfprintf (stderr, " %-10s %8s %8s %8s %8s %8s %8s %9s\n",
+ "Method", "Total", "Overrun", "Errors", "User",
+ "System", "Elapsed", "Bandwidth");
+ HDfprintf (stderr, " %-10s %8s %8s %8s %8s %8s %8s %9s\n",
+ "------", "-----", "-------", "------", "----",
+ "------", "-------", "---------");
+ }
+ sprintf (name, "%s-c", H5Z_g[i].name);
+ HDfprintf (stderr,
+ " %-12s %8Hd %8Hd %8Hd %8.2f %8.2f %8.2f ",
+ name,
+ H5Z_g[i].comp.nbytes,
+ H5Z_g[i].comp.over,
+ H5Z_g[i].comp.failed,
+ H5Z_g[i].comp.timer.utime,
+ H5Z_g[i].comp.timer.stime,
+ H5Z_g[i].comp.timer.etime);
+ if (H5Z_g[i].comp.timer.etime>0) {
+ HDfprintf (stderr, "%9.3e\n",
+ H5Z_g[i].comp.nbytes / H5Z_g[i].comp.timer.etime);
+ } else {
+ HDfprintf (stderr, "%9s\n", "NaN");
+ }
+
+ sprintf (name, "%s-u", H5Z_g[i].name);
+ HDfprintf (stderr,
+ " %-12s %8Hd %8Hd %8Hd %8.2f %8.2f %8.2f ",
+ name,
+ H5Z_g[i].uncomp.nbytes,
+ H5Z_g[i].uncomp.over,
+ H5Z_g[i].uncomp.failed,
+ H5Z_g[i].uncomp.timer.utime,
+ H5Z_g[i].uncomp.timer.stime,
+ H5Z_g[i].uncomp.timer.etime);
+ if (H5Z_g[i].uncomp.timer.etime>0) {
+ HDfprintf (stderr, "%9.3e\n",
+ H5Z_g[i].uncomp.nbytes/H5Z_g[i].uncomp.timer.etime);
+ } else {
+ HDfprintf (stderr, "%9s\n", "NaN");
+ }
+ }
+ }
+#endif
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5Zregister
+ *
+ * Purpose: This function registers new compression and uncompression
+ * methods for a method number. The NAME argument is used for
+ * debugging and may be the null pointer. Either or both of
+ * CFUNC (the compression function) and UFUNC (the uncompression
+ * method) may be null pointers.
+ *
+ * The statistics associated with a method number are not reset
+ * by this function; they accumulate over the life of the
+ * library.
+ *
+ * Return: Success: SUCCEED
+ *
+ * Failure: FAIL
+ *
+ * Programmer: Robb Matzke
+ * Thursday, April 16, 1998
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5Zregister (H5Z_method_t method, const char *name, H5Z_func_t cfunc,
+ H5Z_func_t ufunc)
+{
+ FUNC_ENTER (H5Zregister, FAIL);
+
+ /* Check args */
+ if (method<0 || method>H5Z_MAXVAL) {
+ HRETURN_ERROR (H5E_ARGS, H5E_BADVALUE, FAIL,
+ "invalid data compression method number");
+ }
+ if (method<16) {
+ HRETURN_ERROR (H5E_ARGS, H5E_BADVALUE, FAIL,
+ "unable to modify predefined compression methods");
+ }
+
+ /* Do it */
+ if (H5Z_register (method, name, cfunc, ufunc)<0) {
+ HRETURN_ERROR (H5E_COMP, H5E_CANTINIT, FAIL,
+ "unable to register compression methods");
+ }
+
+ FUNC_LEAVE (SUCCEED);
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5Z_compress
+ *
+ * Purpose: Compress NBYTES from SRC into at most NBYTES of DST.
+ *
+ * Return: Success: Number of bytes in DST
+ *
+ * Failure: 0 if the DST buffer overflowed or something
+ * else went wrong.
+ *
+ * Programmer: Robb Matzke
+ * Thursday, April 16, 1998
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+size_t
+H5Z_compress (const H5O_compress_t *comp, size_t nbytes, const void *src,
+ void *dst/*out*/)
+{
+ size_t ret_value = 0;
+ H5Z_method_t method = comp ? comp->method : H5Z_NONE;
+ H5Z_func_t cfunc = NULL;
+#ifdef H5Z_DEBUG
+ intn over = 0;
+ H5_timer_t timer;
+#endif
+
+ FUNC_ENTER (H5Z_compress, 0);
+
+#ifdef H5Z_DEBUG
+ H5_timer_begin (&timer);
+#endif
+
+ if (H5Z_NONE==method) {
+ /* No compression method */
+ HGOTO_DONE (0);
+
+ } else if (NULL==(cfunc=H5Z_g[method].compress)) {
+ /* No compress function */
+ HGOTO_ERROR (H5E_COMP, H5E_UNSUPPORTED, 0,
+ "compression method is not supported");
+
+ } else if (0==(ret_value=(cfunc)(comp->flags, comp->cd_size,
+ comp->client_data, nbytes,
+ src, nbytes, dst))) {
+ /* Compress failed */
+ HGOTO_ERROR (H5E_COMP, H5E_CANTINIT, 0, "compression failed");
+
+ } else if (ret_value>=nbytes) {
+ /* Output is not smaller than input */
+#ifdef H5Z_DEBUG
+ H5Z_g[method].comp.over += 1;
+ over = 1;
+#endif
+ HGOTO_DONE (0);
+ }
+
+ done:
+#ifdef H5Z_DEBUG
+ H5Z_g[method].comp.nbytes += nbytes;
+ if (0==ret_value && !over) H5Z_g[method].comp.failed += nbytes;
+ H5_timer_end (&(H5Z_g[method].comp.timer), &timer);
+#endif
+ FUNC_LEAVE (ret_value);
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5Z_uncompress
+ *
+ * Purpose: Uncompress SRC_NBYTES from SRC into at most DST_NBYTES of
+ * DST.
+ *
+ * Return: Success: Number of bytes in DST buffer.
+ *
+ * Failure: 0 if the uncompression failed or DST wasn't
+ * big enough to hold the result.
+ *
+ * Programmer: Robb Matzke
+ * Thursday, April 16, 1998
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+size_t
+H5Z_uncompress (const H5O_compress_t *comp, size_t src_nbytes, const void *src,
+ size_t dst_nbytes, void *dst/*out*/)
+{
+ size_t ret_value = 0;
+ H5Z_func_t ufunc = NULL;
+ H5Z_method_t method = comp ? comp->method : H5Z_NONE;
+#ifdef H5Z_DEBUG
+ H5_timer_t timer;
+#endif
+
+ FUNC_ENTER (H5Z_uncompress, 0);
+
+#ifdef H5Z_DEBUG
+ H5_timer_begin (&timer);
+#endif
+
+ if (H5Z_NONE==method) {
+ /* No compression method */
+ assert (src_nbytes<=dst_nbytes);
+ HDmemcpy (dst, src, src_nbytes);
+ ret_value = src_nbytes;
+
+ } else if (src_nbytes==dst_nbytes) {
+ /* Data is not compressed */
+#ifdef H5Z_DEBUG
+ H5Z_g[method].uncomp.over += src_nbytes;
+#endif
+ HDmemcpy (dst, src, src_nbytes);
+ ret_value = src_nbytes;
+
+ } else if (NULL==(ufunc=H5Z_g[method].uncompress)) {
+ /* No uncompress function */
+ HGOTO_ERROR (H5E_COMP, H5E_UNSUPPORTED, 0,
+ "uncompression method is not supported");
+
+ } else if (0==(ret_value=(ufunc)(comp->flags, comp->cd_size,
+ comp->client_data, src_nbytes,
+ src, dst_nbytes, dst))) {
+ /* Uncompress failed */
+ HGOTO_ERROR (H5E_COMP, H5E_CANTINIT, 0, "uncompression failed");
+ }
+
+ done:
+#ifdef H5Z_DEBUG
+ H5Z_g[method].uncomp.nbytes += dst_nbytes;
+ if (0==ret_value) H5Z_g[method].uncomp.failed += dst_nbytes;
+ H5_timer_end (&(H5Z_g[method].uncomp.timer), &timer);
+#endif
+
+ FUNC_LEAVE (ret_value);
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5Z_register
+ *
+ * Purpose: Same as the public version except this one allows compression
+ * methods to be set for predefined method numbers <16.
+ *
+ * Return: Success: SUCCEED
+ *
+ * Failure: FAIL
+ *
+ * Programmer: Robb Matzke
+ * Thursday, April 16, 1998
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5Z_register (H5Z_method_t method, const char *name, H5Z_func_t cfunc,
+ H5Z_func_t ufunc)
+{
+ FUNC_ENTER (H5Z_register, FAIL);
+
+ assert (method>=0 && method<=H5Z_MAXVAL);
+ H5MM_xfree (H5Z_g[method].name);
+ H5Z_g[method].name = H5MM_xstrdup (name);
+ H5Z_g[method].compress = cfunc;
+ H5Z_g[method].uncompress = ufunc;
+
+ FUNC_LEAVE (SUCCEED);
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5Z_zlib_c
+ *
+ * Purpose: Compress SRC_NBYTES bytes from SRC into at most DST_NBYTES of
+ * DST using the compression level as specified in FLAGS.
+ *
+ * Return: Success: Number of bytes compressed into DST limited
+ * by DST_NBYTES.
+ *
+ * Failure: 0
+ *
+ * Programmer: Robb Matzke
+ * Thursday, April 16, 1998
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static size_t
+H5Z_zlib_c (unsigned int flags, size_t __unused__ cd_size,
+ const void __unused__ *client_data, size_t src_nbytes,
+ const void *src, size_t dst_nbytes, void *dst/*out*/)
+{
+ size_t ret_value = 0;
+#ifdef HAVE_ZLIB_H
+ const Bytef *z_src = (const Bytef*)src;
+ Bytef *z_dst = (Bytef*)dst;
+ uLongf z_dst_nbytes = (uLongf)dst_nbytes;
+ uLong z_src_nbytes = (uLong)src_nbytes;
+ int level = flags % 10;
+ int status;
+#endif
+
+ FUNC_ENTER (H5Z_zlib_c, 0);
+
+#if defined(HAVE_LIBZ) && defined (HAVE_ZLIB_H)
+ status = compress2 (z_dst, &z_dst_nbytes, z_src, z_src_nbytes, level);
+ if (Z_BUF_ERROR==status) {
+ ret_value = dst_nbytes;
+ } else if (Z_MEM_ERROR==status) {
+ HGOTO_ERROR (H5E_COMP, H5E_CANTINIT, 0, "deflate memory error");
+ } else if (Z_OK!=status) {
+ HGOTO_ERROR (H5E_COMP, H5E_CANTINIT, 0, "deflate error");
+ } else {
+ ret_value = z_dst_nbytes;
+ }
+#else
+ HGOTO_ERROR (H5E_COMP, H5E_UNSUPPORTED, 0,
+ "hdf5 was not compiled with zlib-1.0.2 or better");
+#endif
+
+ done:
+ FUNC_LEAVE (ret_value);
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5Z_zlib_u
+ *
+ * Purpose: Uncompress SRC_NBYTES from SRC into at most DST_NBYTES of
+ * DST.
+ *
+ * Return: Success: Number of bytes returned in DST.
+ *
+ * Failure: 0
+ *
+ * Programmer: Robb Matzke
+ * Thursday, April 16, 1998
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static size_t
+H5Z_zlib_u (unsigned int __unused__ flags, size_t __unused__ cd_size,
+ const void __unused__ *client_data, size_t src_nbytes,
+ const void *src, size_t dst_nbytes, void *dst/*out*/)
+{
+ size_t ret_value = 0;
+#ifdef HAVE_ZLIB_H
+ const Bytef *z_src = (const Bytef*)src;
+ Bytef *z_dst = (Bytef*)dst;
+ uLongf z_dst_nbytes = (uLongf)dst_nbytes;
+ uLong z_src_nbytes = (uLong)src_nbytes;
+ int status;
+#endif
+
+ FUNC_ENTER (H5Z_zlib_u, 0);
+
+#if defined(HAVE_LIBZ) && defined (HAVE_ZLIB_H)
+ status = uncompress (z_dst, &z_dst_nbytes, z_src, z_src_nbytes);
+ if (Z_BUF_ERROR==status) {
+ HGOTO_ERROR (H5E_COMP, H5E_CANTINIT, 0,
+ "deflate destination buffer was too small");
+ } else if (Z_MEM_ERROR==status) {
+ HGOTO_ERROR (H5E_COMP, H5E_CANTINIT, 0, "deflate memory error");
+ } else if (Z_DATA_ERROR==status) {
+ HGOTO_ERROR (H5E_COMP, H5E_CANTINIT, 0, "deflate corrupted data");
+ } else if (Z_OK!=status) {
+ HGOTO_ERROR (H5E_COMP, H5E_CANTINIT, 0, "deflate error");
+ }
+ ret_value = z_dst_nbytes;
+#else
+ HGOTO_ERROR (H5E_COMP, H5E_UNSUPPORTED, 0,
+ "hdf5 was not compiled with zlib-1.0.2 or better");
+#endif
+
+ done:
+ FUNC_LEAVE (ret_value);
+}