1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 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 */
|