[librsvg/librsvg-2.40] Allow loading one byte at a time with rsvg_handle_write()



commit 20bab7fb4a181419617b5bbbf539b1e00f94a344
Author: Federico Mena Quintero <federico gnome org>
Date:   Tue Oct 3 14:45:37 2017 -0500

    Allow loading one byte at a time with rsvg_handle_write()
    
    This hadn't worked for a long time for compressed files, since we
    weren't holding the state of reading the gzip header.  Now we have a
    test for it.

 rsvg-base.c     |   57 ++++++++++++++++++++++++++++++++++++++++++------------
 rsvg-private.h  |    1 +
 tests/loading.c |    9 ++++++-
 3 files changed, 52 insertions(+), 15 deletions(-)
---
diff --git a/rsvg-base.c b/rsvg-base.c
index 2ae8528..4a20306 100644
--- a/rsvg-base.c
+++ b/rsvg-base.c
@@ -1748,27 +1748,58 @@ rsvg_handle_write (RsvgHandle * handle, const guchar * buf, gsize count, GError
     priv = handle->priv;
 
     rsvg_return_val_if_fail (priv->state == RSVG_HANDLE_STATE_START
+                             || priv->state == RSVG_HANDLE_STATE_EXPECTING_GZ_1
                              || priv->state == RSVG_HANDLE_STATE_READING,
                              FALSE,
                              error);
 
-    if (priv->state == RSVG_HANDLE_STATE_START) {
-        priv->state = RSVG_HANDLE_STATE_READING;
+    while (count > 0) {
+        switch (priv->state) {
+        case RSVG_HANDLE_STATE_START:
+            if (buf[0] == GZ_MAGIC_0) {
+                priv->state = RSVG_HANDLE_STATE_EXPECTING_GZ_1;
+                buf++;
+                count--;
+            } else {
+                priv->state = RSVG_HANDLE_STATE_READING;
+                return rsvg_handle_write_impl (handle, buf, count, error);
+            }
 
-        /* test for GZ marker. todo: store the first 2 bytes in the odd circumstance that someone calls
-         * write() in 1 byte increments */
-        if ((count >= 2) && (buf[0] == GZ_MAGIC_0) && (buf[1] == GZ_MAGIC_1)) {
-            priv->data_input_stream = g_memory_input_stream_new ();
-        }
-    }
+            break;
 
-    if (priv->data_input_stream) {
-        g_memory_input_stream_add_data ((GMemoryInputStream *) priv->data_input_stream,
-                                        g_memdup (buf, count), count, (GDestroyNotify) g_free);
-        return TRUE;
+        case RSVG_HANDLE_STATE_EXPECTING_GZ_1:
+            if (buf[0] == GZ_MAGIC_1) {
+                static const guchar gz_magic[2] = { GZ_MAGIC_0, GZ_MAGIC_1 };
+
+                priv->data_input_stream = g_memory_input_stream_new ();
+                g_memory_input_stream_add_data (G_MEMORY_INPUT_STREAM (priv->data_input_stream), gz_magic, 
2, NULL);
+
+                priv->state = RSVG_HANDLE_STATE_READING;
+                buf++;
+                count--;
+            } else {
+                priv->state = RSVG_HANDLE_STATE_READING;
+                return rsvg_handle_write_impl (handle, buf, count, error);
+            }
+
+            break;
+
+        case RSVG_HANDLE_STATE_READING:
+            if (priv->data_input_stream) {
+                g_memory_input_stream_add_data (G_MEMORY_INPUT_STREAM (priv->data_input_stream),
+                                                g_memdup (buf, count), count, (GDestroyNotify) g_free);
+                return TRUE;
+            } else {
+                return rsvg_handle_write_impl (handle, buf, count, error);
+            }
+            break;
+
+        default:
+            g_assert_not_reached ();
+        }
     }
 
-    return rsvg_handle_write_impl (handle, buf, count, error);
+    return TRUE;
 }
 
 /**
diff --git a/rsvg-private.h b/rsvg-private.h
index 899a815..4803b93 100644
--- a/rsvg-private.h
+++ b/rsvg-private.h
@@ -131,6 +131,7 @@ typedef enum {
 /* Reading state for an RsvgHandle */
 typedef enum {
     RSVG_HANDLE_STATE_START,
+    RSVG_HANDLE_STATE_EXPECTING_GZ_1,
     RSVG_HANDLE_STATE_READING,
     RSVG_HANDLE_STATE_CLOSED_OK,
     RSVG_HANDLE_STATE_CLOSED_ERROR
diff --git a/tests/loading.c b/tests/loading.c
index 3f68dd8..46b8801 100644
--- a/tests/loading.c
+++ b/tests/loading.c
@@ -28,8 +28,12 @@ load_one_byte_at_a_time (gconstpointer data)
     done = FALSE;
 
     do {
-        if (fread (buf, 1, 1, file) == 1) {
-            g_assert (rsvg_handle_write (handle, buf, 1, NULL) != FALSE);
+        size_t num_read;
+
+        num_read = fread (buf, 1, 1, file);
+
+        if (num_read > 0) {
+            g_assert (rsvg_handle_write (handle, buf, num_read, NULL) != FALSE);
         } else {
             g_assert (ferror (file) == 0);
 
@@ -53,6 +57,7 @@ main (int argc, char **argv)
     g_test_init (&argc, &argv, NULL);
 
     g_test_add_data_func ("/load-one-byte-at-a-time", "loading/gnome-cool.svg", load_one_byte_at_a_time);
+    g_test_add_data_func ("/load-compressed-one-byte-at-a-time", "loading/gnome-cool.svgz", 
load_one_byte_at_a_time);
 
     result = g_test_run ();
 


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