1 /* GIO - GLib Input, Output and Streaming Library
3 * Copyright (C) 2006-2007 Red Hat, Inc.
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.
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.
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.
20 * Author: Alexander Larsson <alexl@redhat.com>
26 #include <gfileinputstream.h>
27 #include <gseekable.h>
28 #include "gsimpleasyncresult.h"
31 static void g_file_input_stream_seekable_iface_init (GSeekableIface *iface);
32 static goffset g_file_input_stream_seekable_tell (GSeekable *seekable);
33 static gboolean g_file_input_stream_seekable_can_seek (GSeekable *seekable);
34 static gboolean g_file_input_stream_seekable_seek (GSeekable *seekable,
37 GCancellable *cancellable,
39 static gboolean g_file_input_stream_seekable_can_truncate (GSeekable *seekable);
40 static gboolean g_file_input_stream_seekable_truncate (GSeekable *seekable,
42 GCancellable *cancellable,
44 static void g_file_input_stream_real_query_info_async (GFileInputStream *stream,
47 GCancellable *cancellable,
48 GAsyncReadyCallback callback,
50 static GFileInfo *g_file_input_stream_real_query_info_finish (GFileInputStream *stream,
55 G_DEFINE_TYPE_WITH_CODE (GFileInputStream, g_file_input_stream, G_TYPE_INPUT_STREAM,
56 G_IMPLEMENT_INTERFACE (G_TYPE_SEEKABLE,
57 g_file_input_stream_seekable_iface_init))
59 struct _GFileInputStreamPrivate {
60 GAsyncReadyCallback outstanding_callback;
64 g_file_input_stream_class_init (GFileInputStreamClass *klass)
66 g_type_class_add_private (klass, sizeof (GFileInputStreamPrivate));
68 klass->query_info_async = g_file_input_stream_real_query_info_async;
69 klass->query_info_finish = g_file_input_stream_real_query_info_finish;
73 g_file_input_stream_seekable_iface_init (GSeekableIface *iface)
75 iface->tell = g_file_input_stream_seekable_tell;
76 iface->can_seek = g_file_input_stream_seekable_can_seek;
77 iface->seek = g_file_input_stream_seekable_seek;
78 iface->can_truncate = g_file_input_stream_seekable_can_truncate;
79 iface->truncate = g_file_input_stream_seekable_truncate;
83 g_file_input_stream_init (GFileInputStream *stream)
85 stream->priv = G_TYPE_INSTANCE_GET_PRIVATE (stream,
86 G_TYPE_FILE_INPUT_STREAM,
87 GFileInputStreamPrivate);
91 * g_file_input_stream_query_info:
94 * @cancellable: optional #GCancellable object, %NULL to ignore.
95 * @error: a #GError location to store the error occuring, or %NULL to
100 g_file_input_stream_query_info (GFileInputStream *stream,
102 GCancellable *cancellable,
105 GFileInputStreamClass *class;
106 GInputStream *input_stream;
109 g_return_val_if_fail (G_IS_FILE_INPUT_STREAM (stream), NULL);
111 input_stream = G_INPUT_STREAM (stream);
113 if (g_input_stream_is_closed (input_stream))
115 g_set_error (error, G_IO_ERROR, G_IO_ERROR_CLOSED,
116 _("Stream is already closed"));
120 if (g_input_stream_has_pending (input_stream))
122 g_set_error (error, G_IO_ERROR, G_IO_ERROR_PENDING,
123 _("Stream has outstanding operation"));
129 g_input_stream_set_pending (input_stream, TRUE);
132 g_push_current_cancellable (cancellable);
134 class = G_FILE_INPUT_STREAM_GET_CLASS (stream);
135 if (class->query_info)
136 info = class->query_info (stream, attributes, cancellable, error);
138 g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
139 _("Stream doesn't support query_info"));
142 g_pop_current_cancellable (cancellable);
144 g_input_stream_set_pending (input_stream, FALSE);
150 async_ready_callback_wrapper (GObject *source_object,
154 GFileInputStream *stream = G_FILE_INPUT_STREAM (source_object);
156 g_input_stream_set_pending (G_INPUT_STREAM (stream), FALSE);
157 if (stream->priv->outstanding_callback)
158 (*stream->priv->outstanding_callback) (source_object, res, user_data);
159 g_object_unref (stream);
163 * g_file_input_stream_query_info_async:
166 * @io_priority: the io priority of the request.
167 * @cancellable: optional #GCancellable object, %NULL to ignore. @callback:
172 g_file_input_stream_query_info_async (GFileInputStream *stream,
175 GCancellable *cancellable,
176 GAsyncReadyCallback callback,
179 GFileInputStreamClass *klass;
180 GInputStream *input_stream;
182 g_return_if_fail (G_IS_FILE_INPUT_STREAM (stream));
184 input_stream = G_INPUT_STREAM (stream);
186 if (g_input_stream_is_closed (input_stream))
188 g_simple_async_report_error_in_idle (G_OBJECT (stream),
191 G_IO_ERROR, G_IO_ERROR_CLOSED,
192 _("Stream is already closed"));
196 if (g_input_stream_has_pending (input_stream))
198 g_simple_async_report_error_in_idle (G_OBJECT (stream),
201 G_IO_ERROR, G_IO_ERROR_PENDING,
202 _("Stream has outstanding operation"));
206 klass = G_FILE_INPUT_STREAM_GET_CLASS (stream);
208 g_input_stream_set_pending (input_stream, TRUE);
209 stream->priv->outstanding_callback = callback;
210 g_object_ref (stream);
211 klass->query_info_async (stream, attributes, io_priority, cancellable,
212 async_ready_callback_wrapper, user_data);
216 * g_file_input_stream_query_info_finish:
219 * @error: a #GError location to store the error occuring, or %NULL to
221 * Returns: #GFileInfo.
224 g_file_input_stream_query_info_finish (GFileInputStream *stream,
225 GAsyncResult *result,
228 GSimpleAsyncResult *simple;
229 GFileInputStreamClass *class;
231 g_return_val_if_fail (G_IS_FILE_INPUT_STREAM (stream), NULL);
232 g_return_val_if_fail (G_IS_ASYNC_RESULT (result), NULL);
234 if (G_IS_SIMPLE_ASYNC_RESULT (result))
236 simple = G_SIMPLE_ASYNC_RESULT (result);
237 if (g_simple_async_result_propagate_error (simple, error))
241 class = G_FILE_INPUT_STREAM_GET_CLASS (stream);
242 return class->query_info_finish (stream, result, error);
246 * g_file_input_stream_tell:
252 g_file_input_stream_tell (GFileInputStream *stream)
254 GFileInputStreamClass *class;
257 g_return_val_if_fail (G_IS_FILE_INPUT_STREAM (stream), 0);
259 class = G_FILE_INPUT_STREAM_GET_CLASS (stream);
263 offset = class->tell (stream);
269 g_file_input_stream_seekable_tell (GSeekable *seekable)
271 return g_file_input_stream_tell (G_FILE_INPUT_STREAM (seekable));
275 * g_file_input_stream_can_seek:
278 * Returns: %TRUE if stream can be seeked. %FALSE otherwise.
281 g_file_input_stream_can_seek (GFileInputStream *stream)
283 GFileInputStreamClass *class;
286 g_return_val_if_fail (G_IS_FILE_INPUT_STREAM (stream), FALSE);
288 class = G_FILE_INPUT_STREAM_GET_CLASS (stream);
295 can_seek = class->can_seek (stream);
302 g_file_input_stream_seekable_can_seek (GSeekable *seekable)
304 return g_file_input_stream_can_seek (G_FILE_INPUT_STREAM (seekable));
308 * g_file_input_stream_seek:
312 * @cancellable: optional #GCancellable object, %NULL to ignore.
313 * @error: a #GError location to store the error occuring, or %NULL to
318 g_file_input_stream_seek (GFileInputStream *stream,
321 GCancellable *cancellable,
324 GFileInputStreamClass *class;
325 GInputStream *input_stream;
328 g_return_val_if_fail (G_IS_FILE_INPUT_STREAM (stream), FALSE);
330 input_stream = G_INPUT_STREAM (stream);
331 class = G_FILE_INPUT_STREAM_GET_CLASS (stream);
333 if (g_input_stream_is_closed (input_stream))
335 g_set_error (error, G_IO_ERROR, G_IO_ERROR_CLOSED,
336 _("Stream is already closed"));
340 if (g_input_stream_has_pending (input_stream))
342 g_set_error (error, G_IO_ERROR, G_IO_ERROR_PENDING,
343 _("Stream has outstanding operation"));
349 g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
350 _("Seek not supported on stream"));
354 g_input_stream_set_pending (input_stream, TRUE);
357 g_push_current_cancellable (cancellable);
359 res = class->seek (stream, offset, type, cancellable, error);
362 g_pop_current_cancellable (cancellable);
364 g_input_stream_set_pending (input_stream, FALSE);
370 g_file_input_stream_seekable_seek (GSeekable *seekable,
373 GCancellable *cancellable,
376 return g_file_input_stream_seek (G_FILE_INPUT_STREAM (seekable),
377 offset, type, cancellable, error);
381 g_file_input_stream_seekable_can_truncate (GSeekable *seekable)
387 g_file_input_stream_seekable_truncate (GSeekable *seekable,
389 GCancellable *cancellable,
392 g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
393 _("Truncate not allowed on input stream"));
397 /********************************************
398 * Default implementation of async ops *
399 ********************************************/
404 } QueryInfoAsyncData;
407 query_info_data_free (QueryInfoAsyncData *data)
410 g_object_unref (data->info);
411 g_free (data->attributes);
416 query_info_async_thread (GSimpleAsyncResult *res,
418 GCancellable *cancellable)
420 GFileInputStreamClass *class;
421 GError *error = NULL;
422 QueryInfoAsyncData *data;
425 data = g_simple_async_result_get_op_res_gpointer (res);
429 class = G_FILE_INPUT_STREAM_GET_CLASS (object);
430 if (class->query_info)
431 info = class->query_info (G_FILE_INPUT_STREAM (object), data->attributes, cancellable, &error);
433 g_set_error (&error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
434 _("Stream doesn't support query_info"));
438 g_simple_async_result_set_from_error (res, error);
439 g_error_free (error);
446 g_file_input_stream_real_query_info_async (GFileInputStream *stream,
449 GCancellable *cancellable,
450 GAsyncReadyCallback callback,
453 GSimpleAsyncResult *res;
454 QueryInfoAsyncData *data;
456 data = g_new0 (QueryInfoAsyncData, 1);
457 data->attributes = g_strdup (attributes);
459 res = g_simple_async_result_new (G_OBJECT (stream), callback, user_data, g_file_input_stream_real_query_info_async);
460 g_simple_async_result_set_op_res_gpointer (res, data, (GDestroyNotify)query_info_data_free);
462 g_simple_async_result_run_in_thread (res, query_info_async_thread, io_priority, cancellable);
463 g_object_unref (res);
467 g_file_input_stream_real_query_info_finish (GFileInputStream *stream,
471 GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (res);
472 QueryInfoAsyncData *data;
474 g_assert (g_simple_async_result_get_source_tag (simple) == g_file_input_stream_real_query_info_async);
476 data = g_simple_async_result_get_op_res_gpointer (simple);
478 return g_object_ref (data->info);