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.
parent 6e7114d4
......@@ -1886,27 +1886,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;
}
/**
......
......@@ -126,6 +126,7 @@ struct RsvgSaxHandler {
/* 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
......
......@@ -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 ();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment