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 #define BUFFER_SIZE 16384
32 struct decompress_unwind_data
{
33 ptrdiff_t old_point
, start
;
38 unwind_decompress (void *ddata
) {
39 struct decompress_unwind_data
*data
= ddata
;
40 inflateEnd (data
->stream
);
41 /* Delete any uncompressed data already inserted and restore
44 del_range (data
->start
, PT
);
45 SET_PT (data
->old_point
);
49 DEFUN ("decompress-gzipped-region", Fdecompress_gzipped_region
,
50 Sdecompress_gzipped_region
,
52 doc
: /* Decompress a gzip-compressed region.
53 The text in the region will be replaced by the decompressed data.
54 On failure, nil is returned and the data is left in place.
55 This function can only be called in unibyte buffers.*/)
56 (Lisp_Object start
, Lisp_Object end
)
58 ptrdiff_t istart
, iend
, point
= PT
;
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 only be called 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 /* We're inserting the decompressed data at the end of the
90 stream
.avail_in
= iend
- istart
;
91 stream
.next_in
= (char *) BYTE_POS_ADDR (istart
);
93 unwind_data
.start
= iend
;
94 unwind_data
.stream
= &stream
;
95 unwind_data
.old_point
= point
;
96 record_unwind_protect_ptr (unwind_decompress
, &unwind_data
);
100 /* Run inflate() on input until the output buffer isn't full. */
103 stream
.avail_out
= BUFFER_SIZE
;
104 stream
.next_out
= out
;
105 result
= inflate (&stream
, Z_NO_FLUSH
);
107 unbind_to (count
, Qnil
);
111 decompressed
= BUFFER_SIZE
- stream
.avail_out
;
112 insert_1_both (out
, decompressed
, decompressed
, 0, 0, 0);
114 } while (stream
.avail_out
== 0);
118 unwind_data
.start
= 0;
119 unbind_to (count
, Qnil
);
121 /* Delete the compressed data. */
122 del_range (istart
, iend
);
128 /***********************************************************************
130 ***********************************************************************/
132 syms_of_decompress (void)
134 defsubr (&Sdecompress_gzipped_region
);
137 #endif /* HAVE_ZLIB */