/3rd-party/glib-2.16.6/gio/goutputstream.c
C | 1340 lines | 820 code | 182 blank | 338 comment | 92 complexity | 4da38cbb323355e5786dd59667ee4b86 MD5 | raw file
Possible License(s): LGPL-2.0, AGPL-3.0
1/* GIO - GLib Input, Output and Streaming Library
2 *
3 * Copyright (C) 2006-2007 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 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, write to the
17 * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
18 * Boston, MA 02111-1307, USA.
19 *
20 * Author: Alexander Larsson <alexl@redhat.com>
21 */
22
23#include <config.h>
24#include "goutputstream.h"
25#include "gsimpleasyncresult.h"
26#include "glibintl.h"
27
28#include "gioalias.h"
29
30/**
31 * SECTION:goutputstream
32 * @short_description: Base class for implementing streaming output
33 * @include: gio/gio.h
34 *
35 *
36 **/
37
38G_DEFINE_TYPE (GOutputStream, g_output_stream, G_TYPE_OBJECT);
39
40struct _GOutputStreamPrivate {
41 guint closed : 1;
42 guint pending : 1;
43 guint cancelled : 1;
44 GAsyncReadyCallback outstanding_callback;
45};
46
47static gssize g_output_stream_real_splice (GOutputStream *stream,
48 GInputStream *source,
49 GOutputStreamSpliceFlags flags,
50 GCancellable *cancellable,
51 GError **error);
52static void g_output_stream_real_write_async (GOutputStream *stream,
53 const void *buffer,
54 gsize count,
55 int io_priority,
56 GCancellable *cancellable,
57 GAsyncReadyCallback callback,
58 gpointer data);
59static gssize g_output_stream_real_write_finish (GOutputStream *stream,
60 GAsyncResult *result,
61 GError **error);
62static void g_output_stream_real_splice_async (GOutputStream *stream,
63 GInputStream *source,
64 GOutputStreamSpliceFlags flags,
65 int io_priority,
66 GCancellable *cancellable,
67 GAsyncReadyCallback callback,
68 gpointer data);
69static gssize g_output_stream_real_splice_finish (GOutputStream *stream,
70 GAsyncResult *result,
71 GError **error);
72static void g_output_stream_real_flush_async (GOutputStream *stream,
73 int io_priority,
74 GCancellable *cancellable,
75 GAsyncReadyCallback callback,
76 gpointer data);
77static gboolean g_output_stream_real_flush_finish (GOutputStream *stream,
78 GAsyncResult *result,
79 GError **error);
80static void g_output_stream_real_close_async (GOutputStream *stream,
81 int io_priority,
82 GCancellable *cancellable,
83 GAsyncReadyCallback callback,
84 gpointer data);
85static gboolean g_output_stream_real_close_finish (GOutputStream *stream,
86 GAsyncResult *result,
87 GError **error);
88
89static void
90g_output_stream_finalize (GObject *object)
91{
92 GOutputStream *stream;
93
94 stream = G_OUTPUT_STREAM (object);
95
96 if (G_OBJECT_CLASS (g_output_stream_parent_class)->finalize)
97 (*G_OBJECT_CLASS (g_output_stream_parent_class)->finalize) (object);
98}
99
100static void
101g_output_stream_dispose (GObject *object)
102{
103 GOutputStream *stream;
104
105 stream = G_OUTPUT_STREAM (object);
106
107 if (!stream->priv->closed)
108 g_output_stream_close (stream, NULL, NULL);
109
110 if (G_OBJECT_CLASS (g_output_stream_parent_class)->dispose)
111 (*G_OBJECT_CLASS (g_output_stream_parent_class)->dispose) (object);
112}
113
114static void
115g_output_stream_class_init (GOutputStreamClass *klass)
116{
117 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
118
119 g_type_class_add_private (klass, sizeof (GOutputStreamPrivate));
120
121 gobject_class->finalize = g_output_stream_finalize;
122 gobject_class->dispose = g_output_stream_dispose;
123
124 klass->splice = g_output_stream_real_splice;
125
126 klass->write_async = g_output_stream_real_write_async;
127 klass->write_finish = g_output_stream_real_write_finish;
128 klass->splice_async = g_output_stream_real_splice_async;
129 klass->splice_finish = g_output_stream_real_splice_finish;
130 klass->flush_async = g_output_stream_real_flush_async;
131 klass->flush_finish = g_output_stream_real_flush_finish;
132 klass->close_async = g_output_stream_real_close_async;
133 klass->close_finish = g_output_stream_real_close_finish;
134}
135
136static void
137g_output_stream_init (GOutputStream *stream)
138{
139 stream->priv = G_TYPE_INSTANCE_GET_PRIVATE (stream,
140 G_TYPE_OUTPUT_STREAM,
141 GOutputStreamPrivate);
142}
143
144/**
145 * g_output_stream_write:
146 * @stream: a #GOutputStream.
147 * @buffer: the buffer containing the data to write.
148 * @count: the number of bytes to write
149 * @cancellable: optional cancellable object
150 * @error: location to store the error occuring, or %NULL to ignore
151 *
152 * Tries to write @count bytes from @buffer into the stream. Will block
153 * during the operation.
154 *
155 * If count is zero returns zero and does nothing. A value of @count
156 * larger than %G_MAXSSIZE will cause a %G_IO_ERROR_INVALID_ARGUMENT error.
157 *
158 * On success, the number of bytes written to the stream is returned.
159 * It is not an error if this is not the same as the requested size, as it
160 * can happen e.g. on a partial i/o error, or if there is not enough
161 * storage in the stream. All writes either block until at least one byte
162 * is written, so zero is never returned (unless @count is zero).
163 *
164 * If @cancellable is not NULL, then the operation can be cancelled by
165 * triggering the cancellable object from another thread. If the operation
166 * was cancelled, the error G_IO_ERROR_CANCELLED will be returned. If an
167 * operation was partially finished when the operation was cancelled the
168 * partial result will be returned, without an error.
169 *
170 * On error -1 is returned and @error is set accordingly.
171 *
172 * Return value: Number of bytes written, or -1 on error
173 **/
174gssize
175g_output_stream_write (GOutputStream *stream,
176 const void *buffer,
177 gsize count,
178 GCancellable *cancellable,
179 GError **error)
180{
181 GOutputStreamClass *class;
182 gssize res;
183
184 g_return_val_if_fail (G_IS_OUTPUT_STREAM (stream), -1);
185 g_return_val_if_fail (buffer != NULL, 0);
186
187 if (count == 0)
188 return 0;
189
190 if (((gssize) count) < 0)
191 {
192 g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT,
193 _("Too large count value passed to %s"), G_STRFUNC);
194 return -1;
195 }
196
197 class = G_OUTPUT_STREAM_GET_CLASS (stream);
198
199 if (class->write_fn == NULL)
200 {
201 g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
202 _("Output stream doesn't implement write"));
203 return -1;
204 }
205
206 if (!g_output_stream_set_pending (stream, error))
207 return -1;
208
209 if (cancellable)
210 g_cancellable_push_current (cancellable);
211
212 res = class->write_fn (stream, buffer, count, cancellable, error);
213
214 if (cancellable)
215 g_cancellable_pop_current (cancellable);
216
217 g_output_stream_clear_pending (stream);
218
219 return res;
220}
221
222/**
223 * g_output_stream_write_all:
224 * @stream: a #GOutputStream.
225 * @buffer: the buffer containing the data to write.
226 * @count: the number of bytes to write
227 * @bytes_written: location to store the number of bytes that was
228 * written to the stream
229 * @cancellable: optional #GCancellable object, %NULL to ignore.
230 * @error: location to store the error occuring, or %NULL to ignore
231 *
232 * Tries to write @count bytes from @buffer into the stream. Will block
233 * during the operation.
234 *
235 * This function is similar to g_output_stream_write(), except it tries to
236 * write as many bytes as requested, only stopping on an error.
237 *
238 * On a successful write of @count bytes, %TRUE is returned, and @bytes_written
239 * is set to @count.
240 *
241 * If there is an error during the operation FALSE is returned and @error
242 * is set to indicate the error status, @bytes_written is updated to contain
243 * the number of bytes written into the stream before the error occurred.
244 *
245 * Return value: %TRUE on success, %FALSE if there was an error
246 **/
247gboolean
248g_output_stream_write_all (GOutputStream *stream,
249 const void *buffer,
250 gsize count,
251 gsize *bytes_written,
252 GCancellable *cancellable,
253 GError **error)
254{
255 gsize _bytes_written;
256 gssize res;
257
258 g_return_val_if_fail (G_IS_OUTPUT_STREAM (stream), FALSE);
259 g_return_val_if_fail (buffer != NULL, FALSE);
260
261 _bytes_written = 0;
262 while (_bytes_written < count)
263 {
264 res = g_output_stream_write (stream, (char *)buffer + _bytes_written, count - _bytes_written,
265 cancellable, error);
266 if (res == -1)
267 {
268 if (bytes_written)
269 *bytes_written = _bytes_written;
270 return FALSE;
271 }
272
273 if (res == 0)
274 g_warning ("Write returned zero without error");
275
276 _bytes_written += res;
277 }
278
279 if (bytes_written)
280 *bytes_written = _bytes_written;
281
282 return TRUE;
283}
284
285/**
286 * g_output_stream_flush:
287 * @stream: a #GOutputStream.
288 * @cancellable: optional cancellable object
289 * @error: location to store the error occuring, or %NULL to ignore
290 *
291 * Flushed any outstanding buffers in the stream. Will block during
292 * the operation. Closing the stream will implicitly cause a flush.
293 *
294 * This function is optional for inherited classes.
295 *
296 * If @cancellable is not %NULL, then the operation can be cancelled by
297 * triggering the cancellable object from another thread. If the operation
298 * was cancelled, the error %G_IO_ERROR_CANCELLED will be returned.
299 *
300 * Return value: %TRUE on success, %FALSE on error
301 **/
302gboolean
303g_output_stream_flush (GOutputStream *stream,
304 GCancellable *cancellable,
305 GError **error)
306{
307 GOutputStreamClass *class;
308 gboolean res;
309
310 g_return_val_if_fail (G_IS_OUTPUT_STREAM (stream), FALSE);
311
312 if (!g_output_stream_set_pending (stream, error))
313 return FALSE;
314
315 class = G_OUTPUT_STREAM_GET_CLASS (stream);
316
317 res = TRUE;
318 if (class->flush)
319 {
320 if (cancellable)
321 g_cancellable_push_current (cancellable);
322
323 res = class->flush (stream, cancellable, error);
324
325 if (cancellable)
326 g_cancellable_pop_current (cancellable);
327 }
328
329 g_output_stream_clear_pending (stream);
330
331 return res;
332}
333
334/**
335 * g_output_stream_splice:
336 * @stream: a #GOutputStream.
337 * @source: a #GInputStream.
338 * @flags: a set of #GOutputStreamSpliceFlags.
339 * @cancellable: optional #GCancellable object, %NULL to ignore.
340 * @error: a #GError location to store the error occuring, or %NULL to
341 * ignore.
342 *
343 * Splices an input stream into an output stream.
344 *
345 * Returns: a #gssize containing the size of the data spliced.
346 **/
347gssize
348g_output_stream_splice (GOutputStream *stream,
349 GInputStream *source,
350 GOutputStreamSpliceFlags flags,
351 GCancellable *cancellable,
352 GError **error)
353{
354 GOutputStreamClass *class;
355 gboolean res;
356
357 g_return_val_if_fail (G_IS_OUTPUT_STREAM (stream), -1);
358 g_return_val_if_fail (G_IS_INPUT_STREAM (source), -1);
359
360 if (g_input_stream_is_closed (source))
361 {
362 g_set_error (error, G_IO_ERROR, G_IO_ERROR_CLOSED,
363 _("Source stream is already closed"));
364 return -1;
365 }
366
367 if (!g_output_stream_set_pending (stream, error))
368 return -1;
369
370 class = G_OUTPUT_STREAM_GET_CLASS (stream);
371
372 res = TRUE;
373 if (cancellable)
374 g_cancellable_push_current (cancellable);
375
376 res = class->splice (stream, source, flags, cancellable, error);
377
378 if (cancellable)
379 g_cancellable_pop_current (cancellable);
380
381 g_output_stream_clear_pending (stream);
382
383 return res;
384}
385
386static gssize
387g_output_stream_real_splice (GOutputStream *stream,
388 GInputStream *source,
389 GOutputStreamSpliceFlags flags,
390 GCancellable *cancellable,
391 GError **error)
392{
393 GOutputStreamClass *class = G_OUTPUT_STREAM_GET_CLASS (stream);
394 gssize n_read, n_written;
395 gssize bytes_copied;
396 char buffer[8192], *p;
397 gboolean res;
398
399 bytes_copied = 0;
400 if (class->write_fn == NULL)
401 {
402 g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
403 _("Output stream doesn't implement write"));
404 res = FALSE;
405 goto notsupported;
406 }
407
408 res = TRUE;
409 do
410 {
411 n_read = g_input_stream_read (source, buffer, sizeof (buffer), cancellable, error);
412 if (n_read == -1)
413 {
414 res = FALSE;
415 break;
416 }
417
418 if (n_read == 0)
419 break;
420
421 p = buffer;
422 while (n_read > 0)
423 {
424 n_written = class->write_fn (stream, p, n_read, cancellable, error);
425 if (n_written == -1)
426 {
427 res = FALSE;
428 break;
429 }
430
431 p += n_written;
432 n_read -= n_written;
433 bytes_copied += n_written;
434 }
435 }
436 while (res);
437
438 notsupported:
439 if (!res)
440 error = NULL; /* Ignore further errors */
441
442 if (flags & G_OUTPUT_STREAM_SPLICE_CLOSE_SOURCE)
443 {
444 /* Don't care about errors in source here */
445 g_input_stream_close (source, cancellable, NULL);
446 }
447
448 if (flags & G_OUTPUT_STREAM_SPLICE_CLOSE_TARGET)
449 {
450 /* But write errors on close are bad! */
451 if (!class->close_fn (stream, cancellable, error))
452 res = FALSE;
453 }
454
455 if (res)
456 return bytes_copied;
457
458 return -1;
459}
460
461
462/**
463 * g_output_stream_close:
464 * @stream: A #GOutputStream.
465 * @cancellable: optional cancellable object
466 * @error: location to store the error occuring, or %NULL to ignore
467 *
468 * Closes the stream, releasing resources related to it.
469 *
470 * Once the stream is closed, all other operations will return %G_IO_ERROR_CLOSED.
471 * Closing a stream multiple times will not return an error.
472 *
473 * Closing a stream will automatically flush any outstanding buffers in the
474 * stream.
475 *
476 * Streams will be automatically closed when the last reference
477 * is dropped, but you might want to call this function to make sure
478 * resources are released as early as possible.
479 *
480 * Some streams might keep the backing store of the stream (e.g. a file descriptor)
481 * open after the stream is closed. See the documentation for the individual
482 * stream for details.
483 *
484 * On failure the first error that happened will be reported, but the close
485 * operation will finish as much as possible. A stream that failed to
486 * close will still return %G_IO_ERROR_CLOSED for all operations. Still, it
487 * is important to check and report the error to the user, otherwise
488 * there might be a loss of data as all data might not be written.
489 *
490 * If @cancellable is not NULL, then the operation can be cancelled by
491 * triggering the cancellable object from another thread. If the operation
492 * was cancelled, the error %G_IO_ERROR_CANCELLED will be returned.
493 * Cancelling a close will still leave the stream closed, but there some streams
494 * can use a faster close that doesn't block to e.g. check errors. On
495 * cancellation (as with any error) there is no guarantee that all written
496 * data will reach the target.
497 *
498 * Return value: %TRUE on success, %FALSE on failure
499 **/
500gboolean
501g_output_stream_close (GOutputStream *stream,
502 GCancellable *cancellable,
503 GError **error)
504{
505 GOutputStreamClass *class;
506 gboolean res;
507
508 g_return_val_if_fail (G_IS_OUTPUT_STREAM (stream), FALSE);
509
510 class = G_OUTPUT_STREAM_GET_CLASS (stream);
511
512 if (stream->priv->closed)
513 return TRUE;
514
515 if (!g_output_stream_set_pending (stream, error))
516 return FALSE;
517
518 if (cancellable)
519 g_cancellable_push_current (cancellable);
520
521 if (class->flush)
522 res = class->flush (stream, cancellable, error);
523 else
524 res = TRUE;
525
526 if (!res)
527 {
528 /* flushing caused the error that we want to return,
529 * but we still want to close the underlying stream if possible
530 */
531 if (class->close_fn)
532 class->close_fn (stream, cancellable, NULL);
533 }
534 else
535 {
536 res = TRUE;
537 if (class->close_fn)
538 res = class->close_fn (stream, cancellable, error);
539 }
540
541 if (cancellable)
542 g_cancellable_pop_current (cancellable);
543
544 stream->priv->closed = TRUE;
545 g_output_stream_clear_pending (stream);
546
547 return res;
548}
549
550static void
551async_ready_callback_wrapper (GObject *source_object,
552 GAsyncResult *res,
553 gpointer user_data)
554{
555 GOutputStream *stream = G_OUTPUT_STREAM (source_object);
556
557 g_output_stream_clear_pending (stream);
558 if (stream->priv->outstanding_callback)
559 (*stream->priv->outstanding_callback) (source_object, res, user_data);
560 g_object_unref (stream);
561}
562
563static void
564async_ready_close_callback_wrapper (GObject *source_object,
565 GAsyncResult *res,
566 gpointer user_data)
567{
568 GOutputStream *stream = G_OUTPUT_STREAM (source_object);
569
570 stream->priv->closed = TRUE;
571 g_output_stream_clear_pending (stream);
572 if (stream->priv->outstanding_callback)
573 (*stream->priv->outstanding_callback) (source_object, res, user_data);
574 g_object_unref (stream);
575}
576
577/**
578 * g_output_stream_write_async:
579 * @stream: A #GOutputStream.
580 * @buffer: the buffer containing the data to write.
581 * @count: the number of bytes to write
582 * @io_priority: the io priority of the request.
583 * @cancellable: optional #GCancellable object, %NULL to ignore.
584 * @callback: callback to call when the request is satisfied
585 * @user_data: the data to pass to callback function
586 *
587 * Request an asynchronous write of @count bytes from @buffer into
588 * the stream. When the operation is finished @callback will be called.
589 * You can then call g_output_stream_write_finish() to get the result of the
590 * operation.
591 *
592 * During an async request no other sync and async calls are allowed,
593 * and will result in %G_IO_ERROR_PENDING errors.
594 *
595 * A value of @count larger than %G_MAXSSIZE will cause a
596 * %G_IO_ERROR_INVALID_ARGUMENT error.
597 *
598 * On success, the number of bytes written will be passed to the
599 * @callback. It is not an error if this is not the same as the
600 * requested size, as it can happen e.g. on a partial I/O error,
601 * but generally we try to write as many bytes as requested.
602 *
603 * Any outstanding I/O request with higher priority (lower numerical
604 * value) will be executed before an outstanding request with lower
605 * priority. Default priority is %G_PRIORITY_DEFAULT.
606 *
607 * The asyncronous methods have a default fallback that uses threads
608 * to implement asynchronicity, so they are optional for inheriting
609 * classes. However, if you override one you must override all.
610 *
611 * For the synchronous, blocking version of this function, see
612 * g_output_stream_write().
613 **/
614void
615g_output_stream_write_async (GOutputStream *stream,
616 const void *buffer,
617 gsize count,
618 int io_priority,
619 GCancellable *cancellable,
620 GAsyncReadyCallback callback,
621 gpointer user_data)
622{
623 GOutputStreamClass *class;
624 GSimpleAsyncResult *simple;
625 GError *error = NULL;
626
627 g_return_if_fail (G_IS_OUTPUT_STREAM (stream));
628 g_return_if_fail (buffer != NULL);
629
630 if (count == 0)
631 {
632 simple = g_simple_async_result_new (G_OBJECT (stream),
633 callback,
634 user_data,
635 g_output_stream_write_async);
636 g_simple_async_result_complete_in_idle (simple);
637 g_object_unref (simple);
638 return;
639 }
640
641 if (((gssize) count) < 0)
642 {
643 g_simple_async_report_error_in_idle (G_OBJECT (stream),
644 callback,
645 user_data,
646 G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT,
647 _("Too large count value passed to %s"),
648 G_STRFUNC);
649 return;
650 }
651
652 if (!g_output_stream_set_pending (stream, &error))
653 {
654 g_simple_async_report_gerror_in_idle (G_OBJECT (stream),
655 callback,
656 user_data,
657 error);
658 g_error_free (error);
659 return;
660 }
661
662 class = G_OUTPUT_STREAM_GET_CLASS (stream);
663
664 stream->priv->outstanding_callback = callback;
665 g_object_ref (stream);
666 class->write_async (stream, buffer, count, io_priority, cancellable,
667 async_ready_callback_wrapper, user_data);
668}
669
670/**
671 * g_output_stream_write_finish:
672 * @stream: a #GOutputStream.
673 * @result: a #GAsyncResult.
674 * @error: a #GError location to store the error occuring, or %NULL to
675 * ignore.
676 *
677 * Finishes a stream write operation.
678 *
679 * Returns: a #gssize containing the number of bytes written to the stream.
680 **/
681gssize
682g_output_stream_write_finish (GOutputStream *stream,
683 GAsyncResult *result,
684 GError **error)
685{
686 GSimpleAsyncResult *simple;
687 GOutputStreamClass *class;
688
689 g_return_val_if_fail (G_IS_OUTPUT_STREAM (stream), -1);
690 g_return_val_if_fail (G_IS_ASYNC_RESULT (result), -1);
691
692 if (G_IS_SIMPLE_ASYNC_RESULT (result))
693 {
694 simple = G_SIMPLE_ASYNC_RESULT (result);
695 if (g_simple_async_result_propagate_error (simple, error))
696 return -1;
697
698 /* Special case writes of 0 bytes */
699 if (g_simple_async_result_get_source_tag (simple) == g_output_stream_write_async)
700 return 0;
701 }
702
703 class = G_OUTPUT_STREAM_GET_CLASS (stream);
704 return class->write_finish (stream, result, error);
705}
706
707typedef struct {
708 GInputStream *source;
709 gpointer user_data;
710 GAsyncReadyCallback callback;
711} SpliceUserData;
712
713static void
714async_ready_splice_callback_wrapper (GObject *source_object,
715 GAsyncResult *res,
716 gpointer _data)
717{
718 GOutputStream *stream = G_OUTPUT_STREAM (source_object);
719 SpliceUserData *data = _data;
720
721 g_output_stream_clear_pending (stream);
722
723 if (data->callback)
724 (*data->callback) (source_object, res, data->user_data);
725
726 g_object_unref (stream);
727 g_object_unref (data->source);
728 g_free (data);
729}
730
731/**
732 * g_output_stream_splice_async:
733 * @stream: a #GOutputStream.
734 * @source: a #GInputStream.
735 * @flags: a set of #GOutputStreamSpliceFlags.
736 * @io_priority: the io priority of the request.
737 * @cancellable: optional #GCancellable object, %NULL to ignore.
738 * @callback: a #GAsyncReadyCallback.
739 * @user_data: user data passed to @callback.
740 *
741 * Splices a stream asynchronously.
742 * When the operation is finished @callback will be called.
743 * You can then call g_output_stream_splice_finish() to get the
744 * result of the operation.
745 *
746 * For the synchronous, blocking version of this function, see
747 * g_output_stream_splice().
748 **/
749void
750g_output_stream_splice_async (GOutputStream *stream,
751 GInputStream *source,
752 GOutputStreamSpliceFlags flags,
753 int io_priority,
754 GCancellable *cancellable,
755 GAsyncReadyCallback callback,
756 gpointer user_data)
757{
758 GOutputStreamClass *class;
759 SpliceUserData *data;
760 GError *error = NULL;
761
762 g_return_if_fail (G_IS_OUTPUT_STREAM (stream));
763 g_return_if_fail (G_IS_INPUT_STREAM (source));
764
765 if (g_input_stream_is_closed (source))
766 {
767 g_simple_async_report_error_in_idle (G_OBJECT (stream),
768 callback,
769 user_data,
770 G_IO_ERROR, G_IO_ERROR_CLOSED,
771 _("Source stream is already closed"));
772 return;
773 }
774
775 if (!g_output_stream_set_pending (stream, &error))
776 {
777 g_simple_async_report_gerror_in_idle (G_OBJECT (stream),
778 callback,
779 user_data,
780 error);
781 g_error_free (error);
782 return;
783 }
784
785 class = G_OUTPUT_STREAM_GET_CLASS (stream);
786
787 data = g_new0 (SpliceUserData, 1);
788 data->callback = callback;
789 data->user_data = user_data;
790 data->source = g_object_ref (source);
791
792 g_object_ref (stream);
793 class->splice_async (stream, source, flags, io_priority, cancellable,
794 async_ready_splice_callback_wrapper, data);
795}
796
797/**
798 * g_output_stream_splice_finish:
799 * @stream: a #GOutputStream.
800 * @result: a #GAsyncResult.
801 * @error: a #GError location to store the error occuring, or %NULL to
802 * ignore.
803 *
804 * Finishes an asynchronous stream splice operation.
805 *
806 * Returns: a #gssize of the number of bytes spliced.
807 **/
808gssize
809g_output_stream_splice_finish (GOutputStream *stream,
810 GAsyncResult *result,
811 GError **error)
812{
813 GSimpleAsyncResult *simple;
814 GOutputStreamClass *class;
815
816 g_return_val_if_fail (G_IS_OUTPUT_STREAM (stream), -1);
817 g_return_val_if_fail (G_IS_ASYNC_RESULT (result), -1);
818
819 if (G_IS_SIMPLE_ASYNC_RESULT (result))
820 {
821 simple = G_SIMPLE_ASYNC_RESULT (result);
822 if (g_simple_async_result_propagate_error (simple, error))
823 return -1;
824 }
825
826 class = G_OUTPUT_STREAM_GET_CLASS (stream);
827 return class->splice_finish (stream, result, error);
828}
829
830/**
831 * g_output_stream_flush_async:
832 * @stream: a #GOutputStream.
833 * @io_priority: the io priority of the request.
834 * @cancellable: optional #GCancellable object, %NULL to ignore.
835 * @callback: a #GAsyncReadyCallback to call when the request is satisfied
836 * @user_data: the data to pass to callback function
837 *
838 * Flushes a stream asynchronously.
839 * For behaviour details see g_output_stream_flush().
840 *
841 * When the operation is finished @callback will be
842 * called. You can then call g_output_stream_flush_finish() to get the
843 * result of the operation.
844 **/
845void
846g_output_stream_flush_async (GOutputStream *stream,
847 int io_priority,
848 GCancellable *cancellable,
849 GAsyncReadyCallback callback,
850 gpointer user_data)
851{
852 GOutputStreamClass *class;
853 GSimpleAsyncResult *simple;
854 GError *error = NULL;
855
856 g_return_if_fail (G_IS_OUTPUT_STREAM (stream));
857
858 if (!g_output_stream_set_pending (stream, &error))
859 {
860 g_simple_async_report_gerror_in_idle (G_OBJECT (stream),
861 callback,
862 user_data,
863 error);
864 g_error_free (error);
865 return;
866 }
867
868 stream->priv->outstanding_callback = callback;
869 g_object_ref (stream);
870
871 class = G_OUTPUT_STREAM_GET_CLASS (stream);
872
873 if (class->flush_async == NULL)
874 {
875 simple = g_simple_async_result_new (G_OBJECT (stream),
876 async_ready_callback_wrapper,
877 user_data,
878 g_output_stream_flush_async);
879 g_simple_async_result_complete_in_idle (simple);
880 g_object_unref (simple);
881 return;
882 }
883
884 class->flush_async (stream, io_priority, cancellable,
885 async_ready_callback_wrapper, user_data);
886}
887
888/**
889 * g_output_stream_flush_finish:
890 * @stream: a #GOutputStream.
891 * @result: a GAsyncResult.
892 * @error: a #GError location to store the error occuring, or %NULL to
893 * ignore.
894 *
895 * Finishes flushing an output stream.
896 *
897 * Returns: %TRUE if flush operation suceeded, %FALSE otherwise.
898 **/
899gboolean
900g_output_stream_flush_finish (GOutputStream *stream,
901 GAsyncResult *result,
902 GError **error)
903{
904 GSimpleAsyncResult *simple;
905 GOutputStreamClass *klass;
906
907 g_return_val_if_fail (G_IS_OUTPUT_STREAM (stream), FALSE);
908 g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
909
910 if (G_IS_SIMPLE_ASYNC_RESULT (result))
911 {
912 simple = G_SIMPLE_ASYNC_RESULT (result);
913 if (g_simple_async_result_propagate_error (simple, error))
914 return FALSE;
915
916 /* Special case default implementation */
917 if (g_simple_async_result_get_source_tag (simple) == g_output_stream_flush_async)
918 return TRUE;
919 }
920
921 klass = G_OUTPUT_STREAM_GET_CLASS (stream);
922 return klass->flush_finish (stream, result, error);
923}
924
925
926/**
927 * g_output_stream_close_async:
928 * @stream: A #GOutputStream.
929 * @io_priority: the io priority of the request.
930 * @callback: callback to call when the request is satisfied
931 * @user_data: the data to pass to callback function
932 * @cancellable: optional cancellable object
933 *
934 * Requests an asynchronous close of the stream, releasing resources
935 * related to it. When the operation is finished @callback will be
936 * called. You can then call g_output_stream_close_finish() to get
937 * the result of the operation.
938 *
939 * For behaviour details see g_output_stream_close().
940 *
941 * The asyncronous methods have a default fallback that uses threads
942 * to implement asynchronicity, so they are optional for inheriting
943 * classes. However, if you override one you must override all.
944 **/
945void
946g_output_stream_close_async (GOutputStream *stream,
947 int io_priority,
948 GCancellable *cancellable,
949 GAsyncReadyCallback callback,
950 gpointer user_data)
951{
952 GOutputStreamClass *class;
953 GSimpleAsyncResult *simple;
954 GError *error = NULL;
955
956 g_return_if_fail (G_IS_OUTPUT_STREAM (stream));
957
958 if (stream->priv->closed)
959 {
960 simple = g_simple_async_result_new (G_OBJECT (stream),
961 callback,
962 user_data,
963 g_output_stream_close_async);
964 g_simple_async_result_complete_in_idle (simple);
965 g_object_unref (simple);
966 return;
967 }
968
969 if (!g_output_stream_set_pending (stream, &error))
970 {
971 g_simple_async_report_gerror_in_idle (G_OBJECT (stream),
972 callback,
973 user_data,
974 error);
975 g_error_free (error);
976 return;
977 }
978
979 class = G_OUTPUT_STREAM_GET_CLASS (stream);
980 stream->priv->outstanding_callback = callback;
981 g_object_ref (stream);
982 class->close_async (stream, io_priority, cancellable,
983 async_ready_close_callback_wrapper, user_data);
984}
985
986/**
987 * g_output_stream_close_finish:
988 * @stream: a #GOutputStream.
989 * @result: a #GAsyncResult.
990 * @error: a #GError location to store the error occuring, or %NULL to
991 * ignore.
992 *
993 * Closes an output stream.
994 *
995 * Returns: %TRUE if stream was successfully closed, %FALSE otherwise.
996 **/
997gboolean
998g_output_stream_close_finish (GOutputStream *stream,
999 GAsyncResult *result,
1000 GError **error)
1001{
1002 GSimpleAsyncResult *simple;
1003 GOutputStreamClass *class;
1004
1005 g_return_val_if_fail (G_IS_OUTPUT_STREAM (stream), FALSE);
1006 g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
1007
1008 if (G_IS_SIMPLE_ASYNC_RESULT (result))
1009 {
1010 simple = G_SIMPLE_ASYNC_RESULT (result);
1011 if (g_simple_async_result_propagate_error (simple, error))
1012 return FALSE;
1013
1014 /* Special case already closed */
1015 if (g_simple_async_result_get_source_tag (simple) == g_output_stream_close_async)
1016 return TRUE;
1017 }
1018
1019 class = G_OUTPUT_STREAM_GET_CLASS (stream);
1020 return class->close_finish (stream, result, error);
1021}
1022
1023/**
1024 * g_output_stream_is_closed:
1025 * @stream: a #GOutputStream.
1026 *
1027 * Checks if an output stream has already been closed.
1028 *
1029 * Returns: %TRUE if @stream is closed. %FALSE otherwise.
1030 **/
1031gboolean
1032g_output_stream_is_closed (GOutputStream *stream)
1033{
1034 g_return_val_if_fail (G_IS_OUTPUT_STREAM (stream), TRUE);
1035
1036 return stream->priv->closed;
1037}
1038
1039/**
1040 * g_output_stream_has_pending:
1041 * @stream: a #GOutputStream.
1042 *
1043 * Checks if an ouput stream has pending actions.
1044 *
1045 * Returns: %TRUE if @stream has pending actions.
1046 **/
1047gboolean
1048g_output_stream_has_pending (GOutputStream *stream)
1049{
1050 g_return_val_if_fail (G_IS_OUTPUT_STREAM (stream), FALSE);
1051
1052 return stream->priv->pending;
1053}
1054
1055/**
1056 * g_output_stream_set_pending:
1057 * @stream: a #GOutputStream.
1058 * @error: a #GError location to store the error occuring, or %NULL to
1059 * ignore.
1060 *
1061 * Sets @stream to have actions pending. If the pending flag is
1062 * already set or @stream is closed, it will return %FALSE and set
1063 * @error.
1064 *
1065 * Return value: %TRUE if pending was previously unset and is now set.
1066 **/
1067gboolean
1068g_output_stream_set_pending (GOutputStream *stream,
1069 GError **error)
1070{
1071 g_return_val_if_fail (G_IS_OUTPUT_STREAM (stream), FALSE);
1072
1073 if (stream->priv->closed)
1074 {
1075 g_set_error (error, G_IO_ERROR, G_IO_ERROR_CLOSED,
1076 _("Stream is already closed"));
1077 return FALSE;
1078 }
1079
1080 if (stream->priv->pending)
1081 {
1082 g_set_error (error, G_IO_ERROR, G_IO_ERROR_PENDING,
1083 /* Translators: This is an error you get if there is
1084 * already an operation running against this stream when
1085 * you try to start one */
1086 _("Stream has outstanding operation"));
1087 return FALSE;
1088 }
1089
1090 stream->priv->pending = TRUE;
1091 return TRUE;
1092}
1093
1094/**
1095 * g_output_stream_clear_pending:
1096 * @stream: output stream
1097 *
1098 * Clears the pending flag on @stream.
1099 **/
1100void
1101g_output_stream_clear_pending (GOutputStream *stream)
1102{
1103 g_return_if_fail (G_IS_OUTPUT_STREAM (stream));
1104
1105 stream->priv->pending = FALSE;
1106}
1107
1108
1109/********************************************
1110 * Default implementation of async ops *
1111 ********************************************/
1112
1113typedef struct {
1114 const void *buffer;
1115 gsize count_requested;
1116 gssize count_written;
1117} WriteData;
1118
1119static void
1120write_async_thread (GSimpleAsyncResult *res,
1121 GObject *object,
1122 GCancellable *cancellable)
1123{
1124 WriteData *op;
1125 GOutputStreamClass *class;
1126 GError *error = NULL;
1127
1128 class = G_OUTPUT_STREAM_GET_CLASS (object);
1129 op = g_simple_async_result_get_op_res_gpointer (res);
1130 op->count_written = class->write_fn (G_OUTPUT_STREAM (object), op->buffer, op->count_requested,
1131 cancellable, &error);
1132 if (op->count_written == -1)
1133 {
1134 g_simple_async_result_set_from_error (res, error);
1135 g_error_free (error);
1136 }
1137}
1138
1139static void
1140g_output_stream_real_write_async (GOutputStream *stream,
1141 const void *buffer,
1142 gsize count,
1143 int io_priority,
1144 GCancellable *cancellable,
1145 GAsyncReadyCallback callback,
1146 gpointer user_data)
1147{
1148 GSimpleAsyncResult *res;
1149 WriteData *op;
1150
1151 op = g_new0 (WriteData, 1);
1152 res = g_simple_async_result_new (G_OBJECT (stream), callback, user_data, g_output_stream_real_write_async);
1153 g_simple_async_result_set_op_res_gpointer (res, op, g_free);
1154 op->buffer = buffer;
1155 op->count_requested = count;
1156
1157 g_simple_async_result_run_in_thread (res, write_async_thread, io_priority, cancellable);
1158 g_object_unref (res);
1159}
1160
1161static gssize
1162g_output_stream_real_write_finish (GOutputStream *stream,
1163 GAsyncResult *result,
1164 GError **error)
1165{
1166 GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (result);
1167 WriteData *op;
1168
1169 g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == g_output_stream_real_write_async);
1170 op = g_simple_async_result_get_op_res_gpointer (simple);
1171 return op->count_written;
1172}
1173
1174typedef struct {
1175 GInputStream *source;
1176 GOutputStreamSpliceFlags flags;
1177 gssize bytes_copied;
1178} SpliceData;
1179
1180static void
1181splice_async_thread (GSimpleAsyncResult *result,
1182 GObject *object,
1183 GCancellable *cancellable)
1184{
1185 SpliceData *op;
1186 GOutputStreamClass *class;
1187 GError *error = NULL;
1188 GOutputStream *stream;
1189
1190 stream = G_OUTPUT_STREAM (object);
1191 class = G_OUTPUT_STREAM_GET_CLASS (object);
1192 op = g_simple_async_result_get_op_res_gpointer (result);
1193
1194 op->bytes_copied = class->splice (stream,
1195 op->source,
1196 op->flags,
1197 cancellable,
1198 &error);
1199 if (op->bytes_copied == -1)
1200 {
1201 g_simple_async_result_set_from_error (result, error);
1202 g_error_free (error);
1203 }
1204}
1205
1206static void
1207g_output_stream_real_splice_async (GOutputStream *stream,
1208 GInputStream *source,
1209 GOutputStreamSpliceFlags flags,
1210 int io_priority,
1211 GCancellable *cancellable,
1212 GAsyncReadyCallback callback,
1213 gpointer user_data)
1214{
1215 GSimpleAsyncResult *res;
1216 SpliceData *op;
1217
1218 op = g_new0 (SpliceData, 1);
1219 res = g_simple_async_result_new (G_OBJECT (stream), callback, user_data, g_output_stream_real_splice_async);
1220 g_simple_async_result_set_op_res_gpointer (res, op, g_free);
1221 op->flags = flags;
1222 op->source = source;
1223
1224 /* TODO: In the case where both source and destintion have
1225 non-threadbased async calls we can use a true async copy here */
1226
1227 g_simple_async_result_run_in_thread (res, splice_async_thread, io_priority, cancellable);
1228 g_object_unref (res);
1229}
1230
1231static gssize
1232g_output_stream_real_splice_finish (GOutputStream *stream,
1233 GAsyncResult *result,
1234 GError **error)
1235{
1236 GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (result);
1237 SpliceData *op;
1238
1239 g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == g_output_stream_real_splice_async);
1240 op = g_simple_async_result_get_op_res_gpointer (simple);
1241 return op->bytes_copied;
1242}
1243
1244
1245static void
1246flush_async_thread (GSimpleAsyncResult *res,
1247 GObject *object,
1248 GCancellable *cancellable)
1249{
1250 GOutputStreamClass *class;
1251 gboolean result;
1252 GError *error = NULL;
1253
1254 class = G_OUTPUT_STREAM_GET_CLASS (object);
1255 result = TRUE;
1256 if (class->flush)
1257 result = class->flush (G_OUTPUT_STREAM (object), cancellable, &error);
1258
1259 if (!result)
1260 {
1261 g_simple_async_result_set_from_error (res, error);
1262 g_error_free (error);
1263 }
1264}
1265
1266static void
1267g_output_stream_real_flush_async (GOutputStream *stream,
1268 int io_priority,
1269 GCancellable *cancellable,
1270 GAsyncReadyCallback callback,
1271 gpointer user_data)
1272{
1273 GSimpleAsyncResult *res;
1274
1275 res = g_simple_async_result_new (G_OBJECT (stream), callback, user_data, g_output_stream_real_write_async);
1276
1277 g_simple_async_result_run_in_thread (res, flush_async_thread, io_priority, cancellable);
1278 g_object_unref (res);
1279}
1280
1281static gboolean
1282g_output_stream_real_flush_finish (GOutputStream *stream,
1283 GAsyncResult *result,
1284 GError **error)
1285{
1286 return TRUE;
1287}
1288
1289static void
1290close_async_thread (GSimpleAsyncResult *res,
1291 GObject *object,
1292 GCancellable *cancellable)
1293{
1294 GOutputStreamClass *class;
1295 GError *error = NULL;
1296 gboolean result;
1297
1298 /* Auto handling of cancelation disabled, and ignore
1299 cancellation, since we want to close things anyway, although
1300 possibly in a quick-n-dirty way. At least we never want to leak
1301 open handles */
1302
1303 class = G_OUTPUT_STREAM_GET_CLASS (object);
1304 result = class->close_fn (G_OUTPUT_STREAM (object), cancellable, &error);
1305 if (!result)
1306 {
1307 g_simple_async_result_set_from_error (res, error);
1308 g_error_free (error);
1309 }
1310}
1311
1312static void
1313g_output_stream_real_close_async (GOutputStream *stream,
1314 int io_priority,
1315 GCancellable *cancellable,
1316 GAsyncReadyCallback callback,
1317 gpointer user_data)
1318{
1319 GSimpleAsyncResult *res;
1320
1321 res = g_simple_async_result_new (G_OBJECT (stream), callback, user_data, g_output_stream_real_close_async);
1322
1323 g_simple_async_result_set_handle_cancellation (res, FALSE);
1324
1325 g_simple_async_result_run_in_thread (res, close_async_thread, io_priority, cancellable);
1326 g_object_unref (res);
1327}
1328
1329static gboolean
1330g_output_stream_real_close_finish (GOutputStream *stream,
1331 GAsyncResult *result,
1332 GError **error)
1333{
1334 GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (result);
1335 g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == g_output_stream_real_close_async);
1336 return TRUE;
1337}
1338
1339#define __G_OUTPUT_STREAM_C__
1340#include "gioaliasdef.c"