(root)/
glib-2.79.0/
gio/
gpollableutils.c
       1  /* GIO - GLib Input, Output and Streaming Library
       2   *
       3   * Copyright (C) 2010 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  
      21  #include "config.h"
      22  
      23  #include <errno.h>
      24  
      25  #include "gpollableinputstream.h"
      26  #include "gasynchelper.h"
      27  #include "glibintl.h"
      28  
      29  typedef struct {
      30    GSource       source;
      31  
      32    GObject      *stream;
      33  } GPollableSource;
      34  
      35  static gboolean
      36  pollable_source_dispatch (GSource     *source,
      37  			  GSourceFunc  callback,
      38  			  gpointer     user_data)
      39  {
      40    GPollableSourceFunc func = (GPollableSourceFunc)callback;
      41    GPollableSource *pollable_source = (GPollableSource *)source;
      42  
      43    return (*func) (pollable_source->stream, user_data);
      44  }
      45  
      46  static void
      47  pollable_source_finalize (GSource *source)
      48  {
      49    GPollableSource *pollable_source = (GPollableSource *)source;
      50  
      51    g_object_unref (pollable_source->stream);
      52  }
      53  
      54  static gboolean
      55  pollable_source_closure_callback (GObject  *stream,
      56  				  gpointer  data)
      57  {
      58    GClosure *closure = data;
      59  
      60    GValue param = G_VALUE_INIT;
      61    GValue result_value = G_VALUE_INIT;
      62    gboolean result;
      63  
      64    g_value_init (&result_value, G_TYPE_BOOLEAN);
      65  
      66    g_value_init (&param, G_TYPE_OBJECT);
      67    g_value_set_object (&param, stream);
      68  
      69    g_closure_invoke (closure, &result_value, 1, &param, NULL);
      70  
      71    result = g_value_get_boolean (&result_value);
      72    g_value_unset (&result_value);
      73    g_value_unset (&param);
      74  
      75    return result;
      76  }
      77  
      78  static GSourceFuncs pollable_source_funcs =
      79  {
      80    NULL,
      81    NULL,
      82    pollable_source_dispatch,
      83    pollable_source_finalize,
      84    (GSourceFunc)pollable_source_closure_callback,
      85    NULL,
      86  };
      87  
      88  /**
      89   * g_pollable_source_new:
      90   * @pollable_stream: the stream associated with the new source
      91   *
      92   * Utility method for #GPollableInputStream and #GPollableOutputStream
      93   * implementations. Creates a new #GSource that expects a callback of
      94   * type #GPollableSourceFunc. The new source does not actually do
      95   * anything on its own; use g_source_add_child_source() to add other
      96   * sources to it to cause it to trigger.
      97   *
      98   * Returns: (transfer full): the new #GSource.
      99   *
     100   * Since: 2.28
     101   */
     102  GSource *
     103  g_pollable_source_new (GObject *pollable_stream)
     104  {
     105    GSource *source;
     106    GPollableSource *pollable_source;
     107  
     108    g_return_val_if_fail (G_IS_POLLABLE_INPUT_STREAM (pollable_stream) ||
     109  			G_IS_POLLABLE_OUTPUT_STREAM (pollable_stream), NULL);
     110  
     111    source = g_source_new (&pollable_source_funcs, sizeof (GPollableSource));
     112    g_source_set_static_name (source, "GPollableSource");
     113    pollable_source = (GPollableSource *)source;
     114    pollable_source->stream = g_object_ref (pollable_stream);
     115  
     116    return source;
     117  }
     118  
     119  /**
     120   * g_pollable_source_new_full:
     121   * @pollable_stream: (type GObject): the stream associated with the
     122   *   new source
     123   * @child_source: (nullable): optional child source to attach
     124   * @cancellable: (nullable): optional #GCancellable to attach
     125   *
     126   * Utility method for #GPollableInputStream and #GPollableOutputStream
     127   * implementations. Creates a new #GSource, as with
     128   * g_pollable_source_new(), but also attaching @child_source (with a
     129   * dummy callback), and @cancellable, if they are non-%NULL.
     130   *
     131   * Returns: (transfer full): the new #GSource.
     132   *
     133   * Since: 2.34
     134   */
     135  GSource *
     136  g_pollable_source_new_full (gpointer      pollable_stream,
     137  			    GSource      *child_source,
     138  			    GCancellable *cancellable)
     139  {
     140    GSource *source;
     141  
     142    g_return_val_if_fail (G_IS_POLLABLE_INPUT_STREAM (pollable_stream) ||
     143  			G_IS_POLLABLE_OUTPUT_STREAM (pollable_stream), NULL);
     144  
     145    source = g_pollable_source_new (pollable_stream);
     146    if (child_source)
     147      {
     148        g_source_set_dummy_callback (child_source);
     149        g_source_add_child_source (source, child_source);
     150      }
     151    if (cancellable)
     152      {
     153        GSource *cancellable_source = g_cancellable_source_new (cancellable);
     154  
     155        g_source_set_dummy_callback (cancellable_source);
     156        g_source_add_child_source (source, cancellable_source);
     157        g_source_unref (cancellable_source);
     158      }
     159  
     160    return source;
     161  }
     162  
     163  /**
     164   * g_pollable_stream_read:
     165   * @stream: a #GInputStream
     166   * @buffer: (array length=count) (element-type guint8): a buffer to
     167   *   read data into
     168   * @count: the number of bytes to read
     169   * @blocking: whether to do blocking I/O
     170   * @cancellable: (nullable): optional #GCancellable object, %NULL to ignore.
     171   * @error: location to store the error occurring, or %NULL to ignore
     172   *
     173   * Tries to read from @stream, as with g_input_stream_read() (if
     174   * @blocking is %TRUE) or g_pollable_input_stream_read_nonblocking()
     175   * (if @blocking is %FALSE). This can be used to more easily share
     176   * code between blocking and non-blocking implementations of a method.
     177   *
     178   * If @blocking is %FALSE, then @stream must be a
     179   * #GPollableInputStream for which g_pollable_input_stream_can_poll()
     180   * returns %TRUE, or else the behavior is undefined. If @blocking is
     181   * %TRUE, then @stream does not need to be a #GPollableInputStream.
     182   *
     183   * Returns: the number of bytes read, or -1 on error.
     184   *
     185   * Since: 2.34
     186   */
     187  gssize
     188  g_pollable_stream_read (GInputStream   *stream,
     189  			void           *buffer,
     190  			gsize           count,
     191  			gboolean        blocking,
     192  			GCancellable   *cancellable,
     193  			GError        **error)
     194  {
     195    if (blocking)
     196      {
     197        return g_input_stream_read (stream,
     198  				  buffer, count,
     199  				  cancellable, error);
     200      }
     201    else
     202      {
     203        return g_pollable_input_stream_read_nonblocking (G_POLLABLE_INPUT_STREAM (stream),
     204  						       buffer, count,
     205  						       cancellable, error);
     206      }
     207  }
     208  
     209  /**
     210   * g_pollable_stream_write:
     211   * @stream: a #GOutputStream.
     212   * @buffer: (array length=count) (element-type guint8): the buffer
     213   *   containing the data to write.
     214   * @count: the number of bytes to write
     215   * @blocking: whether to do blocking I/O
     216   * @cancellable: (nullable): optional #GCancellable object, %NULL to ignore.
     217   * @error: location to store the error occurring, or %NULL to ignore
     218   *
     219   * Tries to write to @stream, as with g_output_stream_write() (if
     220   * @blocking is %TRUE) or g_pollable_output_stream_write_nonblocking()
     221   * (if @blocking is %FALSE). This can be used to more easily share
     222   * code between blocking and non-blocking implementations of a method.
     223   *
     224   * If @blocking is %FALSE, then @stream must be a
     225   * #GPollableOutputStream for which
     226   * g_pollable_output_stream_can_poll() returns %TRUE or else the
     227   * behavior is undefined. If @blocking is %TRUE, then @stream does not
     228   * need to be a #GPollableOutputStream.
     229   *
     230   * Returns: the number of bytes written, or -1 on error.
     231   *
     232   * Since: 2.34
     233   */
     234  gssize
     235  g_pollable_stream_write (GOutputStream   *stream,
     236  			 const void      *buffer,
     237  			 gsize            count,
     238  			 gboolean         blocking,
     239  			 GCancellable    *cancellable,
     240  			 GError         **error)
     241  {
     242    if (blocking)
     243      {
     244        return g_output_stream_write (stream,
     245  				    buffer, count,
     246  				    cancellable, error);
     247      }
     248    else
     249      {
     250        return g_pollable_output_stream_write_nonblocking (G_POLLABLE_OUTPUT_STREAM (stream),
     251  							 buffer, count,
     252  							 cancellable, error);
     253      }
     254  }
     255  
     256  /**
     257   * g_pollable_stream_write_all:
     258   * @stream: a #GOutputStream.
     259   * @buffer: (array length=count) (element-type guint8): the buffer
     260   *   containing the data to write.
     261   * @count: the number of bytes to write
     262   * @blocking: whether to do blocking I/O
     263   * @bytes_written: (out): location to store the number of bytes that was 
     264   *   written to the stream
     265   * @cancellable: (nullable): optional #GCancellable object, %NULL to ignore.
     266   * @error: location to store the error occurring, or %NULL to ignore
     267   *
     268   * Tries to write @count bytes to @stream, as with
     269   * g_output_stream_write_all(), but using g_pollable_stream_write()
     270   * rather than g_output_stream_write().
     271   *
     272   * On a successful write of @count bytes, %TRUE is returned, and
     273   * @bytes_written is set to @count.
     274   * 
     275   * If there is an error during the operation (including
     276   * %G_IO_ERROR_WOULD_BLOCK in the non-blocking case), %FALSE is
     277   * returned and @error is set to indicate the error status,
     278   * @bytes_written is updated to contain the number of bytes written
     279   * into the stream before the error occurred.
     280   *
     281   * As with g_pollable_stream_write(), if @blocking is %FALSE, then
     282   * @stream must be a #GPollableOutputStream for which
     283   * g_pollable_output_stream_can_poll() returns %TRUE or else the
     284   * behavior is undefined. If @blocking is %TRUE, then @stream does not
     285   * need to be a #GPollableOutputStream.
     286   *
     287   * Returns: %TRUE on success, %FALSE if there was an error
     288   *
     289   * Since: 2.34
     290   */
     291  gboolean
     292  g_pollable_stream_write_all (GOutputStream  *stream,
     293  			     const void     *buffer,
     294  			     gsize           count,
     295  			     gboolean        blocking,
     296  			     gsize          *bytes_written,
     297  			     GCancellable   *cancellable,
     298  			     GError        **error)
     299  {
     300    gsize _bytes_written;
     301    gssize res;
     302  
     303    _bytes_written = 0;
     304    while (_bytes_written < count)
     305      {
     306        res = g_pollable_stream_write (stream,
     307  				     (char *)buffer + _bytes_written,
     308  				     count - _bytes_written,
     309  				     blocking,
     310  				     cancellable, error);
     311        if (res == -1)
     312  	{
     313  	  if (bytes_written)
     314  	    *bytes_written = _bytes_written;
     315  	  return FALSE;
     316  	}
     317  
     318        if (res == 0)
     319  	g_warning ("Write returned zero without error");
     320  
     321        _bytes_written += res;
     322      }
     323  
     324    if (bytes_written)
     325      *bytes_written = _bytes_written;
     326  
     327    return TRUE;
     328  }