gmio/src/gmio_core/internal/zlib_utils.c

165 lines
5.8 KiB
C
Raw Normal View History

/****************************************************************************
** Copyright (c) 2016, Fougue Ltd. <http://www.fougue.pro>
** All rights reserved.
**
** Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions
** are met:
**
** 1. Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
**
** 2. Redistributions in binary form must reproduce the above
** copyright notice, this list of conditions and the following
** disclaimer in the documentation and/or other materials provided
** with the distribution.
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
****************************************************************************/
#include "zlib_utils.h"
#include "../error.h"
/* zlib doc:
* the windowBits parameter is the base two logarithm of the window size
* (the size of the history buffer). It should be in the range 8..15 for
* this version of the library. Larger values of this parameter result in
* better compression at the expense of memory usage. The default value is
* 15 if deflateInit is used instead.
* windowBits can also be 8..15 for raw deflate. In this case, -windowBits
* determines the window size. deflate() will then generate raw deflate
* data with no zlib header or trailer, and will not compute an adler32
* check value. */
static const int z_window_bits_for_no_zlib_wrapper = -15;
static int gmio_to_zlib_compress_level(int gmio_compress_level)
{
if (gmio_compress_level == GMIO_ZLIB_COMPRESS_LEVEL_DEFAULT)
return Z_DEFAULT_COMPRESSION;
else if (gmio_compress_level == GMIO_ZLIB_COMPRESS_LEVEL_NONE)
return Z_NO_COMPRESSION;
return gmio_compress_level;
}
static int gmio_to_zlib_compress_memusage(int gmio_compress_memusage)
{
if (gmio_compress_memusage == 0)
return 8;
return gmio_compress_memusage;
}
/* Converts zlib error to gmio "zlib-specific" error */
int zlib_error_to_gmio_error(int z_error)
{
switch (z_error) {
case Z_OK: return GMIO_ERROR_OK;
case Z_ERRNO: return GMIO_ERROR_ZLIB_ERRNO;
case Z_STREAM_ERROR: return GMIO_ERROR_ZLIB_STREAM;
case Z_DATA_ERROR: return GMIO_ERROR_ZLIB_DATA;
case Z_MEM_ERROR: return GMIO_ERROR_ZLIB_MEM;
case Z_BUF_ERROR: return GMIO_ERROR_ZLIB_BUF;
case Z_VERSION_ERROR: return GMIO_ERROR_ZLIB_VERSION;
}
return GMIO_ERROR_UNKNOWN;
}
int gmio_zlib_compress_init(
struct z_stream_s* z_stream,
const struct gmio_zlib_compress_options* z_opts)
{
const int zlib_compress_level =
gmio_to_zlib_compress_level(z_opts->level);
const int zlib_compress_memusage =
gmio_to_zlib_compress_memusage(z_opts->memory_usage);
const int z_init_error =
deflateInit2_(
z_stream,
zlib_compress_level,
Z_DEFLATED, /* Method */
z_window_bits_for_no_zlib_wrapper,
zlib_compress_memusage,
z_opts->strategy,
ZLIB_VERSION,
sizeof(struct z_stream_s));
return zlib_error_to_gmio_error(z_init_error);
}
bool gmio_check_zlib_compress_options(
int* error, const struct gmio_zlib_compress_options* z_opts)
{
if (z_opts != NULL) {
if (z_opts->level > 9)
*error = GMIO_ERROR_ZLIB_INVALID_COMPRESS_LEVEL;
if (z_opts->memory_usage > 9)
*error = GMIO_ERROR_ZLIB_INVALID_COMPRESS_MEMORY_USAGE;
}
return gmio_no_error(*error);
}
int gmio_zlib_uncompress_buffer(
uint8_t* dest, size_t* dest_len, const uint8_t* src, size_t src_len)
{
z_stream stream;
int err;
stream.next_in = (z_const Bytef *)src;
stream.avail_in = (uInt)src_len;
/* Check for source > 64K on 16-bit machine: */
if ((uLong)stream.avail_in != src_len)
return GMIO_ERROR_ZLIB_BUF;
stream.next_out = dest;
stream.avail_out = (uInt)*dest_len;
if ((uLong)stream.avail_out != *dest_len)
return GMIO_ERROR_ZLIB_BUF;
stream.zalloc = (alloc_func)NULL;
stream.zfree = (free_func)NULL;
err = inflateInit2_(
&stream,
z_window_bits_for_no_zlib_wrapper,
ZLIB_VERSION,
sizeof(z_stream));
if (err != Z_OK)
return err;
err = inflate(&stream, Z_FINISH);
if (err != Z_STREAM_END) {
inflateEnd(&stream);
if (err == Z_NEED_DICT || (err == Z_BUF_ERROR && stream.avail_in == 0))
return GMIO_ERROR_ZLIB_DATA;
return err;
}
*dest_len = stream.total_out;
err = inflateEnd(&stream);
return zlib_error_to_gmio_error(err);
}
uint32_t gmio_zlib_crc32(const uint8_t *buff, size_t buff_len)
{
return gmio_zlib_crc32_update(gmio_zlib_crc32_initial(), buff, buff_len);
}
uint32_t gmio_zlib_crc32_update(
uint32_t crc, const uint8_t *buff, size_t buff_len)
{
return crc32(crc, (const Bytef*)buff, (uInt)buff_len);
}
uint32_t gmio_zlib_crc32_initial()
{
return crc32(0, NULL, 0);
}