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