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