diff --git a/docs/reference/gio/gio-docs.xml b/docs/reference/gio/gio-docs.xml index 0cfbb70f7..83afa7004 100644 --- a/docs/reference/gio/gio-docs.xml +++ b/docs/reference/gio/gio-docs.xml @@ -76,6 +76,7 @@ + File types and applications diff --git a/docs/reference/gio/gio-sections.txt b/docs/reference/gio/gio-sections.txt index 14b01c462..39265ed2f 100644 --- a/docs/reference/gio/gio-sections.txt +++ b/docs/reference/gio/gio-sections.txt @@ -3202,9 +3202,6 @@ g_pollable_input_stream_can_poll g_pollable_input_stream_is_readable g_pollable_input_stream_create_source g_pollable_input_stream_read_nonblocking - -GPollableSourceFunc -g_pollable_source_new G_POLLABLE_INPUT_STREAM G_POLLABLE_INPUT_STREAM_GET_INTERFACE @@ -3233,6 +3230,17 @@ G_TYPE_POLLABLE_OUTPUT_STREAM g_pollable_output_stream_get_type +
+gpollableutils +GPollableSourceFunc +g_pollable_source_new +g_pollable_source_new_full + +g_pollable_stream_read +g_pollable_stream_write +g_pollable_stream_write_all +
+
gtls G_TLS_ERROR diff --git a/gio/Makefile.am b/gio/Makefile.am index edb534a28..f34dfa307 100644 --- a/gio/Makefile.am +++ b/gio/Makefile.am @@ -381,6 +381,7 @@ libgio_2_0_la_SOURCES = \ gpermission.c \ gpollableinputstream.c \ gpollableoutputstream.c \ + gpollableutils.c \ gpollfilemonitor.c \ gpollfilemonitor.h \ gproxyresolver.c \ @@ -557,6 +558,7 @@ gio_headers = \ gpermission.h \ gpollableinputstream.h \ gpollableoutputstream.h \ + gpollableutils.h \ gproxyaddress.h \ gproxy.h \ gproxyaddressenumerator.h \ diff --git a/gio/gio.h b/gio/gio.h index 94ce7217a..c8afdf5a1 100644 --- a/gio/gio.h +++ b/gio/gio.h @@ -98,6 +98,7 @@ #include #include #include +#include #include #include #include diff --git a/gio/gio.symbols b/gio/gio.symbols index 0efb08eeb..9cb3ff5df 100644 --- a/gio/gio.symbols +++ b/gio/gio.symbols @@ -1481,12 +1481,16 @@ g_pollable_input_stream_can_poll g_pollable_input_stream_create_source g_pollable_input_stream_is_readable g_pollable_input_stream_read_nonblocking -g_pollable_source_new g_pollable_output_stream_get_type g_pollable_output_stream_can_poll g_pollable_output_stream_create_source g_pollable_output_stream_is_writable g_pollable_output_stream_write_nonblocking +g_pollable_source_new +g_pollable_source_new_full +g_pollable_stream_read +g_pollable_stream_write +g_pollable_stream_write_all g_tcp_wrapper_connection_get_type g_tcp_wrapper_connection_get_base_io_stream g_tcp_wrapper_connection_new diff --git a/gio/gpollableinputstream.c b/gio/gpollableinputstream.c index b2c0b8855..9e9f720ed 100644 --- a/gio/gpollableinputstream.c +++ b/gio/gpollableinputstream.c @@ -219,106 +219,3 @@ g_pollable_input_stream_read_nonblocking (GPollableInputStream *stream, return res; } - -/* GPollableSource */ - -typedef struct { - GSource source; - - GObject *stream; -} GPollableSource; - -static gboolean -pollable_source_prepare (GSource *source, - gint *timeout) -{ - *timeout = -1; - return FALSE; -} - -static gboolean -pollable_source_check (GSource *source) -{ - return FALSE; -} - -static gboolean -pollable_source_dispatch (GSource *source, - GSourceFunc callback, - gpointer user_data) -{ - GPollableSourceFunc func = (GPollableSourceFunc)callback; - GPollableSource *pollable_source = (GPollableSource *)source; - - return (*func) (pollable_source->stream, user_data); -} - -static void -pollable_source_finalize (GSource *source) -{ - GPollableSource *pollable_source = (GPollableSource *)source; - - g_object_unref (pollable_source->stream); -} - -static gboolean -pollable_source_closure_callback (GObject *stream, - gpointer data) -{ - GClosure *closure = data; - - GValue param = G_VALUE_INIT; - GValue result_value = G_VALUE_INIT; - gboolean result; - - g_value_init (&result_value, G_TYPE_BOOLEAN); - - g_value_init (¶m, G_TYPE_OBJECT); - g_value_set_object (¶m, stream); - - g_closure_invoke (closure, &result_value, 1, ¶m, NULL); - - result = g_value_get_boolean (&result_value); - g_value_unset (&result_value); - g_value_unset (¶m); - - return result; -} - -static GSourceFuncs pollable_source_funcs = -{ - pollable_source_prepare, - pollable_source_check, - pollable_source_dispatch, - pollable_source_finalize, - (GSourceFunc)pollable_source_closure_callback, - (GSourceDummyMarshal)g_cclosure_marshal_generic, -}; - -/** - * g_pollable_source_new: - * @pollable_stream: the stream associated with the new source - * - * Utility method for #GPollableInputStream and #GPollableOutputStream - * implementations. Creates a new #GSource that expects a callback of - * type #GPollableSourceFunc. The new source does not actually do - * anything on its own; use g_source_add_child_source() to add other - * sources to it to cause it to trigger. - * - * Return value: (transfer full): the new #GSource. - * - * Since: 2.28 - */ -GSource * -g_pollable_source_new (GObject *pollable_stream) -{ - GSource *source; - GPollableSource *pollable_source; - - source = g_source_new (&pollable_source_funcs, sizeof (GPollableSource)); - g_source_set_name (source, "GPollableSource"); - pollable_source = (GPollableSource *)source; - pollable_source->stream = g_object_ref (pollable_stream); - - return source; -} diff --git a/gio/gpollableinputstream.h b/gio/gpollableinputstream.h index 634ff2aeb..49af7ee2d 100644 --- a/gio/gpollableinputstream.h +++ b/gio/gpollableinputstream.h @@ -95,9 +95,6 @@ gssize g_pollable_input_stream_read_nonblocking (GPollableInputStream *stream GCancellable *cancellable, GError **error); -/* Helper method for stream implementations */ -GSource *g_pollable_source_new (GObject *pollable_stream); - G_END_DECLS diff --git a/gio/gpollableutils.c b/gio/gpollableutils.c new file mode 100644 index 000000000..0e653fa88 --- /dev/null +++ b/gio/gpollableutils.c @@ -0,0 +1,350 @@ +/* GIO - GLib Input, Output and Streaming Library + * + * Copyright (C) 2010 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * 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. + */ + +#include "config.h" + +#include + +#include "gpollableinputstream.h" +#include "gasynchelper.h" +#include "glibintl.h" + +/** + * SECTION:gpollableutils + * @short_description: #GPollableInputStream / #GPollableOutputStream utilities + * @include: gio/gio.h + * + * Utility functions for #GPollableInputStream and + * #GPollableOutputStream implementations. + */ + +typedef struct { + GSource source; + + GObject *stream; +} GPollableSource; + +static gboolean +pollable_source_prepare (GSource *source, + gint *timeout) +{ + *timeout = -1; + return FALSE; +} + +static gboolean +pollable_source_check (GSource *source) +{ + return FALSE; +} + +static gboolean +pollable_source_dispatch (GSource *source, + GSourceFunc callback, + gpointer user_data) +{ + GPollableSourceFunc func = (GPollableSourceFunc)callback; + GPollableSource *pollable_source = (GPollableSource *)source; + + return (*func) (pollable_source->stream, user_data); +} + +static void +pollable_source_finalize (GSource *source) +{ + GPollableSource *pollable_source = (GPollableSource *)source; + + g_object_unref (pollable_source->stream); +} + +static gboolean +pollable_source_closure_callback (GObject *stream, + gpointer data) +{ + GClosure *closure = data; + + GValue param = G_VALUE_INIT; + GValue result_value = G_VALUE_INIT; + gboolean result; + + g_value_init (&result_value, G_TYPE_BOOLEAN); + + g_value_init (¶m, G_TYPE_OBJECT); + g_value_set_object (¶m, stream); + + g_closure_invoke (closure, &result_value, 1, ¶m, NULL); + + result = g_value_get_boolean (&result_value); + g_value_unset (&result_value); + g_value_unset (¶m); + + return result; +} + +static GSourceFuncs pollable_source_funcs = +{ + pollable_source_prepare, + pollable_source_check, + pollable_source_dispatch, + pollable_source_finalize, + (GSourceFunc)pollable_source_closure_callback, + (GSourceDummyMarshal)g_cclosure_marshal_generic, +}; + +/** + * g_pollable_source_new: + * @pollable_stream: the stream associated with the new source + * + * Utility method for #GPollableInputStream and #GPollableOutputStream + * implementations. Creates a new #GSource that expects a callback of + * type #GPollableSourceFunc. The new source does not actually do + * anything on its own; use g_source_add_child_source() to add other + * sources to it to cause it to trigger. + * + * Return value: (transfer full): the new #GSource. + * + * Since: 2.28 + */ +GSource * +g_pollable_source_new (GObject *pollable_stream) +{ + GSource *source; + GPollableSource *pollable_source; + + g_return_val_if_fail (G_IS_POLLABLE_INPUT_STREAM (pollable_stream) || + G_IS_POLLABLE_OUTPUT_STREAM (pollable_stream), NULL); + + source = g_source_new (&pollable_source_funcs, sizeof (GPollableSource)); + g_source_set_name (source, "GPollableSource"); + pollable_source = (GPollableSource *)source; + pollable_source->stream = g_object_ref (pollable_stream); + + return source; +} + +/** + * g_pollable_source_new_full: + * @pollable_stream: (type GObject): the stream associated with the + * new source + * @child_source: (allow-none): optional child source to attach + * @cancellable: (allow-none): optional #GCancellable to attach + * + * Utility method for #GPollableInputStream and #GPollableOutputStream + * implementations. Creates a new #GSource, as with + * g_pollable_source_new(), but also attaching @child_source (with a + * dummy callback), and @cancellable, if they are non-%NULL. + * + * Return value: (transfer full): the new #GSource. + * + * Since: 2.34 + */ +GSource * +g_pollable_source_new_full (gpointer pollable_stream, + GSource *child_source, + GCancellable *cancellable) +{ + GSource *source; + + g_return_val_if_fail (G_IS_POLLABLE_INPUT_STREAM (pollable_stream) || + G_IS_POLLABLE_OUTPUT_STREAM (pollable_stream), NULL); + + source = g_pollable_source_new (pollable_stream); + if (child_source) + { + g_source_set_dummy_callback (child_source); + g_source_add_child_source (source, child_source); + } + if (cancellable) + { + GSource *cancellable_source = g_cancellable_source_new (cancellable); + + g_source_set_dummy_callback (cancellable_source); + g_source_add_child_source (source, cancellable_source); + g_source_unref (cancellable_source); + } + + return source; +} + +/** + * g_pollable_stream_read: + * @stream: a #GInputStream + * @buffer: a buffer to read data into + * @count: the number of bytes to read + * @blocking: whether to do blocking I/O + * @cancellable: (allow-none): optional #GCancellable object, %NULL to ignore. + * @error: location to store the error occurring, or %NULL to ignore + * + * Tries to read from @stream, as with g_input_stream_read() (if + * @blocking is %TRUE) or g_pollable_input_stream_read_nonblocking() + * (if @blocking is %FALSE). This can be used to more easily share + * code between blocking and non-blocking implementations of a method. + * + * If @blocking is %FALSE, then @stream must be a + * #GPollableInputStream for which g_pollable_input_stream_can_poll() + * returns %TRUE, or else the behavior is undefined. If @blocking is + * %TRUE, then @stream does not need to be a #GPollableInputStream. + * + * Returns: the number of bytes read, or -1 on error. + * + * Since: 2.34 + */ +gssize +g_pollable_stream_read (GInputStream *stream, + void *buffer, + gsize count, + gboolean blocking, + GCancellable *cancellable, + GError **error) +{ + if (blocking) + { + return g_input_stream_read (stream, + buffer, count, + cancellable, error); + } + else + { + return g_pollable_input_stream_read_nonblocking (G_POLLABLE_INPUT_STREAM (stream), + buffer, count, + cancellable, error); + } +} + +/** + * g_pollable_stream_write: + * @stream: a #GOutputStream. + * @buffer: (array length=count) (element-type guint8): the buffer + * containing the data to write. + * @count: the number of bytes to write + * @blocking: whether to do blocking I/O + * @cancellable: (allow-none): optional #GCancellable object, %NULL to ignore. + * @error: location to store the error occurring, or %NULL to ignore + * + * Tries to write to @stream, as with g_output_stream_write() (if + * @blocking is %TRUE) or g_pollable_output_stream_write_nonblocking() + * (if @blocking is %FALSE). This can be used to more easily share + * code between blocking and non-blocking implementations of a method. + * + * If @blocking is %FALSE, then @stream must be a + * #GPollableOutputStream for which + * g_pollable_output_stream_can_poll() returns %TRUE or else the + * behavior is undefined. If @blocking is %TRUE, then @stream does not + * need to be a #GPollableOutputStream. + * + * Returns: the number of bytes written, or -1 on error. + * + * Since: 2.34 + */ +gssize +g_pollable_stream_write (GOutputStream *stream, + const void *buffer, + gsize count, + gboolean blocking, + GCancellable *cancellable, + GError **error) +{ + if (blocking) + { + return g_output_stream_write (stream, + buffer, count, + cancellable, error); + } + else + { + return g_pollable_output_stream_write_nonblocking (G_POLLABLE_OUTPUT_STREAM (stream), + buffer, count, + cancellable, error); + } +} + +/** + * g_pollable_stream_write_all: + * @stream: a #GOutputStream. + * @buffer: (array length=count) (element-type guint8): the buffer + * containing the data to write. + * @count: the number of bytes to write + * @blocking: whether to do blocking I/O + * @bytes_written: (out): location to store the number of bytes that was + * written to the stream + * @cancellable: (allow-none): optional #GCancellable object, %NULL to ignore. + * @error: location to store the error occurring, or %NULL to ignore + * + * Tries to write @count bytes to @stream, as with + * g_output_stream_write_all(), but using g_pollable_stream_write() + * rather than g_output_stream_write(). + * + * On a successful write of @count bytes, %TRUE is returned, and + * @bytes_written is set to @count. + * + * If there is an error during the operation (including + * %G_IO_ERROR_WOULD_BLOCK in the non-blocking case), %FALSE is + * returned and @error is set to indicate the error status, + * @bytes_written is updated to contain the number of bytes written + * into the stream before the error occurred. + * + * As with g_pollable_stream_write(), if @blocking is %FALSE, then + * @stream must be a #GPollableOutputStream for which + * g_pollable_output_stream_can_poll() returns %TRUE or else the + * behavior is undefined. If @blocking is %TRUE, then @stream does not + * need to be a #GPollableOutputStream. + * + * Return value: %TRUE on success, %FALSE if there was an error + * + * Since: 2.34 + */ +gboolean +g_pollable_stream_write_all (GOutputStream *stream, + const void *buffer, + gsize count, + gboolean blocking, + gsize *bytes_written, + GCancellable *cancellable, + GError **error) +{ + gsize _bytes_written; + gssize res; + + _bytes_written = 0; + while (_bytes_written < count) + { + res = g_pollable_stream_write (stream, + (char *)buffer + _bytes_written, + count - _bytes_written, + blocking, + cancellable, error); + if (res == -1) + { + if (bytes_written) + *bytes_written = _bytes_written; + return FALSE; + } + + if (res == 0) + g_warning ("Write returned zero without error"); + + _bytes_written += res; + } + + if (bytes_written) + *bytes_written = _bytes_written; + + return TRUE; +} diff --git a/gio/gpollableutils.h b/gio/gpollableutils.h new file mode 100644 index 000000000..782f3ca4d --- /dev/null +++ b/gio/gpollableutils.h @@ -0,0 +1,65 @@ +/* GIO - GLib Input, Output and Streaming Library + * + * Copyright (C) 2012 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * 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. + */ + +#if !defined (__GIO_GIO_H_INSIDE__) && !defined (GIO_COMPILATION) +#error "Only can be included directly." +#endif + +#ifndef __G_POLLABLE_UTILS_H__ +#define __G_POLLABLE_UTILS_H__ + +#include + +G_BEGIN_DECLS + +GSource *g_pollable_source_new (GObject *pollable_stream); + +GLIB_AVAILABLE_IN_2_34 +GSource *g_pollable_source_new_full (gpointer pollable_stream, + GSource *child_source, + GCancellable *cancellable); + +GLIB_AVAILABLE_IN_2_34 +gssize g_pollable_stream_read (GInputStream *stream, + void *buffer, + gsize count, + gboolean blocking, + GCancellable *cancellable, + GError **error); + +GLIB_AVAILABLE_IN_2_34 +gssize g_pollable_stream_write (GOutputStream *stream, + const void *buffer, + gsize count, + gboolean blocking, + GCancellable *cancellable, + GError **error); +GLIB_AVAILABLE_IN_2_34 +gboolean g_pollable_stream_write_all (GOutputStream *stream, + const void *buffer, + gsize count, + gboolean blocking, + gsize *bytes_written, + GCancellable *cancellable, + GError **error); + +G_END_DECLS + +#endif /* _G_POLLABLE_UTILS_H_ */