2 Copyright (C) 2013 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/>. */
26 #include "character.h"
29 static Lisp_Object Qzlib_dll
;
35 /* Macro for defining functions that will be loaded from the zlib DLL. */
36 #define DEF_ZLIB_FN(rettype,func,args) static rettype (FAR CDECL *fn_##func)args
38 /* Macro for loading zlib functions from the library. */
39 #define LOAD_ZLIB_FN(lib,func) { \
40 fn_##func = (void *) GetProcAddress (lib, #func); \
41 if (!fn_##func) return 0; \
44 DEF_ZLIB_FN (int, inflateInit2_
,
45 (z_streamp strm
, int windowBits
, const char *version
, int stream_size
));
47 DEF_ZLIB_FN (int, inflate
,
48 (z_streamp strm
, int flush
));
50 DEF_ZLIB_FN (int, inflateEnd
,
54 init_zlib_functions (void)
56 HMODULE library
= w32_delayed_load (Qzlib_dll
);
60 message1 ("zlib library not found");
64 LOAD_ZLIB_FN (library
, inflateInit2_
);
65 LOAD_ZLIB_FN (library
, inflate
);
66 LOAD_ZLIB_FN (library
, inflateEnd
);
70 #define fn_inflateInit2(strm, windowBits) \
71 fn_inflateInit2_((strm), (windowBits), ZLIB_VERSION, sizeof(z_stream))
73 #else /* !WINDOWSNT */
75 #define fn_inflateInit2 inflateInit2
76 #define fn_inflate inflate
77 #define fn_inflateEnd inflateEnd
79 #endif /* WINDOWSNT */
82 struct decompress_unwind_data
84 ptrdiff_t old_point
, start
;
89 unwind_decompress (void *ddata
)
91 struct decompress_unwind_data
*data
= ddata
;
92 fn_inflateEnd (data
->stream
);
94 /* Delete any uncompressed data already inserted and restore point. */
97 del_range (data
->start
, PT
);
98 SET_PT (data
->old_point
);
102 DEFUN ("zlib-available-p", Fzlib_available_p
, Szlib_available_p
, 0, 0, 0,
103 doc
: /* Return t if zlib decompression is available in this instance of Emacs. */)
107 Lisp_Object found
= Fassq (Qzlib_dll
, Vlibrary_cache
);
113 status
= init_zlib_functions () ? Qt
: Qnil
;
114 Vlibrary_cache
= Fcons (Fcons (Qzlib_dll
, status
), Vlibrary_cache
);
122 DEFUN ("zlib-decompress-region", Fzlib_decompress_region
,
123 Szlib_decompress_region
,
125 doc
: /* Decompress a gzip- or zlib-compressed region.
126 Replace the text in the region by the decompressed data.
127 On failure, return nil and leave the data in place.
128 This function can be called only in unibyte buffers. */)
129 (Lisp_Object start
, Lisp_Object end
)
131 ptrdiff_t istart
, iend
, pos_byte
;
134 struct decompress_unwind_data unwind_data
;
135 ptrdiff_t count
= SPECPDL_INDEX ();
137 validate_region (&start
, &end
);
139 if (! NILP (BVAR (current_buffer
, enable_multibyte_characters
)))
140 error ("This function can be called only in unibyte buffers");
142 /* This is a unibyte buffer, so character positions and bytes are
144 istart
= XINT (start
);
146 move_gap_both (iend
, iend
);
148 stream
.zalloc
= Z_NULL
;
149 stream
.zfree
= Z_NULL
;
150 stream
.opaque
= Z_NULL
;
152 stream
.next_in
= Z_NULL
;
154 /* The magic number 32 apparently means "autodect both the gzip and
155 zlib formats" according to zlib.h. */
156 if (fn_inflateInit2 (&stream
, MAX_WBITS
+ 32) != Z_OK
)
159 unwind_data
.start
= iend
;
160 unwind_data
.stream
= &stream
;
161 unwind_data
.old_point
= PT
;
163 record_unwind_protect_ptr (unwind_decompress
, &unwind_data
);
165 /* Insert the decompressed data at the end of the compressed data. */
170 /* Keep calling 'inflate' until it reports an error or end-of-input. */
173 /* Maximum number of bytes that one 'inflate' call should read and write.
174 zlib requires that these values not exceed UINT_MAX.
175 Do not make avail_out too large, as that might unduly delay C-g. */
176 ptrdiff_t avail_in
= min (iend
- pos_byte
, UINT_MAX
);
177 ptrdiff_t avail_out
= min (1 << 14, UINT_MAX
);
179 ptrdiff_t decompressed
;
181 if (GAP_SIZE
< avail_out
)
182 make_gap (avail_out
- GAP_SIZE
);
183 stream
.next_in
= BYTE_POS_ADDR (pos_byte
);
184 stream
.avail_in
= avail_in
;
185 stream
.next_out
= GPT_ADDR
;
186 stream
.avail_out
= avail_out
;
187 inflate_status
= fn_inflate (&stream
, Z_NO_FLUSH
);
188 pos_byte
+= avail_in
- stream
.avail_in
;
189 decompressed
= avail_out
- stream
.avail_out
;
190 insert_from_gap (decompressed
, decompressed
, 0);
193 while (inflate_status
== Z_OK
);
195 if (inflate_status
!= Z_STREAM_END
)
196 return unbind_to (count
, Qnil
);
198 unwind_data
.start
= 0;
200 /* Delete the compressed data. */
201 del_range (istart
, iend
);
203 return unbind_to (count
, Qt
);
207 /***********************************************************************
209 ***********************************************************************/
211 syms_of_decompress (void)
213 DEFSYM (Qzlib_dll
, "zlib");
214 defsubr (&Szlib_decompress_region
);
215 defsubr (&Szlib_available_p
);
218 #endif /* HAVE_ZLIB */