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"
29 #include "gcancellable.h"
30 #include "gasyncresult.h"
37 * SECTION:gfileinputstream
38 * @short_description: File input streaming operations
40 * @see_also: #GInputStream, #GDataInputStream, #GSeekable
42 * GFileInputStream provides input streams that take their
43 * content from a file.
45 * GFileInputStream implements #GSeekable, which allows the input
46 * stream to jump to arbitrary positions in the file, provided the
47 * filesystem of the file allows it. To find the position of a file
48 * input stream, use g_seekable_tell(). To find out if a file input
49 * stream supports seeking, use g_seekable_stream_can_seek().
50 * To position a file input stream, use g_seekable_seek().
53 static void g_file_input_stream_seekable_iface_init (GSeekableIface *iface);
54 static goffset g_file_input_stream_seekable_tell (GSeekable *seekable);
55 static gboolean g_file_input_stream_seekable_can_seek (GSeekable *seekable);
56 static gboolean g_file_input_stream_seekable_seek (GSeekable *seekable,
59 GCancellable *cancellable,
61 static gboolean g_file_input_stream_seekable_can_truncate (GSeekable *seekable);
62 static gboolean g_file_input_stream_seekable_truncate (GSeekable *seekable,
64 GCancellable *cancellable,
66 static void g_file_input_stream_real_query_info_async (GFileInputStream *stream,
67 const char *attributes,
69 GCancellable *cancellable,
70 GAsyncReadyCallback callback,
72 static GFileInfo *g_file_input_stream_real_query_info_finish (GFileInputStream *stream,
77 G_DEFINE_TYPE_WITH_CODE (GFileInputStream, g_file_input_stream, G_TYPE_INPUT_STREAM,
78 G_IMPLEMENT_INTERFACE (G_TYPE_SEEKABLE,
79 g_file_input_stream_seekable_iface_init))
81 struct _GFileInputStreamPrivate {
82 GAsyncReadyCallback outstanding_callback;
86 g_file_input_stream_class_init (GFileInputStreamClass *klass)
88 g_type_class_add_private (klass, sizeof (GFileInputStreamPrivate));
90 klass->query_info_async = g_file_input_stream_real_query_info_async;
91 klass->query_info_finish = g_file_input_stream_real_query_info_finish;
95 g_file_input_stream_seekable_iface_init (GSeekableIface *iface)
97 iface->tell = g_file_input_stream_seekable_tell;
98 iface->can_seek = g_file_input_stream_seekable_can_seek;
99 iface->seek = g_file_input_stream_seekable_seek;
100 iface->can_truncate = g_file_input_stream_seekable_can_truncate;
101 iface->truncate_fn = g_file_input_stream_seekable_truncate;
105 g_file_input_stream_init (GFileInputStream *stream)
107 stream->priv = G_TYPE_INSTANCE_GET_PRIVATE (stream,
108 G_TYPE_FILE_INPUT_STREAM,
109 GFileInputStreamPrivate);
113 * g_file_input_stream_query_info:
114 * @stream: a #GFileInputStream.
115 * @attributes: a file attribute query string.
116 * @cancellable: optional #GCancellable object, %NULL to ignore.
117 * @error: a #GError location to store the error occuring, or %NULL to
120 * Queries a file input stream the given @attributes. This function blocks
121 * while querying the stream. For the asynchronous (non-blocking) version
122 * of this function, see g_file_input_stream_query_info_async(). While the
123 * stream is blocked, the stream will set the pending flag internally, and
124 * any other operations on the stream will fail with %G_IO_ERROR_PENDING.
126 * Returns: a #GFileInfo, or %NULL on error.
129 g_file_input_stream_query_info (GFileInputStream *stream,
130 const char *attributes,
131 GCancellable *cancellable,
134 GFileInputStreamClass *class;
135 GInputStream *input_stream;
138 g_return_val_if_fail (G_IS_FILE_INPUT_STREAM (stream), NULL);
140 input_stream = G_INPUT_STREAM (stream);
142 if (!g_input_stream_set_pending (input_stream, error))
148 g_cancellable_push_current (cancellable);
150 class = G_FILE_INPUT_STREAM_GET_CLASS (stream);
151 if (class->query_info)
152 info = class->query_info (stream, attributes, cancellable, error);
154 g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
155 _("Stream doesn't support query_info"));
158 g_cancellable_pop_current (cancellable);
160 g_input_stream_clear_pending (input_stream);
166 async_ready_callback_wrapper (GObject *source_object,
170 GFileInputStream *stream = G_FILE_INPUT_STREAM (source_object);
172 g_input_stream_clear_pending (G_INPUT_STREAM (stream));
173 if (stream->priv->outstanding_callback)
174 (*stream->priv->outstanding_callback) (source_object, res, user_data);
175 g_object_unref (stream);
179 * g_file_input_stream_query_info_async:
180 * @stream: a #GFileInputStream.
181 * @attributes: a file attribute query string.
182 * @io_priority: the <link linkend="io-priority">I/O priority</link>
184 * @cancellable: optional #GCancellable object, %NULL to ignore.
185 * @callback: callback to call when the request is satisfied
186 * @user_data: the data to pass to callback function
188 * Queries the stream information asynchronously.
189 * When the operation is finished @callback will be called.
190 * You can then call g_file_input_stream_query_info_finish()
191 * to get the result of the operation.
193 * For the synchronous version of this function,
194 * see g_file_input_stream_query_info().
196 * If @cancellable is not %NULL, then the operation can be cancelled by
197 * triggering the cancellable object from another thread. If the operation
198 * was cancelled, the error %G_IO_ERROR_CANCELLED will be set
202 g_file_input_stream_query_info_async (GFileInputStream *stream,
203 const char *attributes,
205 GCancellable *cancellable,
206 GAsyncReadyCallback callback,
209 GFileInputStreamClass *klass;
210 GInputStream *input_stream;
211 GError *error = NULL;
213 g_return_if_fail (G_IS_FILE_INPUT_STREAM (stream));
215 input_stream = G_INPUT_STREAM (stream);
217 if (!g_input_stream_set_pending (input_stream, &error))
219 g_simple_async_report_gerror_in_idle (G_OBJECT (stream),
223 g_error_free (error);
227 klass = G_FILE_INPUT_STREAM_GET_CLASS (stream);
229 stream->priv->outstanding_callback = callback;
230 g_object_ref (stream);
231 klass->query_info_async (stream, attributes, io_priority, cancellable,
232 async_ready_callback_wrapper, user_data);
236 * g_file_input_stream_query_info_finish:
237 * @stream: a #GFileInputStream.
238 * @result: a #GAsyncResult.
239 * @error: a #GError location to store the error occuring,
240 * or %NULL to ignore.
242 * Finishes an asynchronous info query operation.
244 * Returns: #GFileInfo.
247 g_file_input_stream_query_info_finish (GFileInputStream *stream,
248 GAsyncResult *result,
251 GSimpleAsyncResult *simple;
252 GFileInputStreamClass *class;
254 g_return_val_if_fail (G_IS_FILE_INPUT_STREAM (stream), NULL);
255 g_return_val_if_fail (G_IS_ASYNC_RESULT (result), NULL);
257 if (G_IS_SIMPLE_ASYNC_RESULT (result))
259 simple = G_SIMPLE_ASYNC_RESULT (result);
260 if (g_simple_async_result_propagate_error (simple, error))
264 class = G_FILE_INPUT_STREAM_GET_CLASS (stream);
265 return class->query_info_finish (stream, result, error);
269 g_file_input_stream_tell (GFileInputStream *stream)
271 GFileInputStreamClass *class;
274 g_return_val_if_fail (G_IS_FILE_INPUT_STREAM (stream), 0);
276 class = G_FILE_INPUT_STREAM_GET_CLASS (stream);
280 offset = class->tell (stream);
286 g_file_input_stream_seekable_tell (GSeekable *seekable)
288 return g_file_input_stream_tell (G_FILE_INPUT_STREAM (seekable));
292 g_file_input_stream_can_seek (GFileInputStream *stream)
294 GFileInputStreamClass *class;
297 g_return_val_if_fail (G_IS_FILE_INPUT_STREAM (stream), FALSE);
299 class = G_FILE_INPUT_STREAM_GET_CLASS (stream);
306 can_seek = class->can_seek (stream);
313 g_file_input_stream_seekable_can_seek (GSeekable *seekable)
315 return g_file_input_stream_can_seek (G_FILE_INPUT_STREAM (seekable));
319 g_file_input_stream_seek (GFileInputStream *stream,
322 GCancellable *cancellable,
325 GFileInputStreamClass *class;
326 GInputStream *input_stream;
329 g_return_val_if_fail (G_IS_FILE_INPUT_STREAM (stream), FALSE);
331 input_stream = G_INPUT_STREAM (stream);
332 class = G_FILE_INPUT_STREAM_GET_CLASS (stream);
336 g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
337 _("Seek not supported on stream"));
341 if (!g_input_stream_set_pending (input_stream, error))
345 g_cancellable_push_current (cancellable);
347 res = class->seek (stream, offset, type, cancellable, error);
350 g_cancellable_pop_current (cancellable);
352 g_input_stream_clear_pending (input_stream);
358 g_file_input_stream_seekable_seek (GSeekable *seekable,
361 GCancellable *cancellable,
364 return g_file_input_stream_seek (G_FILE_INPUT_STREAM (seekable),
365 offset, type, cancellable, error);
369 g_file_input_stream_seekable_can_truncate (GSeekable *seekable)
375 g_file_input_stream_seekable_truncate (GSeekable *seekable,
377 GCancellable *cancellable,
380 g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
381 _("Truncate not allowed on input stream"));
385 /********************************************
386 * Default implementation of async ops *
387 ********************************************/
392 } QueryInfoAsyncData;
395 query_info_data_free (QueryInfoAsyncData *data)
398 g_object_unref (data->info);
399 g_free (data->attributes);
404 query_info_async_thread (GSimpleAsyncResult *res,
406 GCancellable *cancellable)
408 GFileInputStreamClass *class;
409 GError *error = NULL;
410 QueryInfoAsyncData *data;
413 data = g_simple_async_result_get_op_res_gpointer (res);
417 class = G_FILE_INPUT_STREAM_GET_CLASS (object);
418 if (class->query_info)
419 info = class->query_info (G_FILE_INPUT_STREAM (object), data->attributes, cancellable, &error);
421 g_set_error_literal (&error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
422 _("Stream doesn't support query_info"));
426 g_simple_async_result_set_from_error (res, error);
427 g_error_free (error);
434 g_file_input_stream_real_query_info_async (GFileInputStream *stream,
435 const char *attributes,
437 GCancellable *cancellable,
438 GAsyncReadyCallback callback,
441 GSimpleAsyncResult *res;
442 QueryInfoAsyncData *data;
444 data = g_new0 (QueryInfoAsyncData, 1);
445 data->attributes = g_strdup (attributes);
447 res = g_simple_async_result_new (G_OBJECT (stream), callback, user_data, g_file_input_stream_real_query_info_async);
448 g_simple_async_result_set_op_res_gpointer (res, data, (GDestroyNotify)query_info_data_free);
450 g_simple_async_result_run_in_thread (res, query_info_async_thread, io_priority, cancellable);
451 g_object_unref (res);
455 g_file_input_stream_real_query_info_finish (GFileInputStream *stream,
459 GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (res);
460 QueryInfoAsyncData *data;
462 g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == g_file_input_stream_real_query_info_async);
464 data = g_simple_async_result_get_op_res_gpointer (simple);
466 return g_object_ref (data->info);
471 #define __G_FILE_INPUT_STREAM_C__
472 #include "gioaliasdef.c"