| 
									
										
										
										
											2007-11-26 16:13:05 +00:00
										 |  |  | /* GIO - GLib Input, Output and Streaming Library
 | 
					
						
							|  |  |  |  *  | 
					
						
							|  |  |  |  * Copyright (C) 2006-2007 Red Hat, Inc. | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2022-05-18 09:12:45 +01:00
										 |  |  |  * SPDX-License-Identifier: LGPL-2.1-or-later | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2007-11-26 16:13:05 +00:00
										 |  |  |  * 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 | 
					
						
							| 
									
										
										
										
											2017-05-27 18:21:30 +02:00
										 |  |  |  * version 2.1 of the License, or (at your option) any later version. | 
					
						
							| 
									
										
										
										
											2007-11-26 16:13:05 +00:00
										 |  |  |  * | 
					
						
							|  |  |  |  * 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 | 
					
						
							| 
									
										
										
										
											2014-01-23 12:58:29 +01:00
										 |  |  |  * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
 | 
					
						
							| 
									
										
										
										
											2007-11-26 16:13:05 +00:00
										 |  |  |  * | 
					
						
							|  |  |  |  * Author: Christian Kellner <gicmo@gnome.org>  | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-06-22 15:10:51 +00:00
										 |  |  | #include "config.h"
 | 
					
						
							| 
									
										
										
										
											2007-11-26 16:13:05 +00:00
										 |  |  | #include "gbufferedoutputstream.h"
 | 
					
						
							|  |  |  | #include "goutputstream.h"
 | 
					
						
							| 
									
										
										
										
											2012-03-29 01:50:41 +02:00
										 |  |  | #include "gseekable.h"
 | 
					
						
							| 
									
										
										
										
											2012-08-02 15:49:59 -04:00
										 |  |  | #include "gtask.h"
 | 
					
						
							| 
									
										
										
										
											2007-11-26 16:13:05 +00:00
										 |  |  | #include "string.h"
 | 
					
						
							| 
									
										
										
										
											2012-03-29 01:50:41 +02:00
										 |  |  | #include "gioerror.h"
 | 
					
						
							| 
									
										
										
										
											2007-11-26 16:13:05 +00:00
										 |  |  | #include "glibintl.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-11-27 14:00:13 +00:00
										 |  |  | /**
 | 
					
						
							| 
									
										
										
										
											2023-09-25 21:27:09 -04:00
										 |  |  |  * GBufferedOutputStream: | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2023-10-23 11:17:24 +01:00
										 |  |  |  * Buffered output stream implements [class@Gio.FilterOutputStream] and provides | 
					
						
							| 
									
										
										
										
											2023-09-25 21:27:09 -04:00
										 |  |  |  * for buffered writes. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * By default, `GBufferedOutputStream`'s buffer size is set at 4 kilobytes. | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2023-10-23 11:17:24 +01:00
										 |  |  |  * To create a buffered output stream, use [ctor@Gio.BufferedOutputStream.new], | 
					
						
							|  |  |  |  * or [ctor@Gio.BufferedOutputStream.new_sized] to specify the buffer's size | 
					
						
							| 
									
										
										
										
											2007-12-01 05:25:40 +00:00
										 |  |  |  * at construction. | 
					
						
							| 
									
										
										
										
											2023-09-25 21:27:09 -04:00
										 |  |  |  * | 
					
						
							|  |  |  |  * To get the size of a buffer within a buffered input stream, use | 
					
						
							|  |  |  |  * [method@Gio.BufferedOutputStream.get_buffer_size]. To change the size of a | 
					
						
							|  |  |  |  * buffered output stream's buffer, use [method@Gio.BufferedOutputStream.set_buffer_size]. | 
					
						
							|  |  |  |  * Note that the buffer's size cannot be reduced below the size of the data within the buffer. | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2007-11-27 14:00:13 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-11-26 16:13:05 +00:00
										 |  |  | #define DEFAULT_BUFFER_SIZE 4096
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | struct _GBufferedOutputStreamPrivate { | 
					
						
							|  |  |  |   guint8 *buffer;  | 
					
						
							|  |  |  |   gsize   len; | 
					
						
							|  |  |  |   goffset pos; | 
					
						
							|  |  |  |   gboolean auto_grow; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | enum { | 
					
						
							|  |  |  |   PROP_0, | 
					
						
							| 
									
										
										
										
											2007-12-01 05:25:40 +00:00
										 |  |  |   PROP_BUFSIZE, | 
					
						
							|  |  |  |   PROP_AUTO_GROW | 
					
						
							| 
									
										
										
										
											2007-11-26 16:13:05 +00:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void     g_buffered_output_stream_set_property (GObject      *object, | 
					
						
							|  |  |  |                                                        guint         prop_id, | 
					
						
							|  |  |  |                                                        const GValue *value, | 
					
						
							|  |  |  |                                                        GParamSpec   *pspec); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void     g_buffered_output_stream_get_property (GObject    *object, | 
					
						
							|  |  |  |                                                        guint       prop_id, | 
					
						
							|  |  |  |                                                        GValue     *value, | 
					
						
							|  |  |  |                                                        GParamSpec *pspec); | 
					
						
							|  |  |  | static void     g_buffered_output_stream_finalize     (GObject *object); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static gssize   g_buffered_output_stream_write        (GOutputStream *stream, | 
					
						
							|  |  |  |                                                        const void    *buffer, | 
					
						
							|  |  |  |                                                        gsize          count, | 
					
						
							|  |  |  |                                                        GCancellable  *cancellable, | 
					
						
							|  |  |  |                                                        GError       **error); | 
					
						
							|  |  |  | static gboolean g_buffered_output_stream_flush        (GOutputStream    *stream, | 
					
						
							|  |  |  |                                                        GCancellable  *cancellable, | 
					
						
							|  |  |  |                                                        GError          **error); | 
					
						
							|  |  |  | static gboolean g_buffered_output_stream_close        (GOutputStream  *stream, | 
					
						
							|  |  |  |                                                        GCancellable   *cancellable, | 
					
						
							|  |  |  |                                                        GError        **error); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void     g_buffered_output_stream_flush_async  (GOutputStream        *stream, | 
					
						
							|  |  |  |                                                        int                   io_priority, | 
					
						
							|  |  |  |                                                        GCancellable         *cancellable, | 
					
						
							|  |  |  |                                                        GAsyncReadyCallback   callback, | 
					
						
							|  |  |  |                                                        gpointer              data); | 
					
						
							|  |  |  | static gboolean g_buffered_output_stream_flush_finish (GOutputStream        *stream, | 
					
						
							|  |  |  |                                                        GAsyncResult         *result, | 
					
						
							|  |  |  |                                                        GError              **error); | 
					
						
							|  |  |  | static void     g_buffered_output_stream_close_async  (GOutputStream        *stream, | 
					
						
							|  |  |  |                                                        int                   io_priority, | 
					
						
							|  |  |  |                                                        GCancellable         *cancellable, | 
					
						
							|  |  |  |                                                        GAsyncReadyCallback   callback, | 
					
						
							|  |  |  |                                                        gpointer              data); | 
					
						
							|  |  |  | static gboolean g_buffered_output_stream_close_finish (GOutputStream        *stream, | 
					
						
							|  |  |  |                                                        GAsyncResult         *result, | 
					
						
							|  |  |  |                                                        GError              **error); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-29 01:50:41 +02:00
										 |  |  | static void     g_buffered_output_stream_seekable_iface_init (GSeekableIface  *iface); | 
					
						
							|  |  |  | static goffset  g_buffered_output_stream_tell                (GSeekable       *seekable); | 
					
						
							|  |  |  | static gboolean g_buffered_output_stream_can_seek            (GSeekable       *seekable); | 
					
						
							|  |  |  | static gboolean g_buffered_output_stream_seek                (GSeekable       *seekable, | 
					
						
							|  |  |  | 							      goffset          offset, | 
					
						
							|  |  |  | 							      GSeekType        type, | 
					
						
							|  |  |  | 							      GCancellable    *cancellable, | 
					
						
							|  |  |  | 							      GError         **error); | 
					
						
							|  |  |  | static gboolean g_buffered_output_stream_can_truncate        (GSeekable       *seekable); | 
					
						
							|  |  |  | static gboolean g_buffered_output_stream_truncate            (GSeekable       *seekable, | 
					
						
							|  |  |  | 							      goffset          offset, | 
					
						
							|  |  |  | 							      GCancellable    *cancellable, | 
					
						
							|  |  |  | 							      GError         **error); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | G_DEFINE_TYPE_WITH_CODE (GBufferedOutputStream, | 
					
						
							|  |  |  | 			 g_buffered_output_stream, | 
					
						
							|  |  |  | 			 G_TYPE_FILTER_OUTPUT_STREAM, | 
					
						
							| 
									
										
										
										
											2013-06-11 00:29:58 +01:00
										 |  |  |                          G_ADD_PRIVATE (GBufferedOutputStream) | 
					
						
							| 
									
										
										
										
											2012-03-29 01:50:41 +02:00
										 |  |  | 			 G_IMPLEMENT_INTERFACE (G_TYPE_SEEKABLE, | 
					
						
							|  |  |  | 						g_buffered_output_stream_seekable_iface_init)) | 
					
						
							| 
									
										
										
										
											2007-11-26 16:13:05 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | g_buffered_output_stream_class_init (GBufferedOutputStreamClass *klass) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   GObjectClass *object_class; | 
					
						
							|  |  |  |   GOutputStreamClass *ostream_class; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   object_class = G_OBJECT_CLASS (klass); | 
					
						
							|  |  |  |   object_class->get_property = g_buffered_output_stream_get_property; | 
					
						
							|  |  |  |   object_class->set_property = g_buffered_output_stream_set_property; | 
					
						
							|  |  |  |   object_class->finalize     = g_buffered_output_stream_finalize; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   ostream_class = G_OUTPUT_STREAM_CLASS (klass); | 
					
						
							| 
									
										
										
										
											2007-12-05 10:38:03 +00:00
										 |  |  |   ostream_class->write_fn = g_buffered_output_stream_write; | 
					
						
							| 
									
										
										
										
											2007-11-26 16:13:05 +00:00
										 |  |  |   ostream_class->flush = g_buffered_output_stream_flush; | 
					
						
							| 
									
										
										
										
											2007-12-05 10:38:03 +00:00
										 |  |  |   ostream_class->close_fn = g_buffered_output_stream_close; | 
					
						
							| 
									
										
										
										
											2007-11-26 16:13:05 +00:00
										 |  |  |   ostream_class->flush_async  = g_buffered_output_stream_flush_async; | 
					
						
							|  |  |  |   ostream_class->flush_finish = g_buffered_output_stream_flush_finish; | 
					
						
							|  |  |  |   ostream_class->close_async  = g_buffered_output_stream_close_async; | 
					
						
							|  |  |  |   ostream_class->close_finish = g_buffered_output_stream_close_finish; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-11-29 13:23:09 +00:00
										 |  |  |   /**
 | 
					
						
							|  |  |  |    * GBufferedOutputStream:buffer-size: | 
					
						
							|  |  |  |    * | 
					
						
							|  |  |  |    * The size of the backend buffer, in bytes. | 
					
						
							|  |  |  |    */ | 
					
						
							| 
									
										
										
										
											2007-11-26 16:13:05 +00:00
										 |  |  |   g_object_class_install_property (object_class, | 
					
						
							|  |  |  |                                    PROP_BUFSIZE, | 
					
						
							| 
									
										
										
										
											2023-04-28 01:59:26 +02:00
										 |  |  |                                    g_param_spec_uint ("buffer-size", NULL, NULL, | 
					
						
							| 
									
										
										
										
											2007-11-26 16:13:05 +00:00
										 |  |  |                                                       1, | 
					
						
							|  |  |  |                                                       G_MAXUINT, | 
					
						
							|  |  |  |                                                       DEFAULT_BUFFER_SIZE, | 
					
						
							| 
									
										
										
										
											2007-12-01 06:12:45 +00:00
										 |  |  |                                                       G_PARAM_READWRITE|G_PARAM_CONSTRUCT| | 
					
						
							| 
									
										
										
										
											2007-11-26 16:13:05 +00:00
										 |  |  |                                                       G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB)); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-11-29 13:23:09 +00:00
										 |  |  |   /**
 | 
					
						
							|  |  |  |    * GBufferedOutputStream:auto-grow: | 
					
						
							|  |  |  |    * | 
					
						
							|  |  |  |    * Whether the buffer should automatically grow. | 
					
						
							|  |  |  |    */ | 
					
						
							| 
									
										
										
										
											2007-12-01 05:25:40 +00:00
										 |  |  |   g_object_class_install_property (object_class, | 
					
						
							|  |  |  |                                    PROP_AUTO_GROW, | 
					
						
							| 
									
										
										
										
											2023-04-28 01:59:26 +02:00
										 |  |  |                                    g_param_spec_boolean ("auto-grow", NULL, NULL, | 
					
						
							| 
									
										
										
										
											2007-12-01 05:25:40 +00:00
										 |  |  |                                                          FALSE, | 
					
						
							|  |  |  |                                                          G_PARAM_READWRITE| | 
					
						
							|  |  |  |                                                          G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB)); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-11-26 16:13:05 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /**
 | 
					
						
							|  |  |  |  * g_buffered_output_stream_get_buffer_size: | 
					
						
							| 
									
										
										
										
											2024-07-09 18:03:03 +05:30
										 |  |  |  * @stream: a [class@Gio.BufferedOutputStream]. | 
					
						
							| 
									
										
										
										
											2007-11-26 16:13:05 +00:00
										 |  |  |  *  | 
					
						
							| 
									
										
										
										
											2007-11-27 14:00:13 +00:00
										 |  |  |  * Gets the size of the buffer in the @stream. | 
					
						
							|  |  |  |  *  | 
					
						
							| 
									
										
										
										
											2007-11-26 16:13:05 +00:00
										 |  |  |  * Returns: the current size of the buffer. | 
					
						
							|  |  |  |  **/ | 
					
						
							|  |  |  | gsize | 
					
						
							|  |  |  | g_buffered_output_stream_get_buffer_size (GBufferedOutputStream *stream) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   g_return_val_if_fail (G_IS_BUFFERED_OUTPUT_STREAM (stream), -1); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return stream->priv->len; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /**
 | 
					
						
							|  |  |  |  * g_buffered_output_stream_set_buffer_size: | 
					
						
							| 
									
										
										
										
											2024-07-09 18:03:03 +05:30
										 |  |  |  * @stream: a [class@Gio.BufferedOutputStream]. | 
					
						
							| 
									
										
										
										
											2007-11-26 16:13:05 +00:00
										 |  |  |  * @size: a #gsize. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Sets the size of the internal buffer to @size. | 
					
						
							|  |  |  |  **/     | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | g_buffered_output_stream_set_buffer_size (GBufferedOutputStream *stream, | 
					
						
							| 
									
										
										
										
											2007-12-01 05:25:40 +00:00
										 |  |  |                                           gsize                  size) | 
					
						
							| 
									
										
										
										
											2007-11-26 16:13:05 +00:00
										 |  |  | { | 
					
						
							|  |  |  |   GBufferedOutputStreamPrivate *priv; | 
					
						
							|  |  |  |   guint8 *buffer; | 
					
						
							|  |  |  |    | 
					
						
							|  |  |  |   g_return_if_fail (G_IS_BUFFERED_OUTPUT_STREAM (stream)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   priv = stream->priv; | 
					
						
							|  |  |  |    | 
					
						
							| 
									
										
										
										
											2007-12-01 05:25:40 +00:00
										 |  |  |   if (size == priv->len) | 
					
						
							|  |  |  |     return; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-11-26 16:13:05 +00:00
										 |  |  |   if (priv->buffer) | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2020-11-16 21:51:34 +01:00
										 |  |  |       size = (priv->pos > 0) ? MAX (size, (gsize) priv->pos) : size; | 
					
						
							| 
									
										
										
										
											2007-11-26 16:13:05 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |       buffer = g_malloc (size); | 
					
						
							|  |  |  |       memcpy (buffer, priv->buffer, priv->pos); | 
					
						
							|  |  |  |       g_free (priv->buffer); | 
					
						
							|  |  |  |       priv->buffer = buffer; | 
					
						
							|  |  |  |       priv->len = size; | 
					
						
							|  |  |  |       /* Keep old pos */ | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   else | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       priv->buffer = g_malloc (size); | 
					
						
							|  |  |  |       priv->len = size; | 
					
						
							|  |  |  |       priv->pos = 0; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2007-12-01 05:25:40 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   g_object_notify (G_OBJECT (stream), "buffer-size"); | 
					
						
							| 
									
										
										
										
											2007-11-26 16:13:05 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /**
 | 
					
						
							|  |  |  |  * g_buffered_output_stream_get_auto_grow: | 
					
						
							| 
									
										
										
										
											2024-07-09 18:03:03 +05:30
										 |  |  |  * @stream: a [class@Gio.BufferedOutputStream]. | 
					
						
							| 
									
										
										
										
											2007-11-26 16:13:05 +00:00
										 |  |  |  *  | 
					
						
							| 
									
										
										
										
											2007-11-27 14:00:13 +00:00
										 |  |  |  * Checks if the buffer automatically grows as data is added. | 
					
						
							|  |  |  |  *  | 
					
						
							| 
									
										
										
										
											2024-07-09 18:03:03 +05:30
										 |  |  |  * Returns: `TRUE` if the @stream's buffer automatically grows, | 
					
						
							|  |  |  |  * `FALSE` otherwise. | 
					
						
							| 
									
										
										
										
											2007-11-26 16:13:05 +00:00
										 |  |  |  **/   | 
					
						
							|  |  |  | gboolean | 
					
						
							|  |  |  | g_buffered_output_stream_get_auto_grow (GBufferedOutputStream *stream) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   g_return_val_if_fail (G_IS_BUFFERED_OUTPUT_STREAM (stream), FALSE); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return stream->priv->auto_grow; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /**
 | 
					
						
							|  |  |  |  * g_buffered_output_stream_set_auto_grow: | 
					
						
							| 
									
										
										
										
											2024-07-09 18:03:03 +05:30
										 |  |  |  * @stream: a [class@Gio.BufferedOutputStream]. | 
					
						
							| 
									
										
										
										
											2007-11-27 14:00:13 +00:00
										 |  |  |  * @auto_grow: a #gboolean. | 
					
						
							| 
									
										
										
										
											2007-11-26 16:13:05 +00:00
										 |  |  |  * | 
					
						
							|  |  |  |  * Sets whether or not the @stream's buffer should automatically grow. | 
					
						
							| 
									
										
										
										
											2007-12-12 12:19:02 +00:00
										 |  |  |  * If @auto_grow is true, then each write will just make the buffer | 
					
						
							|  |  |  |  * larger, and you must manually flush the buffer to actually write out | 
					
						
							|  |  |  |  * the data to the underlying stream. | 
					
						
							| 
									
										
										
										
											2007-11-26 16:13:05 +00:00
										 |  |  |  **/ | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | g_buffered_output_stream_set_auto_grow (GBufferedOutputStream *stream, | 
					
						
							| 
									
										
										
										
											2007-12-01 05:25:40 +00:00
										 |  |  |                                         gboolean               auto_grow) | 
					
						
							| 
									
										
										
										
											2007-11-26 16:13:05 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2007-12-01 05:25:40 +00:00
										 |  |  |   GBufferedOutputStreamPrivate *priv; | 
					
						
							| 
									
										
										
										
											2007-11-26 16:13:05 +00:00
										 |  |  |   g_return_if_fail (G_IS_BUFFERED_OUTPUT_STREAM (stream)); | 
					
						
							| 
									
										
										
										
											2007-12-01 05:25:40 +00:00
										 |  |  |   priv = stream->priv; | 
					
						
							|  |  |  |   auto_grow = auto_grow != FALSE; | 
					
						
							|  |  |  |   if (priv->auto_grow != auto_grow) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       priv->auto_grow = auto_grow; | 
					
						
							|  |  |  |       g_object_notify (G_OBJECT (stream), "auto-grow"); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2007-11-26 16:13:05 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							| 
									
										
										
										
											2007-12-01 05:25:40 +00:00
										 |  |  | g_buffered_output_stream_set_property (GObject      *object, | 
					
						
							|  |  |  |                                        guint         prop_id, | 
					
						
							|  |  |  |                                        const GValue *value, | 
					
						
							|  |  |  |                                        GParamSpec   *pspec) | 
					
						
							| 
									
										
										
										
											2007-11-26 16:13:05 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2007-12-01 05:25:40 +00:00
										 |  |  |   GBufferedOutputStream *stream; | 
					
						
							| 
									
										
										
										
											2007-11-26 16:13:05 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-12-01 05:25:40 +00:00
										 |  |  |   stream = G_BUFFERED_OUTPUT_STREAM (object); | 
					
						
							| 
									
										
										
										
											2007-11-26 16:13:05 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   switch (prop_id)  | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |     case PROP_BUFSIZE: | 
					
						
							| 
									
										
										
										
											2007-12-01 05:25:40 +00:00
										 |  |  |       g_buffered_output_stream_set_buffer_size (stream, g_value_get_uint (value)); | 
					
						
							| 
									
										
										
										
											2007-11-26 16:13:05 +00:00
										 |  |  |       break;     | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-12-01 05:25:40 +00:00
										 |  |  |     case PROP_AUTO_GROW: | 
					
						
							|  |  |  |       g_buffered_output_stream_set_auto_grow (stream, g_value_get_boolean (value)); | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-11-26 16:13:05 +00:00
										 |  |  |     default: | 
					
						
							|  |  |  |       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | g_buffered_output_stream_get_property (GObject    *object, | 
					
						
							|  |  |  |                                        guint       prop_id, | 
					
						
							|  |  |  |                                        GValue     *value, | 
					
						
							|  |  |  |                                        GParamSpec *pspec) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   GBufferedOutputStream *buffered_stream; | 
					
						
							|  |  |  |   GBufferedOutputStreamPrivate *priv; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   buffered_stream = G_BUFFERED_OUTPUT_STREAM (object); | 
					
						
							|  |  |  |   priv = buffered_stream->priv; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   switch (prop_id) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |     case PROP_BUFSIZE: | 
					
						
							|  |  |  |       g_value_set_uint (value, priv->len); | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-12-01 05:25:40 +00:00
										 |  |  |     case PROP_AUTO_GROW: | 
					
						
							|  |  |  |       g_value_set_boolean (value, priv->auto_grow); | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-11-26 16:13:05 +00:00
										 |  |  |     default: | 
					
						
							|  |  |  |       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | g_buffered_output_stream_finalize (GObject *object) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   GBufferedOutputStream *stream; | 
					
						
							|  |  |  |   GBufferedOutputStreamPrivate *priv; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   stream = G_BUFFERED_OUTPUT_STREAM (object); | 
					
						
							|  |  |  |   priv = stream->priv; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   g_free (priv->buffer); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-06-16 09:54:04 +00:00
										 |  |  |   G_OBJECT_CLASS (g_buffered_output_stream_parent_class)->finalize (object); | 
					
						
							| 
									
										
										
										
											2007-11-26 16:13:05 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | g_buffered_output_stream_init (GBufferedOutputStream *stream) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2013-06-24 15:43:04 +01:00
										 |  |  |   stream->priv = g_buffered_output_stream_get_instance_private (stream); | 
					
						
							| 
									
										
										
										
											2007-11-26 16:13:05 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-29 01:50:41 +02:00
										 |  |  | static void | 
					
						
							|  |  |  | g_buffered_output_stream_seekable_iface_init (GSeekableIface *iface) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   iface->tell         = g_buffered_output_stream_tell; | 
					
						
							|  |  |  |   iface->can_seek     = g_buffered_output_stream_can_seek; | 
					
						
							|  |  |  |   iface->seek         = g_buffered_output_stream_seek; | 
					
						
							|  |  |  |   iface->can_truncate = g_buffered_output_stream_can_truncate; | 
					
						
							|  |  |  |   iface->truncate_fn  = g_buffered_output_stream_truncate; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-11-26 16:13:05 +00:00
										 |  |  | /**
 | 
					
						
							|  |  |  |  * g_buffered_output_stream_new: | 
					
						
							| 
									
										
										
										
											2024-07-09 18:03:03 +05:30
										 |  |  |  * @base_stream: a [class@Gio.OutputStream]. | 
					
						
							| 
									
										
										
										
											2007-11-26 16:13:05 +00:00
										 |  |  |  *  | 
					
						
							| 
									
										
										
										
											2007-11-27 14:00:13 +00:00
										 |  |  |  * Creates a new buffered output stream for a base stream. | 
					
						
							|  |  |  |  *  | 
					
						
							| 
									
										
										
										
											2024-07-09 18:03:03 +05:30
										 |  |  |  * Returns: a [class@Gio.OutputStream] for the given @base_stream. | 
					
						
							| 
									
										
										
										
											2007-11-26 16:13:05 +00:00
										 |  |  |  **/   | 
					
						
							|  |  |  | GOutputStream * | 
					
						
							|  |  |  | g_buffered_output_stream_new (GOutputStream *base_stream) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   GOutputStream *stream; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   g_return_val_if_fail (G_IS_OUTPUT_STREAM (base_stream), NULL); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   stream = g_object_new (G_TYPE_BUFFERED_OUTPUT_STREAM, | 
					
						
							|  |  |  |                          "base-stream", base_stream, | 
					
						
							|  |  |  |                          NULL); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return stream; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /**
 | 
					
						
							|  |  |  |  * g_buffered_output_stream_new_sized: | 
					
						
							| 
									
										
										
										
											2024-07-09 18:03:03 +05:30
										 |  |  |  * @base_stream: a [class@Gio.OutputStream]. | 
					
						
							| 
									
										
										
										
											2007-11-26 16:13:05 +00:00
										 |  |  |  * @size: a #gsize. | 
					
						
							|  |  |  |  *  | 
					
						
							| 
									
										
										
										
											2007-11-27 14:00:13 +00:00
										 |  |  |  * Creates a new buffered output stream with a given buffer size. | 
					
						
							|  |  |  |  *  | 
					
						
							| 
									
										
										
										
											2024-07-09 18:03:03 +05:30
										 |  |  |  * Returns: a [class@Gio.OutputStream] with an internal buffer set to @size. | 
					
						
							| 
									
										
										
										
											2007-11-26 16:13:05 +00:00
										 |  |  |  **/   | 
					
						
							|  |  |  | GOutputStream * | 
					
						
							|  |  |  | g_buffered_output_stream_new_sized (GOutputStream *base_stream, | 
					
						
							| 
									
										
										
										
											2008-02-04 10:04:40 +00:00
										 |  |  |                                     gsize          size) | 
					
						
							| 
									
										
										
										
											2007-11-26 16:13:05 +00:00
										 |  |  | { | 
					
						
							|  |  |  |   GOutputStream *stream; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   g_return_val_if_fail (G_IS_OUTPUT_STREAM (base_stream), NULL); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   stream = g_object_new (G_TYPE_BUFFERED_OUTPUT_STREAM, | 
					
						
							|  |  |  |                          "base-stream", base_stream, | 
					
						
							|  |  |  |                          "buffer-size", size, | 
					
						
							|  |  |  |                          NULL); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return stream; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static gboolean | 
					
						
							|  |  |  | flush_buffer (GBufferedOutputStream  *stream, | 
					
						
							|  |  |  |               GCancellable           *cancellable, | 
					
						
							|  |  |  |               GError                 **error) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   GBufferedOutputStreamPrivate *priv; | 
					
						
							|  |  |  |   GOutputStream                *base_stream; | 
					
						
							|  |  |  |   gboolean                      res; | 
					
						
							|  |  |  |   gsize                         bytes_written; | 
					
						
							|  |  |  |   gsize                         count; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   priv = stream->priv; | 
					
						
							|  |  |  |   bytes_written = 0; | 
					
						
							|  |  |  |   base_stream = G_FILTER_OUTPUT_STREAM (stream)->base_stream; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   g_return_val_if_fail (G_IS_OUTPUT_STREAM (base_stream), FALSE); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   res = g_output_stream_write_all (base_stream, | 
					
						
							|  |  |  |                                    priv->buffer, | 
					
						
							|  |  |  |                                    priv->pos, | 
					
						
							|  |  |  |                                    &bytes_written, | 
					
						
							|  |  |  |                                    cancellable, | 
					
						
							|  |  |  |                                    error); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   count = priv->pos - bytes_written; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (count > 0) | 
					
						
							| 
									
										
										
											
												Require C90 compliance
Assume all supported platforms implement C90, and therefore they
(correctly) implement atexit(), memmove(), setlocale(), strerror(),
and vprintf(), and have <float.h> and <limits.h>.
(Also remove the configure check testing that "do ... while (0)" works
correctly; the non-do/while-based version of G_STMT_START and
G_STMT_END was removed years ago, but the check remained. Also, remove
some checks that configure.ac claimed were needed for libcharset, but
aren't actually used.)
Note that removing the g_memmove() function is not an ABI break even
on systems where g_memmove() was previously not a macro, because it
was never marked GLIB_AVAILABLE_IN_ALL or listed in glib.symbols, so
it would have been glib-internal since 2004.
https://bugzilla.gnome.org/show_bug.cgi?id=710519
											
										 
											2013-10-19 13:03:58 -04:00
										 |  |  |     memmove (priv->buffer, priv->buffer + bytes_written, count); | 
					
						
							| 
									
										
										
										
											2007-11-26 16:13:05 +00:00
										 |  |  |    | 
					
						
							|  |  |  |   priv->pos -= bytes_written; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return res; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static gssize | 
					
						
							|  |  |  | g_buffered_output_stream_write  (GOutputStream *stream, | 
					
						
							|  |  |  |                                  const void    *buffer, | 
					
						
							|  |  |  |                                  gsize          count, | 
					
						
							|  |  |  |                                  GCancellable  *cancellable, | 
					
						
							|  |  |  |                                  GError       **error) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   GBufferedOutputStream        *bstream; | 
					
						
							|  |  |  |   GBufferedOutputStreamPrivate *priv; | 
					
						
							|  |  |  |   gboolean res; | 
					
						
							|  |  |  |   gsize    n; | 
					
						
							|  |  |  |   gsize new_size; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   bstream = G_BUFFERED_OUTPUT_STREAM (stream); | 
					
						
							|  |  |  |   priv = bstream->priv; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   n = priv->len - priv->pos; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (priv->auto_grow && n < count) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       new_size = MAX (priv->len * 2, priv->len + count); | 
					
						
							|  |  |  |       g_buffered_output_stream_set_buffer_size (bstream, new_size); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   else if (n == 0) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       res = flush_buffer (bstream, cancellable, error); | 
					
						
							|  |  |  |        | 
					
						
							|  |  |  |       if (res == FALSE) | 
					
						
							|  |  |  | 	return -1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   n = priv->len - priv->pos; | 
					
						
							|  |  |  |    | 
					
						
							|  |  |  |   count = MIN (count, n); | 
					
						
							|  |  |  |   memcpy (priv->buffer + priv->pos, buffer, count); | 
					
						
							|  |  |  |   priv->pos += count; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return count; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static gboolean | 
					
						
							|  |  |  | g_buffered_output_stream_flush (GOutputStream  *stream, | 
					
						
							|  |  |  |                                 GCancellable   *cancellable, | 
					
						
							|  |  |  |                                 GError        **error) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   GBufferedOutputStream *bstream; | 
					
						
							|  |  |  |   GOutputStream                *base_stream; | 
					
						
							|  |  |  |   gboolean res; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   bstream = G_BUFFERED_OUTPUT_STREAM (stream); | 
					
						
							|  |  |  |   base_stream = G_FILTER_OUTPUT_STREAM (stream)->base_stream; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   res = flush_buffer (bstream, cancellable, error); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-11-30 05:11:25 +00:00
										 |  |  |   if (res == FALSE) | 
					
						
							| 
									
										
										
										
											2007-11-26 16:13:05 +00:00
										 |  |  |     return FALSE; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-11-30 05:11:25 +00:00
										 |  |  |   res = g_output_stream_flush (base_stream, cancellable, error); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-11-26 16:13:05 +00:00
										 |  |  |   return res; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static gboolean | 
					
						
							|  |  |  | g_buffered_output_stream_close (GOutputStream  *stream, | 
					
						
							|  |  |  |                                 GCancellable   *cancellable, | 
					
						
							|  |  |  |                                 GError        **error) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   GBufferedOutputStream        *bstream; | 
					
						
							|  |  |  |   GOutputStream                *base_stream; | 
					
						
							|  |  |  |   gboolean                      res; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   bstream = G_BUFFERED_OUTPUT_STREAM (stream); | 
					
						
							|  |  |  |   base_stream = G_FILTER_OUTPUT_STREAM (bstream)->base_stream; | 
					
						
							|  |  |  |   res = flush_buffer (bstream, cancellable, error); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-21 14:09:56 +00:00
										 |  |  |   if (g_filter_output_stream_get_close_base_stream (G_FILTER_OUTPUT_STREAM (stream))) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       /* report the first error but still close the stream */ | 
					
						
							|  |  |  |       if (res) | 
					
						
							| 
									
										
										
										
											2009-09-09 00:18:23 -04:00
										 |  |  |         res = g_output_stream_close (base_stream, cancellable, error); | 
					
						
							| 
									
										
										
										
											2009-01-21 14:09:56 +00:00
										 |  |  |       else | 
					
						
							| 
									
										
										
										
											2009-09-09 00:18:23 -04:00
										 |  |  |         g_output_stream_close (base_stream, cancellable, NULL); | 
					
						
							| 
									
										
										
										
											2009-01-21 14:09:56 +00:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2007-11-26 16:13:05 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   return res; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-29 01:50:41 +02:00
										 |  |  | static goffset | 
					
						
							|  |  |  | g_buffered_output_stream_tell (GSeekable *seekable) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   GBufferedOutputStream        *bstream; | 
					
						
							|  |  |  |   GBufferedOutputStreamPrivate *priv; | 
					
						
							|  |  |  |   GOutputStream *base_stream; | 
					
						
							|  |  |  |   GSeekable    *base_stream_seekable; | 
					
						
							|  |  |  |   goffset base_offset; | 
					
						
							|  |  |  |    | 
					
						
							|  |  |  |   bstream = G_BUFFERED_OUTPUT_STREAM (seekable); | 
					
						
							|  |  |  |   priv = bstream->priv; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   base_stream = G_FILTER_OUTPUT_STREAM (seekable)->base_stream; | 
					
						
							|  |  |  |   if (!G_IS_SEEKABLE (base_stream)) | 
					
						
							|  |  |  |     return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   base_stream_seekable = G_SEEKABLE (base_stream); | 
					
						
							|  |  |  |    | 
					
						
							|  |  |  |   base_offset = g_seekable_tell (base_stream_seekable); | 
					
						
							|  |  |  |   return base_offset + priv->pos; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static gboolean | 
					
						
							|  |  |  | g_buffered_output_stream_can_seek (GSeekable *seekable) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   GOutputStream *base_stream; | 
					
						
							|  |  |  |    | 
					
						
							|  |  |  |   base_stream = G_FILTER_OUTPUT_STREAM (seekable)->base_stream; | 
					
						
							|  |  |  |   return G_IS_SEEKABLE (base_stream) && g_seekable_can_seek (G_SEEKABLE (base_stream)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static gboolean | 
					
						
							|  |  |  | g_buffered_output_stream_seek (GSeekable     *seekable, | 
					
						
							|  |  |  | 			       goffset        offset, | 
					
						
							|  |  |  | 			       GSeekType      type, | 
					
						
							|  |  |  | 			       GCancellable  *cancellable, | 
					
						
							|  |  |  | 			       GError       **error) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   GBufferedOutputStream *bstream; | 
					
						
							|  |  |  |   GOutputStream *base_stream; | 
					
						
							|  |  |  |   GSeekable *base_stream_seekable; | 
					
						
							|  |  |  |   gboolean flushed; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   bstream = G_BUFFERED_OUTPUT_STREAM (seekable); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   base_stream = G_FILTER_OUTPUT_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); | 
					
						
							|  |  |  |   flushed = flush_buffer (bstream, cancellable, error); | 
					
						
							|  |  |  |   if (!flushed) | 
					
						
							|  |  |  |     return FALSE; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return g_seekable_seek (base_stream_seekable, offset, type, cancellable, error); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static gboolean | 
					
						
							|  |  |  | g_buffered_output_stream_can_truncate (GSeekable *seekable) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   GOutputStream *base_stream; | 
					
						
							|  |  |  |    | 
					
						
							|  |  |  |   base_stream = G_FILTER_OUTPUT_STREAM (seekable)->base_stream; | 
					
						
							|  |  |  |   return G_IS_SEEKABLE (base_stream) && g_seekable_can_truncate (G_SEEKABLE (base_stream)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static gboolean | 
					
						
							|  |  |  | g_buffered_output_stream_truncate (GSeekable     *seekable, | 
					
						
							|  |  |  | 				   goffset        offset, | 
					
						
							|  |  |  | 				   GCancellable  *cancellable, | 
					
						
							|  |  |  | 				   GError       **error) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   GBufferedOutputStream        *bstream; | 
					
						
							|  |  |  |   GOutputStream *base_stream; | 
					
						
							|  |  |  |   GSeekable *base_stream_seekable; | 
					
						
							|  |  |  |   gboolean flushed; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   bstream = G_BUFFERED_OUTPUT_STREAM (seekable); | 
					
						
							|  |  |  |   base_stream = G_FILTER_OUTPUT_STREAM (seekable)->base_stream; | 
					
						
							|  |  |  |   if (!G_IS_SEEKABLE (base_stream)) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, | 
					
						
							|  |  |  |                            _("Truncate not supported on base stream")); | 
					
						
							|  |  |  |       return FALSE; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   base_stream_seekable = G_SEEKABLE (base_stream); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   flushed = flush_buffer (bstream, cancellable, error); | 
					
						
							|  |  |  |   if (!flushed) | 
					
						
							|  |  |  |     return FALSE; | 
					
						
							|  |  |  |   return g_seekable_truncate (base_stream_seekable, offset, cancellable, error); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-11-26 16:13:05 +00:00
										 |  |  | /* ************************** */ | 
					
						
							|  |  |  | /* Async stuff implementation */ | 
					
						
							|  |  |  | /* ************************** */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* TODO: This should be using the base class async ops, not threads */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | typedef struct { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   guint flush_stream : 1; | 
					
						
							|  |  |  |   guint close_stream : 1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } FlushData; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | free_flush_data (gpointer data) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   g_slice_free (FlushData, data); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* This function is used by all three (i.e. 
 | 
					
						
							|  |  |  |  * _write, _flush, _close) functions since | 
					
						
							|  |  |  |  * all of them will need to flush the buffer | 
					
						
							|  |  |  |  * and so closing and writing is just a special | 
					
						
							|  |  |  |  * case of flushing + some addition stuff */ | 
					
						
							|  |  |  | static void | 
					
						
							| 
									
										
										
										
											2012-08-02 15:49:59 -04:00
										 |  |  | flush_buffer_thread (GTask        *task, | 
					
						
							|  |  |  |                      gpointer      object, | 
					
						
							|  |  |  |                      gpointer      task_data, | 
					
						
							|  |  |  |                      GCancellable *cancellable) | 
					
						
							| 
									
										
										
										
											2007-11-26 16:13:05 +00:00
										 |  |  | { | 
					
						
							|  |  |  |   GBufferedOutputStream *stream; | 
					
						
							|  |  |  |   GOutputStream *base_stream; | 
					
						
							|  |  |  |   FlushData     *fdata; | 
					
						
							|  |  |  |   gboolean       res; | 
					
						
							|  |  |  |   GError        *error = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   stream = G_BUFFERED_OUTPUT_STREAM (object); | 
					
						
							| 
									
										
										
										
											2012-08-02 15:49:59 -04:00
										 |  |  |   fdata = task_data; | 
					
						
							| 
									
										
										
										
											2007-11-26 16:13:05 +00:00
										 |  |  |   base_stream = G_FILTER_OUTPUT_STREAM (stream)->base_stream; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   res = flush_buffer (stream, cancellable, &error); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* if flushing the buffer didn't work don't even bother
 | 
					
						
							|  |  |  |    * to flush the stream but just report that error */ | 
					
						
							|  |  |  |   if (res && fdata->flush_stream) | 
					
						
							| 
									
										
										
										
											2007-11-30 05:11:25 +00:00
										 |  |  |     res = g_output_stream_flush (base_stream, cancellable, &error); | 
					
						
							| 
									
										
										
										
											2007-11-26 16:13:05 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   if (fdata->close_stream)  | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       | 
					
						
							|  |  |  |       /* if flushing the buffer or the stream returned 
 | 
					
						
							|  |  |  |        * an error report that first error but still try  | 
					
						
							|  |  |  |        * close the stream */ | 
					
						
							| 
									
										
										
										
											2009-01-21 14:09:56 +00:00
										 |  |  |       if (g_filter_output_stream_get_close_base_stream (G_FILTER_OUTPUT_STREAM (stream))) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |           if (res == FALSE) | 
					
						
							|  |  |  |             g_output_stream_close (base_stream, cancellable, NULL); | 
					
						
							|  |  |  |           else  | 
					
						
							|  |  |  |             res = g_output_stream_close (base_stream, cancellable, &error); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2007-11-26 16:13:05 +00:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (res == FALSE) | 
					
						
							| 
									
										
										
										
											2012-08-02 15:49:59 -04:00
										 |  |  |     g_task_return_error (task, error); | 
					
						
							|  |  |  |   else | 
					
						
							|  |  |  |     g_task_return_boolean (task, TRUE); | 
					
						
							| 
									
										
										
										
											2007-11-26 16:13:05 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | g_buffered_output_stream_flush_async (GOutputStream        *stream, | 
					
						
							|  |  |  |                                       int                   io_priority, | 
					
						
							|  |  |  |                                       GCancellable         *cancellable, | 
					
						
							|  |  |  |                                       GAsyncReadyCallback   callback, | 
					
						
							|  |  |  |                                       gpointer              data) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2012-08-02 15:49:59 -04:00
										 |  |  |   GTask *task; | 
					
						
							|  |  |  |   FlushData *fdata; | 
					
						
							| 
									
										
										
										
											2007-11-26 16:13:05 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-27 09:51:12 +01:00
										 |  |  |   fdata = g_slice_new0 (FlushData); | 
					
						
							| 
									
										
										
										
											2007-11-26 16:13:05 +00:00
										 |  |  |   fdata->flush_stream = TRUE; | 
					
						
							|  |  |  |   fdata->close_stream = FALSE; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-02 15:49:59 -04:00
										 |  |  |   task = g_task_new (stream, cancellable, callback, data); | 
					
						
							| 
									
										
										
										
											2016-06-16 19:39:38 -04:00
										 |  |  |   g_task_set_source_tag (task, g_buffered_output_stream_flush_async); | 
					
						
							| 
									
										
										
										
											2012-08-02 15:49:59 -04:00
										 |  |  |   g_task_set_task_data (task, fdata, free_flush_data); | 
					
						
							|  |  |  |   g_task_set_priority (task, io_priority); | 
					
						
							| 
									
										
										
										
											2007-11-26 16:13:05 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-02 15:49:59 -04:00
										 |  |  |   g_task_run_in_thread (task, flush_buffer_thread); | 
					
						
							|  |  |  |   g_object_unref (task); | 
					
						
							| 
									
										
										
										
											2007-11-26 16:13:05 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static gboolean | 
					
						
							|  |  |  | g_buffered_output_stream_flush_finish (GOutputStream        *stream, | 
					
						
							|  |  |  |                                        GAsyncResult         *result, | 
					
						
							|  |  |  |                                        GError              **error) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2012-08-02 15:49:59 -04:00
										 |  |  |   g_return_val_if_fail (g_task_is_valid (result, stream), FALSE); | 
					
						
							| 
									
										
										
										
											2007-11-26 16:13:05 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-02 15:49:59 -04:00
										 |  |  |   return g_task_propagate_boolean (G_TASK (result), error); | 
					
						
							| 
									
										
										
										
											2007-11-26 16:13:05 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | g_buffered_output_stream_close_async (GOutputStream        *stream, | 
					
						
							|  |  |  |                                       int                   io_priority, | 
					
						
							|  |  |  |                                       GCancellable         *cancellable, | 
					
						
							|  |  |  |                                       GAsyncReadyCallback   callback, | 
					
						
							|  |  |  |                                       gpointer              data) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2012-08-02 15:49:59 -04:00
										 |  |  |   GTask *task; | 
					
						
							|  |  |  |   FlushData *fdata; | 
					
						
							| 
									
										
										
										
											2007-11-26 16:13:05 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-27 09:51:12 +01:00
										 |  |  |   fdata = g_slice_new0 (FlushData); | 
					
						
							| 
									
										
										
										
											2007-11-26 16:13:05 +00:00
										 |  |  |   fdata->close_stream = TRUE; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-02 15:49:59 -04:00
										 |  |  |   task = g_task_new (stream, cancellable, callback, data); | 
					
						
							| 
									
										
										
										
											2016-06-16 19:39:38 -04:00
										 |  |  |   g_task_set_source_tag (task, g_buffered_output_stream_close_async); | 
					
						
							| 
									
										
										
										
											2012-08-02 15:49:59 -04:00
										 |  |  |   g_task_set_task_data (task, fdata, free_flush_data); | 
					
						
							|  |  |  |   g_task_set_priority (task, io_priority); | 
					
						
							| 
									
										
										
										
											2007-11-26 16:13:05 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-02 15:49:59 -04:00
										 |  |  |   g_task_run_in_thread (task, flush_buffer_thread); | 
					
						
							|  |  |  |   g_object_unref (task); | 
					
						
							| 
									
										
										
										
											2007-11-26 16:13:05 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static gboolean | 
					
						
							|  |  |  | g_buffered_output_stream_close_finish (GOutputStream        *stream, | 
					
						
							|  |  |  |                                        GAsyncResult         *result, | 
					
						
							|  |  |  |                                        GError              **error) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2012-08-02 15:49:59 -04:00
										 |  |  |   g_return_val_if_fail (g_task_is_valid (result, stream), FALSE); | 
					
						
							| 
									
										
										
										
											2007-11-26 16:13:05 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-02 15:49:59 -04:00
										 |  |  |   return g_task_propagate_boolean (G_TASK (result), error); | 
					
						
							| 
									
										
										
										
											2007-11-26 16:13:05 +00:00
										 |  |  | } |