Fix the build
[glib.git] / gio / gfileinputstream.c
blobc3afd00548facf9ab0329f577d3ab6d3e9607c6c
1 /* GIO - GLib Input, Output and Streaming Library
2 *
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>
23 #include "config.h"
25 #include <glib.h>
26 #include <gfileinputstream.h>
27 #include <gseekable.h>
28 #include "gsimpleasyncresult.h"
29 #include "gcancellable.h"
30 #include "gasyncresult.h"
31 #include "gioerror.h"
32 #include "glibintl.h"
34 #include "gioalias.h"
36 /**
37 * SECTION:gfileinputstream
38 * @short_description: File input streaming operations
39 * @include: gio/gio.h
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().
53 **/
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,
59 goffset offset,
60 GSeekType type,
61 GCancellable *cancellable,
62 GError **error);
63 static gboolean g_file_input_stream_seekable_can_truncate (GSeekable *seekable);
64 static gboolean g_file_input_stream_seekable_truncate (GSeekable *seekable,
65 goffset offset,
66 GCancellable *cancellable,
67 GError **error);
68 static void g_file_input_stream_real_query_info_async (GFileInputStream *stream,
69 char *attributes,
70 int io_priority,
71 GCancellable *cancellable,
72 GAsyncReadyCallback callback,
73 gpointer user_data);
74 static GFileInfo *g_file_input_stream_real_query_info_finish (GFileInputStream *stream,
75 GAsyncResult *result,
76 GError **error);
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;
87 static void
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;
96 static void
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;
106 static void
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
120 * ignore.
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.
130 GFileInfo *
131 g_file_input_stream_query_info (GFileInputStream *stream,
132 char *attributes,
133 GCancellable *cancellable,
134 GError **error)
136 GFileInputStreamClass *class;
137 GInputStream *input_stream;
138 GFileInfo *info;
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))
145 return NULL;
147 info = NULL;
149 if (cancellable)
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);
155 else
156 g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
157 _("Stream doesn't support query_info"));
159 if (cancellable)
160 g_cancellable_pop_current (cancellable);
162 g_input_stream_clear_pending (input_stream);
164 return info;
167 static void
168 async_ready_callback_wrapper (GObject *source_object,
169 GAsyncResult *res,
170 gpointer user_data)
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>
185 * of the request.
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
203 void
204 g_file_input_stream_query_info_async (GFileInputStream *stream,
205 char *attributes,
206 int io_priority,
207 GCancellable *cancellable,
208 GAsyncReadyCallback callback,
209 gpointer user_data)
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),
222 callback,
223 user_data,
224 error);
225 g_error_free (error);
226 return;
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.
248 GFileInfo *
249 g_file_input_stream_query_info_finish (GFileInputStream *stream,
250 GAsyncResult *result,
251 GError **error)
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))
263 return NULL;
266 class = G_FILE_INPUT_STREAM_GET_CLASS (stream);
267 return class->query_info_finish (stream, result, error);
270 static goffset
271 g_file_input_stream_tell (GFileInputStream *stream)
273 GFileInputStreamClass *class;
274 goffset offset;
276 g_return_val_if_fail (G_IS_FILE_INPUT_STREAM (stream), 0);
278 class = G_FILE_INPUT_STREAM_GET_CLASS (stream);
280 offset = 0;
281 if (class->tell)
282 offset = class->tell (stream);
284 return offset;
287 static goffset
288 g_file_input_stream_seekable_tell (GSeekable *seekable)
290 return g_file_input_stream_tell (G_FILE_INPUT_STREAM (seekable));
293 static gboolean
294 g_file_input_stream_can_seek (GFileInputStream *stream)
296 GFileInputStreamClass *class;
297 gboolean can_seek;
299 g_return_val_if_fail (G_IS_FILE_INPUT_STREAM (stream), FALSE);
301 class = G_FILE_INPUT_STREAM_GET_CLASS (stream);
303 can_seek = FALSE;
304 if (class->seek)
306 can_seek = TRUE;
307 if (class->can_seek)
308 can_seek = class->can_seek (stream);
311 return can_seek;
314 static gboolean
315 g_file_input_stream_seekable_can_seek (GSeekable *seekable)
317 return g_file_input_stream_can_seek (G_FILE_INPUT_STREAM (seekable));
320 static gboolean
321 g_file_input_stream_seek (GFileInputStream *stream,
322 goffset offset,
323 GSeekType type,
324 GCancellable *cancellable,
325 GError **error)
327 GFileInputStreamClass *class;
328 GInputStream *input_stream;
329 gboolean res;
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);
336 if (!class->seek)
338 g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
339 _("Seek not supported on stream"));
340 return FALSE;
343 if (!g_input_stream_set_pending (input_stream, error))
344 return FALSE;
346 if (cancellable)
347 g_cancellable_push_current (cancellable);
349 res = class->seek (stream, offset, type, cancellable, error);
351 if (cancellable)
352 g_cancellable_pop_current (cancellable);
354 g_input_stream_clear_pending (input_stream);
356 return res;
359 static gboolean
360 g_file_input_stream_seekable_seek (GSeekable *seekable,
361 goffset offset,
362 GSeekType type,
363 GCancellable *cancellable,
364 GError **error)
366 return g_file_input_stream_seek (G_FILE_INPUT_STREAM (seekable),
367 offset, type, cancellable, error);
370 static gboolean
371 g_file_input_stream_seekable_can_truncate (GSeekable *seekable)
373 return FALSE;
376 static gboolean
377 g_file_input_stream_seekable_truncate (GSeekable *seekable,
378 goffset offset,
379 GCancellable *cancellable,
380 GError **error)
382 g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
383 _("Truncate not allowed on input stream"));
384 return FALSE;
387 /********************************************
388 * Default implementation of async ops *
389 ********************************************/
391 typedef struct {
392 char *attributes;
393 GFileInfo *info;
394 } QueryInfoAsyncData;
396 static void
397 query_info_data_free (QueryInfoAsyncData *data)
399 if (data->info)
400 g_object_unref (data->info);
401 g_free (data->attributes);
402 g_free (data);
405 static void
406 query_info_async_thread (GSimpleAsyncResult *res,
407 GObject *object,
408 GCancellable *cancellable)
410 GFileInputStreamClass *class;
411 GError *error = NULL;
412 QueryInfoAsyncData *data;
413 GFileInfo *info;
415 data = g_simple_async_result_get_op_res_gpointer (res);
417 info = NULL;
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);
422 else
423 g_set_error_literal (&error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
424 _("Stream doesn't support query_info"));
426 if (info == NULL)
428 g_simple_async_result_set_from_error (res, error);
429 g_error_free (error);
431 else
432 data->info = info;
435 static void
436 g_file_input_stream_real_query_info_async (GFileInputStream *stream,
437 char *attributes,
438 int io_priority,
439 GCancellable *cancellable,
440 GAsyncReadyCallback callback,
441 gpointer user_data)
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);
456 static GFileInfo *
457 g_file_input_stream_real_query_info_finish (GFileInputStream *stream,
458 GAsyncResult *res,
459 GError **error)
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);
467 if (data->info)
468 return g_object_ref (data->info);
470 return NULL;
473 #define __G_FILE_INPUT_STREAM_C__
474 #include "gioaliasdef.c"