uncompr.c 2.95 KB
Newer Older
Tom Tromey committed
1
/* uncompr.c -- decompress a memory buffer
2
 * Copyright (C) 1995-2003, 2010, 2014, 2016 Jean-loup Gailly, Mark Adler
3
 * For conditions of distribution and use, see copyright notice in zlib.h
Tom Tromey committed
4 5
 */

6
/* @(#) $Id: uncompr.c,v 1.1.1.2 2002/03/11 21:53:27 tromey Exp $ */
Tom Tromey committed
7

8
#define ZLIB_INTERNAL
Tom Tromey committed
9 10 11
#include "zlib.h"

/* ===========================================================================
12 13 14 15 16 17 18 19 20 21 22 23 24 25
     Decompresses the source buffer into the destination buffer.  *sourceLen is
   the byte length of the source buffer. Upon entry, *destLen is the total size
   of the destination buffer, which must be large enough to hold the entire
   uncompressed data. (The size of the uncompressed data must have been saved
   previously by the compressor and transmitted to the decompressor by some
   mechanism outside the scope of this compression library.) Upon exit,
   *destLen is the size of the decompressed data and *sourceLen is the number
   of source bytes consumed. Upon return, source + *sourceLen points to the
   first unused input byte.

     uncompress 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, or
   Z_DATA_ERROR if the input data was corrupted, including if the input data is
   an incomplete zlib stream.
Tom Tromey committed
26
*/
27
int ZEXPORT uncompress2 (dest, destLen, source, sourceLen)
Tom Tromey committed
28 29 30
    Bytef *dest;
    uLongf *destLen;
    const Bytef *source;
31
    uLong *sourceLen;
Tom Tromey committed
32 33 34
{
    z_stream stream;
    int err;
35 36 37
    const uInt max = (uInt)-1;
    uLong len, left;
    Byte buf[1];    /* for detection of incomplete stream when *destLen == 0 */
Tom Tromey committed
38

39 40 41 42 43 44 45 46 47
    len = *sourceLen;
    if (*destLen) {
        left = *destLen;
        *destLen = 0;
    }
    else {
        left = 1;
        dest = buf;
    }
Tom Tromey committed
48

49 50
    stream.next_in = (z_const Bytef *)source;
    stream.avail_in = 0;
Tom Tromey committed
51 52
    stream.zalloc = (alloc_func)0;
    stream.zfree = (free_func)0;
53
    stream.opaque = (voidpf)0;
Tom Tromey committed
54 55 56 57

    err = inflateInit(&stream);
    if (err != Z_OK) return err;

58 59
    stream.next_out = dest;
    stream.avail_out = 0;
Tom Tromey committed
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
    do {
        if (stream.avail_out == 0) {
            stream.avail_out = left > (uLong)max ? max : (uInt)left;
            left -= stream.avail_out;
        }
        if (stream.avail_in == 0) {
            stream.avail_in = len > (uLong)max ? max : (uInt)len;
            len -= stream.avail_in;
        }
        err = inflate(&stream, Z_NO_FLUSH);
    } while (err == Z_OK);

    *sourceLen -= len + stream.avail_in;
    if (dest != buf)
        *destLen = stream.total_out;
    else if (stream.total_out && err == Z_BUF_ERROR)
        left = 1;

    inflateEnd(&stream);
    return err == Z_STREAM_END ? Z_OK :
           err == Z_NEED_DICT ? Z_DATA_ERROR  :
           err == Z_BUF_ERROR && left + stream.avail_out ? Z_DATA_ERROR :
           err;
}

int ZEXPORT uncompress (dest, destLen, source, sourceLen)
    Bytef *dest;
    uLongf *destLen;
    const Bytef *source;
    uLong sourceLen;
{
    return uncompress2(dest, destLen, source, &sourceLen);
Tom Tromey committed
93
}