X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=gio%2Fgbufferedinputstream.c;h=3b147d4290903a9fb8d3532c5f98b6765faba32c;hb=853692bdfd9f8a87aed70d21f643dc13b57c92d1;hp=50b5d8e6ec7a248a2ebb319e69ea061435fd20d3;hpb=73007021796f33d7ccec4e5f2bb2b2f8660347f2;p=platform%2Fupstream%2Fglib.git diff --git a/gio/gbufferedinputstream.c b/gio/gbufferedinputstream.c index 50b5d8e..3b147d4 100644 --- a/gio/gbufferedinputstream.c +++ b/gio/gbufferedinputstream.c @@ -1,5 +1,5 @@ /* GIO - GLib Input, Output and Streaming Library - * + * * Copyright (C) 2006-2007 Red Hat, Inc. * Copyright (C) 2007 Jürg Billeter * @@ -14,11 +14,9 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General - * Public License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place, Suite 330, - * Boston, MA 02111-1307, USA. + * Public License along with this library; if not, see . * - * Author: Christian Kellner + * Author: Christian Kellner */ #include "config.h" @@ -26,36 +24,34 @@ #include "ginputstream.h" #include "gcancellable.h" #include "gasyncresult.h" -#include "gsimpleasyncresult.h" +#include "gtask.h" +#include "gseekable.h" #include "gioerror.h" #include #include "glibintl.h" -#include "gioalias.h" /** * SECTION:gbufferedinputstream * @short_description: Buffered Input Stream * @include: gio/gio.h * @see_also: #GFilterInputStream, #GInputStream - * - * Buffered input stream implements #GFilterInputStream and provides - * for buffered reads. - * + * + * Buffered input stream implements #GFilterInputStream and provides + * for buffered reads. + * * By default, #GBufferedInputStream's buffer size is set at 4 kilobytes. - * - * To create a buffered input stream, use g_buffered_input_stream_new(), - * or g_buffered_input_stream_new_sized() to specify the buffer's size at + * + * To create a buffered input stream, use g_buffered_input_stream_new(), + * or g_buffered_input_stream_new_sized() to specify the buffer's size at * construction. - * - * To get the size of a buffer within a buffered input stream, use - * g_buffered_input_stream_get_buffer_size(). To change the size of a + * + * To get the size of a buffer within a buffered input stream, use + * g_buffered_input_stream_get_buffer_size(). To change the size of a * buffered input stream's buffer, use - * g_buffered_input_stream_set_buffer_size(). Note that the buffer's size + * g_buffered_input_stream_set_buffer_size(). Note that the buffer's size * cannot be reduced below the size of the data within the buffer. - * - **/ - + */ #define DEFAULT_BUFFER_SIZE 4096 @@ -86,53 +82,59 @@ static void g_buffered_input_stream_finalize (GObject *object); static gssize g_buffered_input_stream_skip (GInputStream *stream, - gsize count, - GCancellable *cancellable, - GError **error); + gsize count, + GCancellable *cancellable, + GError **error); static void g_buffered_input_stream_skip_async (GInputStream *stream, - gsize count, - int io_priority, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data); + gsize count, + int io_priority, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); static gssize g_buffered_input_stream_skip_finish (GInputStream *stream, - GAsyncResult *result, - GError **error); + GAsyncResult *result, + GError **error); static gssize g_buffered_input_stream_read (GInputStream *stream, - void *buffer, - gsize count, - GCancellable *cancellable, - GError **error); -static void g_buffered_input_stream_read_async (GInputStream *stream, - void *buffer, - gsize count, - int io_priority, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data); -static gssize g_buffered_input_stream_read_finish (GInputStream *stream, - GAsyncResult *result, - GError **error); + void *buffer, + gsize count, + GCancellable *cancellable, + GError **error); static gssize g_buffered_input_stream_real_fill (GBufferedInputStream *stream, - gssize count, - GCancellable *cancellable, - GError **error); + gssize count, + GCancellable *cancellable, + GError **error); static void g_buffered_input_stream_real_fill_async (GBufferedInputStream *stream, - gssize count, - int io_priority, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data); + gssize count, + int io_priority, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); static gssize g_buffered_input_stream_real_fill_finish (GBufferedInputStream *stream, - GAsyncResult *result, - GError **error); + GAsyncResult *result, + GError **error); + +static void g_buffered_input_stream_seekable_iface_init (GSeekableIface *iface); +static goffset g_buffered_input_stream_tell (GSeekable *seekable); +static gboolean g_buffered_input_stream_can_seek (GSeekable *seekable); +static gboolean g_buffered_input_stream_seek (GSeekable *seekable, + goffset offset, + GSeekType type, + GCancellable *cancellable, + GError **error); +static gboolean g_buffered_input_stream_can_truncate (GSeekable *seekable); +static gboolean g_buffered_input_stream_truncate (GSeekable *seekable, + goffset offset, + GCancellable *cancellable, + GError **error); static void compact_buffer (GBufferedInputStream *stream); -G_DEFINE_TYPE (GBufferedInputStream, - g_buffered_input_stream, - G_TYPE_FILTER_INPUT_STREAM) - +G_DEFINE_TYPE_WITH_CODE (GBufferedInputStream, + g_buffered_input_stream, + G_TYPE_FILTER_INPUT_STREAM, + G_ADD_PRIVATE (GBufferedInputStream) + G_IMPLEMENT_INTERFACE (G_TYPE_SEEKABLE, + g_buffered_input_stream_seekable_iface_init)) static void g_buffered_input_stream_class_init (GBufferedInputStreamClass *klass) @@ -141,8 +143,6 @@ g_buffered_input_stream_class_init (GBufferedInputStreamClass *klass) GInputStreamClass *istream_class; GBufferedInputStreamClass *bstream_class; - g_type_class_add_private (klass, sizeof (GBufferedInputStreamPrivate)); - object_class = G_OBJECT_CLASS (klass); object_class->get_property = g_buffered_input_stream_get_property; object_class->set_property = g_buffered_input_stream_set_property; @@ -153,14 +153,12 @@ g_buffered_input_stream_class_init (GBufferedInputStreamClass *klass) istream_class->skip_async = g_buffered_input_stream_skip_async; istream_class->skip_finish = g_buffered_input_stream_skip_finish; istream_class->read_fn = g_buffered_input_stream_read; - istream_class->read_async = g_buffered_input_stream_read_async; - istream_class->read_finish = g_buffered_input_stream_read_finish; bstream_class = G_BUFFERED_INPUT_STREAM_CLASS (klass); bstream_class->fill = g_buffered_input_stream_real_fill; bstream_class->fill_async = g_buffered_input_stream_real_fill_async; bstream_class->fill_finish = g_buffered_input_stream_real_fill_finish; - + g_object_class_install_property (object_class, PROP_BUFSIZE, g_param_spec_uint ("buffer-size", @@ -177,12 +175,12 @@ g_buffered_input_stream_class_init (GBufferedInputStreamClass *klass) /** * g_buffered_input_stream_get_buffer_size: - * @stream: #GBufferedInputStream. - * + * @stream: a #GBufferedInputStream + * * Gets the size of the input buffer. - * + * * Returns: the current buffer size. - **/ + */ gsize g_buffered_input_stream_get_buffer_size (GBufferedInputStream *stream) { @@ -193,21 +191,21 @@ g_buffered_input_stream_get_buffer_size (GBufferedInputStream *stream) /** * g_buffered_input_stream_set_buffer_size: - * @stream: #GBufferedInputStream. - * @size: a #gsize. + * @stream: a #GBufferedInputStream + * @size: a #gsize * - * Sets the size of the internal buffer of @stream to @size, or to the - * size of the contents of the buffer. The buffer can never be resized + * Sets the size of the internal buffer of @stream to @size, or to the + * size of the contents of the buffer. The buffer can never be resized * smaller than its current contents. - **/ + */ void -g_buffered_input_stream_set_buffer_size (GBufferedInputStream *stream, - gsize size) +g_buffered_input_stream_set_buffer_size (GBufferedInputStream *stream, + gsize size) { GBufferedInputStreamPrivate *priv; gsize in_buffer; guint8 *buffer; - + g_return_if_fail (G_IS_BUFFERED_INPUT_STREAM (stream)); priv = stream->priv; @@ -261,7 +259,6 @@ g_buffered_input_stream_set_property (GObject *object, G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } - } static void @@ -277,7 +274,7 @@ g_buffered_input_stream_get_property (GObject *object, priv = bstream->priv; switch (prop_id) - { + { case PROP_BUFSIZE: g_value_set_uint (value, priv->len); break; @@ -303,23 +300,31 @@ g_buffered_input_stream_finalize (GObject *object) } static void +g_buffered_input_stream_seekable_iface_init (GSeekableIface *iface) +{ + iface->tell = g_buffered_input_stream_tell; + iface->can_seek = g_buffered_input_stream_can_seek; + iface->seek = g_buffered_input_stream_seek; + iface->can_truncate = g_buffered_input_stream_can_truncate; + iface->truncate_fn = g_buffered_input_stream_truncate; +} + +static void g_buffered_input_stream_init (GBufferedInputStream *stream) { - stream->priv = G_TYPE_INSTANCE_GET_PRIVATE (stream, - G_TYPE_BUFFERED_INPUT_STREAM, - GBufferedInputStreamPrivate); + stream->priv = g_buffered_input_stream_get_instance_private (stream); } /** * g_buffered_input_stream_new: - * @base_stream: a #GInputStream. - * - * Creates a new #GInputStream from the given @base_stream, with + * @base_stream: a #GInputStream + * + * Creates a new #GInputStream from the given @base_stream, with * a buffer set to the default size (4 kilobytes). * * Returns: a #GInputStream for the given @base_stream. - **/ + */ GInputStream * g_buffered_input_stream_new (GInputStream *base_stream) { @@ -336,14 +341,14 @@ g_buffered_input_stream_new (GInputStream *base_stream) /** * g_buffered_input_stream_new_sized: - * @base_stream: a #GInputStream. - * @size: a #gsize. - * - * Creates a new #GBufferedInputStream from the given @base_stream, + * @base_stream: a #GInputStream + * @size: a #gsize + * + * Creates a new #GBufferedInputStream from the given @base_stream, * with a buffer set to @size. * * Returns: a #GInputStream. - **/ + */ GInputStream * g_buffered_input_stream_new_sized (GInputStream *base_stream, gsize size) @@ -362,14 +367,14 @@ g_buffered_input_stream_new_sized (GInputStream *base_stream, /** * g_buffered_input_stream_fill: - * @stream: #GBufferedInputStream. - * @count: the number of bytes that will be read from the stream. - * @cancellable: optional #GCancellable object, %NULL to ignore. - * @error: location to store the error occuring, or %NULL to ignore. + * @stream: a #GBufferedInputStream + * @count: the number of bytes that will be read from the stream + * @cancellable: (allow-none): optional #GCancellable object, %NULL to ignore + * @error: location to store the error occurring, or %NULL to ignore * - * Tries to read @count bytes from the stream into the buffer. + * Tries to read @count bytes from the stream into the buffer. * Will block during this read. - * + * * If @count is zero, returns zero and does nothing. A value of @count * larger than %G_MAXSSIZE will cause a %G_IO_ERROR_INVALID_ARGUMENT error. * @@ -388,13 +393,13 @@ g_buffered_input_stream_new_sized (GInputStream *base_stream, * partial result will be returned, without an error. * * On error -1 is returned and @error is set accordingly. - * - * For the asynchronous, non-blocking, version of this function, see + * + * For the asynchronous, non-blocking, version of this function, see * g_buffered_input_stream_fill_async(). * - * Returns: the number of bytes read into @stream's buffer, up to @count, + * Returns: the number of bytes read into @stream's buffer, up to @count, * or -1 on error. - **/ + */ gssize g_buffered_input_stream_fill (GBufferedInputStream *stream, gssize count, @@ -406,9 +411,9 @@ g_buffered_input_stream_fill (GBufferedInputStream *stream, gssize res; g_return_val_if_fail (G_IS_BUFFERED_INPUT_STREAM (stream), -1); - + input_stream = G_INPUT_STREAM (stream); - + if (count < -1) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT, @@ -421,15 +426,15 @@ g_buffered_input_stream_fill (GBufferedInputStream *stream, if (cancellable) g_cancellable_push_current (cancellable); - + class = G_BUFFERED_INPUT_STREAM_GET_CLASS (stream); res = class->fill (stream, count, cancellable, error); if (cancellable) g_cancellable_pop_current (cancellable); - + g_input_stream_clear_pending (input_stream); - + return res; } @@ -447,13 +452,12 @@ async_fill_callback_wrapper (GObject *source_object, /** * g_buffered_input_stream_fill_async: - * @stream: #GBufferedInputStream. - * @count: the number of bytes that will be read from the stream. - * @io_priority: the I/O priority - * of the request. - * @cancellable: optional #GCancellable object - * @callback: a #GAsyncReadyCallback. - * @user_data: a #gpointer. + * @stream: a #GBufferedInputStream + * @count: the number of bytes that will be read from the stream + * @io_priority: the [I/O priority][io-priority] of the request + * @cancellable: (allow-none): optional #GCancellable object + * @callback: (scope async): a #GAsyncReadyCallback + * @user_data: (closure): a #gpointer * * Reads data into @stream's buffer asynchronously, up to @count size. * @io_priority can be used to prioritize reads. For the synchronous @@ -461,7 +465,7 @@ async_fill_callback_wrapper (GObject *source_object, * * If @count is -1 then the attempted read size is equal to the number * of bytes that are required to fill the buffer. - **/ + */ void g_buffered_input_stream_fill_async (GBufferedInputStream *stream, gssize count, @@ -471,45 +475,41 @@ g_buffered_input_stream_fill_async (GBufferedInputStream *stream, gpointer user_data) { GBufferedInputStreamClass *class; - GSimpleAsyncResult *simple; GError *error = NULL; g_return_if_fail (G_IS_BUFFERED_INPUT_STREAM (stream)); if (count == 0) { - simple = g_simple_async_result_new (G_OBJECT (stream), - callback, - user_data, - g_buffered_input_stream_fill_async); - g_simple_async_result_complete_in_idle (simple); - g_object_unref (simple); + GTask *task; + + task = g_task_new (stream, cancellable, callback, user_data); + g_task_set_source_tag (task, g_buffered_input_stream_fill_async); + g_task_return_int (task, 0); + g_object_unref (task); return; } - + if (count < -1) { - g_simple_async_report_error_in_idle (G_OBJECT (stream), - callback, - user_data, - G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT, - _("Too large count value passed to %s"), - G_STRFUNC); + g_task_report_new_error (stream, callback, user_data, + g_buffered_input_stream_fill_async, + G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT, + _("Too large count value passed to %s"), + G_STRFUNC); return; } - + if (!g_input_stream_set_pending (G_INPUT_STREAM (stream), &error)) { - g_simple_async_report_gerror_in_idle (G_OBJECT (stream), - callback, - user_data, - error); - g_error_free (error); + g_task_report_error (stream, callback, user_data, + g_buffered_input_stream_fill_async, + error); return; } - + class = G_BUFFERED_INPUT_STREAM_GET_CLASS (stream); - + stream->priv->outstanding_callback = callback; g_object_ref (stream); class->fill_async (stream, count, io_priority, cancellable, @@ -518,35 +518,28 @@ g_buffered_input_stream_fill_async (GBufferedInputStream *stream, /** * g_buffered_input_stream_fill_finish: - * @stream: a #GBufferedInputStream. - * @result: a #GAsyncResult. - * @error: a #GError. + * @stream: a #GBufferedInputStream + * @result: a #GAsyncResult + * @error: a #GError * * Finishes an asynchronous read. - * - * Returns: a #gssize of the read stream, or %-1 on an error. - **/ + * + * Returns: a #gssize of the read stream, or %-1 on an error. + */ gssize g_buffered_input_stream_fill_finish (GBufferedInputStream *stream, GAsyncResult *result, GError **error) { - GSimpleAsyncResult *simple; GBufferedInputStreamClass *class; g_return_val_if_fail (G_IS_BUFFERED_INPUT_STREAM (stream), -1); g_return_val_if_fail (G_IS_ASYNC_RESULT (result), -1); - if (G_IS_SIMPLE_ASYNC_RESULT (result)) - { - simple = G_SIMPLE_ASYNC_RESULT (result); - if (g_simple_async_result_propagate_error (simple, error)) - return -1; - - /* Special case read of 0 bytes */ - if (g_simple_async_result_get_source_tag (simple) == g_buffered_input_stream_fill_async) - return 0; - } + if (g_async_result_legacy_propagate_error (result, error)) + return -1; + else if (g_async_result_is_tagged (result, g_buffered_input_stream_fill_async)) + return g_task_propagate_int (G_TASK (result), error); class = G_BUFFERED_INPUT_STREAM_GET_CLASS (stream); return class->fill_finish (stream, result, error); @@ -554,12 +547,12 @@ g_buffered_input_stream_fill_finish (GBufferedInputStream *stream, /** * g_buffered_input_stream_get_available: - * @stream: #GBufferedInputStream. - * + * @stream: #GBufferedInputStream + * * Gets the size of the available data within the stream. - * - * Returns: size of the available stream. - **/ + * + * Returns: size of the available stream. + */ gsize g_buffered_input_stream_get_available (GBufferedInputStream *stream) { @@ -570,16 +563,17 @@ g_buffered_input_stream_get_available (GBufferedInputStream *stream) /** * g_buffered_input_stream_peek: - * @stream: a #GBufferedInputStream. - * @buffer: a pointer to an allocated chunk of memory. - * @offset: a #gsize. - * @count: a #gsize. - * - * Peeks in the buffer, copying data of size @count into @buffer, + * @stream: a #GBufferedInputStream + * @buffer: (array length=count) (element-type guint8): a pointer to + * an allocated chunk of memory + * @offset: a #gsize + * @count: a #gsize + * + * Peeks in the buffer, copying data of size @count into @buffer, * offset @offset bytes. - * - * Returns: a #gsize of the number of bytes peeked, or %-1 on error. - **/ + * + * Returns: a #gsize of the number of bytes peeked, or -1 on error. + */ gsize g_buffered_input_stream_peek (GBufferedInputStream *stream, void *buffer, @@ -588,7 +582,7 @@ g_buffered_input_stream_peek (GBufferedInputStream *stream, { gsize available; gsize end; - + g_return_val_if_fail (G_IS_BUFFERED_INPUT_STREAM (stream), -1); g_return_val_if_fail (buffer != NULL, -1); @@ -596,25 +590,26 @@ g_buffered_input_stream_peek (GBufferedInputStream *stream, if (offset > available) return 0; - + end = MIN (offset + count, available); count = end - offset; - + memcpy (buffer, stream->priv->buffer + stream->priv->pos + offset, count); return count; } /** * g_buffered_input_stream_peek_buffer: - * @stream: a #GBufferedInputStream. - * @count: a #gsize to get the number of bytes available in the buffer. + * @stream: a #GBufferedInputStream + * @count: (out): a #gsize to get the number of bytes available in the buffer * * Returns the buffer with the currently available bytes. The returned * buffer must not be modified and will become invalid when reading from * the stream or filling the buffer. * - * Returns: read-only buffer - **/ + * Returns: (array length=count) (element-type guint8) (transfer none): + * read-only buffer + */ const void* g_buffered_input_stream_peek_buffer (GBufferedInputStream *stream, gsize *count) @@ -625,7 +620,7 @@ g_buffered_input_stream_peek_buffer (GBufferedInputStream *stream, priv = stream->priv; - if (count) + if (count) *count = priv->end - priv->pos; return priv->buffer + priv->pos; @@ -640,9 +635,9 @@ compact_buffer (GBufferedInputStream *stream) priv = stream->priv; current_size = priv->end - priv->pos; - - g_memmove (priv->buffer, priv->buffer + priv->pos, current_size); - + + memmove (priv->buffer, priv->buffer + priv->pos, current_size); + priv->pos = 0; priv->end = current_size; } @@ -662,7 +657,7 @@ g_buffered_input_stream_real_fill (GBufferedInputStream *stream, if (count == -1) count = priv->len; - + in_buffer = priv->end - priv->pos; /* Never fill more than can fit in the buffer */ @@ -681,7 +676,7 @@ g_buffered_input_stream_real_fill (GBufferedInputStream *stream, if (nread > 0) priv->end += nread; - + return nread; } @@ -709,10 +704,10 @@ g_buffered_input_stream_skip (GInputStream *stream, return count; } - /* Full request not available, skip all currently available and - * request refill for more + /* Full request not available, skip all currently available and + * request refill for more */ - + priv->pos = 0; priv->end = 0; bytes_skipped = available; @@ -720,30 +715,30 @@ g_buffered_input_stream_skip (GInputStream *stream, if (bytes_skipped > 0) error = NULL; /* Ignore further errors if we already read some data */ - + if (count > priv->len) { /* Large request, shortcut buffer */ - + base_stream = G_FILTER_INPUT_STREAM (stream)->base_stream; nread = g_input_stream_skip (base_stream, count, cancellable, error); - + if (nread < 0 && bytes_skipped == 0) return -1; - + if (nread > 0) bytes_skipped += nread; - + return bytes_skipped; } - + class = G_BUFFERED_INPUT_STREAM_GET_CLASS (stream); nread = class->fill (bstream, priv->len, cancellable, error); - + if (nread < 0) { if (bytes_skipped == 0) @@ -751,13 +746,13 @@ g_buffered_input_stream_skip (GInputStream *stream, else return bytes_skipped; } - + available = priv->end - priv->pos; count = MIN (count, available); - + bytes_skipped += count; priv->pos += count; - + return bytes_skipped; } @@ -786,9 +781,11 @@ g_buffered_input_stream_read (GInputStream *stream, priv->pos += count; return count; } - - /* Full request not available, read all currently availbile and request refill for more */ - + + /* Full request not available, read all currently available and + * request refill for more + */ + memcpy (buffer, priv->buffer + priv->pos, available); priv->pos = 0; priv->end = 0; @@ -797,28 +794,28 @@ g_buffered_input_stream_read (GInputStream *stream, if (bytes_read > 0) error = NULL; /* Ignore further errors if we already read some data */ - + if (count > priv->len) { /* Large request, shortcut buffer */ - + base_stream = G_FILTER_INPUT_STREAM (stream)->base_stream; nread = g_input_stream_read (base_stream, - (char *)buffer + bytes_read, - count, - cancellable, - error); - + (char *)buffer + bytes_read, + count, + cancellable, + error); + if (nread < 0 && bytes_read == 0) return -1; - + if (nread > 0) bytes_read += nread; - + return bytes_read; } - + class = G_BUFFERED_INPUT_STREAM_GET_CLASS (stream); nread = class->fill (bstream, priv->len, cancellable, error); if (nread < 0) @@ -828,29 +825,131 @@ g_buffered_input_stream_read (GInputStream *stream, else return bytes_read; } - + available = priv->end - priv->pos; count = MIN (count, available); - + memcpy ((char *)buffer + bytes_read, (char *)priv->buffer + priv->pos, count); bytes_read += count; priv->pos += count; - + return bytes_read; } +static goffset +g_buffered_input_stream_tell (GSeekable *seekable) +{ + GBufferedInputStream *bstream; + GBufferedInputStreamPrivate *priv; + GInputStream *base_stream; + GSeekable *base_stream_seekable; + gsize available; + goffset base_offset; + + bstream = G_BUFFERED_INPUT_STREAM (seekable); + priv = bstream->priv; + + base_stream = G_FILTER_INPUT_STREAM (seekable)->base_stream; + if (!G_IS_SEEKABLE (base_stream)) + return 0; + base_stream_seekable = G_SEEKABLE (base_stream); + + available = priv->end - priv->pos; + base_offset = g_seekable_tell (base_stream_seekable); + + return base_offset - available; +} + +static gboolean +g_buffered_input_stream_can_seek (GSeekable *seekable) +{ + GInputStream *base_stream; + + base_stream = G_FILTER_INPUT_STREAM (seekable)->base_stream; + return G_IS_SEEKABLE (base_stream) && g_seekable_can_seek (G_SEEKABLE (base_stream)); +} + +static gboolean +g_buffered_input_stream_seek (GSeekable *seekable, + goffset offset, + GSeekType type, + GCancellable *cancellable, + GError **error) +{ + GBufferedInputStream *bstream; + GBufferedInputStreamPrivate *priv; + GInputStream *base_stream; + GSeekable *base_stream_seekable; + + bstream = G_BUFFERED_INPUT_STREAM (seekable); + priv = bstream->priv; + + base_stream = G_FILTER_INPUT_STREAM (seekable)->base_stream; + if (!G_IS_SEEKABLE (base_stream)) + { + g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, + _("Seek not supported on base stream")); + return FALSE; + } + + base_stream_seekable = G_SEEKABLE (base_stream); + + if (type == G_SEEK_CUR) + { + if (offset <= priv->end - priv->pos && offset >= -priv->pos) + { + priv->pos += offset; + return TRUE; + } + else + { + offset -= priv->end - priv->pos; + } + } + + if (g_seekable_seek (base_stream_seekable, offset, type, cancellable, error)) + { + priv->pos = 0; + priv->end = 0; + return TRUE; + } + else + { + return FALSE; + } +} + +static gboolean +g_buffered_input_stream_can_truncate (GSeekable *seekable) +{ + return FALSE; +} + +static gboolean +g_buffered_input_stream_truncate (GSeekable *seekable, + goffset offset, + GCancellable *cancellable, + GError **error) +{ + g_set_error_literal (error, + G_IO_ERROR, + G_IO_ERROR_NOT_SUPPORTED, + _("Cannot truncate GBufferedInputStream")); + return FALSE; +} + /** * g_buffered_input_stream_read_byte: - * @stream: #GBufferedInputStream. - * @cancellable: optional #GCancellable object, %NULL to ignore. - * @error: location to store the error occuring, or %NULL to ignore. + * @stream: a #GBufferedInputStream + * @cancellable: (allow-none): optional #GCancellable object, %NULL to ignore + * @error: location to store the error occurring, or %NULL to ignore * * Tries to read a single byte from the stream or the buffer. Will block * during this read. * * On success, the byte read from the stream is returned. On end of stream * -1 is returned but it's not an exceptional error and @error is not set. - * + * * If @cancellable is not %NULL, then the operation can be cancelled by * triggering the cancellable object from another thread. If the operation * was cancelled, the error %G_IO_ERROR_CANCELLED will be returned. If an @@ -858,9 +957,9 @@ g_buffered_input_stream_read (GInputStream *stream, * partial result will be returned, without an error. * * On error -1 is returned and @error is set accordingly. - * + * * Returns: the byte read from the @stream, or -1 on end of stream or error. - **/ + */ int g_buffered_input_stream_read_byte (GBufferedInputStream *stream, GCancellable *cancellable, @@ -928,37 +1027,28 @@ fill_async_callback (GObject *source_object, { GError *error; gssize res; - GSimpleAsyncResult *simple; + GTask *task = user_data; - simple = user_data; - error = NULL; res = g_input_stream_read_finish (G_INPUT_STREAM (source_object), - result, &error); - - g_simple_async_result_set_op_res_gssize (simple, res); + result, &error); if (res == -1) - { - g_simple_async_result_set_from_error (simple, error); - g_error_free (error); - } + g_task_return_error (task, error); else { + GBufferedInputStream *stream; GBufferedInputStreamPrivate *priv; - GObject *object; - object = g_async_result_get_source_object (G_ASYNC_RESULT (simple)); - priv = G_BUFFERED_INPUT_STREAM (object)->priv; + stream = g_task_get_source_object (task); + priv = G_BUFFERED_INPUT_STREAM (stream)->priv; g_assert_cmpint (priv->end + res, <=, priv->len); priv->end += res; - g_object_unref (object); + g_task_return_int (task, res); } - - /* Complete immediately, not in idle, since we're already in a mainloop callout */ - g_simple_async_result_complete (simple); - g_object_unref (simple); + + g_object_unref (task); } static void @@ -971,14 +1061,14 @@ g_buffered_input_stream_real_fill_async (GBufferedInputStream *stream, { GBufferedInputStreamPrivate *priv; GInputStream *base_stream; - GSimpleAsyncResult *simple; + GTask *task; gsize in_buffer; priv = stream->priv; if (count == -1) count = priv->len; - + in_buffer = priv->end - priv->pos; /* Never fill more than can fit in the buffer */ @@ -988,220 +1078,35 @@ g_buffered_input_stream_real_fill_async (GBufferedInputStream *stream, if (priv->len - priv->end < count) compact_buffer (stream); - simple = g_simple_async_result_new (G_OBJECT (stream), - callback, user_data, - g_buffered_input_stream_real_fill_async); - + task = g_task_new (stream, cancellable, callback, user_data); + base_stream = G_FILTER_INPUT_STREAM (stream)->base_stream; g_input_stream_read_async (base_stream, - priv->buffer + priv->end, - count, - io_priority, - cancellable, - fill_async_callback, - simple); + priv->buffer + priv->end, + count, + io_priority, + cancellable, + fill_async_callback, + task); } static gssize g_buffered_input_stream_real_fill_finish (GBufferedInputStream *stream, - GAsyncResult *result, - GError **error) -{ - GSimpleAsyncResult *simple; - gssize nread; - - simple = G_SIMPLE_ASYNC_RESULT (result); - g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == g_buffered_input_stream_real_fill_async); - - nread = g_simple_async_result_get_op_res_gssize (simple); - return nread; -} - -typedef struct { - gssize bytes_read; - gssize count; - void *buffer; -} ReadAsyncData; - -static void -free_read_async_data (gpointer _data) -{ - ReadAsyncData *data = _data; - g_slice_free (ReadAsyncData, data); -} - -static void -large_read_callback (GObject *source_object, - GAsyncResult *result, - gpointer user_data) -{ - GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (user_data); - ReadAsyncData *data; - GError *error; - gssize nread; - - data = g_simple_async_result_get_op_res_gpointer (simple); - - error = NULL; - nread = g_input_stream_read_finish (G_INPUT_STREAM (source_object), - result, &error); - - /* Only report the error if we've not already read some data */ - if (nread < 0 && data->bytes_read == 0) - g_simple_async_result_set_from_error (simple, error); - - if (nread > 0) - data->bytes_read += nread; - - if (error) - g_error_free (error); - - /* Complete immediately, not in idle, since we're already in a mainloop callout */ - g_simple_async_result_complete (simple); - g_object_unref (simple); -} - -static void -read_fill_buffer_callback (GObject *source_object, - GAsyncResult *result, - gpointer user_data) + GAsyncResult *result, + GError **error) { - GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (user_data); - GBufferedInputStream *bstream; - GBufferedInputStreamPrivate *priv; - ReadAsyncData *data; - GError *error; - gssize nread; - gsize available; - - bstream = G_BUFFERED_INPUT_STREAM (source_object); - priv = bstream->priv; - - data = g_simple_async_result_get_op_res_gpointer (simple); - - error = NULL; - nread = g_buffered_input_stream_fill_finish (bstream, - result, &error); - - if (nread < 0 && data->bytes_read == 0) - g_simple_async_result_set_from_error (simple, error); - - - if (nread > 0) - { - available = priv->end - priv->pos; - data->count = MIN (data->count, available); - - memcpy ((char *)data->buffer + data->bytes_read, (char *)priv->buffer + priv->pos, data->count); - data->bytes_read += data->count; - priv->pos += data->count; - } + g_return_val_if_fail (g_task_is_valid (result, stream), -1); - if (error) - g_error_free (error); - - /* Complete immediately, not in idle, since we're already in a mainloop callout */ - g_simple_async_result_complete (simple); - g_object_unref (simple); + return g_task_propagate_int (G_TASK (result), error); } -static void -g_buffered_input_stream_read_async (GInputStream *stream, - void *buffer, - gsize count, - int io_priority, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) +typedef struct { - GBufferedInputStream *bstream; - GBufferedInputStreamPrivate *priv; - GBufferedInputStreamClass *class; - GInputStream *base_stream; - gsize available; - GSimpleAsyncResult *simple; - ReadAsyncData *data; - - bstream = G_BUFFERED_INPUT_STREAM (stream); - priv = bstream->priv; - - data = g_slice_new (ReadAsyncData); - data->buffer = buffer; - data->bytes_read = 0; - simple = g_simple_async_result_new (G_OBJECT (stream), - callback, user_data, - g_buffered_input_stream_read_async); - g_simple_async_result_set_op_res_gpointer (simple, data, free_read_async_data); - - available = priv->end - priv->pos; - - if (count <= available) - { - memcpy (buffer, priv->buffer + priv->pos, count); - priv->pos += count; - data->bytes_read = count; - - g_simple_async_result_complete_in_idle (simple); - g_object_unref (simple); - return; - } - - - /* Full request not available, read all currently availbile and request refill for more */ - - memcpy (buffer, priv->buffer + priv->pos, available); - priv->pos = 0; - priv->end = 0; - - count -= available; - - data->bytes_read = available; - data->count = count; - - if (count > priv->len) - { - /* Large request, shortcut buffer */ - - base_stream = G_FILTER_INPUT_STREAM (stream)->base_stream; - - g_input_stream_read_async (base_stream, - (char *)buffer + data->bytes_read, - count, - io_priority, cancellable, - large_read_callback, - simple); - } - else - { - class = G_BUFFERED_INPUT_STREAM_GET_CLASS (stream); - class->fill_async (bstream, priv->len, io_priority, cancellable, - read_fill_buffer_callback, simple); - } -} - -static gssize -g_buffered_input_stream_read_finish (GInputStream *stream, - GAsyncResult *result, - GError **error) -{ - GSimpleAsyncResult *simple; - ReadAsyncData *data; - - simple = G_SIMPLE_ASYNC_RESULT (result); - - g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == g_buffered_input_stream_read_async); - - data = g_simple_async_result_get_op_res_gpointer (simple); - - return data->bytes_read; -} - -typedef struct { gssize bytes_skipped; gssize count; } SkipAsyncData; -static void +static void free_skip_async_data (gpointer _data) { SkipAsyncData *data = _data; @@ -1209,42 +1114,44 @@ free_skip_async_data (gpointer _data) } static void -large_skip_callback (GObject *source_object, - GAsyncResult *result, - gpointer user_data) +large_skip_callback (GObject *source_object, + GAsyncResult *result, + gpointer user_data) { - GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (user_data); + GTask *task = G_TASK (user_data); SkipAsyncData *data; GError *error; gssize nread; - data = g_simple_async_result_get_op_res_gpointer (simple); - + data = g_task_get_task_data (task); + error = NULL; nread = g_input_stream_skip_finish (G_INPUT_STREAM (source_object), - result, &error); + result, &error); /* Only report the error if we've not already read some data */ if (nread < 0 && data->bytes_skipped == 0) - g_simple_async_result_set_from_error (simple, error); - - if (nread > 0) - data->bytes_skipped += nread; - - if (error) - g_error_free (error); - - /* Complete immediately, not in idle, since we're already in a mainloop callout */ - g_simple_async_result_complete (simple); - g_object_unref (simple); + g_task_return_error (task, error); + else + { + if (error) + g_error_free (error); + + if (nread > 0) + data->bytes_skipped += nread; + + g_task_return_int (task, data->bytes_skipped); + } + + g_object_unref (task); } static void -skip_fill_buffer_callback (GObject *source_object, - GAsyncResult *result, - gpointer user_data) +skip_fill_buffer_callback (GObject *source_object, + GAsyncResult *result, + gpointer user_data) { - GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (user_data); + GTask *task = G_TASK (user_data); GBufferedInputStream *bstream; GBufferedInputStreamPrivate *priv; SkipAsyncData *data; @@ -1254,48 +1161,49 @@ skip_fill_buffer_callback (GObject *source_object, bstream = G_BUFFERED_INPUT_STREAM (source_object); priv = bstream->priv; - - data = g_simple_async_result_get_op_res_gpointer (simple); - + + data = g_task_get_task_data (task); + error = NULL; nread = g_buffered_input_stream_fill_finish (bstream, - result, &error); - + result, &error); + if (nread < 0 && data->bytes_skipped == 0) - g_simple_async_result_set_from_error (simple, error); + g_task_return_error (task, error); + else + { + if (error) + g_error_free (error); + if (nread > 0) + { + available = priv->end - priv->pos; + data->count = MIN (data->count, available); - if (nread > 0) - { - available = priv->end - priv->pos; - data->count = MIN (data->count, available); - - data->bytes_skipped += data->count; - priv->pos += data->count; + data->bytes_skipped += data->count; + priv->pos += data->count; + } + + g_task_return_int (task, data->bytes_skipped); } - if (error) - g_error_free (error); - - /* Complete immediately, not in idle, since we're already in a mainloop callout */ - g_simple_async_result_complete (simple); - g_object_unref (simple); + g_object_unref (task); } static void -g_buffered_input_stream_skip_async (GInputStream *stream, - gsize count, - int io_priority, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) +g_buffered_input_stream_skip_async (GInputStream *stream, + gsize count, + int io_priority, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) { GBufferedInputStream *bstream; GBufferedInputStreamPrivate *priv; GBufferedInputStreamClass *class; GInputStream *base_stream; gsize available; - GSimpleAsyncResult *simple; + GTask *task; SkipAsyncData *data; bstream = G_BUFFERED_INPUT_STREAM (stream); @@ -1303,51 +1211,49 @@ g_buffered_input_stream_skip_async (GInputStream *stream, data = g_slice_new (SkipAsyncData); data->bytes_skipped = 0; - simple = g_simple_async_result_new (G_OBJECT (stream), - callback, user_data, - g_buffered_input_stream_skip_async); - g_simple_async_result_set_op_res_gpointer (simple, data, free_skip_async_data); - + task = g_task_new (stream, cancellable, callback, user_data); + g_task_set_task_data (task, data, free_skip_async_data); + available = priv->end - priv->pos; - + if (count <= available) { priv->pos += count; - data->bytes_skipped = count; - - g_simple_async_result_complete_in_idle (simple); - g_object_unref (simple); + + g_task_return_int (task, count); + g_object_unref (task); return; } + /* Full request not available, skip all currently available + * and request refill for more + */ - /* Full request not available, skip all currently availbile and request refill for more */ - priv->pos = 0; priv->end = 0; - + count -= available; - + data->bytes_skipped = available; data->count = count; if (count > priv->len) { /* Large request, shortcut buffer */ - + base_stream = G_FILTER_INPUT_STREAM (stream)->base_stream; - + g_input_stream_skip_async (base_stream, - count, - io_priority, cancellable, - large_skip_callback, - simple); + count, + io_priority, cancellable, + large_skip_callback, + task); } else { class = G_BUFFERED_INPUT_STREAM_GET_CLASS (stream); class->fill_async (bstream, priv->len, io_priority, cancellable, - skip_fill_buffer_callback, simple); + skip_fill_buffer_callback, task); } } @@ -1356,18 +1262,7 @@ g_buffered_input_stream_skip_finish (GInputStream *stream, GAsyncResult *result, GError **error) { - GSimpleAsyncResult *simple; - SkipAsyncData *data; - - simple = G_SIMPLE_ASYNC_RESULT (result); - - g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == g_buffered_input_stream_skip_async); + g_return_val_if_fail (g_task_is_valid (result, stream), -1); - data = g_simple_async_result_get_op_res_gpointer (simple); - - return data->bytes_skipped; + return g_task_propagate_int (G_TASK (result), error); } - - -#define __G_BUFFERED_INPUT_STREAM_C__ -#include "gioaliasdef.c"