From: "Juan José García-Ripoll" <juanjose.garciaripoll@gmail.com>
To: emacs-devel@gnu.org
Subject: Re: decompress.c now also compresses
Date: Sun, 29 Mar 2020 17:57:23 +0200 [thread overview]
Message-ID: <86sghr17do.fsf@csic.es> (raw)
In-Reply-To: 86zhbz17mk.fsf@csic.es
[-- Attachment #1: Type: text/plain, Size: 232 bytes --]
Apologies for the corrupted patch: I used emacs' C-c C-v and it looked
good, but "git diff" failed because of cr/lf issues. Here it goes again.
--
Juan José García Ripoll
http://juanjose.garciaripoll.com
http://quinfog.hbar.es
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: decompress.diff --]
[-- Type: text/x-patch, Size: 6952 bytes --]
diff --git a/src/decompress.c b/src/decompress.c
index 5d24638..7f20cb0 100644
--- a/src/decompress.c
+++ b/src/decompress.c
@@ -33,11 +33,23 @@
# include "w32common.h"
# include "w32.h"
+/* We import inflateInit2_ and deflateInit2_ because inflateInit and
+ deflateInit are macros defined on top of these symbols by zlib.h */
DEF_DLL_FN (int, inflateInit2_,
(z_streamp strm, int windowBits, const char *version,
int stream_size));
DEF_DLL_FN (int, inflate, (z_streamp strm, int flush));
DEF_DLL_FN (int, inflateEnd, (z_streamp strm));
+DEF_DLL_FN (int, deflateInit2_,
+ (z_streamp strm, int level, int method, int windowBits,
+ int memLevel, int strategy, const char *version,
+ int stream_size));
+DEF_DLL_FN (int, deflateInit2_,
+ (z_streamp strm, int level, int method, int windowBits,
+ int memLevel, int strategy, const char *version,
+ int stream_size));
+DEF_DLL_FN (int, deflate, (z_streamp strm, int flush));
+DEF_DLL_FN (int, deflateEnd, (z_streamp strm));
static bool zlib_initialized;
@@ -52,16 +64,25 @@ init_zlib_functions (void)
LOAD_DLL_FN (library, inflateInit2_);
LOAD_DLL_FN (library, inflate);
LOAD_DLL_FN (library, inflateEnd);
+ LOAD_DLL_FN (library, deflateInit2_);
+ LOAD_DLL_FN (library, deflate);
+ LOAD_DLL_FN (library, deflateEnd);
return true;
}
# undef inflate
# undef inflateEnd
# undef inflateInit2_
+# undef deflate
+# undef deflateEnd
+# undef deflateInit2_
# define inflate fn_inflate
# define inflateEnd fn_inflateEnd
# define inflateInit2_ fn_inflateInit2_
+# define deflate fn_deflate
+# define deflateEnd fn_deflateEnd
+# define deflateInit2_ fn_deflateInit2_
#endif /* WINDOWSNT */
@@ -70,13 +91,14 @@ init_zlib_functions (void)
{
ptrdiff_t old_point, orig, start, nbytes;
z_stream *stream;
+ int deflating;
};
static void
-unwind_decompress (void *ddata)
+unwind_zlib (void *ddata)
{
struct decompress_unwind_data *data = ddata;
- inflateEnd (data->stream);
+ (data->deflating? deflateEnd : inflateEnd) (data->stream);
/* Delete any uncompressed data already inserted on error, but
without calling the change hooks. */
@@ -180,7 +202,8 @@ DEFUN ("zlib-decompress-region", Fzlib_decompress_region,
unwind_data.stream = &stream;
unwind_data.old_point = PT;
unwind_data.nbytes = 0;
- record_unwind_protect_ptr (unwind_decompress, &unwind_data);
+ unwind_data.deflating = 0;
+ record_unwind_protect_ptr (unwind_zlib, &unwind_data);
/* Insert the decompressed data at the end of the compressed data. */
SET_PT (iend);
@@ -233,6 +256,129 @@ DEFUN ("zlib-decompress-region", Fzlib_decompress_region,
return unbind_to (count, ret);
}
+\f
+DEFUN ("zlib-compress-region", Fzlib_compress_region,
+ Szlib_compress_region,
+ 2, 3, 0,
+ doc: /* Compress a region to a gzip or zlib stream.
+Replace the text in the region by the compressed data.
+
+If optional parameter NO-WRAPPER is nil or omitted, use the GZIP
+wrapper format; otherwise, output just a deflated stream of
+bytes. If decompression is completely successful return t.
+
+This function can be called only in unibyte buffers.*/)
+ (Lisp_Object start, Lisp_Object end, Lisp_Object zlib)
+{
+ ptrdiff_t istart, iend, pos_byte;
+ z_stream stream;
+ int deflate_status, flush;
+ struct decompress_unwind_data unwind_data;
+ ptrdiff_t count = SPECPDL_INDEX ();
+ bool gzipp = NILP (zlib);
+
+ validate_region (&start, &end);
+
+ if (! NILP (BVAR (current_buffer, enable_multibyte_characters)))
+ error ("This function can be called only in unibyte buffers");
+
+#ifdef WINDOWSNT
+ if (!zlib_initialized)
+ zlib_initialized = init_zlib_functions ();
+ if (!zlib_initialized)
+ {
+ message1 ("zlib library not found");
+ return Qnil;
+ }
+#endif
+
+ /* This is a unibyte buffer, so character positions and bytes are
+ the same. */
+ istart = XFIXNUM (start);
+ iend = XFIXNUM (end);
+
+ /* Do the following before manipulating the gap. */
+ modify_text (istart, iend);
+
+ move_gap_both (iend, iend);
+
+ stream.zalloc = Z_NULL;
+ stream.zfree = Z_NULL;
+ stream.opaque = Z_NULL;
+ stream.avail_in = 0;
+ stream.next_in = Z_NULL;
+
+ /* Initiate the deflate() process, choosing the format, compression
+ strategy and level (9), and amount of memory used. */
+ if (deflateInit2 (&stream, 9, Z_DEFLATED, MAX_WBITS + (gzipp? 16: 0),
+ 8, Z_DEFAULT_STRATEGY) != Z_OK)
+ return Qnil;
+
+ unwind_data.orig = istart;
+ unwind_data.start = iend;
+ unwind_data.stream = &stream;
+ unwind_data.old_point = PT;
+ unwind_data.nbytes = 0;
+ unwind_data.deflating = 1;
+ record_unwind_protect_ptr (unwind_zlib, &unwind_data);
+
+ /* Insert the decompressed data at the end of the compressed data. */
+ SET_PT (iend);
+
+ pos_byte = istart;
+
+ /* Keep calling 'deflate' until it reports an error or end-of-input. */
+ flush = Z_NO_FLUSH;
+ do
+ {
+ /* Maximum number of bytes that one 'deflate' call should read and write.
+ Do not make avail_out too large, as that might unduly delay C-g.
+ zlib requires that avail_in and avail_out not exceed UINT_MAX. */
+ ptrdiff_t avail_in = min (iend - pos_byte, UINT_MAX);
+ int avail_out = 16 * 1024;
+ int compressed;
+
+ if (GAP_SIZE < avail_out)
+ make_gap (avail_out - GAP_SIZE);
+ stream.next_in = BYTE_POS_ADDR (pos_byte);
+ stream.avail_in = avail_in;
+ stream.next_out = GPT_ADDR;
+ stream.avail_out = avail_out;
+ deflate_status = deflate (&stream, flush);
+
+ pos_byte += avail_in - stream.avail_in;
+ compressed = avail_out - stream.avail_out;
+ insert_from_gap (compressed, compressed, 0);
+ unwind_data.nbytes += compressed;
+ if (deflate_status == Z_BUF_ERROR && flush == Z_NO_FLUSH) {
+ /* When we run out of input, zlib returns Z_BUF_ERROR.
+ We then have to flush all output. */
+ flush = Z_FINISH;
+ deflate_status = Z_OK;
+ }
+ maybe_quit ();
+ }
+ while (deflate_status == Z_OK);
+
+ Lisp_Object ret = Qt;
+ if (deflate_status != Z_STREAM_END)
+ {
+ /* When compression did not succeed, delete output. */
+ ret = make_int (iend - pos_byte);
+ }
+
+ unwind_data.start = 0;
+
+ /* Delete the uncompressed data. */
+ del_range_2 (istart, istart, /* byte and char offsets are the same. */
+ iend, iend, 0);
+
+ signal_after_change (istart, iend - istart, unwind_data.nbytes);
+ update_compositions (istart, istart, CHECK_HEAD);
+
+ return unbind_to (count, ret);
+}
+
\f
/***********************************************************************
Initialization
@@ -241,6 +387,7 @@ DEFUN ("zlib-decompress-region", Fzlib_decompress_region,
syms_of_decompress (void)
{
defsubr (&Szlib_decompress_region);
+ defsubr (&Szlib_compress_region);
defsubr (&Szlib_available_p);
}
next prev parent reply other threads:[~2020-03-29 15:57 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-03-29 15:52 decompress.c now also compresses Juan José García-Ripoll
2020-03-29 15:57 ` Juan José García-Ripoll [this message]
2020-03-29 16:11 ` Eli Zaretskii
2020-03-29 16:48 ` Juan José García-Ripoll
2020-03-29 16:54 ` Stefan Monnier
2020-03-29 19:27 ` Juan José García-Ripoll
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=86sghr17do.fsf@csic.es \
--to=juanjose.garciaripoll@gmail.com \
--cc=emacs-devel@gnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this external index
https://git.savannah.gnu.org/cgit/emacs.git
https://git.savannah.gnu.org/cgit/emacs/org-mode.git
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.