From ce50248037177b8bde18d095cd1d5553a36a5f43 Mon Sep 17 00:00:00 2001 From: Alexander Larsson Date: Fri, 4 Jan 2008 10:17:57 +0000 Subject: [PATCH] Improve API so that you can use multile chunks of memory and custom 2008-01-04 Alexander Larsson * gio.symbols: * gmemoryinputstream.[ch]: Improve API so that you can use multile chunks of memory and custom destroy functions. (#506374) svn path=/trunk/; revision=6241 --- gio/ChangeLog | 7 ++ gio/gio.symbols | 7 +- gio/gmemoryinputstream.c | 165 +++++++++++++++++++++++---------------- gio/gmemoryinputstream.h | 14 ++-- 4 files changed, 115 insertions(+), 78 deletions(-) diff --git a/gio/ChangeLog b/gio/ChangeLog index c1c92265..dac46af3 100644 --- a/gio/ChangeLog +++ b/gio/ChangeLog @@ -1,3 +1,10 @@ +2008-01-04 Alexander Larsson + + * gio.symbols: + * gmemoryinputstream.[ch]: + Improve API so that you can use multile chunks + of memory and custom destroy functions. (#506374) + 2008-01-03 Alexander Larsson * gfileinfo.c: diff --git a/gio/gio.symbols b/gio/gio.symbols index c2caa43b..79030c6f 100644 --- a/gio/gio.symbols +++ b/gio/gio.symbols @@ -519,10 +519,9 @@ g_loadable_icon_load_finish #if IN_HEADER(__G_MEMORY_INPUT_STREAM_H__) #if IN_FILE(__G_MEMORY_INPUT_STREAM_C__) g_memory_input_stream_get_type G_GNUC_CONST -g_memory_input_stream_from_data -g_memory_input_stream_set_free_data -g_memory_input_stream_get_data -g_memory_input_stream_get_data_size +g_memory_input_stream_new +g_memory_input_stream_new_from_data +g_memory_input_stream_add_data #endif #endif diff --git a/gio/gmemoryinputstream.c b/gio/gmemoryinputstream.c index 87af192f..ddcb729b 100644 --- a/gio/gmemoryinputstream.c +++ b/gio/gmemoryinputstream.c @@ -41,11 +41,18 @@ * */ +typedef struct _Chunk Chunk; + +struct _Chunk { + guint8 *data; + gsize len; + GDestroyNotify destroy; +}; + struct _GMemoryInputStreamPrivate { - guint8 *buffer; - gsize pos; + GSList *chunks; gsize len; - gboolean free_data; + gsize pos; }; static gssize g_memory_input_stream_read (GInputStream *stream, @@ -132,15 +139,29 @@ g_memory_input_stream_class_init (GMemoryInputStreamClass *klass) istream_class->close_finish = g_memory_input_stream_close_finish; } +static void +free_chunk (gpointer data, + gpointer user_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) { GMemoryInputStream *stream; + GMemoryInputStreamPrivate *priv; stream = G_MEMORY_INPUT_STREAM (object); + priv = stream->priv; - if (stream->priv->free_data) - g_free (stream->priv->buffer); + g_slist_foreach (priv->chunks, free_chunk, NULL); + g_slist_free (priv->chunks); if (G_OBJECT_CLASS (g_memory_input_stream_parent_class)->finalize) (*G_OBJECT_CLASS (g_memory_input_stream_parent_class)->finalize) (object); @@ -164,51 +185,65 @@ g_memory_input_stream_init (GMemoryInputStream *stream) GMemoryInputStreamPrivate); } -/** - * g_memory_input_stream_set_free_data: - * @stream: a #GMemoryInputStream. - * @free_data: a #gboolean. If %TRUE, frees the data within @stream. - * - * Sets if the data within the @stream should be freed when the stream - * is freed. - **/ -void -g_memory_input_stream_set_free_data (GMemoryInputStream *stream, - gboolean free_data) +GInputStream * +g_memory_input_stream_new (void) { - g_return_if_fail (G_IS_MEMORY_INPUT_STREAM (stream)); + GInputStream *stream; + + stream = g_object_new (G_TYPE_MEMORY_INPUT_STREAM, NULL); - stream->priv->free_data = free_data; + return stream; } /** - * g_memory_input_stream_from_data: - * @data: input data. - * @len: length of the data. + * g_memory_input_stream_new_from_data: + * @data: input data + * @len: length of the data, may be -1 if @data is a nul-terminated string + * @destroy: function that is called to free @data, or %NULL * * Creates a new #GMemoryInputStream with data in memory of a given size. * * Returns: new #GInputStream read from @data of @len bytes. **/ GInputStream * -g_memory_input_stream_from_data (const void *data, - gssize len) +g_memory_input_stream_new_from_data (const void *data, + gssize len, + GDestroyNotify destroy) { GInputStream *stream; - GMemoryInputStream *memory_stream; - g_return_val_if_fail (data != NULL, NULL); + stream = g_memory_input_stream_new (); - stream = g_object_new (G_TYPE_MEMORY_INPUT_STREAM, NULL); - memory_stream = G_MEMORY_INPUT_STREAM (stream); + g_memory_input_stream_add_data (G_MEMORY_INPUT_STREAM (stream), + data, len, destroy); + + return stream; +} + +void +g_memory_input_stream_add_data (GMemoryInputStream *stream, + const void *data, + 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; if (len == -1) len = strlen (data); - memory_stream->priv->buffer = (guint8 *)data; - memory_stream->priv->len = len; + chunk = g_slice_new (Chunk); + chunk->data = (guint8 *)data; + chunk->len = len; + chunk->destroy = destroy; - return stream; + priv->chunks = g_slist_append (priv->chunks, chunk); + priv->len += chunk->len; } static gssize @@ -219,48 +254,44 @@ g_memory_input_stream_read (GInputStream *stream, GError **error) { GMemoryInputStream *memory_stream; - GMemoryInputStreamPrivate * priv; + GMemoryInputStreamPrivate *priv; + GSList *l; + Chunk *chunk; + gsize offset, start, rest, size; memory_stream = G_MEMORY_INPUT_STREAM (stream); priv = memory_stream->priv; count = MIN (count, priv->len - priv->pos); - memcpy (buffer, priv->buffer + priv->pos, count); - priv->pos += count; - return count; -} + offset = 0; + for (l = priv->chunks; l; l = l->next) + { + chunk = (Chunk *)l->data; -/** - * g_memory_input_stream_get_data: - * @stream: a #GMemoryInputStream - * - * Gets a pointer to the data within the #GMemoryInputStream. - * - * Returns: a pointer to the memory in the @stream. - **/ -const void * -g_memory_input_stream_get_data (GMemoryInputStream *stream) -{ - g_return_val_if_fail (G_IS_MEMORY_INPUT_STREAM (stream), NULL); + if (offset + chunk->len > priv->pos) + break; - return stream->priv->buffer; -} + offset += chunk->len; + } + + start = priv->pos - offset; + rest = count; -/** - * g_memory_input_stream_get_data_size: - * @stream: a #GMemoryInputStream - * - * Gets the size of the data within the #GMemoryInputStream. - * - * Returns: a gsize with the size of the data in @stream. - **/ -gsize -g_memory_input_stream_get_data_size (GMemoryInputStream *stream) -{ - g_return_val_if_fail (G_IS_MEMORY_INPUT_STREAM (stream), -1); + for (; l && rest > 0; l = l->next) + { + chunk = (Chunk *)l->data; + size = MIN (rest, chunk->len - start); + + memcpy (buffer + (count - rest), chunk->data + start, size); + rest -= size; + + start = 0; + } + + priv->pos += count; - return stream->priv->len; + return count; } static gssize @@ -279,8 +310,6 @@ g_memory_input_stream_skip (GInputStream *stream, priv->pos += count; return count; - - } static gboolean @@ -303,7 +332,7 @@ g_memory_input_stream_read_async (GInputStream *stream, GSimpleAsyncResult *simple; gssize nread; - nread = g_memory_input_stream_read (stream, buffer, count, cancellable, NULL); + nread = g_memory_input_stream_read (stream, buffer, count, cancellable, NULL); simple = g_simple_async_result_new (G_OBJECT (stream), callback, user_data, @@ -393,7 +422,7 @@ static goffset g_memory_input_stream_tell (GSeekable *seekable) { GMemoryInputStream *memory_stream; - GMemoryInputStreamPrivate * priv; + GMemoryInputStreamPrivate *priv; memory_stream = G_MEMORY_INPUT_STREAM (seekable); priv = memory_stream->priv; @@ -415,7 +444,7 @@ g_memory_input_stream_seek (GSeekable *seekable, GError **error) { GMemoryInputStream *memory_stream; - GMemoryInputStreamPrivate * priv; + GMemoryInputStreamPrivate *priv; goffset absolute; memory_stream = G_MEMORY_INPUT_STREAM (seekable); @@ -473,7 +502,7 @@ g_memory_input_stream_truncate (GSeekable *seekable, g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, - "Cannot seek on GMemoryInputStream"); + "Cannot truncate GMemoryInputStream"); return FALSE; } diff --git a/gio/gmemoryinputstream.h b/gio/gmemoryinputstream.h index fd07462e..0e3e43f2 100644 --- a/gio/gmemoryinputstream.h +++ b/gio/gmemoryinputstream.h @@ -70,12 +70,14 @@ struct _GMemoryInputStreamClass GType g_memory_input_stream_get_type (void) G_GNUC_CONST; -GInputStream * g_memory_input_stream_from_data (const void *data, - gssize len); -void g_memory_input_stream_set_free_data (GMemoryInputStream *stream, - gboolean free_data); -const void *g_memory_input_stream_get_data (GMemoryInputStream *stream); -gsize g_memory_input_stream_get_data_size (GMemoryInputStream *stream); +GInputStream * g_memory_input_stream_new (void); +GInputStream * g_memory_input_stream_new_from_data (const void *data, + gssize len, + GDestroyNotify destroy); +void g_memory_input_stream_add_data (GMemoryInputStream *stream, + const void *data, + gssize len, + GDestroyNotify destroy); G_END_DECLS -- 2.34.1