X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=gio%2Fgconverteroutputstream.c;h=6e17d55966dc7922b58c95b4bc2077fe866b376a;hb=e55a953642a9e402f4363f9fa347b6061dd78990;hp=d1e1b6f2e67913c66b8f1f11e57523170a2a962b;hpb=45a1c41e8cfdeb4edeb7a671b95e599a49c6c281;p=platform%2Fupstream%2Fglib.git diff --git a/gio/gconverteroutputstream.c b/gio/gconverteroutputstream.c index d1e1b6f..6e17d55 100644 --- a/gio/gconverteroutputstream.c +++ b/gio/gconverteroutputstream.c @@ -13,9 +13,7 @@ * 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: Alexander Larsson */ @@ -25,13 +23,13 @@ #include #include "gconverteroutputstream.h" +#include "gpollableoutputstream.h" #include "gsimpleasyncresult.h" #include "gcancellable.h" #include "gioenumtypes.h" #include "gioerror.h" #include "glibintl.h" -#include "gioalias.h" /** * SECTION:gconverteroutputstream @@ -42,6 +40,8 @@ * Converter output stream implements #GOutputStream and allows * conversion of data of various types during reading. * + * As of GLib 2.34, #GConverterOutputStream implements + * #GPollableOutputStream. **/ #define INITIAL_BUFFER_SIZE 4096 @@ -97,9 +97,24 @@ static gboolean g_converter_output_stream_flush (GOutputStream *stream, GCancellable *cancellable, GError **error); -G_DEFINE_TYPE (GConverterOutputStream, - g_converter_output_stream, - G_TYPE_FILTER_OUTPUT_STREAM) +static gboolean g_converter_output_stream_can_poll (GPollableOutputStream *stream); +static gboolean g_converter_output_stream_is_writable (GPollableOutputStream *stream); +static gssize g_converter_output_stream_write_nonblocking (GPollableOutputStream *stream, + const void *buffer, + gsize size, + GError **error); + +static GSource *g_converter_output_stream_create_source (GPollableOutputStream *stream, + GCancellable *cancellable); + +static void g_converter_output_stream_pollable_iface_init (GPollableOutputStreamInterface *iface); + +G_DEFINE_TYPE_WITH_CODE (GConverterOutputStream, + g_converter_output_stream, + G_TYPE_FILTER_OUTPUT_STREAM, + G_ADD_PRIVATE (GConverterOutputStream) + G_IMPLEMENT_INTERFACE (G_TYPE_POLLABLE_OUTPUT_STREAM, + g_converter_output_stream_pollable_iface_init)) static void g_converter_output_stream_class_init (GConverterOutputStreamClass *klass) @@ -107,8 +122,6 @@ g_converter_output_stream_class_init (GConverterOutputStreamClass *klass) GObjectClass *object_class; GOutputStreamClass *istream_class; - g_type_class_add_private (klass, sizeof (GConverterOutputStreamPrivate)); - object_class = G_OBJECT_CLASS (klass); object_class->get_property = g_converter_output_stream_get_property; object_class->set_property = g_converter_output_stream_set_property; @@ -131,6 +144,15 @@ g_converter_output_stream_class_init (GConverterOutputStreamClass *klass) } static void +g_converter_output_stream_pollable_iface_init (GPollableOutputStreamInterface *iface) +{ + iface->can_poll = g_converter_output_stream_can_poll; + iface->is_writable = g_converter_output_stream_is_writable; + iface->write_nonblocking = g_converter_output_stream_write_nonblocking; + iface->create_source = g_converter_output_stream_create_source; +} + +static void g_converter_output_stream_finalize (GObject *object) { GConverterOutputStreamPrivate *priv; @@ -197,9 +219,7 @@ g_converter_output_stream_get_property (GObject *object, static void g_converter_output_stream_init (GConverterOutputStream *stream) { - stream->priv = G_TYPE_INSTANCE_GET_PRIVATE (stream, - G_TYPE_CONVERTER_OUTPUT_STREAM, - GConverterOutputStreamPrivate); + stream->priv = g_converter_output_stream_get_instance_private (stream); } /** @@ -228,7 +248,7 @@ g_converter_output_stream_new (GOutputStream *base_stream, } static gsize -buffer_available (Buffer *buffer) +buffer_data_size (Buffer *buffer) { return buffer->end - buffer->start; } @@ -259,7 +279,7 @@ compact_buffer (Buffer *buffer) { gsize in_buffer; - in_buffer = buffer_available (buffer); + in_buffer = buffer_data_size (buffer); memmove (buffer->data, buffer->data + buffer->start, in_buffer); @@ -279,7 +299,7 @@ grow_buffer (Buffer *buffer) size = buffer->size * 2; data = g_malloc (size); - in_buffer = buffer_available (buffer); + in_buffer = buffer_data_size (buffer); memcpy (data, buffer->data + buffer->start, @@ -291,13 +311,15 @@ grow_buffer (Buffer *buffer) buffer->size = size; } +/* Ensures that the buffer can fit at_least_size bytes, + * *including* the current in-buffer data */ static void buffer_ensure_space (Buffer *buffer, gsize at_least_size) { gsize in_buffer, left_to_fill; - in_buffer = buffer_available (buffer); + in_buffer = buffer_data_size (buffer); if (in_buffer >= at_least_size) return; @@ -330,7 +352,7 @@ buffer_append (Buffer *buffer, gsize data_size) { buffer_ensure_space (buffer, - buffer_available (buffer) + data_size); + buffer_data_size (buffer) + data_size); memcpy (buffer->data + buffer->end, data, data_size); buffer->end += data_size; } @@ -338,7 +360,7 @@ buffer_append (Buffer *buffer, static gboolean flush_buffer (GConverterOutputStream *stream, - Buffer *buffer, + gboolean blocking, GCancellable *cancellable, GError **error) { @@ -352,15 +374,16 @@ flush_buffer (GConverterOutputStream *stream, base_stream = G_FILTER_OUTPUT_STREAM (stream)->base_stream; - available = buffer_available (&priv->converted_buffer); + available = buffer_data_size (&priv->converted_buffer); if (available > 0) { - res = g_output_stream_write_all (base_stream, - buffer_data (&priv->converted_buffer), - available, - &nwritten, - cancellable, - error); + res = g_pollable_stream_write_all (base_stream, + buffer_data (&priv->converted_buffer), + available, + blocking, + &nwritten, + cancellable, + error); buffer_consumed (&priv->converted_buffer, nwritten); return res; } @@ -369,11 +392,12 @@ flush_buffer (GConverterOutputStream *stream, static gssize -g_converter_output_stream_write (GOutputStream *stream, - const void *buffer, - gsize count, - GCancellable *cancellable, - GError **error) +write_internal (GOutputStream *stream, + const void *buffer, + gsize count, + gboolean blocking, + GCancellable *cancellable, + GError **error) { GConverterOutputStream *cstream; GConverterOutputStreamPrivate *priv; @@ -391,19 +415,19 @@ g_converter_output_stream_write (GOutputStream *stream, /* Write out all available pre-converted data and fail if not possible */ - if (!flush_buffer (cstream, &priv->converted_buffer, cancellable, error)) + if (!flush_buffer (cstream, blocking, cancellable, error)) return -1; if (priv->finished) return 0; /* Convert as much as possible */ - if (buffer_available (&priv->output_buffer) > 0) + if (buffer_data_size (&priv->output_buffer) > 0) { converting_from_buffer = TRUE; buffer_append (&priv->output_buffer, buffer, count); to_convert = buffer_data (&priv->output_buffer); - to_convert_size = buffer_available (&priv->output_buffer); + to_convert_size = buffer_data_size (&priv->output_buffer); } else { @@ -418,12 +442,16 @@ g_converter_output_stream_write (GOutputStream *stream, converted_bytes = 0; while (!priv->finished && converted_bytes < to_convert_size) { + /* Ensure we have *some* target space */ + if (buffer_tailspace (&priv->converted_buffer) == 0) + grow_buffer (&priv->converted_buffer); + /* Try to convert to our buffer */ my_error = NULL; res = g_converter_convert (priv->converter, to_convert + converted_bytes, to_convert_size - converted_bytes, - buffer_data (&priv->converted_buffer), + buffer_data (&priv->converted_buffer) + buffer_data_size (&priv->converted_buffer), buffer_tailspace (&priv->converted_buffer), 0, &bytes_read, @@ -472,6 +500,7 @@ g_converter_output_stream_write (GOutputStream *stream, buffer_append (&priv->output_buffer, buffer, count); /* in the converting_from_buffer case we already appended this */ + g_error_free (my_error); return count; /* consume everything */ } @@ -493,11 +522,21 @@ g_converter_output_stream_write (GOutputStream *stream, even if writing this to the base stream fails. If it does we'll just stop early and report this error when we try again on the next write call. */ - flush_buffer (cstream, &priv->converted_buffer, cancellable, NULL); + flush_buffer (cstream, blocking, cancellable, NULL); return retval; } +static gssize +g_converter_output_stream_write (GOutputStream *stream, + const void *buffer, + gsize count, + GCancellable *cancellable, + GError **error) +{ + return write_internal (stream, buffer, count, TRUE, cancellable, error); +} + static gboolean g_converter_output_stream_flush (GOutputStream *stream, GCancellable *cancellable, @@ -519,7 +558,7 @@ g_converter_output_stream_flush (GOutputStream *stream, /* Write out all available pre-converted data and fail if not possible */ - if (!flush_buffer (cstream, &priv->converted_buffer, cancellable, error)) + if (!flush_buffer (cstream, TRUE, cancellable, error)) return FALSE; /* Ensure we have *some* initial target space */ @@ -529,12 +568,16 @@ g_converter_output_stream_flush (GOutputStream *stream, flushed = FALSE; while (!priv->finished && !flushed) { + /* Ensure we have *some* target space */ + if (buffer_tailspace (&priv->converted_buffer) == 0) + grow_buffer (&priv->converted_buffer); + /* Try to convert to our buffer */ my_error = NULL; res = g_converter_convert (priv->converter, buffer_data (&priv->output_buffer), - buffer_available (&priv->output_buffer), - buffer_data (&priv->converted_buffer), + buffer_data_size (&priv->output_buffer), + buffer_data (&priv->converted_buffer) + buffer_data_size (&priv->converted_buffer), buffer_tailspace (&priv->converted_buffer), is_closing ? G_CONVERTER_INPUT_AT_END : G_CONVERTER_FLUSH, &bytes_read, @@ -552,7 +595,7 @@ g_converter_output_stream_flush (GOutputStream *stream, res == G_CONVERTER_FLUSHED) { /* Should not have retured FLUSHED with input left */ - g_assert (buffer_available (&priv->output_buffer) == 0); + g_assert (buffer_data_size (&priv->output_buffer) == 0); flushed = TRUE; } } @@ -575,24 +618,66 @@ g_converter_output_stream_flush (GOutputStream *stream, /* Any other error, including PARTIAL_INPUT can't be fixed by now and is an error */ g_propagate_error (error, my_error); - return -1; + return FALSE; } } /* Now write all converted data to base stream */ - if (!flush_buffer (cstream, &priv->converted_buffer, cancellable, error)) + if (!flush_buffer (cstream, TRUE, cancellable, error)) return FALSE; return TRUE; } +static gboolean +g_converter_output_stream_can_poll (GPollableOutputStream *stream) +{ + GOutputStream *base_stream = G_FILTER_OUTPUT_STREAM (stream)->base_stream; + + return (G_IS_POLLABLE_OUTPUT_STREAM (base_stream) && + g_pollable_output_stream_can_poll (G_POLLABLE_OUTPUT_STREAM (base_stream))); +} + +static gboolean +g_converter_output_stream_is_writable (GPollableOutputStream *stream) +{ + GOutputStream *base_stream = G_FILTER_OUTPUT_STREAM (stream)->base_stream; + + return g_pollable_output_stream_is_writable (G_POLLABLE_OUTPUT_STREAM (base_stream)); +} + +static gssize +g_converter_output_stream_write_nonblocking (GPollableOutputStream *stream, + const void *buffer, + gsize count, + GError **error) +{ + return write_internal (G_OUTPUT_STREAM (stream), buffer, count, FALSE, + NULL, error); +} + +static GSource * +g_converter_output_stream_create_source (GPollableOutputStream *stream, + GCancellable *cancellable) +{ + GOutputStream *base_stream = G_FILTER_OUTPUT_STREAM (stream)->base_stream; + GSource *base_source, *pollable_source; + + base_source = g_pollable_output_stream_create_source (G_POLLABLE_OUTPUT_STREAM (base_stream), NULL); + pollable_source = g_pollable_source_new_full (stream, base_source, + cancellable); + g_source_unref (base_source); + + return pollable_source; +} + /** * g_converter_output_stream_get_converter: * @converter_stream: a #GConverterOutputStream * * Gets the #GConverter that is used by @converter_stream. * - * Returns: the converter of the converter output stream + * Returns: (transfer none): the converter of the converter output stream * * Since: 2.24 */ @@ -601,6 +686,3 @@ g_converter_output_stream_get_converter (GConverterOutputStream *converter_strea { return converter_stream->priv->converter; } - -#define __G_CONVERTER_OUTPUT_STREAM_C__ -#include "gioaliasdef.c"