hook gvariant vectors up to kdbus
[platform/upstream/glib.git] / gio / gmemoryinputstream.c
1 /* GIO - GLib Input, Output and Streaming Library
2  * 
3  * Copyright (C) 2006-2007 Red Hat, Inc.
4  *
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.
9  *
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.
14  *
15  * You should have received a copy of the GNU Lesser General
16  * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
17  *
18  * Author: Christian Kellner <gicmo@gnome.org> 
19  */
20
21 #include "config.h"
22 #include "gmemoryinputstream.h"
23 #include "gpollableinputstream.h"
24 #include "ginputstream.h"
25 #include "gseekable.h"
26 #include "string.h"
27 #include "gtask.h"
28 #include "gioerror.h"
29 #include "glibintl.h"
30
31
32 /**
33  * SECTION:gmemoryinputstream
34  * @short_description: Streaming input operations on memory chunks
35  * @include: gio/gio.h
36  * @see_also: #GMemoryOutputStream
37  *
38  * #GMemoryInputStream is a class for using arbitrary
39  * memory chunks as input for GIO streaming input operations.
40  *
41  * As of GLib 2.34, #GMemoryInputStream implements
42  * #GPollableInputStream.
43  */
44
45 struct _GMemoryInputStreamPrivate {
46   GSList *chunks;
47   gsize   len;
48   gsize   pos;
49 };
50
51 static gssize   g_memory_input_stream_read         (GInputStream         *stream,
52                                                     void                 *buffer,
53                                                     gsize                 count,
54                                                     GCancellable         *cancellable,
55                                                     GError              **error);
56 static gssize   g_memory_input_stream_skip         (GInputStream         *stream,
57                                                     gsize                 count,
58                                                     GCancellable         *cancellable,
59                                                     GError              **error);
60 static gboolean g_memory_input_stream_close        (GInputStream         *stream,
61                                                     GCancellable         *cancellable,
62                                                     GError              **error);
63 static void     g_memory_input_stream_skip_async   (GInputStream         *stream,
64                                                     gsize                 count,
65                                                     int                   io_priority,
66                                                     GCancellable         *cancellabl,
67                                                     GAsyncReadyCallback   callback,
68                                                     gpointer              datae);
69 static gssize   g_memory_input_stream_skip_finish  (GInputStream         *stream,
70                                                     GAsyncResult         *result,
71                                                     GError              **error);
72 static void     g_memory_input_stream_close_async  (GInputStream         *stream,
73                                                     int                   io_priority,
74                                                     GCancellable         *cancellabl,
75                                                     GAsyncReadyCallback   callback,
76                                                     gpointer              data);
77 static gboolean g_memory_input_stream_close_finish (GInputStream         *stream,
78                                                     GAsyncResult         *result,
79                                                     GError              **error);
80
81 static void     g_memory_input_stream_seekable_iface_init (GSeekableIface  *iface);
82 static goffset  g_memory_input_stream_tell                (GSeekable       *seekable);
83 static gboolean g_memory_input_stream_can_seek            (GSeekable       *seekable);
84 static gboolean g_memory_input_stream_seek                (GSeekable       *seekable,
85                                                            goffset          offset,
86                                                            GSeekType        type,
87                                                            GCancellable    *cancellable,
88                                                            GError         **error);
89 static gboolean g_memory_input_stream_can_truncate        (GSeekable       *seekable);
90 static gboolean g_memory_input_stream_truncate            (GSeekable       *seekable,
91                                                            goffset          offset,
92                                                            GCancellable    *cancellable,
93                                                            GError         **error);
94
95 static void     g_memory_input_stream_pollable_iface_init (GPollableInputStreamInterface *iface);
96 static gboolean g_memory_input_stream_is_readable         (GPollableInputStream *stream);
97 static GSource *g_memory_input_stream_create_source       (GPollableInputStream *stream,
98                                                            GCancellable          *cancellable);
99
100 static void     g_memory_input_stream_finalize            (GObject         *object);
101
102 G_DEFINE_TYPE_WITH_CODE (GMemoryInputStream, g_memory_input_stream, G_TYPE_INPUT_STREAM,
103                          G_ADD_PRIVATE (GMemoryInputStream)
104                          G_IMPLEMENT_INTERFACE (G_TYPE_SEEKABLE,
105                                                 g_memory_input_stream_seekable_iface_init);
106                          G_IMPLEMENT_INTERFACE (G_TYPE_POLLABLE_INPUT_STREAM,
107                                                 g_memory_input_stream_pollable_iface_init);
108                          )
109
110
111 static void
112 g_memory_input_stream_class_init (GMemoryInputStreamClass *klass)
113 {
114   GObjectClass *object_class;
115   GInputStreamClass *istream_class;
116
117   object_class = G_OBJECT_CLASS (klass);
118   object_class->finalize     = g_memory_input_stream_finalize;
119   
120   istream_class = G_INPUT_STREAM_CLASS (klass);
121   istream_class->read_fn  = g_memory_input_stream_read;
122   istream_class->skip  = g_memory_input_stream_skip;
123   istream_class->close_fn = g_memory_input_stream_close;
124
125   istream_class->skip_async  = g_memory_input_stream_skip_async;
126   istream_class->skip_finish  = g_memory_input_stream_skip_finish;
127   istream_class->close_async = g_memory_input_stream_close_async;
128   istream_class->close_finish = g_memory_input_stream_close_finish;
129 }
130
131 static void
132 g_memory_input_stream_finalize (GObject *object)
133 {
134   GMemoryInputStream        *stream;
135   GMemoryInputStreamPrivate *priv;
136
137   stream = G_MEMORY_INPUT_STREAM (object);
138   priv = stream->priv;
139
140   g_slist_free_full (priv->chunks, (GDestroyNotify)g_bytes_unref);
141
142   G_OBJECT_CLASS (g_memory_input_stream_parent_class)->finalize (object);
143 }
144
145 static void
146 g_memory_input_stream_seekable_iface_init (GSeekableIface *iface)
147 {
148   iface->tell         = g_memory_input_stream_tell;
149   iface->can_seek     = g_memory_input_stream_can_seek;
150   iface->seek         = g_memory_input_stream_seek;
151   iface->can_truncate = g_memory_input_stream_can_truncate;
152   iface->truncate_fn  = g_memory_input_stream_truncate;
153 }
154
155 static void
156 g_memory_input_stream_pollable_iface_init (GPollableInputStreamInterface *iface)
157 {
158   iface->is_readable   = g_memory_input_stream_is_readable;
159   iface->create_source = g_memory_input_stream_create_source;
160 }
161
162 static void
163 g_memory_input_stream_init (GMemoryInputStream *stream)
164 {
165   stream->priv = g_memory_input_stream_get_instance_private (stream);
166 }
167
168 /**
169  * g_memory_input_stream_new:
170  *
171  * Creates a new empty #GMemoryInputStream. 
172  *
173  * Returns: a new #GInputStream
174  */
175 GInputStream *
176 g_memory_input_stream_new (void)
177 {
178   GInputStream *stream;
179
180   stream = g_object_new (G_TYPE_MEMORY_INPUT_STREAM, NULL);
181
182   return stream;
183 }
184
185 /**
186  * g_memory_input_stream_new_from_data:
187  * @data: (array length=len) (element-type guint8) (transfer full): input data
188  * @len: length of the data, may be -1 if @data is a nul-terminated string
189  * @destroy: (allow-none): function that is called to free @data, or %NULL
190  *
191  * Creates a new #GMemoryInputStream with data in memory of a given size.
192  * 
193  * Returns: new #GInputStream read from @data of @len bytes.
194  **/
195 GInputStream *
196 g_memory_input_stream_new_from_data (const void     *data, 
197                                      gssize          len,
198                                      GDestroyNotify  destroy)
199 {
200   GInputStream *stream;
201
202   stream = g_memory_input_stream_new ();
203
204   g_memory_input_stream_add_data (G_MEMORY_INPUT_STREAM (stream),
205                                   data, len, destroy);
206
207   return stream;
208 }
209
210 /**
211  * g_memory_input_stream_new_from_bytes:
212  * @bytes: a #GBytes
213  *
214  * Creates a new #GMemoryInputStream with data from the given @bytes.
215  *
216  * Returns: new #GInputStream read from @bytes
217  *
218  * Since: 2.34
219  **/
220 GInputStream *
221 g_memory_input_stream_new_from_bytes (GBytes  *bytes)
222 {
223   
224   GInputStream *stream;
225
226   stream = g_memory_input_stream_new ();
227
228   g_memory_input_stream_add_bytes (G_MEMORY_INPUT_STREAM (stream),
229                                    bytes);
230
231   return stream;
232 }
233
234 /**
235  * g_memory_input_stream_add_data:
236  * @stream: a #GMemoryInputStream
237  * @data: (array length=len) (element-type guint8) (transfer full): input data
238  * @len: length of the data, may be -1 if @data is a nul-terminated string
239  * @destroy: (allow-none): function that is called to free @data, or %NULL
240  *
241  * Appends @data to data that can be read from the input stream
242  */
243 void
244 g_memory_input_stream_add_data (GMemoryInputStream *stream,
245                                 const void         *data,
246                                 gssize              len,
247                                 GDestroyNotify      destroy)
248 {
249   GBytes *bytes;
250
251   if (len == -1)
252     len = strlen (data);
253
254   /* It's safe to discard the const here because we're chaining the
255    * destroy callback.
256    */
257   bytes = g_bytes_new_with_free_func (data, len, destroy, (void*)data);
258
259   g_memory_input_stream_add_bytes (stream, bytes);
260   
261   g_bytes_unref (bytes);
262 }
263
264 /**
265  * g_memory_input_stream_add_bytes:
266  * @stream: a #GMemoryInputStream
267  * @bytes: input data
268  *
269  * Appends @bytes to data that can be read from the input stream.
270  *
271  * Since: 2.34
272  */
273 void
274 g_memory_input_stream_add_bytes (GMemoryInputStream *stream,
275                                  GBytes             *bytes)
276 {
277   GMemoryInputStreamPrivate *priv;
278  
279   g_return_if_fail (G_IS_MEMORY_INPUT_STREAM (stream));
280   g_return_if_fail (bytes != NULL);
281
282   priv = stream->priv;
283
284   priv->chunks = g_slist_append (priv->chunks, g_bytes_ref (bytes));
285   priv->len += g_bytes_get_size (bytes);
286 }
287
288 static gssize
289 g_memory_input_stream_read (GInputStream  *stream,
290                             void          *buffer,
291                             gsize          count,
292                             GCancellable  *cancellable,
293                             GError       **error)
294 {
295   GMemoryInputStream *memory_stream;
296   GMemoryInputStreamPrivate *priv;
297   GSList *l;
298   GBytes *chunk;
299   gsize len;
300   gsize offset, start, rest, size;
301
302   memory_stream = G_MEMORY_INPUT_STREAM (stream);
303   priv = memory_stream->priv;
304
305   count = MIN (count, priv->len - priv->pos);
306
307   offset = 0;
308   for (l = priv->chunks; l; l = l->next) 
309     {
310       chunk = (GBytes *)l->data;
311       len = g_bytes_get_size (chunk);
312
313       if (offset + len > priv->pos)
314         break;
315
316       offset += len;
317     }
318   
319   start = priv->pos - offset;
320   rest = count;
321
322   for (; l && rest > 0; l = l->next)
323     {
324       const guint8* chunk_data;
325       chunk = (GBytes *)l->data;
326
327       chunk_data = g_bytes_get_data (chunk, &len);
328
329       size = MIN (rest, len - start);
330
331       memcpy ((guint8 *)buffer + (count - rest), chunk_data + start, size);
332       rest -= size;
333
334       start = 0;
335     }
336
337   priv->pos += count;
338
339   return count;
340 }
341
342 static gssize
343 g_memory_input_stream_skip (GInputStream  *stream,
344                             gsize          count,
345                             GCancellable  *cancellable,
346                             GError       **error)
347 {
348   GMemoryInputStream *memory_stream;
349   GMemoryInputStreamPrivate *priv;
350
351   memory_stream = G_MEMORY_INPUT_STREAM (stream);
352   priv = memory_stream->priv;
353
354   count = MIN (count, priv->len - priv->pos);
355   priv->pos += count;
356
357   return count;
358 }
359
360 static gboolean
361 g_memory_input_stream_close (GInputStream  *stream,
362                              GCancellable  *cancellable,
363                              GError       **error)
364 {
365   return TRUE;
366 }
367
368 static void
369 g_memory_input_stream_skip_async (GInputStream        *stream,
370                                   gsize                count,
371                                   int                  io_priority,
372                                   GCancellable        *cancellable,
373                                   GAsyncReadyCallback  callback,
374                                   gpointer             user_data)
375 {
376   GTask *task;
377   gssize nskipped;
378   GError *error = NULL;
379
380   nskipped = G_INPUT_STREAM_GET_CLASS (stream)->skip (stream, count, cancellable, &error);
381   task = g_task_new (stream, cancellable, callback, user_data);
382   if (error)
383     g_task_return_error (task, error);
384   else
385     g_task_return_int (task, nskipped);
386   g_object_unref (task);
387 }
388
389 static gssize
390 g_memory_input_stream_skip_finish (GInputStream  *stream,
391                                    GAsyncResult  *result,
392                                    GError       **error)
393 {
394   g_return_val_if_fail (g_task_is_valid (result, stream), -1);
395
396   return g_task_propagate_int (G_TASK (result), error);
397 }
398
399 static void
400 g_memory_input_stream_close_async (GInputStream        *stream,
401                                    int                  io_priority,
402                                    GCancellable        *cancellable,
403                                    GAsyncReadyCallback  callback,
404                                    gpointer             user_data)
405 {
406   GTask *task;
407
408   task = g_task_new (stream, cancellable, callback, user_data);
409   g_task_return_boolean (task, TRUE);
410   g_object_unref (task);
411 }
412
413 static gboolean
414 g_memory_input_stream_close_finish (GInputStream  *stream,
415                                     GAsyncResult  *result,
416                                     GError       **error)
417 {
418   return TRUE;
419 }
420
421 static goffset
422 g_memory_input_stream_tell (GSeekable *seekable)
423 {
424   GMemoryInputStream *memory_stream;
425   GMemoryInputStreamPrivate *priv;
426
427   memory_stream = G_MEMORY_INPUT_STREAM (seekable);
428   priv = memory_stream->priv;
429
430   return priv->pos;
431 }
432
433 static
434 gboolean g_memory_input_stream_can_seek (GSeekable *seekable)
435 {
436   return TRUE;
437 }
438
439 static gboolean
440 g_memory_input_stream_seek (GSeekable     *seekable,
441                             goffset        offset,
442                             GSeekType      type,
443                             GCancellable  *cancellable,
444                             GError       **error)
445 {
446   GMemoryInputStream *memory_stream;
447   GMemoryInputStreamPrivate *priv;
448   goffset absolute;
449
450   memory_stream = G_MEMORY_INPUT_STREAM (seekable);
451   priv = memory_stream->priv;
452
453   switch (type) 
454     {
455     case G_SEEK_CUR:
456       absolute = priv->pos + offset;
457       break;
458
459     case G_SEEK_SET:
460       absolute = offset;
461       break;
462
463     case G_SEEK_END:
464       absolute = priv->len + offset;
465       break;
466   
467     default:
468       g_set_error_literal (error,
469                            G_IO_ERROR,
470                            G_IO_ERROR_INVALID_ARGUMENT,
471                            _("Invalid GSeekType supplied"));
472
473       return FALSE;
474     }
475
476   if (absolute < 0 || absolute > priv->len)
477     {
478       g_set_error_literal (error,
479                            G_IO_ERROR,
480                            G_IO_ERROR_INVALID_ARGUMENT,
481                            _("Invalid seek request"));
482       return FALSE;
483     }
484
485   priv->pos = absolute;
486
487   return TRUE;
488 }
489
490 static gboolean
491 g_memory_input_stream_can_truncate (GSeekable *seekable)
492 {
493   return FALSE;
494 }
495
496 static gboolean
497 g_memory_input_stream_truncate (GSeekable     *seekable,
498                                 goffset        offset,
499                                 GCancellable  *cancellable,
500                                 GError       **error)
501 {
502   g_set_error_literal (error,
503                        G_IO_ERROR,
504                        G_IO_ERROR_NOT_SUPPORTED,
505                        _("Cannot truncate GMemoryInputStream"));
506   return FALSE;
507 }
508
509 static gboolean
510 g_memory_input_stream_is_readable (GPollableInputStream *stream)
511 {
512   return TRUE;
513 }
514
515 static GSource *
516 g_memory_input_stream_create_source (GPollableInputStream *stream,
517                                      GCancellable         *cancellable)
518 {
519   GSource *base_source, *pollable_source;
520
521   base_source = g_timeout_source_new (0);
522   pollable_source = g_pollable_source_new_full (stream, base_source,
523                                                 cancellable);
524   g_source_unref (base_source);
525
526   return pollable_source;
527 }