[libgsf] GsfOutputGzip: add "deflate-level" to control compression



commit f64435e6db5ba5a555bd15194c62e9d07c1fb908
Author: Morten Welinder <terra gnome org>
Date:   Fri Oct 18 16:04:19 2019 -0400

    GsfOutputGzip: add "deflate-level" to control compression
    
    This must be set before the first write in order to take effect.

 ChangeLog             |  6 ++++
 NEWS                  |  1 +
 gsf/gsf-output-gzip.c | 81 +++++++++++++++++++++++++++++++--------------------
 3 files changed, 57 insertions(+), 31 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index 4290099..28d8c7f 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2019-10-18  Morten Welinder  <terra gnome org>
+
+       * gsf/gsf-output-gzip.c (gsf_output_gzip_class_init): Add
+       "deflate-level" attribute to control compression.  Must be set
+       before first write.  Based on code from Allin Cottrell.
+
 2019-10-16  Morten Welinder  <terra gnome org>
 
        * gsf/gsf-output-memory.c (gsf_output_memory_steal_bytes): New
diff --git a/NEWS b/NEWS
index 7c165ae..c822b27 100644
--- a/NEWS
+++ b/NEWS
@@ -2,6 +2,7 @@ libgsf 1.14.47
 
 Allin Cottrell:
        * GsfOutputMemory improvement.
+       * Teach GsfOutputGzip to control compression level.
 
 --------------------------------------------------------------------------
 libgsf 1.14.46
