Add some tests for invalid booleans
[glib.git] / gio / gfileinputstream.c
blob24c8a61fcd6fd7f646554a37f227cedc42299464
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 "glibintl.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,
35 goffset offset,
36 GSeekType type,
37 GCancellable *cancellable,
38 GError **error);
39 static gboolean g_file_input_stream_seekable_can_truncate (GSeekable *seekable);
40 static gboolean g_file_input_stream_seekable_truncate (GSeekable *seekable,
41 goffset offset,
42 GCancellable *cancellable,
43 GError **error);
44 static void g_file_input_stream_real_query_info_async (GFileInputStream *stream,
45 char *attributes,
46 int io_priority,
47 GCancellable *cancellable,
48 GAsyncReadyCallback callback,
49 gpointer user_data);
50 static GFileInfo *g_file_input_stream_real_query_info_finish (GFileInputStream *stream,
51 GAsyncResult *result,
52 GError **error);
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;
63 static void
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;
72 static void
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;
82 static void
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);
90 /**
91 * g_file_input_stream_query_info:
92 * @stream:
93 * @attributes:
94 * @cancellable: optional #GCancellable object, %NULL to ignore.
95 * @error: a #GError location to store the error occuring, or %NULL to
96 * ignore.
97 * Returns:
98 **/
99 GFileInfo *
100 g_file_input_stream_query_info (GFileInputStream *stream,
101 char *attributes,
102 GCancellable *cancellable,
103 GError **error)
105 GFileInputStreamClass *class;
106 GInputStream *input_stream;
107 GFileInfo *info;
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"));
117 return NULL;
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"));
124 return NULL;
127 info = NULL;
129 g_input_stream_set_pending (input_stream, TRUE);
131 if (cancellable)
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);
137 else
138 g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
139 _("Stream doesn't support query_info"));
141 if (cancellable)
142 g_pop_current_cancellable (cancellable);
144 g_input_stream_set_pending (input_stream, FALSE);
146 return info;
149 static void
150 async_ready_callback_wrapper (GObject *source_object,
151 GAsyncResult *res,
152 gpointer user_data)
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:
164 * @stream:
165 * @attributes:
166 * @io_priority: the io priority of the request.
167 * @cancellable: optional #GCancellable object, %NULL to ignore. @callback:
168 * @user_data:
171 void
172 g_file_input_stream_query_info_async (GFileInputStream *stream,
173 char *attributes,
174 int io_priority,
175 GCancellable *cancellable,
176 GAsyncReadyCallback callback,
177 gpointer user_data)
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),
189 callback,
190 user_data,
191 G_IO_ERROR, G_IO_ERROR_CLOSED,
192 _("Stream is already closed"));
193 return;
196 if (g_input_stream_has_pending (input_stream))
198 g_simple_async_report_error_in_idle (G_OBJECT (stream),
199 callback,
200 user_data,
201 G_IO_ERROR, G_IO_ERROR_PENDING,
202 _("Stream has outstanding operation"));
203 return;
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:
217 * @stream:
218 * @result:
219 * @error: a #GError location to store the error occuring, or %NULL to
220 * ignore.
221 * Returns: #GFileInfo.
223 GFileInfo *
224 g_file_input_stream_query_info_finish (GFileInputStream *stream,
225 GAsyncResult *result,
226 GError **error)
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))
238 return NULL;
241 class = G_FILE_INPUT_STREAM_GET_CLASS (stream);
242 return class->query_info_finish (stream, result, error);
246 * g_file_input_stream_tell:
247 * @stream:
249 * Returns:
251 goffset
252 g_file_input_stream_tell (GFileInputStream *stream)
254 GFileInputStreamClass *class;
255 goffset offset;
257 g_return_val_if_fail (G_IS_FILE_INPUT_STREAM (stream), 0);
259 class = G_FILE_INPUT_STREAM_GET_CLASS (stream);
261 offset = 0;
262 if (class->tell)
263 offset = class->tell (stream);
265 return offset;
268 static goffset
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:
276 * @stream:
278 * Returns: %TRUE if stream can be seeked. %FALSE otherwise.
280 gboolean
281 g_file_input_stream_can_seek (GFileInputStream *stream)
283 GFileInputStreamClass *class;
284 gboolean can_seek;
286 g_return_val_if_fail (G_IS_FILE_INPUT_STREAM (stream), FALSE);
288 class = G_FILE_INPUT_STREAM_GET_CLASS (stream);
290 can_seek = FALSE;
291 if (class->seek)
293 can_seek = TRUE;
294 if (class->can_seek)
295 can_seek = class->can_seek (stream);
298 return can_seek;
301 static gboolean
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:
309 * @stream:
310 * @offset:
311 * @type:
312 * @cancellable: optional #GCancellable object, %NULL to ignore.
313 * @error: a #GError location to store the error occuring, or %NULL to
314 * ignore.
315 * Returns:
317 gboolean
318 g_file_input_stream_seek (GFileInputStream *stream,
319 goffset offset,
320 GSeekType type,
321 GCancellable *cancellable,
322 GError **error)
324 GFileInputStreamClass *class;
325 GInputStream *input_stream;
326 gboolean res;
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"));
337 return FALSE;
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"));
344 return FALSE;
347 if (!class->seek)
349 g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
350 _("Seek not supported on stream"));
351 return FALSE;
354 g_input_stream_set_pending (input_stream, TRUE);
356 if (cancellable)
357 g_push_current_cancellable (cancellable);
359 res = class->seek (stream, offset, type, cancellable, error);
361 if (cancellable)
362 g_pop_current_cancellable (cancellable);
364 g_input_stream_set_pending (input_stream, FALSE);
366 return res;
369 static gboolean
370 g_file_input_stream_seekable_seek (GSeekable *seekable,
371 goffset offset,
372 GSeekType type,
373 GCancellable *cancellable,
374 GError **error)
376 return g_file_input_stream_seek (G_FILE_INPUT_STREAM (seekable),
377 offset, type, cancellable, error);
380 static gboolean
381 g_file_input_stream_seekable_can_truncate (GSeekable *seekable)
383 return FALSE;
386 static gboolean
387 g_file_input_stream_seekable_truncate (GSeekable *seekable,
388 goffset offset,
389 GCancellable *cancellable,
390 GError **error)
392 g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
393 _("Truncate not allowed on input stream"));
394 return FALSE;
397 /********************************************
398 * Default implementation of async ops *
399 ********************************************/
401 typedef struct {
402 char *attributes;
403 GFileInfo *info;
404 } QueryInfoAsyncData;
406 static void
407 query_info_data_free (QueryInfoAsyncData *data)
409 if (data->info)
410 g_object_unref (data->info);
411 g_free (data->attributes);
412 g_free (data);
415 static void
416 query_info_async_thread (GSimpleAsyncResult *res,
417 GObject *object,
418 GCancellable *cancellable)
420 GFileInputStreamClass *class;
421 GError *error = NULL;
422 QueryInfoAsyncData *data;
423 GFileInfo *info;
425 data = g_simple_async_result_get_op_res_gpointer (res);
427 info = NULL;
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);
432 else
433 g_set_error (&error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
434 _("Stream doesn't support query_info"));
436 if (info == NULL)
438 g_simple_async_result_set_from_error (res, error);
439 g_error_free (error);
441 else
442 data->info = info;
445 static void
446 g_file_input_stream_real_query_info_async (GFileInputStream *stream,
447 char *attributes,
448 int io_priority,
449 GCancellable *cancellable,
450 GAsyncReadyCallback callback,
451 gpointer user_data)
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);
466 static GFileInfo *
467 g_file_input_stream_real_query_info_finish (GFileInputStream *stream,
468 GAsyncResult *res,
469 GError **error)
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);
477 if (data->info)
478 return g_object_ref (data->info);
480 return NULL;