Subject: * lisp/progmodes/prolog.el: Improve handling of if/then/else
[emacs.git] / src / decompress.c
blob460d4fe76701ebd367da8c690d342f08cd56129a
1 /* Interface to zlib.
2 Copyright (C) 2013-2015 Free Software Foundation, Inc.
4 This file is part of GNU Emacs.
6 GNU Emacs is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
11 GNU Emacs is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
19 #include <config.h>
21 #ifdef HAVE_ZLIB
23 #include <zlib.h>
25 #include "lisp.h"
26 #include "character.h"
27 #include "buffer.h"
29 #include <verify.h>
31 #ifdef WINDOWSNT
32 # include <windows.h>
33 # include "w32.h"
35 DEF_DLL_FN (int, inflateInit2_,
36 (z_streamp strm, int windowBits, const char *version,
37 int stream_size));
38 DEF_DLL_FN (int, inflate, (z_streamp strm, int flush));
39 DEF_DLL_FN (int, inflateEnd, (z_streamp strm));
41 static bool zlib_initialized;
43 static bool
44 init_zlib_functions (void)
46 HMODULE library = w32_delayed_load (Qzlib_dll);
48 if (!library)
49 return false;
51 LOAD_DLL_FN (library, inflateInit2_);
52 LOAD_DLL_FN (library, inflate);
53 LOAD_DLL_FN (library, inflateEnd);
54 return true;
57 # undef inflate
58 # undef inflateEnd
59 # undef inflateInit2_
61 # define inflate fn_inflate
62 # define inflateEnd fn_inflateEnd
63 # define inflateInit2_ fn_inflateInit2_
65 #endif /* WINDOWSNT */
68 struct decompress_unwind_data
70 ptrdiff_t old_point, start, nbytes;
71 z_stream *stream;
74 static void
75 unwind_decompress (void *ddata)
77 struct decompress_unwind_data *data = ddata;
78 inflateEnd (data->stream);
80 /* Delete any uncompressed data already inserted on error. */
81 if (data->start)
82 del_range (data->start, data->start + data->nbytes);
84 /* Put point where it was, or if the buffer has shrunk because the
85 compressed data is bigger than the uncompressed, at
86 point-max. */
87 SET_PT (min (data->old_point, ZV));
90 DEFUN ("zlib-available-p", Fzlib_available_p, Szlib_available_p, 0, 0, 0,
91 doc: /* Return t if zlib decompression is available in this instance of Emacs. */)
92 (void)
94 #ifdef WINDOWSNT
95 Lisp_Object found = Fassq (Qzlib_dll, Vlibrary_cache);
96 if (CONSP (found))
97 return XCDR (found);
98 else
100 Lisp_Object status;
101 zlib_initialized = init_zlib_functions ();
102 status = zlib_initialized ? Qt : Qnil;
103 Vlibrary_cache = Fcons (Fcons (Qzlib_dll, status), Vlibrary_cache);
104 return status;
106 #else
107 return Qt;
108 #endif
111 DEFUN ("zlib-decompress-region", Fzlib_decompress_region,
112 Szlib_decompress_region,
113 2, 2, 0,
114 doc: /* Decompress a gzip- or zlib-compressed region.
115 Replace the text in the region by the decompressed data.
116 On failure, return nil and leave the data in place.
117 This function can be called only in unibyte buffers. */)
118 (Lisp_Object start, Lisp_Object end)
120 ptrdiff_t istart, iend, pos_byte;
121 z_stream stream;
122 int inflate_status;
123 struct decompress_unwind_data unwind_data;
124 ptrdiff_t count = SPECPDL_INDEX ();
126 validate_region (&start, &end);
128 if (! NILP (BVAR (current_buffer, enable_multibyte_characters)))
129 error ("This function can be called only in unibyte buffers");
131 #ifdef WINDOWSNT
132 if (!zlib_initialized)
133 zlib_initialized = init_zlib_functions ();
134 if (!zlib_initialized)
136 message1 ("zlib library not found");
137 return Qnil;
139 #endif
141 /* This is a unibyte buffer, so character positions and bytes are
142 the same. */
143 istart = XINT (start);
144 iend = XINT (end);
145 move_gap_both (iend, iend);
147 stream.zalloc = Z_NULL;
148 stream.zfree = Z_NULL;
149 stream.opaque = Z_NULL;
150 stream.avail_in = 0;
151 stream.next_in = Z_NULL;
153 /* The magic number 32 apparently means "autodetect both the gzip and
154 zlib formats" according to zlib.h. */
155 if (inflateInit2 (&stream, MAX_WBITS + 32) != Z_OK)
156 return Qnil;
158 unwind_data.start = iend;
159 unwind_data.stream = &stream;
160 unwind_data.old_point = PT;
161 unwind_data.nbytes = 0;
162 record_unwind_protect_ptr (unwind_decompress, &unwind_data);
164 /* Insert the decompressed data at the end of the compressed data. */
165 SET_PT (iend);
167 pos_byte = istart;
169 /* Keep calling 'inflate' until it reports an error or end-of-input. */
172 /* Maximum number of bytes that one 'inflate' call should read and write.
173 Do not make avail_out too large, as that might unduly delay C-g.
174 zlib requires that avail_in and avail_out not exceed UINT_MAX. */
175 ptrdiff_t avail_in = min (iend - pos_byte, UINT_MAX);
176 int avail_out = 16 * 1024;
177 int decompressed;
179 if (GAP_SIZE < avail_out)
180 make_gap (avail_out - GAP_SIZE);
181 stream.next_in = BYTE_POS_ADDR (pos_byte);
182 stream.avail_in = avail_in;
183 stream.next_out = GPT_ADDR;
184 stream.avail_out = avail_out;
185 inflate_status = inflate (&stream, Z_NO_FLUSH);
186 pos_byte += avail_in - stream.avail_in;
187 decompressed = avail_out - stream.avail_out;
188 insert_from_gap (decompressed, decompressed, 0);
189 unwind_data.nbytes += decompressed;
190 QUIT;
192 while (inflate_status == Z_OK);
194 if (inflate_status != Z_STREAM_END)
195 return unbind_to (count, Qnil);
197 unwind_data.start = 0;
199 /* Delete the compressed data. */
200 del_range (istart, iend);
202 return unbind_to (count, Qt);
206 /***********************************************************************
207 Initialization
208 ***********************************************************************/
209 void
210 syms_of_decompress (void)
212 defsubr (&Szlib_decompress_region);
213 defsubr (&Szlib_available_p);
216 #endif /* HAVE_ZLIB */