diff --git a/gsf/gsf-output-gzip.c b/gsf/gsf-output-gzip.c
index 3d7b05c..d132fa6 100644
--- a/gsf/gsf-output-gzip.c
+++ b/gsf/gsf-output-gzip.c
@@ -35,10 +35,12 @@ struct _GsfOutputGZip {
 
        GsfOutput *sink; /* compressed data */
        gboolean raw; /* No header and no trailer.  */
+       gint deflate_level; /* zlib compression level */
 
        z_stream  stream;
        uLong     crc;     /* crc32 of uncompressed data */
        size_t    isize;
+       gboolean setup;
 
        guint8   *buf;
        size_t    buf_size;
@@ -51,7 +53,8 @@ typedef struct {
 enum {
        PROP_0,
        PROP_RAW,
-       PROP_SINK
+       PROP_SINK,
+       PROP_DEFLATE_LEVEL
 };
 
 
@@ -63,7 +66,7 @@ init_gzip (GsfOutputGZip *gzip)
 {
        int ret;
 
-       ret = deflateInit2 (&gzip->stream, Z_DEFAULT_COMPRESSION,
+       ret = deflateInit2 (&gzip->stream, gzip->deflate_level,
                            Z_DEFLATED, -MAX_WBITS, MAX_MEM_LEVEL,
                            Z_DEFAULT_STRATEGY);
        if (ret != Z_OK)
@@ -104,6 +107,24 @@ gzip_output_header (GsfOutputGZip *gzip)
        return ret;
 }
 
+static void
+gsf_output_gzip_setup (GsfOutputGZip *gzip)
+{
+       if (gzip->setup)
+               return;
+
+       if (!init_gzip (gzip))
+               gsf_output_set_error (GSF_OUTPUT (gzip),
+                                     0,
+                                     "Failed to initialize zlib structure");
+       else if (!gzip->raw && !gzip_output_header (gzip))
+               gsf_output_set_error (GSF_OUTPUT (gzip),
+                                     0,
+                                     "Failed to write gzip header");
+       else
+               gzip->setup = TRUE;
+}
+
 /**
  * gsf_output_gzip_new:
  * @sink: The underlying data source.
@@ -204,6 +225,9 @@ gsf_output_gzip_write (GsfOutput *output,
 
        g_return_val_if_fail (data, FALSE);
 
+       // Write header, if needed
+       gsf_output_gzip_setup (gzip);
+
        gzip->stream.next_in  = (unsigned char *) data;
        gzip->stream.avail_in = num_bytes;
 
@@ -246,8 +270,12 @@ gsf_output_gzip_seek (G_GNUC_UNUSED GsfOutput *output,
 static gboolean
 gsf_output_gzip_close (GsfOutput *output)
 {
+       GsfOutputGZip *gzip = GSF_OUTPUT_GZIP (output);
+
+       // Just in case nothing was ever written
+       gsf_output_gzip_setup (gzip);
+
        if (!gsf_output_error (output)) {
-               GsfOutputGZip *gzip = GSF_OUTPUT_GZIP (output);
 
                if (!gzip_flush (gzip))
                        return FALSE;
@@ -279,8 +307,10 @@ gsf_output_gzip_init (GObject *obj)
        gzip->stream.avail_in   = gzip->stream.avail_out = 0;
        gzip->crc               = crc32 (0L, Z_NULL, 0);
        gzip->isize             = 0;
+       gzip->setup             = FALSE;
        gzip->buf               = NULL;
        gzip->buf_size          = 0;
+       gzip->deflate_level     = Z_DEFAULT_COMPRESSION;
 }
 
 static void
@@ -298,6 +328,9 @@ gsf_output_gzip_get_property (GObject     *object,
        case PROP_SINK:
                g_value_set_object (value, gzip->sink);
                break;
+       case PROP_DEFLATE_LEVEL:
+               g_value_set_int (value, gzip->deflate_level);
+               break;
        default:
                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
                break;
@@ -329,45 +362,20 @@ gsf_output_gzip_set_property (GObject      *object,
        case PROP_SINK:
                gsf_output_gzip_set_sink (gzip, g_value_get_object (value));
                break;
+       case PROP_DEFLATE_LEVEL:
+               gzip->deflate_level = g_value_get_int (value);
+               break;
        default:
                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
                break;
        }
 }
 
-static GObject*
-gsf_output_gzip_constructor (GType                  type,
-                            guint                  n_construct_properties,
-                            GObjectConstructParam *construct_params)
-{
-       GsfOutputGZip *gzip;
-
-       gzip = (GsfOutputGZip *)(parent_class->constructor (type,
-                                                           n_construct_properties,
-                                                           construct_params));
-
-       if (!gzip->sink)
-               gsf_output_set_error (GSF_OUTPUT (gzip),
-                                     0,
-                                     "NULL sink");
-       else if (!init_gzip (gzip))
-               gsf_output_set_error (GSF_OUTPUT (gzip),
-                                     0,
-                                     "Failed to initialize zlib structure");
-       else if (!gzip->raw && !gzip_output_header (gzip))
-               gsf_output_set_error (GSF_OUTPUT (gzip),
-                                     0,
-                                     "Failed to write gzip header");
-
-       return (GObject *)gzip;
-}
-
 static void
 gsf_output_gzip_class_init (GObjectClass *gobject_class)
 {
        GsfOutputClass *output_class = GSF_OUTPUT_CLASS (gobject_class);
 
-       gobject_class->constructor  = gsf_output_gzip_constructor;
        gobject_class->finalize     = gsf_output_gzip_finalize;
        gobject_class->set_property = gsf_output_gzip_set_property;
        gobject_class->get_property = gsf_output_gzip_get_property;
@@ -393,6 +401,17 @@ gsf_output_gzip_class_init (GObjectClass *gobject_class)
                                      GSF_PARAM_STATIC |
                                      G_PARAM_READWRITE |
                                      G_PARAM_CONSTRUCT_ONLY));
+       g_object_class_install_property
+               (gobject_class,
+                PROP_DEFLATE_LEVEL,
+                g_param_spec_int ("deflate-level",
+                                  _("Deflate Level"),
+                                  _("The level of deflate compression used, zero meaning none "
+                                    "and -1 meaning the zlib default"),
+                                  -1, 9,
+                                  Z_DEFAULT_COMPRESSION,
+                                  GSF_PARAM_STATIC |
+                                  G_PARAM_READWRITE));
 
        parent_class = g_type_class_peek_parent (gobject_class);
 }


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]