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"
30 struct decompress_unwind_data
32 ptrdiff_t old_point
, start
;
37 unwind_decompress (void *ddata
)
39 struct decompress_unwind_data
*data
= ddata
;
40 inflateEnd (data
->stream
);
42 /* Delete any uncompressed data already inserted and restore point. */
45 del_range (data
->start
, PT
);
46 SET_PT (data
->old_point
);
50 DEFUN ("decompress-gzipped-region", Fdecompress_gzipped_region
,
51 Sdecompress_gzipped_region
,
53 doc
: /* Decompress a gzip-compressed region.
54 Replace the text in the region by the decompressed data.
55 On failure, return nil and leave the data in place.
56 This function can be called only in unibyte buffers. */)
57 (Lisp_Object start
, Lisp_Object end
)
59 ptrdiff_t istart
, iend
, pos_byte
;
62 struct decompress_unwind_data unwind_data
;
63 ptrdiff_t count
= SPECPDL_INDEX ();
65 validate_region (&start
, &end
);
67 if (! NILP (BVAR (current_buffer
, enable_multibyte_characters
)))
68 error ("This function can be called only in unibyte buffers");
70 /* This is a unibyte buffer, so character positions and bytes are
72 istart
= XINT (start
);
74 move_gap_both (iend
, iend
);
76 stream
.zalloc
= Z_NULL
;
77 stream
.zfree
= Z_NULL
;
78 stream
.opaque
= Z_NULL
;
80 stream
.next_in
= Z_NULL
;
82 /* This magic number apparently means "this is gzip". */
83 if (inflateInit2 (&stream
, 16 + MAX_WBITS
) != Z_OK
)
86 unwind_data
.start
= iend
;
87 unwind_data
.stream
= &stream
;
88 unwind_data
.old_point
= PT
;
90 record_unwind_protect_ptr (unwind_decompress
, &unwind_data
);
92 /* Insert the decompressed data at the end of the compressed data. */
97 /* Keep calling 'inflate' until it reports an error or end-of-input. */
100 /* Maximum number of bytes that one 'inflate' call should read and write.
101 zlib requires that these values not exceed UINT_MAX.
102 Do not make avail_out too large, as that might unduly delay C-g. */
103 ptrdiff_t avail_in
= min (iend
- pos_byte
, UINT_MAX
);
104 ptrdiff_t avail_out
= min (1 << 14, UINT_MAX
);
106 ptrdiff_t decompressed
;
108 if (GAP_SIZE
< avail_out
)
109 make_gap (avail_out
- GAP_SIZE
);
110 stream
.next_in
= BYTE_POS_ADDR (pos_byte
);
111 stream
.avail_in
= avail_in
;
112 stream
.next_out
= GPT_ADDR
;
113 stream
.avail_out
= avail_out
;
114 inflate_status
= inflate (&stream
, Z_NO_FLUSH
);
115 pos_byte
+= avail_in
- stream
.avail_in
;
116 decompressed
= avail_out
- stream
.avail_out
;
117 insert_from_gap (decompressed
, decompressed
, 0);
120 while (inflate_status
== Z_OK
);
122 if (inflate_status
!= Z_STREAM_END
)
123 return unbind_to (count
, Qnil
);
125 unwind_data
.start
= 0;
127 /* Delete the compressed data. */
128 del_range (istart
, iend
);
130 return unbind_to (count
, Qt
);
134 /***********************************************************************
136 ***********************************************************************/
138 syms_of_decompress (void)
140 defsubr (&Sdecompress_gzipped_region
);
143 #endif /* HAVE_ZLIB */