2e113bdab1c53a8e825623f79bd048c672042f8c
[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 "glibintl.h"
30
31 #include "gioalias.h"
32
33 /**
34  * SECTION:gmemoryinputstream
35  * @short_description: Streaming input operations on memory chunks
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  */
42
43 struct _GMemoryInputStreamPrivate {
44   guint8 *buffer;      
45   gsize   pos;
46   gsize   len;
47   gboolean free_data;
48 };
49
50 static gssize   g_memory_input_stream_read         (GInputStream         *stream,
51                                                     void                 *buffer,
52                                                     gsize                 count,
53                                                     GCancellable         *cancellable,
54                                                     GError              **error);
55 static gssize   g_memory_input_stream_skip         (GInputStream         *stream,
56                                                     gsize                 count,
57                                                     GCancellable         *cancellable,
58                                                     GError              **error);
59 static gboolean g_memory_input_stream_close        (GInputStream         *stream,
60                                                     GCancellable         *cancellable,
61                                                     GError              **error);
62 static void     g_memory_input_stream_read_async   (GInputStream         *stream,
63                                                     void                 *buffer,
64                                                     gsize                 count,
65                                                     int                   io_priority,
66                                                     GCancellable         *cancellable,
67                                                     GAsyncReadyCallback   callback,
68                                                     gpointer              user_data);
69 static gssize   g_memory_input_stream_read_finish  (GInputStream         *stream,
70                                                     GAsyncResult         *result,
71                                                     GError              **error);
72 static void     g_memory_input_stream_skip_async   (GInputStream         *stream,
73                                                     gsize                 count,
74                                                     int                   io_priority,
75                                                     GCancellable         *cancellabl,
76                                                     GAsyncReadyCallback   callback,
77                                                     gpointer              datae);
78 static gssize   g_memory_input_stream_skip_finish  (GInputStream         *stream,
79                                                     GAsyncResult         *result,
80                                                     GError              **error);
81 static void     g_memory_input_stream_close_async  (GInputStream         *stream,
82                                                     int                   io_priority,
83                                                     GCancellable         *cancellabl,
84                                                     GAsyncReadyCallback   callback,
85                                                     gpointer              data);
86 static gboolean g_memory_input_stream_close_finish (GInputStream         *stream,
87                                                     GAsyncResult         *result,
88                                                     GError              **error);
89
90 static void     g_memory_input_stream_seekable_iface_init (GSeekableIface  *iface);
91 static goffset  g_memory_input_stream_tell                (GSeekable       *seekable);
92 static gboolean g_memory_input_stream_can_seek            (GSeekable       *seekable);
93 static gboolean g_memory_input_stream_seek                (GSeekable       *seekable,
94                                                            goffset          offset,
95                                                            GSeekType        type,
96                                                            GCancellable    *cancellable,
97                                                            GError         **error);
98 static gboolean g_memory_input_stream_can_truncate        (GSeekable       *seekable);
99 static gboolean g_memory_input_stream_truncate            (GSeekable       *seekable,
100                                                            goffset          offset,
101                                                            GCancellable    *cancellable,
102                                                            GError         **error);
103 static void     g_memory_input_stream_finalize            (GObject         *object);
104
105 G_DEFINE_TYPE_WITH_CODE (GMemoryInputStream, g_memory_input_stream, G_TYPE_INPUT_STREAM,
106                          G_IMPLEMENT_INTERFACE (G_TYPE_SEEKABLE,
107                                                 g_memory_input_stream_seekable_iface_init))
108
109
110 static void
111 g_memory_input_stream_class_init (GMemoryInputStreamClass *klass)
112 {
113   GObjectClass *object_class;
114   GInputStreamClass *istream_class;
115
116   g_type_class_add_private (klass, sizeof (GMemoryInputStreamPrivate));
117
118   object_class = G_OBJECT_CLASS (klass);
119   object_class->finalize     = g_memory_input_stream_finalize;
120   
121   istream_class = G_INPUT_STREAM_CLASS (klass);
122   istream_class->read_fn  = g_memory_input_stream_read;
123   istream_class->skip  = g_memory_input_stream_skip;
124   istream_class->close_fn = g_memory_input_stream_close;
125
126   istream_class->read_async  = g_memory_input_stream_read_async;
127   istream_class->read_finish  = g_memory_input_stream_read_finish;
128   istream_class->skip_async  = g_memory_input_stream_skip_async;
129   istream_class->skip_finish  = g_memory_input_stream_skip_finish;
130   istream_class->close_async = g_memory_input_stream_close_async;
131   istream_class->close_finish = g_memory_input_stream_close_finish;
132 }
133
134 static void
135 g_memory_input_stream_finalize (GObject *object)
136 {
137   GMemoryInputStream        *stream;
138
139   stream = G_MEMORY_INPUT_STREAM (object);
140
141   if (stream->priv->free_data)
142     g_free (stream->priv->buffer);
143
144   if (G_OBJECT_CLASS (g_memory_input_stream_parent_class)->finalize)
145     (*G_OBJECT_CLASS (g_memory_input_stream_parent_class)->finalize) (object);
146 }
147
148 static void
149 g_memory_input_stream_seekable_iface_init (GSeekableIface *iface)
150 {
151   iface->tell         = g_memory_input_stream_tell;
152   iface->can_seek     = g_memory_input_stream_can_seek;
153   iface->seek         = g_memory_input_stream_seek;
154   iface->can_truncate = g_memory_input_stream_can_truncate;
155   iface->truncate_fn  = g_memory_input_stream_truncate;
156 }
157
158 static void
159 g_memory_input_stream_init (GMemoryInputStream *stream)
160 {
161   stream->priv = G_TYPE_INSTANCE_GET_PRIVATE (stream,
162                                               G_TYPE_MEMORY_INPUT_STREAM,
163                                               GMemoryInputStreamPrivate);
164 }
165
166 /**
167  * g_memory_input_stream_set_free_data:
168  * @stream: a #GMemoryInputStream.
169  * @free_data: a #gboolean. If %TRUE, frees the data within @stream.
170  * 
171  * Sets if the data within the @stream should be freed when the stream 
172  * is freed. 
173  **/
174 void
175 g_memory_input_stream_set_free_data (GMemoryInputStream *stream,
176                                      gboolean            free_data)
177 {
178   g_return_if_fail (G_IS_MEMORY_INPUT_STREAM (stream));
179
180   stream->priv->free_data = free_data;
181 }
182
183 /**
184  * g_memory_input_stream_from_data:
185  * @data: input data.
186  * @len: length of the data.
187  *
188  * Creates a new #GMemoryInputStream with data in memory of a given size.
189  * 
190  * Returns: new #GInputStream read from @data of @len bytes.
191  **/
192 GInputStream *
193 g_memory_input_stream_from_data (const void *data, 
194                                  gssize      len)
195 {
196   GInputStream *stream;
197   GMemoryInputStream *memory_stream;
198
199   g_return_val_if_fail (data != NULL, NULL);
200
201   stream = g_object_new (G_TYPE_MEMORY_INPUT_STREAM, NULL);
202   memory_stream = G_MEMORY_INPUT_STREAM (stream);
203
204   if (len == -1)
205     len = strlen (data);
206   
207   memory_stream->priv->buffer = (guint8 *)data;
208   memory_stream->priv->len = len;
209
210   return stream;
211 }
212
213 static gssize
214 g_memory_input_stream_read (GInputStream  *stream,
215                             void          *buffer,
216                             gsize          count,
217                             GCancellable  *cancellable,
218                             GError       **error)
219 {
220   GMemoryInputStream *memory_stream;
221   GMemoryInputStreamPrivate * priv;
222
223   memory_stream = G_MEMORY_INPUT_STREAM (stream);
224   priv = memory_stream->priv;
225
226   count = MIN (count, priv->len - priv->pos);
227   memcpy (buffer, priv->buffer + priv->pos, count);
228   priv->pos += count;
229
230   return count;
231 }
232
233 /**
234  * g_memory_input_stream_get_data:
235  * @stream: a #GMemoryInputStream
236  * 
237  * Gets a pointer to the data within the #GMemoryInputStream.
238  *
239  * Returns: a pointer to the memory in the @stream.
240  **/
241 const void *
242 g_memory_input_stream_get_data (GMemoryInputStream *stream)
243 {
244   g_return_val_if_fail (G_IS_MEMORY_INPUT_STREAM (stream), NULL);
245
246   return stream->priv->buffer;
247 }
248
249 /**
250  * g_memory_input_stream_get_data_size:
251  * @stream: a #GMemoryInputStream
252  * 
253  * Gets the size of the data within the #GMemoryInputStream.
254  *
255  * Returns: a gsize with the size of the data in @stream.
256  **/
257 gsize
258 g_memory_input_stream_get_data_size (GMemoryInputStream *stream)
259 {
260   g_return_val_if_fail (G_IS_MEMORY_INPUT_STREAM (stream), -1);
261
262   return stream->priv->len;
263 }
264
265 static gssize
266 g_memory_input_stream_skip (GInputStream  *stream,
267                             gsize          count,
268                             GCancellable  *cancellable,
269                             GError       **error)
270 {
271   GMemoryInputStream *memory_stream;
272   GMemoryInputStreamPrivate *priv;
273
274   memory_stream = G_MEMORY_INPUT_STREAM (stream);
275   priv = memory_stream->priv;
276
277   count = MIN (count, priv->len - priv->pos);
278   priv->pos += count;
279
280   return count;
281  
282
283 }
284
285 static gboolean
286 g_memory_input_stream_close (GInputStream  *stream,
287                              GCancellable  *cancellable,
288                              GError       **error)
289 {
290   return TRUE;
291 }
292
293 static void
294 g_memory_input_stream_read_async (GInputStream        *stream,
295                                   void                *buffer,
296                                   gsize                count,
297                                   int                  io_priority,
298                                   GCancellable        *cancellable,
299                                   GAsyncReadyCallback  callback,
300                                   gpointer             user_data)
301 {
302   GSimpleAsyncResult *simple;
303   gssize nread;
304
305   nread =  g_memory_input_stream_read (stream,  buffer, count, cancellable, NULL);
306   simple = g_simple_async_result_new (G_OBJECT (stream),
307                                       callback,
308                                       user_data,
309                                       g_memory_input_stream_read_async);
310   g_simple_async_result_set_op_res_gssize (simple, nread);
311   g_simple_async_result_complete_in_idle (simple);
312   g_object_unref (simple);
313 }
314
315 static gssize
316 g_memory_input_stream_read_finish (GInputStream  *stream,
317                                    GAsyncResult  *result,
318                                    GError       **error)
319 {
320   GSimpleAsyncResult *simple;
321   gssize nread;
322
323   simple = G_SIMPLE_ASYNC_RESULT (result);
324   g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == g_memory_input_stream_read_async);
325   
326   nread = g_simple_async_result_get_op_res_gssize (simple);
327   return nread;
328 }
329
330 static void
331 g_memory_input_stream_skip_async (GInputStream        *stream,
332                                   gsize                count,
333                                   int                  io_priority,
334                                   GCancellable        *cancellable,
335                                   GAsyncReadyCallback  callback,
336                                   gpointer             user_data)
337 {
338   GSimpleAsyncResult *simple;
339   gssize nskipped;
340
341   nskipped = g_memory_input_stream_skip (stream, count, cancellable, NULL);
342   simple = g_simple_async_result_new (G_OBJECT (stream),
343                                       callback,
344                                       user_data,
345                                       g_memory_input_stream_skip_async);
346   g_simple_async_result_set_op_res_gssize (simple, nskipped);
347   g_simple_async_result_complete_in_idle (simple);
348   g_object_unref (simple);
349 }
350
351 static gssize
352 g_memory_input_stream_skip_finish (GInputStream  *stream,
353                                    GAsyncResult  *result,
354                                    GError       **error)
355 {
356   GSimpleAsyncResult *simple;
357   gssize nskipped;
358
359   simple = G_SIMPLE_ASYNC_RESULT (result);
360   g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == g_memory_input_stream_skip_async);
361   
362   nskipped = g_simple_async_result_get_op_res_gssize (simple);
363   return nskipped;
364 }
365
366 static void
367 g_memory_input_stream_close_async (GInputStream        *stream,
368                                    int                  io_priority,
369                                    GCancellable        *cancellable,
370                                    GAsyncReadyCallback  callback,
371                                    gpointer             user_data)
372 {
373   GSimpleAsyncResult *simple;
374   
375   simple = g_simple_async_result_new (G_OBJECT (stream),
376                                       callback,
377                                       user_data,
378                                       g_memory_input_stream_close_async);
379   g_simple_async_result_complete_in_idle (simple);
380   g_object_unref (simple);
381 }
382
383 static gboolean
384 g_memory_input_stream_close_finish (GInputStream  *stream,
385                                     GAsyncResult  *result,
386                                     GError       **error)
387 {
388   return TRUE;
389 }
390
391 static goffset
392 g_memory_input_stream_tell (GSeekable *seekable)
393 {
394   GMemoryInputStream *memory_stream;
395   GMemoryInputStreamPrivate * priv;
396
397   memory_stream = G_MEMORY_INPUT_STREAM (seekable);
398   priv = memory_stream->priv;
399
400   return priv->pos;
401 }
402
403 static
404 gboolean g_memory_input_stream_can_seek (GSeekable *seekable)
405 {
406   return TRUE;
407 }
408
409 static gboolean
410 g_memory_input_stream_seek (GSeekable     *seekable,
411                             goffset        offset,
412                             GSeekType      type,
413                             GCancellable  *cancellable,
414                             GError       **error)
415 {
416   GMemoryInputStream *memory_stream;
417   GMemoryInputStreamPrivate * priv;
418   goffset absolute;
419
420   memory_stream = G_MEMORY_INPUT_STREAM (seekable);
421   priv = memory_stream->priv;
422
423   switch (type) 
424     {
425     case G_SEEK_CUR:
426       absolute = priv->pos + offset;
427       break;
428
429     case G_SEEK_SET:
430       absolute = offset;
431       break;
432
433     case G_SEEK_END:
434       absolute = priv->len + offset;
435       break;
436   
437     default:
438       g_set_error (error,
439                    G_IO_ERROR,
440                    G_IO_ERROR_INVALID_ARGUMENT,
441                    "Invalid GSeekType supplied");
442
443       return FALSE;
444     }
445
446   if (absolute < 0 || absolute > priv->len)
447     {
448       g_set_error (error,
449                    G_IO_ERROR,
450                    G_IO_ERROR_INVALID_ARGUMENT,
451                    "Invalid seek request");
452       return FALSE;
453     }
454
455   priv->pos = absolute;
456
457   return TRUE;
458 }
459
460 static gboolean
461 g_memory_input_stream_can_truncate (GSeekable *seekable)
462 {
463   return FALSE;
464 }
465
466 static gboolean
467 g_memory_input_stream_truncate (GSeekable     *seekable,
468                                 goffset        offset,
469                                 GCancellable  *cancellable,
470                                 GError       **error)
471 {
472   g_set_error (error,
473                G_IO_ERROR,
474                G_IO_ERROR_NOT_SUPPORTED,
475                "Cannot seek on GMemoryInputStream");
476   return FALSE;
477 }
478
479 #define __G_MEMORY_INPUT_STREAM_C__
480 #include "gioaliasdef.c"