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