X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=gio%2Fgbufferedinputstream.c;h=78e61cbf40ce7dc54d011b73482c97f966115a97;hb=9e0c07870af1dac84c033031cf301671779c8328;hp=62c96f986a35fabe254f223402471ffc9ee3cd3f;hpb=c524cabff279c6a3bc6b95eb4c20f7c6a5e34e31;p=platform%2Fupstream%2Fglib.git diff --git a/gio/gbufferedinputstream.c b/gio/gbufferedinputstream.c index 62c96f9..78e61cb 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 * @@ -18,39 +18,41 @@ * Free Software Foundation, Inc., 59 Temple Place, Suite 330, * Boston, MA 02111-1307, USA. * - * Author: Christian Kellner + * Author: Christian Kellner */ -#include +#include "config.h" #include "gbufferedinputstream.h" #include "ginputstream.h" +#include "gcancellable.h" +#include "gasyncresult.h" #include "gsimpleasyncresult.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 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 - * buffered input stream's buffer, use g_buffered_input_stream_set_buffer_size(). - * Note: the buffer's size cannot be reduced below the size of the data within the - * buffer. * - **/ - + * 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 + * buffered input stream's buffer, use + * 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 @@ -81,46 +83,46 @@ 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); + 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); + 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); + GAsyncResult *result, + 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 compact_buffer (GBufferedInputStream *stream); @@ -147,7 +149,7 @@ g_buffered_input_stream_class_init (GBufferedInputStreamClass *klass) istream_class->skip = g_buffered_input_stream_skip; istream_class->skip_async = g_buffered_input_stream_skip_async; istream_class->skip_finish = g_buffered_input_stream_skip_finish; - istream_class->read = g_buffered_input_stream_read; + 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; @@ -155,7 +157,7 @@ g_buffered_input_stream_class_init (GBufferedInputStreamClass *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", @@ -172,41 +174,44 @@ 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, or %-1 on error. - **/ + * + * Returns: the current buffer size. + */ gsize g_buffered_input_stream_get_buffer_size (GBufferedInputStream *stream) { - g_return_val_if_fail (G_IS_BUFFERED_INPUT_STREAM (stream), -1); + g_return_val_if_fail (G_IS_BUFFERED_INPUT_STREAM (stream), 0); return stream->priv->len; } /** * 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; + if (priv->len == size) + return; + if (priv->buffer) { in_buffer = priv->end - priv->pos; @@ -229,6 +234,8 @@ g_buffered_input_stream_set_buffer_size (GBufferedInputStream *stream, priv->end = 0; priv->buffer = g_malloc (size); } + + g_object_notify (G_OBJECT (stream), "buffer-size"); } static void @@ -237,13 +244,11 @@ g_buffered_input_stream_set_property (GObject *object, const GValue *value, GParamSpec *pspec) { - GBufferedInputStreamPrivate *priv; GBufferedInputStream *bstream; bstream = G_BUFFERED_INPUT_STREAM (object); - priv = bstream->priv; - switch (prop_id) + switch (prop_id) { case PROP_BUFSIZE: g_buffered_input_stream_set_buffer_size (bstream, g_value_get_uint (value)); @@ -253,7 +258,6 @@ g_buffered_input_stream_set_property (GObject *object, G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } - } static void @@ -269,7 +273,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; @@ -291,8 +295,7 @@ g_buffered_input_stream_finalize (GObject *object) g_free (priv->buffer); - if (G_OBJECT_CLASS (g_buffered_input_stream_parent_class)->finalize) - (*G_OBJECT_CLASS (g_buffered_input_stream_parent_class)->finalize) (object); + G_OBJECT_CLASS (g_buffered_input_stream_parent_class)->finalize (object); } static void @@ -306,13 +309,13 @@ g_buffered_input_stream_init (GBufferedInputStream *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) { @@ -329,14 +332,14 @@ g_buffered_input_stream_new (GInputStream *base_stream) /** * g_buffered_input_stream_new_sized: - * @base_stream: a #GOutputStream. - * @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) @@ -355,14 +358,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: optional #GCancellable object, %NULL to ignore + * @error: location to store the error occuring, 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. * @@ -371,6 +374,9 @@ g_buffered_input_stream_new_sized (GInputStream *base_stream, * can happen e.g. near the end of a file. Zero is returned on end of file * (or if @count is zero), but never otherwise. * + * If @count is -1 then the attempted read size is equal to the number of + * bytes that are required to fill the buffer. + * * 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 @@ -378,13 +384,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, @@ -396,36 +402,30 @@ 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 (g_input_stream_is_closed (input_stream)) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_CLOSED, - _("Stream is already closed")); - return -1; - } - - if (g_input_stream_has_pending (input_stream)) + + if (count < -1) { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_PENDING, - _("Stream has outstanding operation")); + g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT, + _("Too large count value passed to %s"), G_STRFUNC); return -1; } - - g_input_stream_set_pending (input_stream, TRUE); + + if (!g_input_stream_set_pending (input_stream, error)) + return -1; if (cancellable) - g_push_current_cancellable (cancellable); - + g_cancellable_push_current (cancellable); + class = G_BUFFERED_INPUT_STREAM_GET_CLASS (stream); res = class->fill (stream, count, cancellable, error); if (cancellable) - g_pop_current_cancellable (cancellable); - - g_input_stream_set_pending (input_stream, FALSE); - + g_cancellable_pop_current (cancellable); + + g_input_stream_clear_pending (input_stream); + return res; } @@ -436,25 +436,28 @@ async_fill_callback_wrapper (GObject *source_object, { GBufferedInputStream *stream = G_BUFFERED_INPUT_STREAM (source_object); - g_input_stream_set_pending (G_INPUT_STREAM (stream), FALSE); + g_input_stream_clear_pending (G_INPUT_STREAM (stream)); (*stream->priv->outstanding_callback) (source_object, res, user_data); g_object_unref (stream); } /** * g_buffered_input_stream_fill_async: - * @stream: #GBufferedInputStream. - * @count: a #gssize. - * @io_priority: the I/O priority - * of the request. + * @stream: a #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. + * @callback: a #GAsyncReadyCallback + * @user_data: a #gpointer * * Reads data into @stream's buffer asynchronously, up to @count size. * @io_priority can be used to prioritize reads. For the synchronous * version of this function, see g_buffered_input_stream_fill(). - **/ + * + * 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, @@ -465,53 +468,44 @@ g_buffered_input_stream_fill_async (GBufferedInputStream *stream, { 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); + callback, + user_data, + g_buffered_input_stream_fill_async); g_simple_async_result_complete_in_idle (simple); g_object_unref (simple); return; } - - if (((gssize) count) < 0) - { - 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 g_input_stream_read_async")); - return; - } - - if (g_input_stream_is_closed (G_INPUT_STREAM (stream))) + + if (count < -1) { g_simple_async_report_error_in_idle (G_OBJECT (stream), - callback, - user_data, - G_IO_ERROR, G_IO_ERROR_CLOSED, - _("Stream is already closed")); + callback, + user_data, + G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT, + _("Too large count value passed to %s"), + G_STRFUNC); return; } - - if (g_input_stream_has_pending (G_INPUT_STREAM (stream))) + + if (!g_input_stream_set_pending (G_INPUT_STREAM (stream), &error)) { - g_simple_async_report_error_in_idle (G_OBJECT (stream), - callback, - user_data, - G_IO_ERROR, G_IO_ERROR_PENDING, - _("Stream has outstanding operation")); + g_simple_async_report_gerror_in_idle (G_OBJECT (stream), + callback, + user_data, + error); + g_error_free (error); return; } class = G_BUFFERED_INPUT_STREAM_GET_CLASS (stream); - - g_input_stream_set_pending (G_INPUT_STREAM (stream), TRUE); + stream->priv->outstanding_callback = callback; g_object_ref (stream); class->fill_async (stream, count, io_priority, cancellable, @@ -520,14 +514,14 @@ 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, @@ -556,12 +550,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) { @@ -572,16 +566,16 @@ 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: 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, @@ -590,7 +584,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); @@ -598,25 +592,25 @@ 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: 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 - **/ + */ const void* g_buffered_input_stream_peek_buffer (GBufferedInputStream *stream, gsize *count) @@ -627,7 +621,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; @@ -642,9 +636,9 @@ compact_buffer (GBufferedInputStream *stream) priv = stream->priv; current_size = priv->end - priv->pos; - + g_memmove (priv->buffer, priv->buffer + priv->pos, current_size); - + priv->pos = 0; priv->end = current_size; } @@ -664,7 +658,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 */ @@ -683,7 +677,7 @@ g_buffered_input_stream_real_fill (GBufferedInputStream *stream, if (nread > 0) priv->end += nread; - + return nread; } @@ -695,6 +689,7 @@ g_buffered_input_stream_skip (GInputStream *stream, { GBufferedInputStream *bstream; GBufferedInputStreamPrivate *priv; + GBufferedInputStreamClass *class; GInputStream *base_stream; gsize available, bytes_skipped; gssize nread; @@ -710,10 +705,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; @@ -721,31 +716,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; } - - g_input_stream_set_pending (stream, FALSE); /* to avoid already pending error */ - nread = g_buffered_input_stream_fill (bstream, priv->len, cancellable, error); - g_input_stream_set_pending (stream, TRUE); /* enable again */ - + + class = G_BUFFERED_INPUT_STREAM_GET_CLASS (stream); + nread = class->fill (bstream, priv->len, cancellable, error); + if (nread < 0) { if (bytes_skipped == 0) @@ -753,13 +747,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; } @@ -772,6 +766,7 @@ g_buffered_input_stream_read (GInputStream *stream, { GBufferedInputStream *bstream; GBufferedInputStreamPrivate *priv; + GBufferedInputStreamClass *class; GInputStream *base_stream; gsize available, bytes_read; gssize nread; @@ -787,9 +782,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; @@ -798,31 +795,30 @@ 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; } - - g_input_stream_set_pending (stream, FALSE); /* to avoid already pending error */ - nread = g_buffered_input_stream_fill (bstream, priv->len, cancellable, error); - g_input_stream_set_pending (stream, TRUE); /* enable again */ + + class = G_BUFFERED_INPUT_STREAM_GET_CLASS (stream); + nread = class->fill (bstream, priv->len, cancellable, error); if (nread < 0) { if (bytes_read == 0) @@ -830,29 +826,29 @@ 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; } /** * 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: optional #GCancellable object, %NULL to ignore + * @error: location to store the error occuring, 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 @@ -860,15 +856,16 @@ 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, GError **error) { GBufferedInputStreamPrivate *priv; + GBufferedInputStreamClass *class; GInputStream *input_stream; gsize available; gssize nread; @@ -880,35 +877,37 @@ g_buffered_input_stream_read_byte (GBufferedInputStream *stream, if (g_input_stream_is_closed (input_stream)) { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_CLOSED, - _("Stream is already closed")); + g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_CLOSED, + _("Stream is already closed")); return -1; } - if (g_input_stream_has_pending (input_stream)) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_PENDING, - _("Stream has outstanding operation")); - return -1; - } + if (!g_input_stream_set_pending (input_stream, error)) + return -1; available = priv->end - priv->pos; - if (available < 1) - return priv->buffer[priv->pos++]; + if (available != 0) + { + g_input_stream_clear_pending (input_stream); + return priv->buffer[priv->pos++]; + } /* Byte not available, request refill for more */ if (cancellable) - g_push_current_cancellable (cancellable); + g_cancellable_push_current (cancellable); priv->pos = 0; priv->end = 0; - nread = g_buffered_input_stream_fill (stream, priv->len, cancellable, error); + class = G_BUFFERED_INPUT_STREAM_GET_CLASS (stream); + nread = class->fill (stream, priv->len, cancellable, error); if (cancellable) - g_pop_current_cancellable (cancellable); + g_cancellable_pop_current (cancellable); + + g_input_stream_clear_pending (input_stream); if (nread <= 0) return -1; /* error or end of stream */ @@ -930,19 +929,33 @@ fill_async_callback (GObject *source_object, GSimpleAsyncResult *simple; simple = user_data; - + error = NULL; res = g_input_stream_read_finish (G_INPUT_STREAM (source_object), - result, &error); + result, &error); g_simple_async_result_set_op_res_gssize (simple, res); if (res == -1) { - g_simple_async_result_set_from_error (simple, error); - g_error_free (error); + g_simple_async_result_take_error (simple, error); + } + else + { + GBufferedInputStreamPrivate *priv; + GObject *object; + + object = g_async_result_get_source_object (G_ASYNC_RESULT (simple)); + priv = G_BUFFERED_INPUT_STREAM (object)->priv; + + g_assert_cmpint (priv->end + res, <=, priv->len); + priv->end += res; + + g_object_unref (object); } - - /* Complete immediately, not in idle, since we're already in a mainloop callout */ + + /* Complete immediately, not in idle, since we're already + * in a mainloop callout + */ g_simple_async_result_complete (simple); g_object_unref (simple); } @@ -964,7 +977,7 @@ g_buffered_input_stream_real_fill_async (GBufferedInputStream *stream, if (count == -1) count = priv->len; - + in_buffer = priv->end - priv->pos; /* Never fill more than can fit in the buffer */ @@ -975,41 +988,42 @@ g_buffered_input_stream_real_fill_async (GBufferedInputStream *stream, compact_buffer (stream); simple = g_simple_async_result_new (G_OBJECT (stream), - callback, user_data, - g_buffered_input_stream_real_fill_async); - + callback, user_data, + g_buffered_input_stream_real_fill_async); + 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, + simple); } static gssize g_buffered_input_stream_real_fill_finish (GBufferedInputStream *stream, - GAsyncResult *result, - GError **error) + GAsyncResult *result, + GError **error) { GSimpleAsyncResult *simple; gssize nread; simple = G_SIMPLE_ASYNC_RESULT (result); - g_assert (g_simple_async_result_get_source_tag (simple) == g_buffered_input_stream_real_fill_async); - + 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 { +typedef struct +{ gssize bytes_read; gssize count; void *buffer; } ReadAsyncData; -static void +static void free_read_async_data (gpointer _data) { ReadAsyncData *data = _data; @@ -1018,8 +1032,8 @@ free_read_async_data (gpointer _data) static void large_read_callback (GObject *source_object, - GAsyncResult *result, - gpointer user_data) + GAsyncResult *result, + gpointer user_data) { GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (user_data); ReadAsyncData *data; @@ -1027,30 +1041,31 @@ large_read_callback (GObject *source_object, 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); + 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); - + g_simple_async_result_take_error (simple, error); + else if (error) + g_error_free (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 */ + + /* 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) +read_fill_buffer_callback (GObject *source_object, + GAsyncResult *result, + gpointer user_data) { GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (user_data); GBufferedInputStream *bstream; @@ -1062,48 +1077,47 @@ read_fill_buffer_callback (GObject *source_object, bstream = G_BUFFERED_INPUT_STREAM (source_object); priv = bstream->priv; - - g_input_stream_set_pending (G_INPUT_STREAM (bstream), TRUE); /* enable again */ - + 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); + result, &error); + if (nread < 0 && data->bytes_read == 0) + g_simple_async_result_take_error (simple, error); + else if (error) + g_error_free (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; } - if (error) - g_error_free (error); - - /* Complete immediately, not in idle, since we're already in a mainloop callout */ + /* 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 -g_buffered_input_stream_read_async (GInputStream *stream, - void *buffer, - gsize count, - int io_priority, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) +g_buffered_input_stream_read_async (GInputStream *stream, + void *buffer, + 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; @@ -1116,54 +1130,55 @@ g_buffered_input_stream_read_async (GInputStream *stream, 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); + 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 */ - + /* 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; - + 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); + (char *)buffer + data->bytes_read, + count, + io_priority, cancellable, + large_read_callback, + simple); } else { - g_input_stream_set_pending (stream, FALSE); /* to avoid already pending error */ - g_buffered_input_stream_fill_async (bstream, priv->len, - io_priority, cancellable, - read_fill_buffer_callback, simple); + class = G_BUFFERED_INPUT_STREAM_GET_CLASS (stream); + class->fill_async (bstream, priv->len, io_priority, cancellable, + read_fill_buffer_callback, simple); } } @@ -1174,22 +1189,23 @@ g_buffered_input_stream_read_finish (GInputStream *stream, { GSimpleAsyncResult *simple; ReadAsyncData *data; - + simple = G_SIMPLE_ASYNC_RESULT (result); - - g_assert (g_simple_async_result_get_source_tag (simple) == g_buffered_input_stream_read_async); + + 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 { +typedef struct +{ gssize bytes_skipped; gssize count; } SkipAsyncData; -static void +static void free_skip_async_data (gpointer _data) { SkipAsyncData *data = _data; @@ -1197,9 +1213,9 @@ 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); SkipAsyncData *data; @@ -1207,30 +1223,31 @@ large_skip_callback (GObject *source_object, gssize nread; data = g_simple_async_result_get_op_res_gpointer (simple); - + 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); - + g_simple_async_result_take_error (simple, error); + else if (error) + g_error_free (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 */ + + /* 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 -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); GBufferedInputStream *bstream; @@ -1242,46 +1259,45 @@ skip_fill_buffer_callback (GObject *source_object, bstream = G_BUFFERED_INPUT_STREAM (source_object); priv = bstream->priv; - - g_input_stream_set_pending (G_INPUT_STREAM (bstream), TRUE); /* enable again */ - + 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_skipped == 0) - g_simple_async_result_set_from_error (simple, error); + result, &error); + if (nread < 0 && data->bytes_skipped == 0) + g_simple_async_result_take_error (simple, error); + else if (error) + g_error_free (error); if (nread > 0) { available = priv->end - priv->pos; data->count = MIN (data->count, available); - + data->bytes_skipped += data->count; priv->pos += data->count; } - if (error) - g_error_free (error); - - /* Complete immediately, not in idle, since we're already in a mainloop callout */ + /* 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 -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; @@ -1293,51 +1309,51 @@ 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); + callback, user_data, + g_buffered_input_stream_skip_async); g_simple_async_result_set_op_res_gpointer (simple, 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); 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, + simple); } else { - g_input_stream_set_pending (stream, FALSE); /* to avoid already pending error */ - g_buffered_input_stream_fill_async (bstream, priv->len, - io_priority, cancellable, - skip_fill_buffer_callback, simple); + class = G_BUFFERED_INPUT_STREAM_GET_CLASS (stream); + class->fill_async (bstream, priv->len, io_priority, cancellable, + skip_fill_buffer_callback, simple); } } @@ -1348,16 +1364,12 @@ g_buffered_input_stream_skip_finish (GInputStream *stream, { GSimpleAsyncResult *simple; SkipAsyncData *data; - + simple = G_SIMPLE_ASYNC_RESULT (result); - - g_assert (g_simple_async_result_get_source_tag (simple) == g_buffered_input_stream_skip_async); + + g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == g_buffered_input_stream_skip_async); data = g_simple_async_result_get_op_res_gpointer (simple); - + return data->bytes_skipped; } - - -#define __G_BUFFERED_INPUT_STREAM_C__ -#include "gioaliasdef.c"