Coverage Report

Created: 2025-06-13 06:55

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