LCOV - code coverage report
Current view: top level - gio - ginputstream.c (source / functions) Coverage Total Hit
Test: unnamed Lines: 74.8 % 465 348
Test Date: 2024-11-26 05:23:01 Functions: 91.7 % 48 44
Branches: - 0 0

             Branch data     Line data    Source code
       1                 :             : /* GIO - GLib Input, Output and Streaming Library
       2                 :             :  * 
       3                 :             :  * Copyright (C) 2006-2007 Red Hat, Inc.
       4                 :             :  *
       5                 :             :  * SPDX-License-Identifier: LGPL-2.1-or-later
       6                 :             :  *
       7                 :             :  * This library is free software; you can redistribute it and/or
       8                 :             :  * modify it under the terms of the GNU Lesser General Public
       9                 :             :  * License as published by the Free Software Foundation; either
      10                 :             :  * version 2.1 of the License, or (at your option) any later version.
      11                 :             :  *
      12                 :             :  * This library is distributed in the hope that it will be useful,
      13                 :             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      14                 :             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      15                 :             :  * Lesser General Public License for more details.
      16                 :             :  *
      17                 :             :  * You should have received a copy of the GNU Lesser General
      18                 :             :  * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
      19                 :             :  *
      20                 :             :  * Author: Alexander Larsson <alexl@redhat.com>
      21                 :             :  */
      22                 :             : 
      23                 :             : #include "config.h"
      24                 :             : #include <glib.h>
      25                 :             : #include "glibintl.h"
      26                 :             : 
      27                 :             : #include "ginputstream.h"
      28                 :             : #include "gioprivate.h"
      29                 :             : #include "gseekable.h"
      30                 :             : #include "gcancellable.h"
      31                 :             : #include "gasyncresult.h"
      32                 :             : #include "gioerror.h"
      33                 :             : #include "gpollableinputstream.h"
      34                 :             : 
      35                 :             : /**
      36                 :             :  * GInputStream:
      37                 :             :  *
      38                 :             :  * `GInputStream` is a base class for implementing streaming input.
      39                 :             :  *
      40                 :             :  * It has functions to read from a stream ([method@Gio.InputStream.read]),
      41                 :             :  * to close a stream ([method@Gio.InputStream.close]) and to skip some content
      42                 :             :  * ([method@Gio.InputStream.skip]).
      43                 :             :  *
      44                 :             :  * To copy the content of an input stream to an output stream without 
      45                 :             :  * manually handling the reads and writes, use [method@Gio.OutputStream.splice].
      46                 :             :  *
      47                 :             :  * See the documentation for [class@Gio.IOStream] for details of thread safety
      48                 :             :  * of streaming APIs.
      49                 :             :  *
      50                 :             :  * All of these functions have async variants too.
      51                 :             :  **/
      52                 :             : 
      53                 :             : struct _GInputStreamPrivate {
      54                 :             :   guint closed : 1;
      55                 :             :   guint pending : 1;
      56                 :             :   GAsyncReadyCallback outstanding_callback;
      57                 :             : };
      58                 :             : 
      59                 :     6002382 : G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (GInputStream, g_input_stream, G_TYPE_OBJECT)
      60                 :             : 
      61                 :             : static gssize   g_input_stream_real_skip         (GInputStream         *stream,
      62                 :             :                                                   gsize                 count,
      63                 :             :                                                   GCancellable         *cancellable,
      64                 :             :                                                   GError              **error);
      65                 :             : static void     g_input_stream_real_read_async   (GInputStream         *stream,
      66                 :             :                                                   void                 *buffer,
      67                 :             :                                                   gsize                 count,
      68                 :             :                                                   int                   io_priority,
      69                 :             :                                                   GCancellable         *cancellable,
      70                 :             :                                                   GAsyncReadyCallback   callback,
      71                 :             :                                                   gpointer              user_data);
      72                 :             : static gssize   g_input_stream_real_read_finish  (GInputStream         *stream,
      73                 :             :                                                   GAsyncResult         *result,
      74                 :             :                                                   GError              **error);
      75                 :             : static void     g_input_stream_real_skip_async   (GInputStream         *stream,
      76                 :             :                                                   gsize                 count,
      77                 :             :                                                   int                   io_priority,
      78                 :             :                                                   GCancellable         *cancellable,
      79                 :             :                                                   GAsyncReadyCallback   callback,
      80                 :             :                                                   gpointer              data);
      81                 :             : static gssize   g_input_stream_real_skip_finish  (GInputStream         *stream,
      82                 :             :                                                   GAsyncResult         *result,
      83                 :             :                                                   GError              **error);
      84                 :             : static void     g_input_stream_real_close_async  (GInputStream         *stream,
      85                 :             :                                                   int                   io_priority,
      86                 :             :                                                   GCancellable         *cancellable,
      87                 :             :                                                   GAsyncReadyCallback   callback,
      88                 :             :                                                   gpointer              data);
      89                 :             : static gboolean g_input_stream_real_close_finish (GInputStream         *stream,
      90                 :             :                                                   GAsyncResult         *result,
      91                 :             :                                                   GError              **error);
      92                 :             : 
      93                 :             : static void
      94                 :        4370 : g_input_stream_dispose (GObject *object)
      95                 :             : {
      96                 :             :   GInputStream *stream;
      97                 :             : 
      98                 :        4370 :   stream = G_INPUT_STREAM (object);
      99                 :             :   
     100                 :        4370 :   if (!stream->priv->closed)
     101                 :        1944 :     g_input_stream_close (stream, NULL, NULL);
     102                 :             : 
     103                 :        4370 :   G_OBJECT_CLASS (g_input_stream_parent_class)->dispose (object);
     104                 :        4370 : }
     105                 :             : 
     106                 :             : 
     107                 :             : static void
     108                 :         156 : g_input_stream_class_init (GInputStreamClass *klass)
     109                 :             : {
     110                 :         156 :   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
     111                 :             :   
     112                 :         156 :   gobject_class->dispose = g_input_stream_dispose;
     113                 :             :   
     114                 :         156 :   klass->skip = g_input_stream_real_skip;
     115                 :         156 :   klass->read_async = g_input_stream_real_read_async;
     116                 :         156 :   klass->read_finish = g_input_stream_real_read_finish;
     117                 :         156 :   klass->skip_async = g_input_stream_real_skip_async;
     118                 :         156 :   klass->skip_finish = g_input_stream_real_skip_finish;
     119                 :         156 :   klass->close_async = g_input_stream_real_close_async;
     120                 :         156 :   klass->close_finish = g_input_stream_real_close_finish;
     121                 :         156 : }
     122                 :             : 
     123                 :             : static void
     124                 :        4645 : g_input_stream_init (GInputStream *stream)
     125                 :             : {
     126                 :        4645 :   stream->priv = g_input_stream_get_instance_private (stream);
     127                 :        4645 : }
     128                 :             : 
     129                 :             : /**
     130                 :             :  * g_input_stream_read:
     131                 :             :  * @stream: a #GInputStream.
     132                 :             :  * @buffer: (array length=count) (element-type guint8) (out caller-allocates):
     133                 :             :  *   a buffer to read data into (which should be at least count bytes long).
     134                 :             :  * @count: (in): the number of bytes that will be read from the stream
     135                 :             :  * @cancellable: (nullable): optional #GCancellable object, %NULL to ignore.
     136                 :             :  * @error: location to store the error occurring, or %NULL to ignore
     137                 :             :  *
     138                 :             :  * Tries to read @count bytes from the stream into the buffer starting at
     139                 :             :  * @buffer. Will block during this read.
     140                 :             :  * 
     141                 :             :  * If count is zero returns zero and does nothing. A value of @count
     142                 :             :  * larger than %G_MAXSSIZE will cause a %G_IO_ERROR_INVALID_ARGUMENT error.
     143                 :             :  *
     144                 :             :  * On success, the number of bytes read into the buffer is returned.
     145                 :             :  * It is not an error if this is not the same as the requested size, as it
     146                 :             :  * can happen e.g. near the end of a file. Zero is returned on end of file
     147                 :             :  * (or if @count is zero),  but never otherwise.
     148                 :             :  *
     149                 :             :  * The returned @buffer is not a nul-terminated string, it can contain nul bytes
     150                 :             :  * at any position, and this function doesn't nul-terminate the @buffer.
     151                 :             :  *
     152                 :             :  * If @cancellable is not %NULL, then the operation can be cancelled by
     153                 :             :  * triggering the cancellable object from another thread. If the operation
     154                 :             :  * was cancelled, the error %G_IO_ERROR_CANCELLED will be returned. If an
     155                 :             :  * operation was partially finished when the operation was cancelled the
     156                 :             :  * partial result will be returned, without an error.
     157                 :             :  *
     158                 :             :  * On error -1 is returned and @error is set accordingly.
     159                 :             :  * 
     160                 :             :  * Returns: Number of bytes read, or -1 on error, or 0 on end of file.
     161                 :             :  **/
     162                 :             : gssize
     163                 :     1206800 : g_input_stream_read  (GInputStream  *stream,
     164                 :             :                       void          *buffer,
     165                 :             :                       gsize          count,
     166                 :             :                       GCancellable  *cancellable,
     167                 :             :                       GError       **error)
     168                 :             : {
     169                 :             :   GInputStreamClass *class;
     170                 :             :   gssize res;
     171                 :             : 
     172                 :     1206800 :   g_return_val_if_fail (G_IS_INPUT_STREAM (stream), -1);
     173                 :     1206800 :   g_return_val_if_fail (buffer != NULL, 0);
     174                 :             : 
     175                 :     1206800 :   if (count == 0)
     176                 :           7 :     return 0;
     177                 :             :   
     178                 :     1206793 :   if (((gssize) count) < 0)
     179                 :             :     {
     180                 :           0 :       g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT,
     181                 :             :                    _("Too large count value passed to %s"), G_STRFUNC);
     182                 :           0 :       return -1;
     183                 :             :     }
     184                 :             : 
     185                 :     1206793 :   class = G_INPUT_STREAM_GET_CLASS (stream);
     186                 :             : 
     187                 :     1206793 :   if (class->read_fn == NULL) 
     188                 :             :     {
     189                 :           0 :       g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
     190                 :             :                            _("Input stream doesn’t implement read"));
     191                 :           0 :       return -1;
     192                 :             :     }
     193                 :             : 
     194                 :     1206793 :   if (!g_input_stream_set_pending (stream, error))
     195                 :           0 :     return -1;
     196                 :             : 
     197                 :     1206793 :   if (cancellable)
     198                 :        7000 :     g_cancellable_push_current (cancellable);
     199                 :             :   
     200                 :     1206793 :   res = class->read_fn (stream, buffer, count, cancellable, error);
     201                 :             : 
     202                 :     1206793 :   if (cancellable)
     203                 :        7000 :     g_cancellable_pop_current (cancellable);
     204                 :             :   
     205                 :     1206793 :   g_input_stream_clear_pending (stream);
     206                 :             : 
     207                 :     1206793 :   return res;
     208                 :             : }
     209                 :             : 
     210                 :             : /**
     211                 :             :  * g_input_stream_read_all:
     212                 :             :  * @stream: a #GInputStream.
     213                 :             :  * @buffer: (array length=count) (element-type guint8) (out caller-allocates):
     214                 :             :  *   a buffer to read data into (which should be at least count bytes long).
     215                 :             :  * @count: (in): the number of bytes that will be read from the stream
     216                 :             :  * @bytes_read: (out): location to store the number of bytes that was read from the stream
     217                 :             :  * @cancellable: (nullable): optional #GCancellable object, %NULL to ignore.
     218                 :             :  * @error: location to store the error occurring, or %NULL to ignore
     219                 :             :  *
     220                 :             :  * Tries to read @count bytes from the stream into the buffer starting at
     221                 :             :  * @buffer. Will block during this read.
     222                 :             :  *
     223                 :             :  * This function is similar to g_input_stream_read(), except it tries to
     224                 :             :  * read as many bytes as requested, only stopping on an error or end of stream.
     225                 :             :  *
     226                 :             :  * On a successful read of @count bytes, or if we reached the end of the
     227                 :             :  * stream,  %TRUE is returned, and @bytes_read is set to the number of bytes
     228                 :             :  * read into @buffer.
     229                 :             :  * 
     230                 :             :  * If there is an error during the operation %FALSE is returned and @error
     231                 :             :  * is set to indicate the error status.
     232                 :             :  *
     233                 :             :  * As a special exception to the normal conventions for functions that
     234                 :             :  * use #GError, if this function returns %FALSE (and sets @error) then
     235                 :             :  * @bytes_read will be set to the number of bytes that were successfully
     236                 :             :  * read before the error was encountered.  This functionality is only
     237                 :             :  * available from C.  If you need it from another language then you must
     238                 :             :  * write your own loop around g_input_stream_read().
     239                 :             :  *
     240                 :             :  * Returns: %TRUE on success, %FALSE if there was an error
     241                 :             :  **/
     242                 :             : gboolean
     243                 :          34 : g_input_stream_read_all (GInputStream  *stream,
     244                 :             :                          void          *buffer,
     245                 :             :                          gsize          count,
     246                 :             :                          gsize         *bytes_read,
     247                 :             :                          GCancellable  *cancellable,
     248                 :             :                          GError       **error)
     249                 :             : {
     250                 :             :   gsize _bytes_read;
     251                 :             :   gssize res;
     252                 :             : 
     253                 :          34 :   g_return_val_if_fail (G_IS_INPUT_STREAM (stream), FALSE);
     254                 :          34 :   g_return_val_if_fail (buffer != NULL, FALSE);
     255                 :             : 
     256                 :          34 :   _bytes_read = 0;
     257                 :          67 :   while (_bytes_read < count)
     258                 :             :     {
     259                 :          52 :       res = g_input_stream_read (stream, (char *)buffer + _bytes_read, count - _bytes_read,
     260                 :             :                                  cancellable, error);
     261                 :          52 :       if (res == -1)
     262                 :             :         {
     263                 :           1 :           if (bytes_read)
     264                 :           1 :             *bytes_read = _bytes_read;
     265                 :           1 :           return FALSE;
     266                 :             :         }
     267                 :             :       
     268                 :          51 :       if (res == 0)
     269                 :          18 :         break;
     270                 :             : 
     271                 :          33 :       _bytes_read += res;
     272                 :             :     }
     273                 :             : 
     274                 :          33 :   if (bytes_read)
     275                 :          31 :     *bytes_read = _bytes_read;
     276                 :          33 :   return TRUE;
     277                 :             : }
     278                 :             : 
     279                 :             : /**
     280                 :             :  * g_input_stream_read_bytes:
     281                 :             :  * @stream: a #GInputStream.
     282                 :             :  * @count: maximum number of bytes that will be read from the stream. Common
     283                 :             :  * values include 4096 and 8192.
     284                 :             :  * @cancellable: (nullable): optional #GCancellable object, %NULL to ignore.
     285                 :             :  * @error: location to store the error occurring, or %NULL to ignore
     286                 :             :  *
     287                 :             :  * Like g_input_stream_read(), this tries to read @count bytes from
     288                 :             :  * the stream in a blocking fashion. However, rather than reading into
     289                 :             :  * a user-supplied buffer, this will create a new #GBytes containing
     290                 :             :  * the data that was read. This may be easier to use from language
     291                 :             :  * bindings.
     292                 :             :  *
     293                 :             :  * If count is zero, returns a zero-length #GBytes and does nothing. A
     294                 :             :  * value of @count larger than %G_MAXSSIZE will cause a
     295                 :             :  * %G_IO_ERROR_INVALID_ARGUMENT error.
     296                 :             :  *
     297                 :             :  * On success, a new #GBytes is returned. It is not an error if the
     298                 :             :  * size of this object is not the same as the requested size, as it
     299                 :             :  * can happen e.g. near the end of a file. A zero-length #GBytes is
     300                 :             :  * returned on end of file (or if @count is zero), but never
     301                 :             :  * otherwise.
     302                 :             :  *
     303                 :             :  * If @cancellable is not %NULL, then the operation can be cancelled by
     304                 :             :  * triggering the cancellable object from another thread. If the operation
     305                 :             :  * was cancelled, the error %G_IO_ERROR_CANCELLED will be returned. If an
     306                 :             :  * operation was partially finished when the operation was cancelled the
     307                 :             :  * partial result will be returned, without an error.
     308                 :             :  *
     309                 :             :  * On error %NULL is returned and @error is set accordingly.
     310                 :             :  *
     311                 :             :  * Returns: (transfer full): a new #GBytes, or %NULL on error
     312                 :             :  *
     313                 :             :  * Since: 2.34
     314                 :             :  **/
     315                 :             : GBytes *
     316                 :           1 : g_input_stream_read_bytes (GInputStream  *stream,
     317                 :             :                            gsize          count,
     318                 :             :                            GCancellable  *cancellable,
     319                 :             :                            GError       **error)
     320                 :             : {
     321                 :             :   guchar *buf;
     322                 :             :   gssize nread;
     323                 :             : 
     324                 :           1 :   buf = g_malloc (count);
     325                 :           1 :   nread = g_input_stream_read (stream, buf, count, cancellable, error);
     326                 :           1 :   if (nread == -1)
     327                 :             :     {
     328                 :           0 :       g_free (buf);
     329                 :           0 :       return NULL;
     330                 :             :     }
     331                 :           1 :   else if (nread == 0)
     332                 :             :     {
     333                 :           0 :       g_free (buf);
     334                 :           0 :       return g_bytes_new_static ("", 0);
     335                 :             :     }
     336                 :             :   else
     337                 :           1 :     return g_bytes_new_take (buf, nread);
     338                 :             : }
     339                 :             : 
     340                 :             : /**
     341                 :             :  * g_input_stream_skip:
     342                 :             :  * @stream: a #GInputStream.
     343                 :             :  * @count: the number of bytes that will be skipped from the stream
     344                 :             :  * @cancellable: (nullable): optional #GCancellable object, %NULL to ignore. 
     345                 :             :  * @error: location to store the error occurring, or %NULL to ignore
     346                 :             :  *
     347                 :             :  * Tries to skip @count bytes from the stream. Will block during the operation.
     348                 :             :  *
     349                 :             :  * This is identical to g_input_stream_read(), from a behaviour standpoint,
     350                 :             :  * but the bytes that are skipped are not returned to the user. Some
     351                 :             :  * streams have an implementation that is more efficient than reading the data.
     352                 :             :  *
     353                 :             :  * This function is optional for inherited classes, as the default implementation
     354                 :             :  * emulates it using read.
     355                 :             :  *
     356                 :             :  * If @cancellable is not %NULL, then the operation can be cancelled by
     357                 :             :  * triggering the cancellable object from another thread. If the operation
     358                 :             :  * was cancelled, the error %G_IO_ERROR_CANCELLED will be returned. If an
     359                 :             :  * operation was partially finished when the operation was cancelled the
     360                 :             :  * partial result will be returned, without an error.
     361                 :             :  *
     362                 :             :  * Returns: Number of bytes skipped, or -1 on error
     363                 :             :  **/
     364                 :             : gssize
     365                 :         133 : g_input_stream_skip (GInputStream  *stream,
     366                 :             :                      gsize          count,
     367                 :             :                      GCancellable  *cancellable,
     368                 :             :                      GError       **error)
     369                 :             : {
     370                 :             :   GInputStreamClass *class;
     371                 :             :   gssize res;
     372                 :             : 
     373                 :         133 :   g_return_val_if_fail (G_IS_INPUT_STREAM (stream), -1);
     374                 :             : 
     375                 :         133 :   if (count == 0)
     376                 :           1 :     return 0;
     377                 :             : 
     378                 :         132 :   if (((gssize) count) < 0)
     379                 :             :     {
     380                 :           0 :       g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT,
     381                 :             :                    _("Too large count value passed to %s"), G_STRFUNC);
     382                 :           0 :       return -1;
     383                 :             :     }
     384                 :             :   
     385                 :         132 :   class = G_INPUT_STREAM_GET_CLASS (stream);
     386                 :             : 
     387                 :         132 :   if (!g_input_stream_set_pending (stream, error))
     388                 :           0 :     return -1;
     389                 :             : 
     390                 :         132 :   if (cancellable)
     391                 :           0 :     g_cancellable_push_current (cancellable);
     392                 :             :   
     393                 :         132 :   res = class->skip (stream, count, cancellable, error);
     394                 :             : 
     395                 :         132 :   if (cancellable)
     396                 :           0 :     g_cancellable_pop_current (cancellable);
     397                 :             :   
     398                 :         132 :   g_input_stream_clear_pending (stream);
     399                 :             : 
     400                 :         132 :   return res;
     401                 :             : }
     402                 :             : 
     403                 :             : static gssize
     404                 :           8 : g_input_stream_real_skip (GInputStream  *stream,
     405                 :             :                           gsize          count,
     406                 :             :                           GCancellable  *cancellable,
     407                 :             :                           GError       **error)
     408                 :             : {
     409                 :             :   GInputStreamClass *class;
     410                 :             :   gssize ret, read_bytes;
     411                 :             :   char buffer[8192];
     412                 :             :   GError *my_error;
     413                 :             : 
     414                 :           8 :   if (G_IS_SEEKABLE (stream) && g_seekable_can_seek (G_SEEKABLE (stream)))
     415                 :             :     {
     416                 :           8 :       GSeekable *seekable = G_SEEKABLE (stream);
     417                 :             :       goffset start, end;
     418                 :             :       gboolean success;
     419                 :             : 
     420                 :             :       /* g_seekable_seek() may try to set pending itself */
     421                 :           8 :       stream->priv->pending = FALSE;
     422                 :             : 
     423                 :           8 :       start = g_seekable_tell (seekable);
     424                 :             : 
     425                 :           8 :       if (g_seekable_seek (G_SEEKABLE (stream),
     426                 :             :                            0,
     427                 :             :                            G_SEEK_END,
     428                 :             :                            cancellable,
     429                 :             :                            NULL))
     430                 :             :         {
     431                 :           8 :           end = g_seekable_tell (seekable);
     432                 :           8 :           g_assert (start >= 0);
     433                 :           8 :           g_assert (end >= start);
     434                 :           8 :           if (start > (goffset) (G_MAXOFFSET - count) ||
     435                 :           8 :               (goffset) (start + count) > end)
     436                 :             :             {
     437                 :           3 :               stream->priv->pending = TRUE;
     438                 :           3 :               return end - start;
     439                 :             :             }
     440                 :             : 
     441                 :           5 :           success = g_seekable_seek (G_SEEKABLE (stream),
     442                 :           5 :                                      start + count,
     443                 :             :                                      G_SEEK_SET,
     444                 :             :                                      cancellable,
     445                 :             :                                      error);
     446                 :           5 :           stream->priv->pending = TRUE;
     447                 :             : 
     448                 :           5 :           if (success)
     449                 :           5 :             return count;
     450                 :             :           else
     451                 :           0 :             return -1;
     452                 :             :         }
     453                 :             :     }
     454                 :             : 
     455                 :             :   /* If not seekable, or seek failed, fall back to reading data: */
     456                 :             : 
     457                 :           0 :   class = G_INPUT_STREAM_GET_CLASS (stream);
     458                 :             : 
     459                 :           0 :   read_bytes = 0;
     460                 :             :   while (1)
     461                 :             :     {
     462                 :           0 :       my_error = NULL;
     463                 :             : 
     464                 :           0 :       ret = class->read_fn (stream, buffer, MIN (sizeof (buffer), count),
     465                 :             :                             cancellable, &my_error);
     466                 :           0 :       if (ret == -1)
     467                 :             :         {
     468                 :           0 :           if (read_bytes > 0 &&
     469                 :           0 :               my_error->domain == G_IO_ERROR &&
     470                 :           0 :               my_error->code == G_IO_ERROR_CANCELLED)
     471                 :             :             {
     472                 :           0 :               g_error_free (my_error);
     473                 :           0 :               return read_bytes;
     474                 :             :             }
     475                 :             : 
     476                 :           0 :           g_propagate_error (error, my_error);
     477                 :           0 :           return -1;
     478                 :             :         }
     479                 :             : 
     480                 :           0 :       count -= ret;
     481                 :           0 :       read_bytes += ret;
     482                 :             : 
     483                 :           0 :       if (ret == 0 || count == 0)
     484                 :           0 :         return read_bytes;
     485                 :             :     }
     486                 :             : }
     487                 :             : 
     488                 :             : /**
     489                 :             :  * g_input_stream_close:
     490                 :             :  * @stream: A #GInputStream.
     491                 :             :  * @cancellable: (nullable): optional #GCancellable object, %NULL to ignore.
     492                 :             :  * @error: location to store the error occurring, or %NULL to ignore
     493                 :             :  *
     494                 :             :  * Closes the stream, releasing resources related to it.
     495                 :             :  *
     496                 :             :  * Once the stream is closed, all other operations will return %G_IO_ERROR_CLOSED.
     497                 :             :  * Closing a stream multiple times will not return an error.
     498                 :             :  *
     499                 :             :  * Streams will be automatically closed when the last reference
     500                 :             :  * is dropped, but you might want to call this function to make sure 
     501                 :             :  * resources are released as early as possible.
     502                 :             :  *
     503                 :             :  * Some streams might keep the backing store of the stream (e.g. a file descriptor)
     504                 :             :  * open after the stream is closed. See the documentation for the individual
     505                 :             :  * stream for details.
     506                 :             :  *
     507                 :             :  * On failure the first error that happened will be reported, but the close
     508                 :             :  * operation will finish as much as possible. A stream that failed to
     509                 :             :  * close will still return %G_IO_ERROR_CLOSED for all operations. Still, it
     510                 :             :  * is important to check and report the error to the user.
     511                 :             :  *
     512                 :             :  * If @cancellable is not %NULL, then the operation can be cancelled by
     513                 :             :  * triggering the cancellable object from another thread. If the operation
     514                 :             :  * was cancelled, the error %G_IO_ERROR_CANCELLED will be returned.
     515                 :             :  * Cancelling a close will still leave the stream closed, but some streams
     516                 :             :  * can use a faster close that doesn't block to e.g. check errors. 
     517                 :             :  *
     518                 :             :  * Returns: %TRUE on success, %FALSE on failure
     519                 :             :  **/
     520                 :             : gboolean
     521                 :        3884 : g_input_stream_close (GInputStream  *stream,
     522                 :             :                       GCancellable  *cancellable,
     523                 :             :                       GError       **error)
     524                 :             : {
     525                 :             :   GInputStreamClass *class;
     526                 :             :   gboolean res;
     527                 :             : 
     528                 :        3884 :   g_return_val_if_fail (G_IS_INPUT_STREAM (stream), FALSE);
     529                 :             : 
     530                 :        3884 :   class = G_INPUT_STREAM_GET_CLASS (stream);
     531                 :             : 
     532                 :        3884 :   if (stream->priv->closed)
     533                 :           9 :     return TRUE;
     534                 :             : 
     535                 :        3875 :   res = TRUE;
     536                 :             : 
     537                 :        3875 :   if (!g_input_stream_set_pending (stream, error))
     538                 :           0 :     return FALSE;
     539                 :             : 
     540                 :        3875 :   if (cancellable)
     541                 :           0 :     g_cancellable_push_current (cancellable);
     542                 :             : 
     543                 :        3875 :   if (class->close_fn)
     544                 :        2281 :     res = class->close_fn (stream, cancellable, error);
     545                 :             : 
     546                 :        3875 :   if (cancellable)
     547                 :           0 :     g_cancellable_pop_current (cancellable);
     548                 :             : 
     549                 :        3875 :   g_input_stream_clear_pending (stream);
     550                 :             :   
     551                 :        3875 :   stream->priv->closed = TRUE;
     552                 :             :   
     553                 :        3875 :   return res;
     554                 :             : }
     555                 :             : 
     556                 :             : static void
     557                 :       15148 : async_ready_callback_wrapper (GObject      *source_object,
     558                 :             :                               GAsyncResult *res,
     559                 :             :                               gpointer      user_data)
     560                 :             : {
     561                 :       15148 :   GInputStream *stream = G_INPUT_STREAM (source_object);
     562                 :             : 
     563                 :       15148 :   g_input_stream_clear_pending (stream);
     564                 :       15148 :   if (stream->priv->outstanding_callback)
     565                 :       15148 :     (*stream->priv->outstanding_callback) (source_object, res, user_data);
     566                 :       15148 :   g_object_unref (stream);
     567                 :       15148 : }
     568                 :             : 
     569                 :             : static void
     570                 :         507 : async_ready_close_callback_wrapper (GObject      *source_object,
     571                 :             :                                     GAsyncResult *res,
     572                 :             :                                     gpointer      user_data)
     573                 :             : {
     574                 :         507 :   GInputStream *stream = G_INPUT_STREAM (source_object);
     575                 :             : 
     576                 :         507 :   g_input_stream_clear_pending (stream);
     577                 :         507 :   stream->priv->closed = TRUE;
     578                 :         507 :   if (stream->priv->outstanding_callback)
     579                 :         507 :     (*stream->priv->outstanding_callback) (source_object, res, user_data);
     580                 :         507 :   g_object_unref (stream);
     581                 :         507 : }
     582                 :             : 
     583                 :             : /**
     584                 :             :  * g_input_stream_read_async:
     585                 :             :  * @stream: A #GInputStream.
     586                 :             :  * @buffer: (array length=count) (element-type guint8) (out caller-allocates):
     587                 :             :  *   a buffer to read data into (which should be at least count bytes long).
     588                 :             :  * @count: (in): the number of bytes that will be read from the stream
     589                 :             :  * @io_priority: the [I/O priority](iface.AsyncResult.html#io-priority)
     590                 :             :  * of the request. 
     591                 :             :  * @cancellable: (nullable): optional #GCancellable object, %NULL to ignore.
     592                 :             :  * @callback: (scope async): a #GAsyncReadyCallback
     593                 :             :  *   to call when the request is satisfied
     594                 :             :  * @user_data: the data to pass to callback function
     595                 :             :  *
     596                 :             :  * Request an asynchronous read of @count bytes from the stream into the buffer
     597                 :             :  * starting at @buffer. When the operation is finished @callback will be called. 
     598                 :             :  * You can then call g_input_stream_read_finish() to get the result of the 
     599                 :             :  * operation.
     600                 :             :  *
     601                 :             :  * During an async request no other sync and async calls are allowed on @stream, and will
     602                 :             :  * result in %G_IO_ERROR_PENDING errors. 
     603                 :             :  *
     604                 :             :  * A value of @count larger than %G_MAXSSIZE will cause a %G_IO_ERROR_INVALID_ARGUMENT error.
     605                 :             :  *
     606                 :             :  * On success, the number of bytes read into the buffer will be passed to the
     607                 :             :  * callback. It is not an error if this is not the same as the requested size, as it
     608                 :             :  * can happen e.g. near the end of a file, but generally we try to read
     609                 :             :  * as many bytes as requested. Zero is returned on end of file
     610                 :             :  * (or if @count is zero),  but never otherwise.
     611                 :             :  *
     612                 :             :  * Any outstanding i/o request with higher priority (lower numerical value) will
     613                 :             :  * be executed before an outstanding request with lower priority. Default
     614                 :             :  * priority is %G_PRIORITY_DEFAULT.
     615                 :             :  *
     616                 :             :  * The asynchronous methods have a default fallback that uses threads to implement
     617                 :             :  * asynchronicity, so they are optional for inheriting classes. However, if you
     618                 :             :  * override one you must override all.
     619                 :             :  **/
     620                 :             : void
     621                 :        7953 : g_input_stream_read_async (GInputStream        *stream,
     622                 :             :                            void                *buffer,
     623                 :             :                            gsize                count,
     624                 :             :                            int                  io_priority,
     625                 :             :                            GCancellable        *cancellable,
     626                 :             :                            GAsyncReadyCallback  callback,
     627                 :             :                            gpointer             user_data)
     628                 :             : {
     629                 :             :   GInputStreamClass *class;
     630                 :        7953 :   GError *error = NULL;
     631                 :             : 
     632                 :        7958 :   g_return_if_fail (G_IS_INPUT_STREAM (stream));
     633                 :        7953 :   g_return_if_fail (buffer != NULL);
     634                 :             : 
     635                 :        7953 :   if (count == 0)
     636                 :             :     {
     637                 :             :       GTask *task;
     638                 :             : 
     639                 :           0 :       task = g_task_new (stream, cancellable, callback, user_data);
     640                 :           0 :       g_task_set_source_tag (task, g_input_stream_read_async);
     641                 :           0 :       g_task_return_int (task, 0);
     642                 :           0 :       g_object_unref (task);
     643                 :           0 :       return;
     644                 :             :     }
     645                 :             :   
     646                 :        7953 :   if (((gssize) count) < 0)
     647                 :             :     {
     648                 :           0 :       g_task_report_new_error (stream, callback, user_data,
     649                 :             :                                g_input_stream_read_async,
     650                 :             :                                G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT,
     651                 :           0 :                                _("Too large count value passed to %s"),
     652                 :             :                                G_STRFUNC);
     653                 :           0 :       return;
     654                 :             :     }
     655                 :             : 
     656                 :        7953 :   if (!g_input_stream_set_pending (stream, &error))
     657                 :             :     {
     658                 :           5 :       g_task_report_error (stream, callback, user_data,
     659                 :             :                            g_input_stream_read_async,
     660                 :             :                            error);
     661                 :           5 :       return;
     662                 :             :     }
     663                 :             : 
     664                 :        7948 :   class = G_INPUT_STREAM_GET_CLASS (stream);
     665                 :        7948 :   stream->priv->outstanding_callback = callback;
     666                 :        7948 :   g_object_ref (stream);
     667                 :        7948 :   class->read_async (stream, buffer, count, io_priority, cancellable,
     668                 :             :                      async_ready_callback_wrapper, user_data);
     669                 :             : }
     670                 :             : 
     671                 :             : /**
     672                 :             :  * g_input_stream_read_finish:
     673                 :             :  * @stream: a #GInputStream.
     674                 :             :  * @result: a #GAsyncResult.
     675                 :             :  * @error: a #GError location to store the error occurring, or %NULL to 
     676                 :             :  * ignore.
     677                 :             :  * 
     678                 :             :  * Finishes an asynchronous stream read operation. 
     679                 :             :  * 
     680                 :             :  * Returns: number of bytes read in, or -1 on error, or 0 on end of file.
     681                 :             :  **/
     682                 :             : gssize
     683                 :       14825 : g_input_stream_read_finish (GInputStream  *stream,
     684                 :             :                             GAsyncResult  *result,
     685                 :             :                             GError       **error)
     686                 :             : {
     687                 :             :   GInputStreamClass *class;
     688                 :             :   
     689                 :       14825 :   g_return_val_if_fail (G_IS_INPUT_STREAM (stream), -1);
     690                 :       14825 :   g_return_val_if_fail (G_IS_ASYNC_RESULT (result), -1);
     691                 :             : 
     692                 :       14825 :   if (g_async_result_legacy_propagate_error (result, error))
     693                 :           0 :     return -1;
     694                 :       14825 :   else if (g_async_result_is_tagged (result, g_input_stream_read_async))
     695                 :           5 :     return g_task_propagate_int (G_TASK (result), error);
     696                 :             : 
     697                 :       14820 :   class = G_INPUT_STREAM_GET_CLASS (stream);
     698                 :       14820 :   return class->read_finish (stream, result, error);
     699                 :             : }
     700                 :             : 
     701                 :             : typedef struct
     702                 :             : {
     703                 :             :   gchar *buffer;
     704                 :             :   gsize to_read;
     705                 :             :   gsize bytes_read;
     706                 :             : } AsyncReadAll;
     707                 :             : 
     708                 :             : static void
     709                 :          10 : free_async_read_all (gpointer data)
     710                 :             : {
     711                 :          10 :   g_slice_free (AsyncReadAll, data);
     712                 :          10 : }
     713                 :             : 
     714                 :             : static void
     715                 :          28 : read_all_callback (GObject      *stream,
     716                 :             :                    GAsyncResult *result,
     717                 :             :                    gpointer      user_data)
     718                 :             : {
     719                 :          28 :   GTask *task = user_data;
     720                 :          28 :   AsyncReadAll *data = g_task_get_task_data (task);
     721                 :          28 :   gboolean got_eof = FALSE;
     722                 :             : 
     723                 :          28 :   if (result)
     724                 :             :     {
     725                 :          18 :       GError *error = NULL;
     726                 :             :       gssize nread;
     727                 :             : 
     728                 :          18 :       nread = g_input_stream_read_finish (G_INPUT_STREAM (stream), result, &error);
     729                 :             : 
     730                 :          18 :       if (nread == -1)
     731                 :             :         {
     732                 :           0 :           g_task_return_error (task, error);
     733                 :           0 :           g_object_unref (task);
     734                 :           0 :           return;
     735                 :             :         }
     736                 :             : 
     737                 :          18 :       g_assert_cmpint (nread, <=, data->to_read);
     738                 :          18 :       data->to_read -= nread;
     739                 :          18 :       data->bytes_read += nread;
     740                 :          18 :       got_eof = (nread == 0);
     741                 :             :     }
     742                 :             : 
     743                 :          28 :   if (got_eof || data->to_read == 0)
     744                 :             :     {
     745                 :          10 :       g_task_return_boolean (task, TRUE);
     746                 :          10 :       g_object_unref (task);
     747                 :             :     }
     748                 :             : 
     749                 :             :   else
     750                 :          36 :     g_input_stream_read_async (G_INPUT_STREAM (stream),
     751                 :          18 :                                data->buffer + data->bytes_read,
     752                 :             :                                data->to_read,
     753                 :             :                                g_task_get_priority (task),
     754                 :             :                                g_task_get_cancellable (task),
     755                 :             :                                read_all_callback, task);
     756                 :             : }
     757                 :             : 
     758                 :             : 
     759                 :             : static void
     760                 :           0 : read_all_async_thread (GTask        *task,
     761                 :             :                        gpointer      source_object,
     762                 :             :                        gpointer      task_data,
     763                 :             :                        GCancellable *cancellable)
     764                 :             : {
     765                 :           0 :   GInputStream *stream = source_object;
     766                 :           0 :   AsyncReadAll *data = task_data;
     767                 :           0 :   GError *error = NULL;
     768                 :             : 
     769                 :           0 :   if (g_input_stream_read_all (stream, data->buffer, data->to_read, &data->bytes_read,
     770                 :             :                                g_task_get_cancellable (task), &error))
     771                 :           0 :     g_task_return_boolean (task, TRUE);
     772                 :             :   else
     773                 :           0 :     g_task_return_error (task, error);
     774                 :           0 : }
     775                 :             : 
     776                 :             : /**
     777                 :             :  * g_input_stream_read_all_async:
     778                 :             :  * @stream: A #GInputStream
     779                 :             :  * @buffer: (array length=count) (element-type guint8) (out caller-allocates):
     780                 :             :  *   a buffer to read data into (which should be at least count bytes long)
     781                 :             :  * @count: (in): the number of bytes that will be read from the stream
     782                 :             :  * @io_priority: the [I/O priority](iface.AsyncResult.html#io-priority) of the request
     783                 :             :  * @cancellable: (nullable): optional #GCancellable object, %NULL to ignore
     784                 :             :  * @callback: (scope async): a #GAsyncReadyCallback
     785                 :             :  *   to call when the request is satisfied
     786                 :             :  * @user_data: the data to pass to callback function
     787                 :             :  *
     788                 :             :  * Request an asynchronous read of @count bytes from the stream into the
     789                 :             :  * buffer starting at @buffer.
     790                 :             :  *
     791                 :             :  * This is the asynchronous equivalent of [method@InputStream.read_all].
     792                 :             :  *
     793                 :             :  * Call [method@InputStream.read_all_finish] to collect the result.
     794                 :             :  *
     795                 :             :  * Any outstanding I/O request with higher priority (lower numerical
     796                 :             :  * value) will be executed before an outstanding request with lower
     797                 :             :  * priority. Default priority is %G_PRIORITY_DEFAULT.
     798                 :             :  *
     799                 :             :  * Since: 2.44
     800                 :             :  **/
     801                 :             : void
     802                 :          10 : g_input_stream_read_all_async (GInputStream        *stream,
     803                 :             :                                void                *buffer,
     804                 :             :                                gsize                count,
     805                 :             :                                int                  io_priority,
     806                 :             :                                GCancellable        *cancellable,
     807                 :             :                                GAsyncReadyCallback  callback,
     808                 :             :                                gpointer             user_data)
     809                 :             : {
     810                 :             :   AsyncReadAll *data;
     811                 :             :   GTask *task;
     812                 :             : 
     813                 :          10 :   g_return_if_fail (G_IS_INPUT_STREAM (stream));
     814                 :          10 :   g_return_if_fail (buffer != NULL || count == 0);
     815                 :             : 
     816                 :          10 :   task = g_task_new (stream, cancellable, callback, user_data);
     817                 :          10 :   data = g_slice_new0 (AsyncReadAll);
     818                 :          10 :   data->buffer = buffer;
     819                 :          10 :   data->to_read = count;
     820                 :             : 
     821                 :          10 :   g_task_set_source_tag (task, g_input_stream_read_all_async);
     822                 :          10 :   g_task_set_task_data (task, data, free_async_read_all);
     823                 :          10 :   g_task_set_priority (task, io_priority);
     824                 :             : 
     825                 :             :   /* If async reads are going to be handled via the threadpool anyway
     826                 :             :    * then we may as well do it with a single dispatch instead of
     827                 :             :    * bouncing in and out.
     828                 :             :    */
     829                 :          10 :   if (g_input_stream_async_read_is_via_threads (stream))
     830                 :             :     {
     831                 :           0 :       g_task_run_in_thread (task, read_all_async_thread);
     832                 :           0 :       g_object_unref (task);
     833                 :             :     }
     834                 :             :   else
     835                 :          10 :     read_all_callback (G_OBJECT (stream), NULL, task);
     836                 :             : }
     837                 :             : 
     838                 :             : /**
     839                 :             :  * g_input_stream_read_all_finish:
     840                 :             :  * @stream: a #GInputStream
     841                 :             :  * @result: a #GAsyncResult
     842                 :             :  * @bytes_read: (out): location to store the number of bytes that was read from the stream
     843                 :             :  * @error: a #GError location to store the error occurring, or %NULL to ignore
     844                 :             :  *
     845                 :             :  * Finishes an asynchronous stream read operation started with
     846                 :             :  * [method@InputStream.read_all_async].
     847                 :             :  *
     848                 :             :  * As a special exception to the normal conventions for functions that
     849                 :             :  * use #GError, if this function returns %FALSE (and sets @error) then
     850                 :             :  * @bytes_read will be set to the number of bytes that were successfully
     851                 :             :  * read before the error was encountered.  This functionality is only
     852                 :             :  * available from C.  If you need it from another language then you must
     853                 :             :  * write your own loop around g_input_stream_read_async().
     854                 :             :  *
     855                 :             :  * Returns: %TRUE on success, %FALSE if there was an error
     856                 :             :  *
     857                 :             :  * Since: 2.44
     858                 :             :  **/
     859                 :             : gboolean
     860                 :          10 : g_input_stream_read_all_finish (GInputStream  *stream,
     861                 :             :                                 GAsyncResult  *result,
     862                 :             :                                 gsize         *bytes_read,
     863                 :             :                                 GError       **error)
     864                 :             : {
     865                 :             :   GTask *task;
     866                 :             : 
     867                 :          10 :   g_return_val_if_fail (G_IS_INPUT_STREAM (stream), FALSE);
     868                 :          10 :   g_return_val_if_fail (g_task_is_valid (result, stream), FALSE);
     869                 :             : 
     870                 :          10 :   task = G_TASK (result);
     871                 :             : 
     872                 :          10 :   if (bytes_read)
     873                 :             :     {
     874                 :          10 :       AsyncReadAll *data = g_task_get_task_data (task);
     875                 :             : 
     876                 :          10 :       *bytes_read = data->bytes_read;
     877                 :             :     }
     878                 :             : 
     879                 :          10 :   return g_task_propagate_boolean (task, error);
     880                 :             : }
     881                 :             : 
     882                 :             : static void
     883                 :           0 : read_bytes_callback (GObject      *stream,
     884                 :             :                      GAsyncResult *result,
     885                 :             :                      gpointer      user_data)
     886                 :             : {
     887                 :           0 :   GTask *task = user_data;
     888                 :           0 :   guchar *buf = g_task_get_task_data (task);
     889                 :           0 :   GError *error = NULL;
     890                 :             :   gssize nread;
     891                 :           0 :   GBytes *bytes = NULL;
     892                 :             : 
     893                 :           0 :   nread = g_input_stream_read_finish (G_INPUT_STREAM (stream),
     894                 :             :                                       result, &error);
     895                 :           0 :   if (nread == -1)
     896                 :             :     {
     897                 :           0 :       g_free (buf);
     898                 :           0 :       g_task_return_error (task, error);
     899                 :             :     }
     900                 :           0 :   else if (nread == 0)
     901                 :             :     {
     902                 :           0 :       g_free (buf);
     903                 :           0 :       bytes = g_bytes_new_static ("", 0);
     904                 :             :     }
     905                 :             :   else
     906                 :           0 :     bytes = g_bytes_new_take (buf, nread);
     907                 :             : 
     908                 :           0 :   if (bytes)
     909                 :           0 :     g_task_return_pointer (task, bytes, (GDestroyNotify)g_bytes_unref);
     910                 :             : 
     911                 :           0 :   g_object_unref (task);
     912                 :           0 : }
     913                 :             : 
     914                 :             : /**
     915                 :             :  * g_input_stream_read_bytes_async:
     916                 :             :  * @stream: A #GInputStream.
     917                 :             :  * @count: the number of bytes that will be read from the stream
     918                 :             :  * @io_priority: the [I/O priority](iface.AsyncResult.html#io-priority) of the request
     919                 :             :  * @cancellable: (nullable): optional #GCancellable object, %NULL to ignore.
     920                 :             :  * @callback: (scope async): a #GAsyncReadyCallback
     921                 :             :  *   to call when the request is satisfied
     922                 :             :  * @user_data: the data to pass to callback function
     923                 :             :  *
     924                 :             :  * Request an asynchronous read of @count bytes from the stream into a
     925                 :             :  * new #GBytes. When the operation is finished @callback will be
     926                 :             :  * called. You can then call g_input_stream_read_bytes_finish() to get the
     927                 :             :  * result of the operation.
     928                 :             :  *
     929                 :             :  * During an async request no other sync and async calls are allowed
     930                 :             :  * on @stream, and will result in %G_IO_ERROR_PENDING errors.
     931                 :             :  *
     932                 :             :  * A value of @count larger than %G_MAXSSIZE will cause a
     933                 :             :  * %G_IO_ERROR_INVALID_ARGUMENT error.
     934                 :             :  *
     935                 :             :  * On success, the new #GBytes will be passed to the callback. It is
     936                 :             :  * not an error if this is smaller than the requested size, as it can
     937                 :             :  * happen e.g. near the end of a file, but generally we try to read as
     938                 :             :  * many bytes as requested. Zero is returned on end of file (or if
     939                 :             :  * @count is zero), but never otherwise.
     940                 :             :  *
     941                 :             :  * Any outstanding I/O request with higher priority (lower numerical
     942                 :             :  * value) will be executed before an outstanding request with lower
     943                 :             :  * priority. Default priority is %G_PRIORITY_DEFAULT.
     944                 :             :  *
     945                 :             :  * Since: 2.34
     946                 :             :  **/
     947                 :             : void
     948                 :           0 : g_input_stream_read_bytes_async (GInputStream          *stream,
     949                 :             :                                  gsize                  count,
     950                 :             :                                  int                    io_priority,
     951                 :             :                                  GCancellable          *cancellable,
     952                 :             :                                  GAsyncReadyCallback    callback,
     953                 :             :                                  gpointer               user_data)
     954                 :             : {
     955                 :             :   GTask *task;
     956                 :             :   guchar *buf;
     957                 :             : 
     958                 :           0 :   task = g_task_new (stream, cancellable, callback, user_data);
     959                 :           0 :   g_task_set_source_tag (task, g_input_stream_read_bytes_async);
     960                 :             : 
     961                 :           0 :   buf = g_malloc (count);
     962                 :           0 :   g_task_set_task_data (task, buf, NULL);
     963                 :             : 
     964                 :           0 :   g_input_stream_read_async (stream, buf, count,
     965                 :             :                              io_priority, cancellable,
     966                 :             :                              read_bytes_callback, task);
     967                 :           0 : }
     968                 :             : 
     969                 :             : /**
     970                 :             :  * g_input_stream_read_bytes_finish:
     971                 :             :  * @stream: a #GInputStream.
     972                 :             :  * @result: a #GAsyncResult.
     973                 :             :  * @error: a #GError location to store the error occurring, or %NULL to
     974                 :             :  *   ignore.
     975                 :             :  *
     976                 :             :  * Finishes an asynchronous stream read-into-#GBytes operation.
     977                 :             :  *
     978                 :             :  * Returns: (transfer full): the newly-allocated #GBytes, or %NULL on error
     979                 :             :  *
     980                 :             :  * Since: 2.34
     981                 :             :  **/
     982                 :             : GBytes *
     983                 :           0 : g_input_stream_read_bytes_finish (GInputStream  *stream,
     984                 :             :                                   GAsyncResult  *result,
     985                 :             :                                   GError       **error)
     986                 :             : {
     987                 :           0 :   g_return_val_if_fail (G_IS_INPUT_STREAM (stream), NULL);
     988                 :           0 :   g_return_val_if_fail (g_task_is_valid (result, stream), NULL);
     989                 :             : 
     990                 :           0 :   return g_task_propagate_pointer (G_TASK (result), error);
     991                 :             : }
     992                 :             : 
     993                 :             : /**
     994                 :             :  * g_input_stream_skip_async:
     995                 :             :  * @stream: A #GInputStream.
     996                 :             :  * @count: the number of bytes that will be skipped from the stream
     997                 :             :  * @io_priority: the [I/O priority](iface.AsyncResult.html#io-priority) of the request
     998                 :             :  * @cancellable: (nullable): optional #GCancellable object, %NULL to ignore.
     999                 :             :  * @callback: (scope async): a #GAsyncReadyCallback
    1000                 :             :  *   to call when the request is satisfied
    1001                 :             :  * @user_data: the data to pass to callback function
    1002                 :             :  *
    1003                 :             :  * Request an asynchronous skip of @count bytes from the stream.
    1004                 :             :  * When the operation is finished @callback will be called.
    1005                 :             :  * You can then call g_input_stream_skip_finish() to get the result
    1006                 :             :  * of the operation.
    1007                 :             :  *
    1008                 :             :  * During an async request no other sync and async calls are allowed,
    1009                 :             :  * and will result in %G_IO_ERROR_PENDING errors.
    1010                 :             :  *
    1011                 :             :  * A value of @count larger than %G_MAXSSIZE will cause a %G_IO_ERROR_INVALID_ARGUMENT error.
    1012                 :             :  *
    1013                 :             :  * On success, the number of bytes skipped will be passed to the callback.
    1014                 :             :  * It is not an error if this is not the same as the requested size, as it
    1015                 :             :  * can happen e.g. near the end of a file, but generally we try to skip
    1016                 :             :  * as many bytes as requested. Zero is returned on end of file
    1017                 :             :  * (or if @count is zero), but never otherwise.
    1018                 :             :  *
    1019                 :             :  * Any outstanding i/o request with higher priority (lower numerical value)
    1020                 :             :  * will be executed before an outstanding request with lower priority.
    1021                 :             :  * Default priority is %G_PRIORITY_DEFAULT.
    1022                 :             :  *
    1023                 :             :  * The asynchronous methods have a default fallback that uses threads to
    1024                 :             :  * implement asynchronicity, so they are optional for inheriting classes.
    1025                 :             :  * However, if you override one, you must override all.
    1026                 :             :  **/
    1027                 :             : void
    1028                 :        7200 : g_input_stream_skip_async (GInputStream        *stream,
    1029                 :             :                            gsize                count,
    1030                 :             :                            int                  io_priority,
    1031                 :             :                            GCancellable        *cancellable,
    1032                 :             :                            GAsyncReadyCallback  callback,
    1033                 :             :                            gpointer             user_data)
    1034                 :             : {
    1035                 :             :   GInputStreamClass *class;
    1036                 :        7200 :   GError *error = NULL;
    1037                 :             : 
    1038                 :        7200 :   g_return_if_fail (G_IS_INPUT_STREAM (stream));
    1039                 :             : 
    1040                 :        7200 :   if (count == 0)
    1041                 :             :     {
    1042                 :             :       GTask *task;
    1043                 :             : 
    1044                 :           0 :       task = g_task_new (stream, cancellable, callback, user_data);
    1045                 :           0 :       g_task_set_source_tag (task, g_input_stream_skip_async);
    1046                 :           0 :       g_task_return_int (task, 0);
    1047                 :           0 :       g_object_unref (task);
    1048                 :           0 :       return;
    1049                 :             :     }
    1050                 :             :   
    1051                 :        7200 :   if (((gssize) count) < 0)
    1052                 :             :     {
    1053                 :           0 :       g_task_report_new_error (stream, callback, user_data,
    1054                 :             :                                g_input_stream_skip_async,
    1055                 :             :                                G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT,
    1056                 :           0 :                                _("Too large count value passed to %s"),
    1057                 :             :                                G_STRFUNC);
    1058                 :           0 :       return;
    1059                 :             :     }
    1060                 :             : 
    1061                 :        7200 :   if (!g_input_stream_set_pending (stream, &error))
    1062                 :             :     {
    1063                 :           0 :       g_task_report_error (stream, callback, user_data,
    1064                 :             :                            g_input_stream_skip_async,
    1065                 :             :                            error);
    1066                 :           0 :       return;
    1067                 :             :     }
    1068                 :             : 
    1069                 :        7200 :   class = G_INPUT_STREAM_GET_CLASS (stream);
    1070                 :        7200 :   stream->priv->outstanding_callback = callback;
    1071                 :        7200 :   g_object_ref (stream);
    1072                 :        7200 :   class->skip_async (stream, count, io_priority, cancellable,
    1073                 :             :                      async_ready_callback_wrapper, user_data);
    1074                 :             : }
    1075                 :             : 
    1076                 :             : /**
    1077                 :             :  * g_input_stream_skip_finish:
    1078                 :             :  * @stream: a #GInputStream.
    1079                 :             :  * @result: a #GAsyncResult.
    1080                 :             :  * @error: a #GError location to store the error occurring, or %NULL to 
    1081                 :             :  * ignore.
    1082                 :             :  * 
    1083                 :             :  * Finishes a stream skip operation.
    1084                 :             :  * 
    1085                 :             :  * Returns: the size of the bytes skipped, or `-1` on error.
    1086                 :             :  **/
    1087                 :             : gssize
    1088                 :        7200 : g_input_stream_skip_finish (GInputStream  *stream,
    1089                 :             :                             GAsyncResult  *result,
    1090                 :             :                             GError       **error)
    1091                 :             : {
    1092                 :             :   GInputStreamClass *class;
    1093                 :             : 
    1094                 :        7200 :   g_return_val_if_fail (G_IS_INPUT_STREAM (stream), -1);
    1095                 :        7200 :   g_return_val_if_fail (G_IS_ASYNC_RESULT (result), -1);
    1096                 :             : 
    1097                 :        7200 :   if (g_async_result_legacy_propagate_error (result, error))
    1098                 :           0 :     return -1;
    1099                 :        7200 :   else if (g_async_result_is_tagged (result, g_input_stream_skip_async))
    1100                 :           0 :     return g_task_propagate_int (G_TASK (result), error);
    1101                 :             : 
    1102                 :        7200 :   class = G_INPUT_STREAM_GET_CLASS (stream);
    1103                 :        7200 :   return class->skip_finish (stream, result, error);
    1104                 :             : }
    1105                 :             : 
    1106                 :             : /**
    1107                 :             :  * g_input_stream_close_async:
    1108                 :             :  * @stream: A #GInputStream.
    1109                 :             :  * @io_priority: the [I/O priority](iface.AsyncResult.html#io-priority) of the request
    1110                 :             :  * @cancellable: (nullable): optional cancellable object
    1111                 :             :  * @callback: (scope async): a #GAsyncReadyCallback
    1112                 :             :  *   to call when the request is satisfied
    1113                 :             :  * @user_data: the data to pass to callback function
    1114                 :             :  *
    1115                 :             :  * Requests an asynchronous closes of the stream, releasing resources related to it.
    1116                 :             :  * When the operation is finished @callback will be called. 
    1117                 :             :  * You can then call g_input_stream_close_finish() to get the result of the 
    1118                 :             :  * operation.
    1119                 :             :  *
    1120                 :             :  * For behaviour details see g_input_stream_close().
    1121                 :             :  *
    1122                 :             :  * The asynchronous methods have a default fallback that uses threads to implement
    1123                 :             :  * asynchronicity, so they are optional for inheriting classes. However, if you
    1124                 :             :  * override one you must override all.
    1125                 :             :  **/
    1126                 :             : void
    1127                 :         517 : g_input_stream_close_async (GInputStream        *stream,
    1128                 :             :                             int                  io_priority,
    1129                 :             :                             GCancellable        *cancellable,
    1130                 :             :                             GAsyncReadyCallback  callback,
    1131                 :             :                             gpointer             user_data)
    1132                 :             : {
    1133                 :             :   GInputStreamClass *class;
    1134                 :         517 :   GError *error = NULL;
    1135                 :             : 
    1136                 :         517 :   g_return_if_fail (G_IS_INPUT_STREAM (stream));
    1137                 :             : 
    1138                 :         517 :   if (stream->priv->closed)
    1139                 :             :     {
    1140                 :             :       GTask *task;
    1141                 :             : 
    1142                 :           0 :       task = g_task_new (stream, cancellable, callback, user_data);
    1143                 :           0 :       g_task_set_source_tag (task, g_input_stream_close_async);
    1144                 :           0 :       g_task_return_boolean (task, TRUE);
    1145                 :           0 :       g_object_unref (task);
    1146                 :           0 :       return;
    1147                 :             :     }
    1148                 :             : 
    1149                 :         517 :   if (!g_input_stream_set_pending (stream, &error))
    1150                 :             :     {
    1151                 :           0 :       g_task_report_error (stream, callback, user_data,
    1152                 :             :                            g_input_stream_close_async,
    1153                 :             :                            error);
    1154                 :           0 :       return;
    1155                 :             :     }
    1156                 :             :   
    1157                 :         517 :   class = G_INPUT_STREAM_GET_CLASS (stream);
    1158                 :         517 :   stream->priv->outstanding_callback = callback;
    1159                 :         517 :   g_object_ref (stream);
    1160                 :         517 :   class->close_async (stream, io_priority, cancellable,
    1161                 :             :                       async_ready_close_callback_wrapper, user_data);
    1162                 :             : }
    1163                 :             : 
    1164                 :             : /**
    1165                 :             :  * g_input_stream_close_finish:
    1166                 :             :  * @stream: a #GInputStream.
    1167                 :             :  * @result: a #GAsyncResult.
    1168                 :             :  * @error: a #GError location to store the error occurring, or %NULL to 
    1169                 :             :  * ignore.
    1170                 :             :  * 
    1171                 :             :  * Finishes closing a stream asynchronously, started from g_input_stream_close_async().
    1172                 :             :  * 
    1173                 :             :  * Returns: %TRUE if the stream was closed successfully.
    1174                 :             :  **/
    1175                 :             : gboolean
    1176                 :         507 : g_input_stream_close_finish (GInputStream  *stream,
    1177                 :             :                              GAsyncResult  *result,
    1178                 :             :                              GError       **error)
    1179                 :             : {
    1180                 :             :   GInputStreamClass *class;
    1181                 :             : 
    1182                 :         507 :   g_return_val_if_fail (G_IS_INPUT_STREAM (stream), FALSE);
    1183                 :         507 :   g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
    1184                 :             : 
    1185                 :         507 :   if (g_async_result_legacy_propagate_error (result, error))
    1186                 :           0 :     return FALSE;
    1187                 :         507 :   else if (g_async_result_is_tagged (result, g_input_stream_close_async))
    1188                 :           0 :     return g_task_propagate_boolean (G_TASK (result), error);
    1189                 :             : 
    1190                 :         507 :   class = G_INPUT_STREAM_GET_CLASS (stream);
    1191                 :         507 :   return class->close_finish (stream, result, error);
    1192                 :             : }
    1193                 :             : 
    1194                 :             : /**
    1195                 :             :  * g_input_stream_is_closed:
    1196                 :             :  * @stream: input stream.
    1197                 :             :  * 
    1198                 :             :  * Checks if an input stream is closed.
    1199                 :             :  * 
    1200                 :             :  * Returns: %TRUE if the stream is closed.
    1201                 :             :  **/
    1202                 :             : gboolean
    1203                 :         192 : g_input_stream_is_closed (GInputStream *stream)
    1204                 :             : {
    1205                 :         192 :   g_return_val_if_fail (G_IS_INPUT_STREAM (stream), TRUE);
    1206                 :             :   
    1207                 :         192 :   return stream->priv->closed;
    1208                 :             : }
    1209                 :             :  
    1210                 :             : /**
    1211                 :             :  * g_input_stream_has_pending:
    1212                 :             :  * @stream: input stream.
    1213                 :             :  * 
    1214                 :             :  * Checks if an input stream has pending actions.
    1215                 :             :  * 
    1216                 :             :  * Returns: %TRUE if @stream has pending actions.
    1217                 :             :  **/  
    1218                 :             : gboolean
    1219                 :        2244 : g_input_stream_has_pending (GInputStream *stream)
    1220                 :             : {
    1221                 :        2244 :   g_return_val_if_fail (G_IS_INPUT_STREAM (stream), TRUE);
    1222                 :             :   
    1223                 :        2244 :   return stream->priv->pending;
    1224                 :             : }
    1225                 :             : 
    1226                 :             : /**
    1227                 :             :  * g_input_stream_set_pending:
    1228                 :             :  * @stream: input stream
    1229                 :             :  * @error: a #GError location to store the error occurring, or %NULL to 
    1230                 :             :  * ignore.
    1231                 :             :  * 
    1232                 :             :  * Sets @stream to have actions pending. If the pending flag is
    1233                 :             :  * already set or @stream is closed, it will return %FALSE and set
    1234                 :             :  * @error.
    1235                 :             :  *
    1236                 :             :  * Returns: %TRUE if pending was previously unset and is now set.
    1237                 :             :  **/
    1238                 :             : gboolean
    1239                 :     1774166 : g_input_stream_set_pending (GInputStream *stream, GError **error)
    1240                 :             : {
    1241                 :     1774166 :   g_return_val_if_fail (G_IS_INPUT_STREAM (stream), FALSE);
    1242                 :             :   
    1243                 :     1774166 :   if (stream->priv->closed)
    1244                 :             :     {
    1245                 :           0 :       g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_CLOSED,
    1246                 :             :                            _("Stream is already closed"));
    1247                 :           0 :       return FALSE;
    1248                 :             :     }
    1249                 :             :   
    1250                 :     1774166 :   if (stream->priv->pending)
    1251                 :             :     {
    1252                 :           5 :       g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_PENDING,
    1253                 :             :                 /* Translators: This is an error you get if there is already an
    1254                 :             :                  * operation running against this stream when you try to start
    1255                 :             :                  * one */
    1256                 :             :                  _("Stream has outstanding operation"));
    1257                 :           5 :       return FALSE;
    1258                 :             :     }
    1259                 :             :   
    1260                 :     1774161 :   stream->priv->pending = TRUE;
    1261                 :     1774161 :   return TRUE;
    1262                 :             : }
    1263                 :             : 
    1264                 :             : /**
    1265                 :             :  * g_input_stream_clear_pending:
    1266                 :             :  * @stream: input stream
    1267                 :             :  * 
    1268                 :             :  * Clears the pending flag on @stream.
    1269                 :             :  **/
    1270                 :             : void
    1271                 :     1774151 : g_input_stream_clear_pending (GInputStream *stream)
    1272                 :             : {
    1273                 :     1774151 :   g_return_if_fail (G_IS_INPUT_STREAM (stream));
    1274                 :             :   
    1275                 :     1774151 :   stream->priv->pending = FALSE;
    1276                 :             : }
    1277                 :             : 
    1278                 :             : /*< internal >
    1279                 :             :  * g_input_stream_async_read_is_via_threads:
    1280                 :             :  * @stream: input stream
    1281                 :             :  *
    1282                 :             :  * Checks if an input stream's read_async function uses threads.
    1283                 :             :  *
    1284                 :             :  * Returns: %TRUE if @stream's read_async function uses threads.
    1285                 :             :  **/
    1286                 :             : gboolean
    1287                 :       22022 : g_input_stream_async_read_is_via_threads (GInputStream *stream)
    1288                 :             : {
    1289                 :             :   GInputStreamClass *class;
    1290                 :             : 
    1291                 :       22022 :   g_return_val_if_fail (G_IS_INPUT_STREAM (stream), FALSE);
    1292                 :             : 
    1293                 :       22022 :   class = G_INPUT_STREAM_GET_CLASS (stream);
    1294                 :             : 
    1295                 :       44044 :   return (class->read_async == g_input_stream_real_read_async &&
    1296                 :       43987 :       !(G_IS_POLLABLE_INPUT_STREAM (stream) &&
    1297                 :       21965 :         g_pollable_input_stream_can_poll (G_POLLABLE_INPUT_STREAM (stream))));
    1298                 :             : }
    1299                 :             : 
    1300                 :             : /*< internal >
    1301                 :             :  * g_input_stream_async_close_is_via_threads:
    1302                 :             :  * @stream: input stream
    1303                 :             :  *
    1304                 :             :  * Checks if an input stream's close_async function uses threads.
    1305                 :             :  *
    1306                 :             :  * Returns: %TRUE if @stream's close_async function uses threads.
    1307                 :             :  **/
    1308                 :             : gboolean
    1309                 :         409 : g_input_stream_async_close_is_via_threads (GInputStream *stream)
    1310                 :             : {
    1311                 :             :   GInputStreamClass *class;
    1312                 :             : 
    1313                 :         409 :   g_return_val_if_fail (G_IS_INPUT_STREAM (stream), FALSE);
    1314                 :             : 
    1315                 :         409 :   class = G_INPUT_STREAM_GET_CLASS (stream);
    1316                 :             : 
    1317                 :         409 :   return class->close_async == g_input_stream_real_close_async;
    1318                 :             : }
    1319                 :             : 
    1320                 :             : /********************************************
    1321                 :             :  *   Default implementation of async ops    *
    1322                 :             :  ********************************************/
    1323                 :             : 
    1324                 :             : typedef struct {
    1325                 :             :   void   *buffer;
    1326                 :             :   gsize   count;
    1327                 :             : } ReadData;
    1328                 :             : 
    1329                 :             : static void
    1330                 :       14925 : free_read_data (ReadData *op)
    1331                 :             : {
    1332                 :       14925 :   g_slice_free (ReadData, op);
    1333                 :       14925 : }
    1334                 :             : 
    1335                 :             : static void
    1336                 :          52 : read_async_thread (GTask        *task,
    1337                 :             :                    gpointer      source_object,
    1338                 :             :                    gpointer      task_data,
    1339                 :             :                    GCancellable *cancellable)
    1340                 :             : {
    1341                 :          52 :   GInputStream *stream = source_object;
    1342                 :          52 :   ReadData *op = task_data;
    1343                 :             :   GInputStreamClass *class;
    1344                 :          52 :   GError *error = NULL;
    1345                 :             :   gssize nread;
    1346                 :             :  
    1347                 :          52 :   class = G_INPUT_STREAM_GET_CLASS (stream);
    1348                 :             : 
    1349                 :          52 :   nread = class->read_fn (stream,
    1350                 :             :                           op->buffer, op->count,
    1351                 :             :                           g_task_get_cancellable (task),
    1352                 :             :                           &error);
    1353                 :          52 :   if (nread == -1)
    1354                 :           0 :     g_task_return_error (task, error);
    1355                 :             :   else
    1356                 :          52 :     g_task_return_int (task, nread);
    1357                 :          52 : }
    1358                 :             : 
    1359                 :             : static void read_async_pollable (GPollableInputStream *stream,
    1360                 :             :                                  GTask                *task);
    1361                 :             : 
    1362                 :             : static gboolean
    1363                 :        7104 : read_async_pollable_ready (GPollableInputStream *stream,
    1364                 :             :                            gpointer              user_data)
    1365                 :             : {
    1366                 :        7104 :   GTask *task = user_data;
    1367                 :             : 
    1368                 :        7104 :   read_async_pollable (stream, task);
    1369                 :        7104 :   return FALSE;
    1370                 :             : }
    1371                 :             : 
    1372                 :             : static void
    1373                 :       21977 : read_async_pollable (GPollableInputStream *stream,
    1374                 :             :                      GTask                *task)
    1375                 :             : {
    1376                 :       21977 :   ReadData *op = g_task_get_task_data (task);
    1377                 :       21977 :   GError *error = NULL;
    1378                 :             :   gssize nread;
    1379                 :             : 
    1380                 :       21977 :   if (g_task_return_error_if_cancelled (task))
    1381                 :        7332 :     return;
    1382                 :             : 
    1383                 :       21749 :   nread = G_POLLABLE_INPUT_STREAM_GET_INTERFACE (stream)->
    1384                 :             :     read_nonblocking (stream, op->buffer, op->count, &error);
    1385                 :             : 
    1386                 :       21749 :   if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK))
    1387                 :             :     {
    1388                 :             :       GSource *source;
    1389                 :             : 
    1390                 :        7104 :       g_error_free (error);
    1391                 :             : 
    1392                 :        7104 :       source = g_pollable_input_stream_create_source (stream,
    1393                 :             :                                                       g_task_get_cancellable (task));
    1394                 :        7104 :       g_task_attach_source (task, source,
    1395                 :             :                             (GSourceFunc) read_async_pollable_ready);
    1396                 :        7104 :       g_source_unref (source);
    1397                 :        7104 :       return;
    1398                 :             :     }
    1399                 :             : 
    1400                 :       14645 :   if (nread == -1)
    1401                 :           0 :     g_task_return_error (task, error);
    1402                 :             :   else
    1403                 :       14645 :     g_task_return_int (task, nread);
    1404                 :             :   /* g_input_stream_real_read_async() unrefs task */
    1405                 :             : }
    1406                 :             : 
    1407                 :             : 
    1408                 :             : static void
    1409                 :       14925 : g_input_stream_real_read_async (GInputStream        *stream,
    1410                 :             :                                 void                *buffer,
    1411                 :             :                                 gsize                count,
    1412                 :             :                                 int                  io_priority,
    1413                 :             :                                 GCancellable        *cancellable,
    1414                 :             :                                 GAsyncReadyCallback  callback,
    1415                 :             :                                 gpointer             user_data)
    1416                 :             : {
    1417                 :             :   GTask *task;
    1418                 :             :   ReadData *op;
    1419                 :             :   
    1420                 :       14925 :   op = g_slice_new0 (ReadData);
    1421                 :       14925 :   task = g_task_new (stream, cancellable, callback, user_data);
    1422                 :       14925 :   g_task_set_source_tag (task, g_input_stream_real_read_async);
    1423                 :       14925 :   g_task_set_task_data (task, op, (GDestroyNotify) free_read_data);
    1424                 :       14925 :   g_task_set_priority (task, io_priority);
    1425                 :       14925 :   op->buffer = buffer;
    1426                 :       14925 :   op->count = count;
    1427                 :             : 
    1428                 :       14925 :   if (!g_input_stream_async_read_is_via_threads (stream))
    1429                 :       14873 :     read_async_pollable (G_POLLABLE_INPUT_STREAM (stream), task);
    1430                 :             :   else
    1431                 :          52 :     g_task_run_in_thread (task, read_async_thread);
    1432                 :       14925 :   g_object_unref (task);
    1433                 :       14925 : }
    1434                 :             : 
    1435                 :             : static gssize
    1436                 :       14820 : g_input_stream_real_read_finish (GInputStream  *stream,
    1437                 :             :                                  GAsyncResult  *result,
    1438                 :             :                                  GError       **error)
    1439                 :             : {
    1440                 :       14820 :   g_return_val_if_fail (g_task_is_valid (result, stream), -1);
    1441                 :             : 
    1442                 :       14820 :   return g_task_propagate_int (G_TASK (result), error);
    1443                 :             : }
    1444                 :             : 
    1445                 :             : 
    1446                 :             : static void
    1447                 :           3 : skip_async_thread (GTask        *task,
    1448                 :             :                    gpointer      source_object,
    1449                 :             :                    gpointer      task_data,
    1450                 :             :                    GCancellable *cancellable)
    1451                 :             : {
    1452                 :           3 :   GInputStream *stream = source_object;
    1453                 :           3 :   gsize count = GPOINTER_TO_SIZE (task_data);
    1454                 :             :   GInputStreamClass *class;
    1455                 :           3 :   GError *error = NULL;
    1456                 :             :   gssize ret;
    1457                 :             : 
    1458                 :           3 :   class = G_INPUT_STREAM_GET_CLASS (stream);
    1459                 :           3 :   ret = class->skip (stream, count,
    1460                 :             :                      g_task_get_cancellable (task),
    1461                 :             :                      &error);
    1462                 :           3 :   if (ret == -1)
    1463                 :           0 :     g_task_return_error (task, error);
    1464                 :             :   else
    1465                 :           3 :     g_task_return_int (task, ret);
    1466                 :           3 : }
    1467                 :             : 
    1468                 :             : typedef struct {
    1469                 :             :   char buffer[8192];
    1470                 :             :   gsize count;
    1471                 :             :   gsize count_skipped;
    1472                 :             : } SkipFallbackAsyncData;
    1473                 :             : 
    1474                 :             : static void
    1475                 :        6977 : skip_callback_wrapper (GObject      *source_object,
    1476                 :             :                        GAsyncResult *res,
    1477                 :             :                        gpointer      user_data)
    1478                 :             : {
    1479                 :             :   GInputStreamClass *class;
    1480                 :        6977 :   GTask *task = user_data;
    1481                 :        6977 :   SkipFallbackAsyncData *data = g_task_get_task_data (task);
    1482                 :        6977 :   GError *error = NULL;
    1483                 :             :   gssize ret;
    1484                 :             : 
    1485                 :        6977 :   ret = g_input_stream_read_finish (G_INPUT_STREAM (source_object), res, &error);
    1486                 :             : 
    1487                 :        6977 :   if (ret > 0)
    1488                 :             :     {
    1489                 :        6975 :       data->count -= ret;
    1490                 :        6975 :       data->count_skipped += ret;
    1491                 :             : 
    1492                 :        6975 :       if (data->count > 0)
    1493                 :             :         {
    1494                 :           0 :           class = G_INPUT_STREAM_GET_CLASS (source_object);
    1495                 :           0 :           class->read_async (G_INPUT_STREAM (source_object),
    1496                 :           0 :                              data->buffer, MIN (8192, data->count),
    1497                 :             :                              g_task_get_priority (task),
    1498                 :             :                              g_task_get_cancellable (task),
    1499                 :             :                              skip_callback_wrapper, task);
    1500                 :           0 :           return;
    1501                 :             :         }
    1502                 :             :     }
    1503                 :             : 
    1504                 :        6979 :   if (ret == -1 &&
    1505                 :           2 :       g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED) &&
    1506                 :           2 :       data->count_skipped)
    1507                 :             :     {
    1508                 :             :       /* No error, return partial read */
    1509                 :           0 :       g_clear_error (&error);
    1510                 :             :     }
    1511                 :             : 
    1512                 :        6977 :   if (error)
    1513                 :           2 :     g_task_return_error (task, error);
    1514                 :             :   else
    1515                 :        6975 :     g_task_return_int (task, data->count_skipped);
    1516                 :        6977 :   g_object_unref (task);
    1517                 :             :  }
    1518                 :             : 
    1519                 :             : static void
    1520                 :        6980 : g_input_stream_real_skip_async (GInputStream        *stream,
    1521                 :             :                                 gsize                count,
    1522                 :             :                                 int                  io_priority,
    1523                 :             :                                 GCancellable        *cancellable,
    1524                 :             :                                 GAsyncReadyCallback  callback,
    1525                 :             :                                 gpointer             user_data)
    1526                 :             : {
    1527                 :             :   GInputStreamClass *class;
    1528                 :             :   SkipFallbackAsyncData *data;
    1529                 :             :   GTask *task;
    1530                 :             : 
    1531                 :        6980 :   class = G_INPUT_STREAM_GET_CLASS (stream);
    1532                 :             : 
    1533                 :        6980 :   task = g_task_new (stream, cancellable, callback, user_data);
    1534                 :        6980 :   g_task_set_source_tag (task, g_input_stream_real_skip_async);
    1535                 :        6980 :   g_task_set_priority (task, io_priority);
    1536                 :             : 
    1537                 :        6980 :   if (g_input_stream_async_read_is_via_threads (stream))
    1538                 :             :     {
    1539                 :             :       /* Read is thread-using async fallback.
    1540                 :             :        * Make skip use threads too, so that we can use a possible sync skip
    1541                 :             :        * implementation. */
    1542                 :           3 :       g_task_set_task_data (task, GSIZE_TO_POINTER (count), NULL);
    1543                 :             : 
    1544                 :           3 :       g_task_run_in_thread (task, skip_async_thread);
    1545                 :           3 :       g_object_unref (task);
    1546                 :             :     }
    1547                 :             :   else
    1548                 :             :     {
    1549                 :             :       /* TODO: Skip fallback uses too much memory, should do multiple read calls */
    1550                 :             :       
    1551                 :             :       /* There is a custom async read function, lets use that. */
    1552                 :        6977 :       data = g_new (SkipFallbackAsyncData, 1);
    1553                 :        6977 :       data->count = count;
    1554                 :        6977 :       data->count_skipped = 0;
    1555                 :        6977 :       g_task_set_task_data (task, data, g_free);
    1556                 :        6977 :       g_task_set_check_cancellable (task, FALSE);
    1557                 :        6977 :       class->read_async (stream, data->buffer, MIN (8192, count), io_priority, cancellable,
    1558                 :             :                          skip_callback_wrapper, task);
    1559                 :             :     }
    1560                 :             : 
    1561                 :        6980 : }
    1562                 :             : 
    1563                 :             : static gssize
    1564                 :        6980 : g_input_stream_real_skip_finish (GInputStream  *stream,
    1565                 :             :                                  GAsyncResult  *result,
    1566                 :             :                                  GError       **error)
    1567                 :             : {
    1568                 :        6980 :   g_return_val_if_fail (g_task_is_valid (result, stream), -1);
    1569                 :             : 
    1570                 :        6980 :   return g_task_propagate_int (G_TASK (result), error);
    1571                 :             : }
    1572                 :             : 
    1573                 :             : static void
    1574                 :         459 : close_async_thread (GTask        *task,
    1575                 :             :                     gpointer      source_object,
    1576                 :             :                     gpointer      task_data,
    1577                 :             :                     GCancellable *cancellable)
    1578                 :             : {
    1579                 :         459 :   GInputStream *stream = source_object;
    1580                 :             :   GInputStreamClass *class;
    1581                 :         459 :   GError *error = NULL;
    1582                 :             :   gboolean result;
    1583                 :             : 
    1584                 :         459 :   class = G_INPUT_STREAM_GET_CLASS (stream);
    1585                 :         459 :   if (class->close_fn)
    1586                 :             :     {
    1587                 :         459 :       result = class->close_fn (stream,
    1588                 :             :                                 g_task_get_cancellable (task),
    1589                 :             :                                 &error);
    1590                 :         459 :       if (!result)
    1591                 :             :         {
    1592                 :           0 :           g_task_return_error (task, error);
    1593                 :           0 :           return;
    1594                 :             :         }
    1595                 :             :     }
    1596                 :             : 
    1597                 :         459 :   g_task_return_boolean (task, TRUE);
    1598                 :             : }
    1599                 :             : 
    1600                 :             : static void
    1601                 :         459 : g_input_stream_real_close_async (GInputStream        *stream,
    1602                 :             :                                  int                  io_priority,
    1603                 :             :                                  GCancellable        *cancellable,
    1604                 :             :                                  GAsyncReadyCallback  callback,
    1605                 :             :                                  gpointer             user_data)
    1606                 :             : {
    1607                 :             :   GTask *task;
    1608                 :             : 
    1609                 :         459 :   task = g_task_new (stream, cancellable, callback, user_data);
    1610                 :         459 :   g_task_set_source_tag (task, g_input_stream_real_close_async);
    1611                 :         459 :   g_task_set_check_cancellable (task, FALSE);
    1612                 :         459 :   g_task_set_priority (task, io_priority);
    1613                 :             :   
    1614                 :         459 :   g_task_run_in_thread (task, close_async_thread);
    1615                 :         459 :   g_object_unref (task);
    1616                 :         459 : }
    1617                 :             : 
    1618                 :             : static gboolean
    1619                 :         449 : g_input_stream_real_close_finish (GInputStream  *stream,
    1620                 :             :                                   GAsyncResult  *result,
    1621                 :             :                                   GError       **error)
    1622                 :             : {
    1623                 :         449 :   g_return_val_if_fail (g_task_is_valid (result, stream), FALSE);
    1624                 :             : 
    1625                 :         449 :   return g_task_propagate_boolean (G_TASK (result), error);
    1626                 :             : }
        

Generated by: LCOV version 2.0-1