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