Added. Added. Added. Added.
[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  = g_memory_input_stream_read;
123   istream_class->skip  = g_memory_input_stream_skip;
124   istream_class->close = 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     = 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:
169  * @free_data:
170  * 
171  **/
172 void
173 g_memory_input_stream_set_free_data (GMemoryInputStream *stream,
174                                      gboolean free_data)
175 {
176   g_return_if_fail (G_IS_MEMORY_INPUT_STREAM (stream));
177
178   stream->priv->free_data = free_data;
179 }
180
181 /**
182  * g_memory_input_stream_from_data:
183  * @data: input data.
184  * @len: length of the data.
185  * 
186  * Returns: new #GInputStream read from @data of @len bytes.
187  **/
188 GInputStream *
189 g_memory_input_stream_from_data (const void *data, gssize len)
190 {
191   GInputStream *stream;
192   GMemoryInputStream *memory_stream;
193
194   g_return_val_if_fail (data != NULL, NULL);
195
196   stream = g_object_new (G_TYPE_MEMORY_INPUT_STREAM, NULL);
197   memory_stream = G_MEMORY_INPUT_STREAM (stream);
198
199   if (len == -1)
200     len = strlen (data);
201   
202   memory_stream->priv->buffer = (guint8 *)data;
203   memory_stream->priv->len = len;
204
205   return stream;
206 }
207
208 static gssize
209 g_memory_input_stream_read (GInputStream *stream,
210                             void         *buffer,
211                             gsize         count,
212                             GCancellable *cancellable,
213                             GError      **error)
214 {
215   GMemoryInputStream *memory_stream;
216   GMemoryInputStreamPrivate * priv;
217
218   memory_stream = G_MEMORY_INPUT_STREAM (stream);
219   priv = memory_stream->priv;
220
221   count = MIN (count, priv->len - priv->pos);
222   memcpy (buffer, priv->buffer + priv->pos, count);
223   priv->pos += count;
224
225   return count;
226 }
227
228 /**
229  * g_memory_input_stream_get_data:
230  * @stream:
231  * 
232  * Returns: 
233  **/
234 const void *
235 g_memory_input_stream_get_data (GMemoryInputStream *stream)
236 {
237   g_return_val_if_fail (G_IS_MEMORY_INPUT_STREAM (stream), NULL);
238
239   return stream->priv->buffer;
240 }
241
242 /**
243  * g_memory_input_stream_get_data_size:
244  * @stream:
245  * 
246  * Returns: 
247  **/
248 gsize
249 g_memory_input_stream_get_data_size (GMemoryInputStream *stream)
250 {
251   g_return_val_if_fail (G_IS_MEMORY_INPUT_STREAM (stream), -1);
252
253   return stream->priv->len;
254 }
255
256 static gssize
257 g_memory_input_stream_skip (GInputStream              *stream,
258                             gsize                      count,
259                             GCancellable              *cancellable,
260                             GError                   **error)
261 {
262   GMemoryInputStream *memory_stream;
263   GMemoryInputStreamPrivate *priv;
264
265   memory_stream = G_MEMORY_INPUT_STREAM (stream);
266   priv = memory_stream->priv;
267
268   count = MIN (count, priv->len - priv->pos);
269   priv->pos += count;
270
271   return count;
272  
273
274 }
275
276 static gboolean
277 g_memory_input_stream_close (GInputStream *stream,
278                              GCancellable *cancellable,
279                              GError      **error)
280 {
281   return TRUE;
282 }
283
284 static void
285 g_memory_input_stream_read_async (GInputStream              *stream,
286                                   void                      *buffer,
287                                   gsize                      count,
288                                   int                        io_priority,
289                                   GCancellable              *cancellable,
290                                   GAsyncReadyCallback        callback,
291                                   gpointer                   user_data)
292 {
293   GSimpleAsyncResult *simple;
294   gssize nread;
295
296   nread =  g_memory_input_stream_read (stream,  buffer, count, cancellable, NULL);
297   simple = g_simple_async_result_new (G_OBJECT (stream),
298                                       callback,
299                                       user_data,
300                                       g_memory_input_stream_read_async);
301   g_simple_async_result_set_op_res_gssize (simple, nread);
302   g_simple_async_result_complete_in_idle (simple);
303   g_object_unref (simple);
304 }
305
306 static gssize
307 g_memory_input_stream_read_finish (GInputStream              *stream,
308                                    GAsyncResult              *result,
309                                    GError                   **error)
310 {
311   GSimpleAsyncResult *simple;
312   gssize nread;
313
314   simple = G_SIMPLE_ASYNC_RESULT (result);
315   g_assert (g_simple_async_result_get_source_tag (simple) == g_memory_input_stream_read_async);
316   
317   nread = g_simple_async_result_get_op_res_gssize (simple);
318   return nread;
319 }
320
321 static void
322 g_memory_input_stream_skip_async (GInputStream              *stream,
323                                   gsize                      count,
324                                   int                        io_priority,
325                                   GCancellable              *cancellable,
326                                   GAsyncReadyCallback        callback,
327                                   gpointer                   user_data)
328 {
329   GSimpleAsyncResult *simple;
330   gssize nskipped;
331
332   nskipped = g_memory_input_stream_skip (stream, count, cancellable, NULL);
333   simple = g_simple_async_result_new (G_OBJECT (stream),
334                                       callback,
335                                       user_data,
336                                       g_memory_input_stream_skip_async);
337   g_simple_async_result_set_op_res_gssize (simple, nskipped);
338   g_simple_async_result_complete_in_idle (simple);
339   g_object_unref (simple);
340 }
341
342 static gssize
343 g_memory_input_stream_skip_finish (GInputStream              *stream,
344                                    GAsyncResult              *result,
345                                    GError                   **error)
346 {
347   GSimpleAsyncResult *simple;
348   gssize nskipped;
349
350   simple = G_SIMPLE_ASYNC_RESULT (result);
351   g_assert (g_simple_async_result_get_source_tag (simple) == g_memory_input_stream_skip_async);
352   
353   nskipped = g_simple_async_result_get_op_res_gssize (simple);
354   return nskipped;
355 }
356
357 static void
358 g_memory_input_stream_close_async (GInputStream              *stream,
359                                    int                        io_priority,
360                                    GCancellable              *cancellable,
361                                    GAsyncReadyCallback        callback,
362                                    gpointer                   user_data)
363 {
364   GSimpleAsyncResult *simple;
365   
366   simple = g_simple_async_result_new (G_OBJECT (stream),
367                                       callback,
368                                       user_data,
369                                       g_memory_input_stream_close_async);
370   g_simple_async_result_complete_in_idle (simple);
371   g_object_unref (simple);
372 }
373
374 static gboolean
375 g_memory_input_stream_close_finish (GInputStream              *stream,
376                                     GAsyncResult              *result,
377                                     GError                   **error)
378 {
379   return TRUE;
380 }
381
382 static goffset
383 g_memory_input_stream_tell (GSeekable *seekable)
384 {
385   GMemoryInputStream *memory_stream;
386   GMemoryInputStreamPrivate * priv;
387
388   memory_stream = G_MEMORY_INPUT_STREAM (seekable);
389   priv = memory_stream->priv;
390
391   return priv->pos;
392 }
393
394 static
395 gboolean g_memory_input_stream_can_seek (GSeekable *seekable)
396 {
397   return TRUE;
398 }
399
400 static gboolean
401 g_memory_input_stream_seek (GSeekable       *seekable,
402                             goffset          offset,
403                             GSeekType        type,
404                             GCancellable    *cancellable,
405                             GError         **error)
406 {
407   GMemoryInputStream *memory_stream;
408   GMemoryInputStreamPrivate * priv;
409   goffset absolute;
410
411   memory_stream = G_MEMORY_INPUT_STREAM (seekable);
412   priv = memory_stream->priv;
413
414   switch (type) {
415
416     case G_SEEK_CUR:
417       absolute = priv->pos + offset;
418       break;
419
420     case G_SEEK_SET:
421       absolute = offset;
422       break;
423
424     case G_SEEK_END:
425       absolute = priv->len + offset;
426       break;
427   
428     default:
429       g_set_error (error,
430                    G_IO_ERROR,
431                    G_IO_ERROR_INVALID_ARGUMENT,
432                    "Invalid GSeekType supplied");
433
434       return FALSE;
435   }
436
437   if (absolute < 0 || absolute > priv->len)
438     {
439       g_set_error (error,
440                    G_IO_ERROR,
441                    G_IO_ERROR_INVALID_ARGUMENT,
442                    "Invalid seek request");
443       return FALSE;
444     }
445
446   priv->pos = absolute;
447
448   return TRUE;
449 }
450
451 static gboolean
452 g_memory_input_stream_can_truncate (GSeekable *seekable)
453 {
454   return FALSE;
455 }
456
457 static gboolean
458 g_memory_input_stream_truncate (GSeekable      *seekable,
459                                 goffset          offset,
460                                 GCancellable    *cancellable,
461                                 GError         **error)
462 {
463   g_set_error (error,
464                G_IO_ERROR,
465                G_IO_ERROR_NOT_SUPPORTED,
466                "Cannot seek on GMemoryInputStream");
467   return FALSE;
468 }
469
470 #define __G_MEMORY_INPUT_STREAM_C__
471 #include "gioaliasdef.c"
472
473 /* vim: ts=2 sw=2 et */