compress.c 3 KB
Newer Older
Mark Adler's avatar
Mark Adler committed
1
/* compress.c -- compress a memory buffer
2
 * Copyright (C) 1995-2005, 2014 Jean-loup Gailly, Mark Adler
Mark Adler's avatar
Mark Adler committed
3
 * For conditions of distribution and use, see copyright notice in zlib.h
Mark Adler's avatar
Mark Adler committed
4 5
 */

Mark Adler's avatar
Mark Adler committed
6
/* @(#) $Id$ */
Mark Adler's avatar
Mark Adler committed
7

8 9
#include <limits.h>

Mark Adler's avatar
Mark Adler committed
10 11 12
#include "zlib.h"

/* ===========================================================================
Mark Adler's avatar
Mark Adler committed
13 14 15 16 17 18 19 20 21
     Compresses the source buffer into the destination buffer. The level
   parameter has the same meaning as in deflateInit.  sourceLen is the byte
   length of the source buffer. Upon entry, destLen is the total size of the
   destination buffer, which must be at least 0.1% larger than sourceLen plus
   12 bytes. Upon exit, destLen is the actual size of the compressed buffer.

     compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
   memory, Z_BUF_ERROR if there was not enough room in the output buffer,
   Z_STREAM_ERROR if the level parameter is invalid.
Mark Adler's avatar
Mark Adler committed
22
*/
23
int ZEXPORT compress2(unsigned char *dest,
24
                      unsigned long *destLenPtr,
25 26 27
                      const unsigned char *source,
                      unsigned long sourceLen,
                      int level)
Mark Adler's avatar
Mark Adler committed
28 29 30
{
    z_stream stream;
    int err;
31
    unsigned long destLen = *destLenPtr;
Mark Adler's avatar
Mark Adler committed
32 33 34

    stream.zalloc = (alloc_func)0;
    stream.zfree = (free_func)0;
35
    stream.opaque = (void *)0;
Mark Adler's avatar
Mark Adler committed
36

Mark Adler's avatar
Mark Adler committed
37
    err = deflateInit(&stream, level);
Mark Adler's avatar
Mark Adler committed
38 39
    if (err != Z_OK) return err;

40 41 42 43 44 45 46 47 48 49 50 51 52
    stream.next_in = source;
    stream.next_out = dest;

    do {
        unsigned long avail_in = sourceLen - stream.total_in;
        unsigned long avail_out = destLen - stream.total_out;
        int flush;

        stream.avail_in = avail_in < UINT_MAX ? avail_in : UINT_MAX;
        stream.avail_out = avail_out < UINT_MAX ? avail_out : UINT_MAX;
        flush = stream.avail_in == avail_in ? Z_FINISH : Z_NO_FLUSH;
        err = deflate(&stream, flush);
    } while (err == Z_OK);
Mark Adler's avatar
Mark Adler committed
53

54 55 56
    *destLenPtr = stream.total_out;
    deflateEnd(&stream);
    return err == Z_STREAM_END ? Z_OK : err;
Mark Adler's avatar
Mark Adler committed
57
}
Mark Adler's avatar
Mark Adler committed
58 59 60

/* ===========================================================================
 */
61 62 63 64
int ZEXPORT compress(unsigned char *dest,
                     unsigned long *destLen,
                     const unsigned char *source,
                     unsigned long sourceLen)
Mark Adler's avatar
Mark Adler committed
65 66 67
{
    return compress2(dest, destLen, source, sourceLen, Z_DEFAULT_COMPRESSION);
}
Mark Adler's avatar
Mark Adler committed
68

69 70 71 72 73 74
/* ========================================================================= */
static unsigned long saturateAddBound(unsigned long a, unsigned long b)
{
    return ULONG_MAX - a < b ? ULONG_MAX : a + b;
}

Mark Adler's avatar
Mark Adler committed
75 76 77 78
/* ===========================================================================
     If the default memLevel or windowBits for deflateInit() is changed, then
   this function needs to be updated.
 */
79
unsigned long ZEXPORT compressBound(unsigned long sourceLen)
Mark Adler's avatar
Mark Adler committed
80
{
81 82 83 84 85 86
    unsigned long complen = sourceLen;
    complen = saturateAddBound(complen, sourceLen >> 12);
    complen = saturateAddBound(complen, sourceLen >> 14);
    complen = saturateAddBound(complen, sourceLen >> 25);
    complen = saturateAddBound(complen, 13);
    return complen;
Mark Adler's avatar
Mark Adler committed
87
}