]> git.lizzy.rs Git - zlib.git/blobdiff - uncompr.c
Add comment about not using windowBits of 8 for deflate().
[zlib.git] / uncompr.c
index 4c8b3af044f4d52e44f0e2e3a04118f89c2fc050..2ec3eba6d024e68ae96aa3f08ecd526e6a903433 100644 (file)
--- a/uncompr.c
+++ b/uncompr.c
@@ -1,10 +1,11 @@
 /* uncompr.c -- decompress a memory buffer
- * Copyright (C) 1995 Jean-loup Gailly.
- * For conditions of distribution and use, see copyright notice in zlib.h 
+ * Copyright (C) 1995-2003, 2010, 2014 Jean-loup Gailly, Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
  */
 
-/* $Id: uncompr.c,v 1.4 1995/04/10 16:22:22 jloup Exp $ */
+/* @(#) $Id$ */
 
+#define ZLIB_INTERNAL
 #include "zlib.h"
 
 /* ===========================================================================
    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 actual size of the compressed buffer.
-     This function can be used to decompress a whole file at once if the
-   input file is mmap'ed.
 
      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.
+   buffer, or Z_DATA_ERROR if the input data was corrupted, including if the
+   input data is an incomplete zlib stream.
 */
-int uncompress (dest, destLen, source, sourceLen)
-    Byte *dest;
-    uLong *destLen;
-    Byte *source;
+int ZEXPORT uncompress (dest, destLen, source, sourceLen)
+    Bytef *dest;
+    uLongf *destLen;
+    const Bytef *source;
     uLong sourceLen;
 {
     z_stream stream;
     int err;
+    const uInt max = -1;
+    uLong left;
+    Byte buf[1];    /* for detection of incomplete stream when *destLen == 0 */
 
-    stream.next_in = source;
-    stream.avail_in = (uInt)sourceLen;
-    /* Check for source > 64K on 16-bit machine: */
-    if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR;
-
-    stream.next_out = dest;
-    stream.avail_out = (uInt)*destLen;
-    if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR;
+    if (*destLen) {
+        left = *destLen;
+        *destLen = 0;
+    }
+    else {
+        left = 1;
+        dest = buf;
+    }
 
+    stream.next_in = (z_const Bytef *)source;
+    stream.avail_in = 0;
     stream.zalloc = (alloc_func)0;
     stream.zfree = (free_func)0;
+    stream.opaque = (voidpf)0;
 
     err = inflateInit(&stream);
     if (err != Z_OK) return err;
 
-    err = inflate(&stream, Z_FINISH);
-    if (err != Z_STREAM_END) {
-       inflateEnd(&stream);
-       return err;
-    }
-    *destLen = stream.total_out;
+    stream.next_out = dest;
+    stream.avail_out = 0;
+
+    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 = sourceLen > (uLong)max ? max : (uInt)sourceLen;
+            sourceLen -= stream.avail_in;
+        }
+        err = inflate(&stream, Z_NO_FLUSH);
+    } while (err == Z_OK);
+
+    if (dest != buf)
+        *destLen = stream.total_out;
+    else if (stream.total_out && err == Z_BUF_ERROR)
+        left = 1;
 
-    err = inflateEnd(&stream);
-    return err;
+    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;
 }