gio/ docs/reference/gio Merged gio-standalone into glib.
[platform/upstream/glib.git] / gio / gdatainputstream.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: Alexander Larsson <alexl@redhat.com>
21  */
22
23 #include <config.h>
24 #include "gdatainputstream.h"
25 #include "glibintl.h"
26
27 struct _GDataInputStreamPrivate {
28   GDataStreamByteOrder byte_order;
29   GDataStreamNewlineType newline_type;
30 };
31
32 enum {
33   PROP_0
34 };
35
36 static void g_data_input_stream_set_property (GObject      *object,
37                                               guint         prop_id,
38                                               const GValue *value,
39                                               GParamSpec   *pspec);
40 static void g_data_input_stream_get_property (GObject      *object,
41                                               guint         prop_id,
42                                               GValue       *value,
43                                               GParamSpec   *pspec);
44
45 G_DEFINE_TYPE (GDataInputStream,
46                g_data_input_stream,
47                G_TYPE_BUFFERED_INPUT_STREAM)
48
49
50 static void
51 g_data_input_stream_class_init (GDataInputStreamClass *klass)
52 {
53   GObjectClass *object_class;
54
55   g_type_class_add_private (klass, sizeof (GDataInputStreamPrivate));
56
57   object_class = G_OBJECT_CLASS (klass);
58   object_class->get_property = g_data_input_stream_get_property;
59   object_class->set_property = g_data_input_stream_set_property;
60 }
61
62 static void
63 g_data_input_stream_set_property (GObject         *object,
64                                   guint            prop_id,
65                                   const GValue    *value,
66                                   GParamSpec      *pspec)
67 {
68   GDataInputStreamPrivate *priv;
69   GDataInputStream        *dstream;
70
71   dstream = G_DATA_INPUT_STREAM (object);
72   priv = dstream->priv;
73
74   switch (prop_id) 
75     {
76
77     default:
78       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
79       break;
80     }
81
82 }
83
84 static void
85 g_data_input_stream_get_property (GObject    *object,
86                                       guint       prop_id,
87                                       GValue     *value,
88                                       GParamSpec *pspec)
89 {
90   GDataInputStreamPrivate *priv;
91   GDataInputStream        *dstream;
92
93   dstream = G_DATA_INPUT_STREAM (object);
94   priv = dstream->priv;
95
96   switch (prop_id)
97     { 
98   
99     default:
100       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
101       break;
102     }
103
104 }
105 static void
106 g_data_input_stream_init (GDataInputStream *stream)
107 {
108   stream->priv = G_TYPE_INSTANCE_GET_PRIVATE (stream,
109                                               G_TYPE_DATA_INPUT_STREAM,
110                                               GDataInputStreamPrivate);
111
112   stream->priv->byte_order = G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN;
113   stream->priv->newline_type = G_DATA_STREAM_NEWLINE_TYPE_LF;
114 }
115
116 /**
117  * g_data_input_stream_new:
118  * @base_stream: a given #GInputStream.
119  * 
120  * Returns: a new #GDataInputStream.
121  **/
122 GDataInputStream *
123 g_data_input_stream_new (GInputStream *base_stream)
124 {
125   GDataInputStream *stream;
126
127   g_return_val_if_fail (G_IS_INPUT_STREAM (base_stream), NULL);
128
129   stream = g_object_new (G_TYPE_DATA_INPUT_STREAM,
130                          "base-stream", base_stream,
131                          NULL);
132
133   return stream;
134 }
135
136 /**
137  * g_data_input_stream_set_byte_order:
138  * @stream: a given #GDataInputStream.
139  * @order: a #GDataStreamByteOrder to set.
140  * 
141  * This function sets the byte order for the given @stream. All subsequent
142  * reads from the @stream will be read in the given @order.
143  *  
144  **/
145 void
146 g_data_input_stream_set_byte_order (GDataInputStream *stream,
147                                     GDataStreamByteOrder order)
148 {
149   g_return_if_fail (G_IS_DATA_INPUT_STREAM (stream));
150
151   stream->priv->byte_order = order;
152 }
153
154 /**
155  * g_data_input_stream_get_byte_order:
156  * @stream: a given #GDataInputStream.
157  * 
158  * Returns the @stream's current #GDataStreamByteOrder. 
159  **/
160 GDataStreamByteOrder
161 g_data_input_stream_get_byte_order (GDataInputStream *stream)
162 {
163   g_return_val_if_fail (G_IS_DATA_INPUT_STREAM (stream), G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN);
164
165   return stream->priv->byte_order;
166 }
167
168 /**
169  * g_data_input_stream_set_newline_type:
170  * @stream: a given #GDataInputStream.
171  * @type: the type of new line return as #GDataStreamNewlineType.
172  * 
173  * Sets the newline type for the @stream.
174  * 
175  * TODO: is it valid to set this to G_DATA_STREAM_NEWLINE_TYPE_ANY, or
176  * should it always be set to {_LF, _CR, _CR_LF}
177  *  
178  **/
179 void
180 g_data_input_stream_set_newline_type (GDataInputStream        *stream,
181                                       GDataStreamNewlineType   type)
182 {
183   g_return_if_fail (G_IS_DATA_INPUT_STREAM (stream));
184
185   stream->priv->newline_type = type;
186 }
187
188 /**
189  * g_data_input_stream_get_newline_type:
190  * @stream: a given #GDataInputStream.
191  * 
192  * Gets the current newline type for the @stream.
193  * 
194  * Returns: #GDataStreamNewlineType for the given @stream.
195  **/
196 GDataStreamNewlineType
197 g_data_input_stream_get_newline_type (GDataInputStream *stream)
198 {
199   g_return_val_if_fail (G_IS_DATA_INPUT_STREAM (stream), G_DATA_STREAM_NEWLINE_TYPE_ANY);
200
201   return stream->priv->newline_type;
202 }
203
204 static gboolean
205 read_data (GDataInputStream *stream,
206           void *buffer,
207           gsize size,
208           GCancellable *cancellable,
209           GError **error)
210 {
211   gsize available;
212   gssize res;
213
214   while ((available = g_buffered_input_stream_get_available (G_BUFFERED_INPUT_STREAM (stream))) < size)
215     {
216       res = g_buffered_input_stream_fill (G_BUFFERED_INPUT_STREAM (stream),
217                                           size - available,
218                                           cancellable, error);
219       if (res < 0)
220         return FALSE;
221       if (res == 0)
222         {
223           g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
224                        _("Unexpected early end-of-stream"));
225           return FALSE;
226         }
227     }
228   
229   /* This should always succeed, since its in the buffer */
230   res = g_input_stream_read (G_INPUT_STREAM (stream),
231                              buffer, size,
232                              NULL, NULL);
233   g_assert (res == size);
234   return TRUE;
235 }
236
237
238 /**
239  * g_data_input_stream_read_byte:
240  * @stream: a given #GDataInputStream.
241  * @cancellable: optional #GCancellable object, %NULL to ignore.
242  * @error: #GError for error reporting.
243  * 
244  * In order to get the correct byte order for this read operation, 
245  * see g_data_stream_get_byte_order() and g_data_stream_set_byte_order().
246  * 
247  * Returns: an unsigned 8-bit/1-byte value read from the @stream or %0 
248  * if an error occured.
249  **/
250
251 guchar
252 g_data_input_stream_read_byte (GDataInputStream        *stream,
253                               GCancellable            *cancellable,
254                               GError                 **error)
255 {
256   guchar c;
257   
258   g_return_val_if_fail (G_IS_DATA_INPUT_STREAM (stream), '\0');
259   
260   if (read_data (stream, &c, 1, cancellable, error))
261       return c;
262   
263   return 0;
264 }
265
266
267 /**
268  * g_data_input_stream_read_int16:
269  * @stream: a given #GDataInputStream.
270  * @cancellable: optional #GCancellable object, %NULL to ignore.
271  * @error: #GError for error reporting.
272  * 
273  * In order to get the correct byte order for this read operation, 
274  * see g_data_stream_get_byte_order() and g_data_stream_set_byte_order().
275  * 
276  * Returns a signed 16-bit/2-byte value read from @stream or %0 if 
277  * an error occured.
278  **/
279 gint16
280 g_data_input_stream_read_int16 (GDataInputStream        *stream,
281                                GCancellable            *cancellable,
282                                GError                 **error)
283 {
284   gint16 v;
285   
286   g_return_val_if_fail (G_IS_DATA_INPUT_STREAM (stream), 0);
287   
288   if (read_data (stream, &v, 2, cancellable, error))
289     {
290       switch (stream->priv->byte_order)
291         {
292         case G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN:
293           v = GINT16_FROM_BE (v);
294           break;
295         case G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN:
296           v = GINT16_FROM_LE (v);
297           break;
298         case G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN:
299         default:
300           break;
301         }
302       return v;
303     }
304   
305   return 0;
306 }
307
308
309 /**
310  * g_data_input_stream_read_uint16:
311  * @stream: a given #GDataInputStream.
312  * @cancellable: optional #GCancellable object, %NULL to ignore.
313  * @error: #GError for error reporting.
314  *
315  * In order to get the correct byte order for this read operation, 
316  * see g_data_stream_get_byte_order() and g_data_stream_set_byte_order(). 
317  * 
318  * Returns an unsigned 16-bit/2-byte value read from the @stream or %0 if 
319  * an error occured. 
320  **/
321 guint16
322 g_data_input_stream_read_uint16 (GDataInputStream        *stream,
323                                 GCancellable            *cancellable,
324                                 GError                 **error)
325 {
326   guint16 v;
327   
328   g_return_val_if_fail (G_IS_DATA_INPUT_STREAM (stream), 0);
329   
330   if (read_data (stream, &v, 2, cancellable, error))
331     {
332       switch (stream->priv->byte_order)
333         {
334         case G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN:
335           v = GUINT16_FROM_BE (v);
336           break;
337         case G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN:
338           v = GUINT16_FROM_LE (v);
339           break;
340         case G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN:
341         default:
342           break;
343         }
344       return v;
345     }
346   
347   return 0;
348 }
349
350
351 /**
352  * g_data_input_stream_read_int32:
353  * @stream: a given #GDataInputStream.
354  * @cancellable: optional #GCancellable object, %NULL to ignore.
355  * @error: #GError for error reporting.
356  * 
357  * In order to get the correct byte order for this read operation, 
358  * see g_data_stream_get_byte_order() and g_data_stream_set_byte_order().
359  *   
360  * Returns a signed 32-bit/4-byte value read from the @stream or %0 if 
361  * an error occured. 
362  **/
363 gint32
364 g_data_input_stream_read_int32 (GDataInputStream        *stream,
365                                GCancellable            *cancellable,
366                                GError                 **error)
367 {
368   gint32 v;
369   
370   g_return_val_if_fail (G_IS_DATA_INPUT_STREAM (stream), 0);
371   
372   if (read_data (stream, &v, 4, cancellable, error))
373     {
374       switch (stream->priv->byte_order)
375         {
376         case G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN:
377           v = GINT32_FROM_BE (v);
378           break;
379         case G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN:
380           v = GINT32_FROM_LE (v);
381           break;
382         case G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN:
383         default:
384           break;
385         }
386       return v;
387     }
388   
389   return 0;
390 }
391
392
393 /**
394  * g_data_input_stream_read_uint32:
395  * @stream: a given #GDataInputStream.
396  * @cancellable: optional #GCancellable object, %NULL to ignore.
397  * @error: #GError for error reporting.
398  * 
399  * In order to get the correct byte order for this read operation, 
400  * see g_data_stream_get_byte_order() and g_data_stream_set_byte_order().
401  * 
402  * Returns an unsigned 32-bit/4-byte value read from the @stream or %0 if 
403  * an error occured. 
404  **/
405 guint32
406 g_data_input_stream_read_uint32 (GDataInputStream        *stream,
407                                 GCancellable            *cancellable,
408                                 GError                 **error)
409 {
410   guint32 v;
411   
412   g_return_val_if_fail (G_IS_DATA_INPUT_STREAM (stream), 0);
413   
414   if (read_data (stream, &v, 4, cancellable, error))
415     {
416       switch (stream->priv->byte_order)
417         {
418         case G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN:
419           v = GUINT32_FROM_BE (v);
420           break;
421         case G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN:
422           v = GUINT32_FROM_LE (v);
423           break;
424         case G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN:
425         default:
426           break;
427         }
428       return v;
429     }
430   
431   return 0;
432 }
433
434
435 /**
436  * g_data_input_stream_read_int64:
437  * @stream: a given #GDataInputStream.
438  * @cancellable: optional #GCancellable object, %NULL to ignore.
439  * @error: #GError for error reporting.
440  * 
441  * In order to get the correct byte order for this read operation, 
442  * see g_data_stream_get_byte_order() and g_data_stream_set_byte_order().
443  * 
444  * Returns a signed 64-bit/8-byte value read from @stream or %0 if 
445  * an error occured.  
446  **/
447 gint64
448 g_data_input_stream_read_int64 (GDataInputStream        *stream,
449                                GCancellable            *cancellable,
450                                GError                 **error)
451 {
452   gint64 v;
453   
454   g_return_val_if_fail (G_IS_DATA_INPUT_STREAM (stream), 0);
455   
456   if (read_data (stream, &v, 8, cancellable, error))
457     {
458       switch (stream->priv->byte_order)
459         {
460         case G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN:
461           v = GINT64_FROM_BE (v);
462           break;
463         case G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN:
464           v = GINT64_FROM_LE (v);
465           break;
466         case G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN:
467         default:
468           break;
469         }
470       return v;
471     }
472   
473   return 0;
474 }
475
476
477 /**
478  * g_data_input_stream_read_uint64:
479  * @stream: a given #GDataInputStream.
480  * @cancellable: optional #GCancellable object, %NULL to ignore.
481  * @error: #GError for error reporting.
482  * 
483  * In order to get the correct byte order for this read operation, 
484  * see g_data_stream_get_byte_order().
485  * 
486  * Returns an unsigned 64-bit/8-byte read from @stream or %0 if 
487  * an error occured. 
488  **/
489 guint64
490 g_data_input_stream_read_uint64 (GDataInputStream        *stream,
491                                 GCancellable            *cancellable,
492                                 GError                 **error)
493 {
494   guint64 v;
495   
496   g_return_val_if_fail (G_IS_DATA_INPUT_STREAM (stream), 0);
497   
498   if (read_data (stream, &v, 8, cancellable, error))
499     {
500       switch (stream->priv->byte_order)
501         {
502         case G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN:
503           v = GUINT64_FROM_BE (v);
504           break;
505         case G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN:
506           v = GUINT64_FROM_LE (v);
507           break;
508         case G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN:
509         default:
510           break;
511         }
512       return v;
513     }
514   
515   return 0;
516 }
517
518 static gssize
519 scan_for_newline (GDataInputStream *stream,
520                   gsize *checked_out,
521                   gboolean *last_saw_cr_out,
522                   int *newline_len_out)
523 {
524   GBufferedInputStream *bstream;
525   GDataInputStreamPrivate *priv;
526   char buffer[100];
527   gsize start, end, peeked;
528   int i;
529   gssize found_pos;
530   int newline_len;
531   gsize available, checked;
532   gboolean last_saw_cr;
533
534   priv = stream->priv;
535   
536   bstream = G_BUFFERED_INPUT_STREAM (stream);
537   
538   available = g_buffered_input_stream_get_available (bstream);
539
540   checked = *checked_out;
541   last_saw_cr = *last_saw_cr_out;
542   found_pos = -1;
543   newline_len = 0;
544   
545   while (checked < available)
546     {
547       start = checked;
548       end = MIN (start + sizeof(buffer), available);
549       peeked = g_buffered_input_stream_peek (bstream, buffer, start, end - start);
550       end = start + peeked;
551
552       for (i = 0; i < peeked; i++)
553         {
554           switch (priv->newline_type)
555             {
556             case G_DATA_STREAM_NEWLINE_TYPE_LF:
557               if (buffer[i] == 10)
558                 {
559                   found_pos = start + i;
560                   newline_len = 1;
561                 }
562               break;
563             case G_DATA_STREAM_NEWLINE_TYPE_CR:
564               if (buffer[i] == 13)
565                 {
566                   found_pos = start + i;
567                   newline_len = 1;
568                 }
569               break;
570             case G_DATA_STREAM_NEWLINE_TYPE_CR_LF:
571               if (last_saw_cr && buffer[i] == 10)
572                 {
573                   found_pos = start + i - 1;
574                   newline_len = 2;
575                 }
576               break;
577             default:
578             case G_DATA_STREAM_NEWLINE_TYPE_ANY:
579               if (buffer[i] == 10) /* LF */
580                 {
581                   if (last_saw_cr)
582                     {
583                       /* CR LF */
584                       found_pos = start + i - 1;
585                       newline_len = 2;
586                     }
587                   else
588                     {
589                       /* LF */
590                       found_pos = start + i;
591                       newline_len = 1;
592                     }
593                 }
594               else if (last_saw_cr)
595                 {
596                   /* Last was cr, this is not LF, end is CR */
597                   found_pos = start + i - 1;
598                   newline_len = 1;
599                 }
600               /* Don't check for CR here, instead look at last_saw_cr on next byte */
601               break;
602             }
603           
604           last_saw_cr = (buffer[i] == 13);
605
606           if (found_pos != -1)
607             {
608               *newline_len_out = newline_len;
609               return found_pos;
610             }
611         }
612       checked = end;
613     }
614
615   *checked_out = checked;
616   *last_saw_cr_out = last_saw_cr;
617   return -1;
618 }
619                   
620
621 /**
622  * g_data_input_stream_read_line:
623  * @stream: a given #GDataInputStream.
624  * @length: a #gsize to get the length of the data read in.
625  * @cancellable: optional #GCancellable object, %NULL to ignore.
626  * @error: #GError for error reporting.
627  * 
628  * Returns a string with the line that was read in. Set @length to 
629  * a #gsize to get the length of the read line. This function will 
630  * return %NULL on an error.
631  **/
632 char *
633 g_data_input_stream_read_line (GDataInputStream        *stream,
634                               gsize                   *length,
635                               GCancellable            *cancellable,
636                               GError                 **error)
637 {
638   GBufferedInputStream *bstream;
639   gsize checked;
640   gboolean last_saw_cr;
641   gssize found_pos;
642   gssize res;
643   int newline_len;
644   char *line;
645   
646   g_return_val_if_fail (G_IS_DATA_INPUT_STREAM (stream), NULL);  
647
648   bstream = G_BUFFERED_INPUT_STREAM (stream);
649
650   newline_len = 0;
651   checked = 0;
652   last_saw_cr = FALSE;
653
654   while ((found_pos = scan_for_newline (stream, &checked, &last_saw_cr, &newline_len)) == -1)
655     {
656       if (g_buffered_input_stream_get_available (bstream) ==
657           g_buffered_input_stream_get_buffer_size (bstream))
658         g_buffered_input_stream_set_buffer_size (bstream,
659                                                  2 * g_buffered_input_stream_get_buffer_size (bstream));
660
661       res = g_buffered_input_stream_fill (bstream, -1, cancellable, error);
662       if (res < 0)
663         return NULL;
664       if (res == 0)
665         {
666           /* End of stream */
667           if (g_buffered_input_stream_get_available (bstream) == 0)
668             {
669               if (length)
670                 *length = 0;
671               return NULL;
672             }
673           else
674             {
675               found_pos = checked;
676               newline_len = 0;
677               break;
678             }
679         }
680     }
681
682   line = g_malloc (found_pos + newline_len + 1);
683
684   res = g_input_stream_read (G_INPUT_STREAM (stream),
685                              line,
686                              found_pos + newline_len,
687                              NULL, NULL);
688   if (length)
689     *length = (gsize)found_pos;
690   g_assert (res == found_pos + newline_len);
691   line[found_pos] = 0;
692   
693   return line;
694 }
695
696
697 /**
698  * g_data_input_stream_read_until:
699  * @stream: a given #GDataInputStream.
700  * @stop_char: character to terminate the read.
701  * @length: a #gsize to get the length of the data read in.
702  * @cancellable: optional #GCancellable object, %NULL to ignore.
703  * @error: #GError for error reporting.
704  * 
705  * NOTE: not supported for #GDataInputStream.
706  * Returns %NULL.
707  **/
708 char *
709 g_data_input_stream_read_until (GDataInputStream        *stream,
710                                gchar                    stop_char,
711                                gsize                   *length,
712                                GCancellable            *cancellable,
713                                GError                 **error)
714 {
715   /* TODO: should be implemented */
716   g_assert_not_reached ();
717   return NULL;
718 }