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. In addition to the generic
48 * g_seekable_ API, GFileInputStream has its own API for seeking
49 * and positioning. To find the position of a file input stream,
50 * use g_file_input_stream_tell(). To find out if a file input
51 * stream supports seeking, use g_file_input_stream_can_seek().
52 * To position a file input stream, use g_file_input_stream_seek().
55 static void g_file_input_stream_seekable_iface_init (GSeekableIface
*iface
);
56 static goffset
g_file_input_stream_seekable_tell (GSeekable
*seekable
);
57 static gboolean
g_file_input_stream_seekable_can_seek (GSeekable
*seekable
);
58 static gboolean
g_file_input_stream_seekable_seek (GSeekable
*seekable
,
61 GCancellable
*cancellable
,
63 static gboolean
g_file_input_stream_seekable_can_truncate (GSeekable
*seekable
);
64 static gboolean
g_file_input_stream_seekable_truncate (GSeekable
*seekable
,
66 GCancellable
*cancellable
,
68 static void g_file_input_stream_real_query_info_async (GFileInputStream
*stream
,
71 GCancellable
*cancellable
,
72 GAsyncReadyCallback callback
,
74 static GFileInfo
*g_file_input_stream_real_query_info_finish (GFileInputStream
*stream
,
79 G_DEFINE_TYPE_WITH_CODE (GFileInputStream
, g_file_input_stream
, G_TYPE_INPUT_STREAM
,
80 G_IMPLEMENT_INTERFACE (G_TYPE_SEEKABLE
,
81 g_file_input_stream_seekable_iface_init
))
83 struct _GFileInputStreamPrivate
{
84 GAsyncReadyCallback outstanding_callback
;
88 g_file_input_stream_class_init (GFileInputStreamClass
*klass
)
90 g_type_class_add_private (klass
, sizeof (GFileInputStreamPrivate
));
92 klass
->query_info_async
= g_file_input_stream_real_query_info_async
;
93 klass
->query_info_finish
= g_file_input_stream_real_query_info_finish
;
97 g_file_input_stream_seekable_iface_init (GSeekableIface
*iface
)
99 iface
->tell
= g_file_input_stream_seekable_tell
;
100 iface
->can_seek
= g_file_input_stream_seekable_can_seek
;
101 iface
->seek
= g_file_input_stream_seekable_seek
;
102 iface
->can_truncate
= g_file_input_stream_seekable_can_truncate
;
103 iface
->truncate_fn
= g_file_input_stream_seekable_truncate
;
107 g_file_input_stream_init (GFileInputStream
*stream
)
109 stream
->priv
= G_TYPE_INSTANCE_GET_PRIVATE (stream
,
110 G_TYPE_FILE_INPUT_STREAM
,
111 GFileInputStreamPrivate
);
115 * g_file_input_stream_query_info:
116 * @stream: a #GFileInputStream.
117 * @attributes: a file attribute query string.
118 * @cancellable: optional #GCancellable object, %NULL to ignore.
119 * @error: a #GError location to store the error occuring, or %NULL to
122 * Queries a file input stream the given @attributes. This function blocks
123 * while querying the stream. For the asynchronous (non-blocking) version
124 * of this function, see g_file_input_stream_query_info_async(). While the
125 * stream is blocked, the stream will set the pending flag internally, and
126 * any other operations on the stream will fail with %G_IO_ERROR_PENDING.
128 * Returns: a #GFileInfo, or %NULL on error.
131 g_file_input_stream_query_info (GFileInputStream
*stream
,
133 GCancellable
*cancellable
,
136 GFileInputStreamClass
*class;
137 GInputStream
*input_stream
;
140 g_return_val_if_fail (G_IS_FILE_INPUT_STREAM (stream
), NULL
);
142 input_stream
= G_INPUT_STREAM (stream
);
144 if (!g_input_stream_set_pending (input_stream
, error
))
150 g_cancellable_push_current (cancellable
);
152 class = G_FILE_INPUT_STREAM_GET_CLASS (stream
);
153 if (class->query_info
)
154 info
= class->query_info (stream
, attributes
, cancellable
, error
);
156 g_set_error_literal (error
, G_IO_ERROR
, G_IO_ERROR_NOT_SUPPORTED
,
157 _("Stream doesn't support query_info"));
160 g_cancellable_pop_current (cancellable
);
162 g_input_stream_clear_pending (input_stream
);
168 async_ready_callback_wrapper (GObject
*source_object
,
172 GFileInputStream
*stream
= G_FILE_INPUT_STREAM (source_object
);
174 g_input_stream_clear_pending (G_INPUT_STREAM (stream
));
175 if (stream
->priv
->outstanding_callback
)
176 (*stream
->priv
->outstanding_callback
) (source_object
, res
, user_data
);
177 g_object_unref (stream
);
181 * g_file_input_stream_query_info_async:
182 * @stream: a #GFileInputStream.
183 * @attributes: a file attribute query string.
184 * @io_priority: the <link linkend="io-priority">I/O priority</link>
186 * @cancellable: optional #GCancellable object, %NULL to ignore.
187 * @callback: callback to call when the request is satisfied
188 * @user_data: the data to pass to callback function
190 * Queries the stream information asynchronously.
191 * When the operation is finished @callback will be called.
192 * You can then call g_file_input_stream_query_info_finish()
193 * to get the result of the operation.
195 * For the synchronous version of this function,
196 * see g_file_input_stream_query_info().
198 * If @cancellable is not %NULL, then the operation can be cancelled by
199 * triggering the cancellable object from another thread. If the operation
200 * was cancelled, the error %G_IO_ERROR_CANCELLED will be set
204 g_file_input_stream_query_info_async (GFileInputStream
*stream
,
207 GCancellable
*cancellable
,
208 GAsyncReadyCallback callback
,
211 GFileInputStreamClass
*klass
;
212 GInputStream
*input_stream
;
213 GError
*error
= NULL
;
215 g_return_if_fail (G_IS_FILE_INPUT_STREAM (stream
));
217 input_stream
= G_INPUT_STREAM (stream
);
219 if (!g_input_stream_set_pending (input_stream
, &error
))
221 g_simple_async_report_gerror_in_idle (G_OBJECT (stream
),
225 g_error_free (error
);
229 klass
= G_FILE_INPUT_STREAM_GET_CLASS (stream
);
231 stream
->priv
->outstanding_callback
= callback
;
232 g_object_ref (stream
);
233 klass
->query_info_async (stream
, attributes
, io_priority
, cancellable
,
234 async_ready_callback_wrapper
, user_data
);
238 * g_file_input_stream_query_info_finish:
239 * @stream: a #GFileInputStream.
240 * @result: a #GAsyncResult.
241 * @error: a #GError location to store the error occuring,
242 * or %NULL to ignore.
244 * Finishes an asynchronous info query operation.
246 * Returns: #GFileInfo.
249 g_file_input_stream_query_info_finish (GFileInputStream
*stream
,
250 GAsyncResult
*result
,
253 GSimpleAsyncResult
*simple
;
254 GFileInputStreamClass
*class;
256 g_return_val_if_fail (G_IS_FILE_INPUT_STREAM (stream
), NULL
);
257 g_return_val_if_fail (G_IS_ASYNC_RESULT (result
), NULL
);
259 if (G_IS_SIMPLE_ASYNC_RESULT (result
))
261 simple
= G_SIMPLE_ASYNC_RESULT (result
);
262 if (g_simple_async_result_propagate_error (simple
, error
))
266 class = G_FILE_INPUT_STREAM_GET_CLASS (stream
);
267 return class->query_info_finish (stream
, result
, error
);
271 g_file_input_stream_tell (GFileInputStream
*stream
)
273 GFileInputStreamClass
*class;
276 g_return_val_if_fail (G_IS_FILE_INPUT_STREAM (stream
), 0);
278 class = G_FILE_INPUT_STREAM_GET_CLASS (stream
);
282 offset
= class->tell (stream
);
288 g_file_input_stream_seekable_tell (GSeekable
*seekable
)
290 return g_file_input_stream_tell (G_FILE_INPUT_STREAM (seekable
));
294 g_file_input_stream_can_seek (GFileInputStream
*stream
)
296 GFileInputStreamClass
*class;
299 g_return_val_if_fail (G_IS_FILE_INPUT_STREAM (stream
), FALSE
);
301 class = G_FILE_INPUT_STREAM_GET_CLASS (stream
);
308 can_seek
= class->can_seek (stream
);
315 g_file_input_stream_seekable_can_seek (GSeekable
*seekable
)
317 return g_file_input_stream_can_seek (G_FILE_INPUT_STREAM (seekable
));
321 g_file_input_stream_seek (GFileInputStream
*stream
,
324 GCancellable
*cancellable
,
327 GFileInputStreamClass
*class;
328 GInputStream
*input_stream
;
331 g_return_val_if_fail (G_IS_FILE_INPUT_STREAM (stream
), FALSE
);
333 input_stream
= G_INPUT_STREAM (stream
);
334 class = G_FILE_INPUT_STREAM_GET_CLASS (stream
);
338 g_set_error_literal (error
, G_IO_ERROR
, G_IO_ERROR_NOT_SUPPORTED
,
339 _("Seek not supported on stream"));
343 if (!g_input_stream_set_pending (input_stream
, error
))
347 g_cancellable_push_current (cancellable
);
349 res
= class->seek (stream
, offset
, type
, cancellable
, error
);
352 g_cancellable_pop_current (cancellable
);
354 g_input_stream_clear_pending (input_stream
);
360 g_file_input_stream_seekable_seek (GSeekable
*seekable
,
363 GCancellable
*cancellable
,
366 return g_file_input_stream_seek (G_FILE_INPUT_STREAM (seekable
),
367 offset
, type
, cancellable
, error
);
371 g_file_input_stream_seekable_can_truncate (GSeekable
*seekable
)
377 g_file_input_stream_seekable_truncate (GSeekable
*seekable
,
379 GCancellable
*cancellable
,
382 g_set_error_literal (error
, G_IO_ERROR
, G_IO_ERROR_NOT_SUPPORTED
,
383 _("Truncate not allowed on input stream"));
387 /********************************************
388 * Default implementation of async ops *
389 ********************************************/
394 } QueryInfoAsyncData
;
397 query_info_data_free (QueryInfoAsyncData
*data
)
400 g_object_unref (data
->info
);
401 g_free (data
->attributes
);
406 query_info_async_thread (GSimpleAsyncResult
*res
,
408 GCancellable
*cancellable
)
410 GFileInputStreamClass
*class;
411 GError
*error
= NULL
;
412 QueryInfoAsyncData
*data
;
415 data
= g_simple_async_result_get_op_res_gpointer (res
);
419 class = G_FILE_INPUT_STREAM_GET_CLASS (object
);
420 if (class->query_info
)
421 info
= class->query_info (G_FILE_INPUT_STREAM (object
), data
->attributes
, cancellable
, &error
);
423 g_set_error_literal (&error
, G_IO_ERROR
, G_IO_ERROR_NOT_SUPPORTED
,
424 _("Stream doesn't support query_info"));
428 g_simple_async_result_set_from_error (res
, error
);
429 g_error_free (error
);
436 g_file_input_stream_real_query_info_async (GFileInputStream
*stream
,
439 GCancellable
*cancellable
,
440 GAsyncReadyCallback callback
,
443 GSimpleAsyncResult
*res
;
444 QueryInfoAsyncData
*data
;
446 data
= g_new0 (QueryInfoAsyncData
, 1);
447 data
->attributes
= g_strdup (attributes
);
449 res
= g_simple_async_result_new (G_OBJECT (stream
), callback
, user_data
, g_file_input_stream_real_query_info_async
);
450 g_simple_async_result_set_op_res_gpointer (res
, data
, (GDestroyNotify
)query_info_data_free
);
452 g_simple_async_result_run_in_thread (res
, query_info_async_thread
, io_priority
, cancellable
);
453 g_object_unref (res
);
457 g_file_input_stream_real_query_info_finish (GFileInputStream
*stream
,
461 GSimpleAsyncResult
*simple
= G_SIMPLE_ASYNC_RESULT (res
);
462 QueryInfoAsyncData
*data
;
464 g_warn_if_fail (g_simple_async_result_get_source_tag (simple
) == g_file_input_stream_real_query_info_async
);
466 data
= g_simple_async_result_get_op_res_gpointer (simple
);
468 return g_object_ref (data
->info
);
473 #define __G_FILE_INPUT_STREAM_C__
474 #include "gioaliasdef.c"