From 1bedf248794fe5cf9dad5e40c18329e79f9d855e Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Thu, 17 May 2012 14:36:15 -0400 Subject: [PATCH] GMemoryInputStream: Add API to accept GBytes And s/Chunk/GBytes/ internally. GBytes is really a perfect match for GMemoryInputStream. https://bugzilla.gnome.org/show_bug.cgi?id=672102 --- gio/gio.symbols | 2 + gio/gmemoryinputstream.c | 111 ++++++++++++++++++++++++--------------- gio/gmemoryinputstream.h | 6 +++ 3 files changed, 78 insertions(+), 41 deletions(-) diff --git a/gio/gio.symbols b/gio/gio.symbols index 3f6f773e2..3dbbb5de5 100644 --- a/gio/gio.symbols +++ b/gio/gio.symbols @@ -548,6 +548,8 @@ g_loadable_icon_load_finish g_memory_input_stream_get_type g_memory_input_stream_new g_memory_input_stream_new_from_data +g_memory_input_stream_new_from_bytes +g_memory_input_stream_add_bytes g_memory_input_stream_add_data g_memory_output_stream_get_type g_memory_output_stream_new diff --git a/gio/gmemoryinputstream.c b/gio/gmemoryinputstream.c index dac0ac166..630def264 100644 --- a/gio/gmemoryinputstream.c +++ b/gio/gmemoryinputstream.c @@ -44,14 +44,6 @@ * #GPollableInputStream. */ -typedef struct _Chunk Chunk; - -struct _Chunk { - guint8 *data; - gsize len; - GDestroyNotify destroy; -}; - struct _GMemoryInputStreamPrivate { GSList *chunks; gsize len; @@ -139,17 +131,6 @@ g_memory_input_stream_class_init (GMemoryInputStreamClass *klass) istream_class->close_finish = g_memory_input_stream_close_finish; } -static void -free_chunk (gpointer data) -{ - Chunk *chunk = data; - - if (chunk->destroy) - chunk->destroy (chunk->data); - - g_slice_free (Chunk, chunk); -} - static void g_memory_input_stream_finalize (GObject *object) { @@ -159,7 +140,7 @@ g_memory_input_stream_finalize (GObject *object) stream = G_MEMORY_INPUT_STREAM (object); priv = stream->priv; - g_slist_free_full (priv->chunks, free_chunk); + g_slist_free_full (priv->chunks, (GDestroyNotify)g_bytes_unref); G_OBJECT_CLASS (g_memory_input_stream_parent_class)->finalize (object); } @@ -231,6 +212,29 @@ g_memory_input_stream_new_from_data (const void *data, return stream; } +/** + * g_memory_input_stream_new_from_bytes: + * @bytes: a #GBytes + * + * Creates a new #GMemoryInputStream with data from the given @bytes. + * + * Returns: new #GInputStream read from @bytes + * Since: 2.34 + **/ +GInputStream * +g_memory_input_stream_new_from_bytes (GBytes *bytes) +{ + + GInputStream *stream; + + stream = g_memory_input_stream_new (); + + g_memory_input_stream_add_bytes (G_MEMORY_INPUT_STREAM (stream), + bytes); + + return stream; +} + /** * g_memory_input_stream_add_data: * @stream: a #GMemoryInputStream @@ -246,24 +250,43 @@ g_memory_input_stream_add_data (GMemoryInputStream *stream, gssize len, GDestroyNotify destroy) { - GMemoryInputStreamPrivate *priv; - Chunk *chunk; - - g_return_if_fail (G_IS_MEMORY_INPUT_STREAM (stream)); - g_return_if_fail (data != NULL); - - priv = stream->priv; + GBytes *bytes; if (len == -1) len = strlen (data); - - chunk = g_slice_new (Chunk); - chunk->data = (guint8 *)data; - chunk->len = len; - chunk->destroy = destroy; - priv->chunks = g_slist_append (priv->chunks, chunk); - priv->len += chunk->len; + /* It's safe to discard the const here because we're chaining the + * destroy callback. + */ + bytes = g_bytes_new_with_free_func (data, len, destroy, (void*)data); + + g_memory_input_stream_add_bytes (stream, bytes); + + g_bytes_unref (bytes); +} + +/** + * g_memory_input_stream_add_bytes: + * @stream: a #GMemoryInputStream + * @bytes: input data + * + * Appends @bytes to data that can be read from the input stream. + * + * Since: 2.34 + */ +void +g_memory_input_stream_add_bytes (GMemoryInputStream *stream, + GBytes *bytes) +{ + GMemoryInputStreamPrivate *priv; + + g_return_if_fail (G_IS_MEMORY_INPUT_STREAM (stream)); + g_return_if_fail (bytes != NULL); + + priv = stream->priv; + + priv->chunks = g_slist_append (priv->chunks, g_bytes_ref (bytes)); + priv->len += g_bytes_get_size (bytes); } static gssize @@ -276,7 +299,8 @@ g_memory_input_stream_read (GInputStream *stream, GMemoryInputStream *memory_stream; GMemoryInputStreamPrivate *priv; GSList *l; - Chunk *chunk; + GBytes *chunk; + gsize len; gsize offset, start, rest, size; memory_stream = G_MEMORY_INPUT_STREAM (stream); @@ -287,12 +311,13 @@ g_memory_input_stream_read (GInputStream *stream, offset = 0; for (l = priv->chunks; l; l = l->next) { - chunk = (Chunk *)l->data; + chunk = (GBytes *)l->data; + len = g_bytes_get_size (chunk); - if (offset + chunk->len > priv->pos) + if (offset + len > priv->pos) break; - offset += chunk->len; + offset += len; } start = priv->pos - offset; @@ -300,10 +325,14 @@ g_memory_input_stream_read (GInputStream *stream, for (; l && rest > 0; l = l->next) { - chunk = (Chunk *)l->data; - size = MIN (rest, chunk->len - start); + const guint8* chunk_data; + chunk = (GBytes *)l->data; - memcpy ((guint8 *)buffer + (count - rest), chunk->data + start, size); + chunk_data = g_bytes_get_data (chunk, &len); + + size = MIN (rest, len - start); + + memcpy ((guint8 *)buffer + (count - rest), chunk_data + start, size); rest -= size; start = 0; diff --git a/gio/gmemoryinputstream.h b/gio/gmemoryinputstream.h index e629db1d9..1625ae944 100644 --- a/gio/gmemoryinputstream.h +++ b/gio/gmemoryinputstream.h @@ -72,10 +72,16 @@ GInputStream * g_memory_input_stream_new (void); GInputStream * g_memory_input_stream_new_from_data (const void *data, gssize len, GDestroyNotify destroy); +GLIB_AVAILABLE_IN_2_34 +GInputStream * g_memory_input_stream_new_from_bytes (GBytes *bytes); + void g_memory_input_stream_add_data (GMemoryInputStream *stream, const void *data, gssize len, GDestroyNotify destroy); +GLIB_AVAILABLE_IN_2_34 +void g_memory_input_stream_add_bytes (GMemoryInputStream *stream, + GBytes *bytes); G_END_DECLS