X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=gio%2Fginputstream.c;h=a1ba73608e6ee2c650e431bd0538b21a6eb7bf98;hb=f14a66e3df9e5e3f0f170b68e976011c80ffc041;hp=0bf067ee3556b5898789a45c4fe5f7dc051af3b1;hpb=20f4d1820b8d4d0fc4447188e33efffd6d4a88d8;p=platform%2Fupstream%2Fglib.git diff --git a/gio/ginputstream.c b/gio/ginputstream.c index 0bf067e..a1ba736 100644 --- a/gio/ginputstream.c +++ b/gio/ginputstream.c @@ -141,6 +141,9 @@ g_input_stream_init (GInputStream *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. * + * The returned @buffer is not a nul-terminated string, it can contain nul bytes + * at any position, and this function doesn't nul-terminate 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 @@ -220,8 +223,14 @@ g_input_stream_read (GInputStream *stream, * read into @buffer. * * If there is an error during the operation %FALSE is returned and @error - * is set to indicate the error status, @bytes_read is updated to contain - * the number of bytes read into @buffer before the error occurred. + * is set to indicate the error status. + * + * As a special exception to the normal conventions for functions that + * use #GError, if this function returns %FALSE (and sets @error) then + * @bytes_read will be set to the number of bytes that were successfully + * read before the error was encountered. This functionality is only + * available from C. If you need it from another language then you must + * write your own loop around g_input_stream_read(). * * Returns: %TRUE on success, %FALSE if there was an error **/ @@ -295,6 +304,8 @@ g_input_stream_read_all (GInputStream *stream, * On error %NULL is returned and @error is set accordingly. * * Returns: a new #GBytes, or %NULL on error + * + * Since: 2.34 **/ GBytes * g_input_stream_read_bytes (GInputStream *stream, @@ -650,6 +661,185 @@ g_input_stream_read_finish (GInputStream *stream, return class->read_finish (stream, result, error); } +typedef struct +{ + gchar *buffer; + gsize to_read; + gsize bytes_read; +} AsyncReadAll; + +static void +free_async_read_all (gpointer data) +{ + g_slice_free (AsyncReadAll, data); +} + +static void +read_all_callback (GObject *stream, + GAsyncResult *result, + gpointer user_data) +{ + GTask *task = user_data; + AsyncReadAll *data = g_task_get_task_data (task); + gboolean got_eof = FALSE; + + if (result) + { + GError *error = NULL; + gssize nread; + + nread = g_input_stream_read_finish (G_INPUT_STREAM (stream), result, &error); + + if (nread == -1) + { + g_task_return_error (task, error); + g_object_unref (task); + return; + } + + g_assert_cmpint (nread, <=, data->to_read); + data->to_read -= nread; + data->bytes_read += nread; + got_eof = (nread == 0); + } + + if (got_eof || data->to_read == 0) + { + g_task_return_boolean (task, TRUE); + g_object_unref (task); + } + + else + g_input_stream_read_async (G_INPUT_STREAM (stream), + data->buffer + data->bytes_read, + data->to_read, + g_task_get_priority (task), + g_task_get_cancellable (task), + read_all_callback, task); +} + + +static void +read_all_async_thread (GTask *task, + gpointer source_object, + gpointer task_data, + GCancellable *cancellable) +{ + GInputStream *stream = source_object; + AsyncReadAll *data = task_data; + GError *error = NULL; + + if (g_input_stream_read_all (stream, data->buffer, data->to_read, &data->bytes_read, + g_task_get_cancellable (task), &error)) + g_task_return_boolean (task, TRUE); + else + g_task_return_error (task, error); +} + +/** + * g_input_stream_read_all_async: + * @stream: A #GInputStream + * @buffer: (array length=count) (element-type guint8): a buffer to + * read data into (which should be at least count bytes long) + * @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, %NULL to ignore + * @callback: (scope async): callback to call when the request is satisfied + * @user_data: (closure): the data to pass to callback function + * + * Request an asynchronous read of @count bytes from the stream into the + * buffer starting at @buffer. + * + * This is the asynchronous equivalent of g_input_stream_read_all(). + * + * Call g_input_stream_read_all_finish() to collect the result. + * + * Any outstanding I/O request with higher priority (lower numerical + * value) will be executed before an outstanding request with lower + * priority. Default priority is %G_PRIORITY_DEFAULT. + * + * Since: 2.44 + **/ +void +g_input_stream_read_all_async (GInputStream *stream, + void *buffer, + gsize count, + int io_priority, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + AsyncReadAll *data; + GTask *task; + + g_return_if_fail (G_IS_INPUT_STREAM (stream)); + g_return_if_fail (buffer != NULL || count == 0); + + task = g_task_new (stream, cancellable, callback, user_data); + data = g_slice_new0 (AsyncReadAll); + data->buffer = buffer; + data->to_read = count; + + g_task_set_task_data (task, data, free_async_read_all); + g_task_set_priority (task, io_priority); + + /* If async reads are going to be handled via the threadpool anyway + * then we may as well do it with a single dispatch instead of + * bouncing in and out. + */ + if (g_input_stream_async_read_is_via_threads (stream)) + { + g_task_run_in_thread (task, read_all_async_thread); + g_object_unref (task); + } + else + read_all_callback (G_OBJECT (stream), NULL, task); +} + +/** + * g_input_stream_read_all_finish: + * @stream: a #GInputStream + * @result: a #GAsyncResult + * @bytes_read: (out): location to store the number of bytes that was read from the stream + * @error: a #GError location to store the error occurring, or %NULL to ignore + * + * Finishes an asynchronous stream read operation started with + * g_input_stream_read_all_async(). + * + * As a special exception to the normal conventions for functions that + * use #GError, if this function returns %FALSE (and sets @error) then + * @bytes_read will be set to the number of bytes that were successfully + * read before the error was encountered. This functionality is only + * available from C. If you need it from another language then you must + * write your own loop around g_input_stream_read_async(). + * + * Returns: %TRUE on success, %FALSE if there was an error + * + * Since: 2.44 + **/ +gboolean +g_input_stream_read_all_finish (GInputStream *stream, + GAsyncResult *result, + gsize *bytes_read, + GError **error) +{ + GTask *task; + + g_return_val_if_fail (G_IS_INPUT_STREAM (stream), FALSE); + g_return_val_if_fail (g_task_is_valid (result, stream), FALSE); + + task = G_TASK (result); + + if (bytes_read) + { + AsyncReadAll *data = g_task_get_task_data (task); + + *bytes_read = data->bytes_read; + } + + return g_task_propagate_boolean (task, error); +} + static void read_bytes_callback (GObject *stream, GAsyncResult *result, @@ -711,6 +901,8 @@ read_bytes_callback (GObject *stream, * Any outstanding I/O request with higher priority (lower numerical * value) will be executed before an outstanding request with lower * priority. Default priority is %G_PRIORITY_DEFAULT. + * + * Since: 2.34 **/ void g_input_stream_read_bytes_async (GInputStream *stream, @@ -742,6 +934,8 @@ g_input_stream_read_bytes_async (GInputStream *stream, * Finishes an asynchronous stream read-into-#GBytes operation. * * Returns: the newly-allocated #GBytes, or %NULL on error + * + * Since: 2.34 **/ GBytes * g_input_stream_read_bytes_finish (GInputStream *stream,