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