Branch data Line data Source code
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 : 7159 : pollable_source_dispatch (GSource *source,
37 : : GSourceFunc callback,
38 : : gpointer user_data)
39 : : {
40 : 7159 : GPollableSourceFunc func = (GPollableSourceFunc)callback;
41 : 7159 : GPollableSource *pollable_source = (GPollableSource *)source;
42 : :
43 : 7159 : return (*func) (pollable_source->stream, user_data);
44 : : }
45 : :
46 : : static void
47 : 7159 : pollable_source_finalize (GSource *source)
48 : : {
49 : 7159 : GPollableSource *pollable_source = (GPollableSource *)source;
50 : :
51 : 7159 : g_object_unref (pollable_source->stream);
52 : 7159 : }
53 : :
54 : : static gboolean
55 : 1 : pollable_source_closure_callback (GObject *stream,
56 : : gpointer data)
57 : : {
58 : 1 : GClosure *closure = data;
59 : :
60 : 1 : GValue param = G_VALUE_INIT;
61 : 1 : GValue result_value = G_VALUE_INIT;
62 : : gboolean result;
63 : :
64 : 1 : g_value_init (&result_value, G_TYPE_BOOLEAN);
65 : :
66 : 1 : g_value_init (¶m, G_TYPE_OBJECT);
67 : 1 : g_value_set_object (¶m, stream);
68 : :
69 : 1 : g_closure_invoke (closure, &result_value, 1, ¶m, NULL);
70 : :
71 : 1 : result = g_value_get_boolean (&result_value);
72 : 1 : g_value_unset (&result_value);
73 : 1 : g_value_unset (¶m);
74 : :
75 : 1 : 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 : 7159 : g_pollable_source_new (GObject *pollable_stream)
104 : : {
105 : : GSource *source;
106 : : GPollableSource *pollable_source;
107 : :
108 : 7159 : g_return_val_if_fail (G_IS_POLLABLE_INPUT_STREAM (pollable_stream) ||
109 : : G_IS_POLLABLE_OUTPUT_STREAM (pollable_stream), NULL);
110 : :
111 : 7159 : source = g_source_new (&pollable_source_funcs, sizeof (GPollableSource));
112 : 7159 : g_source_set_static_name (source, "GPollableSource");
113 : 7159 : pollable_source = (GPollableSource *)source;
114 : 7159 : pollable_source->stream = g_object_ref (pollable_stream);
115 : :
116 : 7159 : 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 : 1 : g_pollable_source_new_full (gpointer pollable_stream,
137 : : GSource *child_source,
138 : : GCancellable *cancellable)
139 : : {
140 : : GSource *source;
141 : :
142 : 1 : g_return_val_if_fail (G_IS_POLLABLE_INPUT_STREAM (pollable_stream) ||
143 : : G_IS_POLLABLE_OUTPUT_STREAM (pollable_stream), NULL);
144 : :
145 : 1 : source = g_pollable_source_new (pollable_stream);
146 : 1 : if (child_source)
147 : : {
148 : 1 : g_source_set_dummy_callback (child_source);
149 : 1 : g_source_add_child_source (source, child_source);
150 : : }
151 : 1 : if (cancellable)
152 : : {
153 : 0 : GSource *cancellable_source = g_cancellable_source_new (cancellable);
154 : :
155 : 0 : g_source_set_dummy_callback (cancellable_source);
156 : 0 : g_source_add_child_source (source, cancellable_source);
157 : 0 : g_source_unref (cancellable_source);
158 : : }
159 : :
160 : 1 : 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 : 3796 : g_pollable_stream_read (GInputStream *stream,
189 : : void *buffer,
190 : : gsize count,
191 : : gboolean blocking,
192 : : GCancellable *cancellable,
193 : : GError **error)
194 : : {
195 : 3796 : if (blocking)
196 : : {
197 : 3718 : return g_input_stream_read (stream,
198 : : buffer, count,
199 : : cancellable, error);
200 : : }
201 : : else
202 : : {
203 : 78 : 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 : 3726 : g_pollable_stream_write (GOutputStream *stream,
236 : : const void *buffer,
237 : : gsize count,
238 : : gboolean blocking,
239 : : GCancellable *cancellable,
240 : : GError **error)
241 : : {
242 : 3726 : if (blocking)
243 : : {
244 : 3717 : return g_output_stream_write (stream,
245 : : buffer, count,
246 : : cancellable, error);
247 : : }
248 : : else
249 : : {
250 : 9 : 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 : 3726 : 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 : 3726 : _bytes_written = 0;
304 : 7452 : while (_bytes_written < count)
305 : : {
306 : 3726 : res = g_pollable_stream_write (stream,
307 : : (char *)buffer + _bytes_written,
308 : : count - _bytes_written,
309 : : blocking,
310 : : cancellable, error);
311 : 3726 : if (res == -1)
312 : : {
313 : 0 : if (bytes_written)
314 : 0 : *bytes_written = _bytes_written;
315 : 0 : return FALSE;
316 : : }
317 : :
318 : 3726 : if (res == 0)
319 : 0 : g_warning ("Write returned zero without error");
320 : :
321 : 3726 : _bytes_written += res;
322 : : }
323 : :
324 : 3726 : if (bytes_written)
325 : 3726 : *bytes_written = _bytes_written;
326 : :
327 : 3726 : return TRUE;
328 : : }
|