gmio/src/gmio_core/internal/zlib_utils.c
2017-01-26 18:05:12 +01:00

165 lines
5.8 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/****************************************************************************
** Copyright (c) 2017, 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);
}