/* Interface to zlib.
- Copyright (C) 2013 Free Software Foundation, Inc.
+ Copyright (C) 2013-2014 Free Software Foundation, Inc.
This file is part of GNU Emacs.
\f
struct decompress_unwind_data
{
- ptrdiff_t old_point, start;
+ ptrdiff_t old_point, start, nbytes;
z_stream *stream;
};
struct decompress_unwind_data *data = ddata;
fn_inflateEnd (data->stream);
- /* Delete any uncompressed data already inserted and restore point. */
+ /* Delete any uncompressed data already inserted on error. */
if (data->start)
- {
- del_range (data->start, PT);
- SET_PT (data->old_point);
- }
+ del_range (data->start, data->start + data->nbytes);
+
+ /* Put point where it was, or if the buffer has shrunk because the
+ compressed data is bigger than the uncompressed, at
+ point-max. */
+ SET_PT (min (data->old_point, ZV));
}
DEFUN ("zlib-available-p", Fzlib_available_p, Szlib_available_p, 0, 0, 0,
else
{
Lisp_Object status;
- status = init_zlib_functions () ? Qt : Qnil;
+ zlib_initialized = init_zlib_functions ();
+ status = zlib_initialized ? Qt : Qnil;
Vlibrary_cache = Fcons (Fcons (Qzlib_dll, status), Vlibrary_cache);
return status;
}
z_stream stream;
int inflate_status;
struct decompress_unwind_data unwind_data;
- ptrdiff_t count = SPECPDL_INDEX ();
+ dynwind_begin ();
validate_region (&start, &end);
#ifdef WINDOWSNT
if (!zlib_initialized)
zlib_initialized = init_zlib_functions ();
+ if (!zlib_initialized) {
+ dynwind_end ();
+ return Qnil;
+ }
#endif
/* This is a unibyte buffer, so character positions and bytes are
stream.avail_in = 0;
stream.next_in = Z_NULL;
- /* The magic number 32 apparently means "autodect both the gzip and
+ /* The magic number 32 apparently means "autodetect both the gzip and
zlib formats" according to zlib.h. */
- if (fn_inflateInit2 (&stream, MAX_WBITS + 32) != Z_OK)
+ if (fn_inflateInit2 (&stream, MAX_WBITS + 32) != Z_OK) {
+ dynwind_end ();
return Qnil;
+ }
unwind_data.start = iend;
unwind_data.stream = &stream;
unwind_data.old_point = PT;
-
+ unwind_data.nbytes = 0;
record_unwind_protect_ptr (unwind_decompress, &unwind_data);
/* Insert the decompressed data at the end of the compressed data. */
{
/* Maximum number of bytes that one 'inflate' call should read and write.
Do not make avail_out too large, as that might unduly delay C-g.
- In any case zlib requires that these values not exceed UINT_MAX. */
+ zlib requires that avail_in and avail_out not exceed UINT_MAX. */
ptrdiff_t avail_in = min (iend - pos_byte, UINT_MAX);
- enum { avail_out = 1 << 14 };
- verify (avail_out <= UINT_MAX);
-
- ptrdiff_t decompressed;
+ int avail_out = 16 * 1024;
+ int decompressed;
if (GAP_SIZE < avail_out)
make_gap (avail_out - GAP_SIZE);
pos_byte += avail_in - stream.avail_in;
decompressed = avail_out - stream.avail_out;
insert_from_gap (decompressed, decompressed, 0);
+ unwind_data.nbytes += decompressed;
QUIT;
}
while (inflate_status == Z_OK);
- if (inflate_status != Z_STREAM_END)
- return unbind_to (count, Qnil);
+ if (inflate_status != Z_STREAM_END){
+
+ dynwind_end ();
+ return Qnil;
+ }
unwind_data.start = 0;
/* Delete the compressed data. */
del_range (istart, iend);
- return unbind_to (count, Qt);
+ dynwind_end ();
+ return Qt;
}
\f
void
syms_of_decompress (void)
{
+#include "decompress.x"
+
DEFSYM (Qzlib_dll, "zlib");
- defsubr (&Szlib_decompress_region);
- defsubr (&Szlib_available_p);
}
#endif /* HAVE_ZLIB */