Doc fixes
[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  * Copyright (C) 2007 Jürg Billeter
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General
17  * Public License along with this library; if not, write to the
18  * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
19  * Boston, MA 02111-1307, USA.
20  *
21  * Author: Alexander Larsson <alexl@redhat.com>
22  */
23
24 #include <config.h>
25 #include "gdatainputstream.h"
26 #include "gioenumtypes.h"
27 #include "glibintl.h"
28
29 #include "gioalias.h"
30
31 /**
32  * SECTION:gdatainputstream
33  * @short_description: Data Input Stream
34  * @include: gio/gio.h
35  * @see_also: #GInputStream
36  * 
37  * Data input stream implements #GInputStream and includes functions for 
38  * reading structured data directly from a binary input stream.
39  *
40  **/
41
42 struct _GDataInputStreamPrivate {
43   GDataStreamByteOrder byte_order;
44   GDataStreamNewlineType newline_type;
45 };
46
47 enum {
48   PROP_0,
49   PROP_BYTE_ORDER,
50   PROP_NEWLINE_TYPE
51 };
52
53 static void g_data_input_stream_set_property (GObject      *object,
54                                               guint         prop_id,
55                                               const GValue *value,
56                                               GParamSpec   *pspec);
57 static void g_data_input_stream_get_property (GObject      *object,
58                                               guint         prop_id,
59                                               GValue       *value,
60                                               GParamSpec   *pspec);
61
62 G_DEFINE_TYPE (GDataInputStream,
63                g_data_input_stream,
64                G_TYPE_BUFFERED_INPUT_STREAM)
65
66
67 static void
68 g_data_input_stream_class_init (GDataInputStreamClass *klass)
69 {
70   GObjectClass *object_class;
71
72   g_type_class_add_private (klass, sizeof (GDataInputStreamPrivate));
73
74   object_class = G_OBJECT_CLASS (klass);
75   object_class->get_property = g_data_input_stream_get_property;
76   object_class->set_property = g_data_input_stream_set_property;
77
78   /**
79    * GDataStream:byte-order:
80    *
81    * The ::byte-order property determines the byte ordering that
82    * is used when reading multi-byte entities (such as integers)
83    * from the stream.
84    */ 
85   g_object_class_install_property (object_class,
86                                    PROP_BYTE_ORDER,
87                                    g_param_spec_enum ("byte-order",
88                                                       P_("Byte order"),
89                                                       P_("The byte order"),
90                                                       G_TYPE_DATA_STREAM_BYTE_ORDER,
91                                                       G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN,
92                                                       G_PARAM_READWRITE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_BLURB));
93
94   /**
95    * GDataStream:newline-type:
96    *
97    * The :newline-type property determines what is considered
98    * as a line ending when reading complete lines from the stream.
99    */ 
100   g_object_class_install_property (object_class,
101                                    PROP_NEWLINE_TYPE,
102                                    g_param_spec_enum ("newline-type",
103                                                       P_("Newline type"),
104                                                       P_("The accepted types of line ending"),
105                                                       G_TYPE_DATA_STREAM_NEWLINE_TYPE,
106                                                       G_DATA_STREAM_NEWLINE_TYPE_LF,
107                                                       G_PARAM_READWRITE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_BLURB));
108 }
109
110 static void
111 g_data_input_stream_set_property (GObject      *object,
112                                   guint         prop_id,
113                                   const GValue *value,
114                                   GParamSpec   *pspec)
115 {
116   GDataInputStreamPrivate *priv;
117   GDataInputStream        *dstream;
118
119   dstream = G_DATA_INPUT_STREAM (object);
120   priv = dstream->priv;
121
122    switch (prop_id) 
123     {
124     case PROP_BYTE_ORDER:
125       g_data_input_stream_set_byte_order (dstream, g_value_get_enum (value));
126       break;
127
128     case PROP_NEWLINE_TYPE:
129       g_data_input_stream_set_newline_type (dstream, g_value_get_enum (value));
130       break;
131
132     default:
133       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
134       break;
135     }
136
137 }
138
139 static void
140 g_data_input_stream_get_property (GObject    *object,
141                                   guint       prop_id,
142                                   GValue     *value,
143                                   GParamSpec *pspec)
144 {
145   GDataInputStreamPrivate *priv;
146   GDataInputStream        *dstream;
147
148   dstream = G_DATA_INPUT_STREAM (object);
149   priv = dstream->priv;
150
151   switch (prop_id)
152     { 
153     case PROP_BYTE_ORDER:
154       g_value_set_enum (value, priv->byte_order);
155       break;
156
157     case PROP_NEWLINE_TYPE:
158       g_value_set_enum (value, priv->newline_type);
159       break;
160
161     default:
162       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
163       break;
164     }
165
166 }
167 static void
168 g_data_input_stream_init (GDataInputStream *stream)
169 {
170   stream->priv = G_TYPE_INSTANCE_GET_PRIVATE (stream,
171                                               G_TYPE_DATA_INPUT_STREAM,
172                                               GDataInputStreamPrivate);
173
174   stream->priv->byte_order = G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN;
175   stream->priv->newline_type = G_DATA_STREAM_NEWLINE_TYPE_LF;
176 }
177
178 /**
179  * g_data_input_stream_new:
180  * @base_stream: a #GInputStream.
181  * 
182  * Creates a new data input stream for the @base_stream.
183  * 
184  * Returns: a new #GDataInputStream.
185  **/
186 GDataInputStream *
187 g_data_input_stream_new (GInputStream *base_stream)
188 {
189   GDataInputStream *stream;
190
191   g_return_val_if_fail (G_IS_INPUT_STREAM (base_stream), NULL);
192
193   stream = g_object_new (G_TYPE_DATA_INPUT_STREAM,
194                          "base-stream", base_stream,
195                          NULL);
196
197   return stream;
198 }
199
200 /**
201  * g_data_input_stream_set_byte_order:
202  * @stream: a given #GDataInputStream.
203  * @order: a #GDataStreamByteOrder to set.
204  * 
205  * This function sets the byte order for the given @stream. All subsequent
206  * reads from the @stream will be read in the given @order.
207  *  
208  **/
209 void
210 g_data_input_stream_set_byte_order (GDataInputStream     *stream,
211                                     GDataStreamByteOrder  order)
212 {
213   GDataInputStreamPrivate *priv;
214
215   g_return_if_fail (G_IS_DATA_INPUT_STREAM (stream));
216
217   priv = stream->priv;
218
219   if (priv->byte_order != order)
220     {
221       priv->byte_order = order;
222       
223       g_object_notify (G_OBJECT (stream), "byte-order");
224     }
225 }
226
227 /**
228  * g_data_input_stream_get_byte_order:
229  * @stream: a given #GDataInputStream.
230  * 
231  * Gets the byte order for the data input stream.
232  * 
233  * Returns: the @stream's current #GDataStreamByteOrder. 
234  **/
235 GDataStreamByteOrder
236 g_data_input_stream_get_byte_order (GDataInputStream *stream)
237 {
238   g_return_val_if_fail (G_IS_DATA_INPUT_STREAM (stream), G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN);
239
240   return stream->priv->byte_order;
241 }
242
243 /**
244  * g_data_input_stream_set_newline_type:
245  * @stream: a #GDataInputStream.
246  * @type: the type of new line return as #GDataStreamNewlineType.
247  * 
248  * Sets the newline type for the @stream.
249  * 
250  * Note that using G_DATA_STREAM_NEWLINE_TYPE_ANY is slightly unsafe. If a read
251  * chunk ends in "CR" we must read an additional byte to know if this is "CR" or
252  * "CR LF", and this might block if there is no more data availible.
253  *  
254  **/
255 void
256 g_data_input_stream_set_newline_type (GDataInputStream       *stream,
257                                       GDataStreamNewlineType  type)
258 {
259   GDataInputStreamPrivate *priv;
260
261   g_return_if_fail (G_IS_DATA_INPUT_STREAM (stream));
262
263   priv = stream->priv;
264   
265   if (priv->newline_type != type)
266     {
267       priv->newline_type = type;
268
269       g_object_notify (G_OBJECT (stream), "newline-type");
270     }
271 }
272
273 /**
274  * g_data_input_stream_get_newline_type:
275  * @stream: a given #GDataInputStream.
276  * 
277  * Gets the current newline type for the @stream.
278  * 
279  * Returns: #GDataStreamNewlineType for the given @stream.
280  **/
281 GDataStreamNewlineType
282 g_data_input_stream_get_newline_type (GDataInputStream *stream)
283 {
284   g_return_val_if_fail (G_IS_DATA_INPUT_STREAM (stream), G_DATA_STREAM_NEWLINE_TYPE_ANY);
285
286   return stream->priv->newline_type;
287 }
288
289 static gboolean
290 read_data (GDataInputStream  *stream,
291            void              *buffer,
292            gsize              size,
293            GCancellable      *cancellable,
294            GError           **error)
295 {
296   gsize available;
297   gssize res;
298
299   while ((available = g_buffered_input_stream_get_available (G_BUFFERED_INPUT_STREAM (stream))) < size)
300     {
301       res = g_buffered_input_stream_fill (G_BUFFERED_INPUT_STREAM (stream),
302                                           size - available,
303                                           cancellable, error);
304       if (res < 0)
305         return FALSE;
306       if (res == 0)
307         {
308           g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
309                        _("Unexpected early end-of-stream"));
310           return FALSE;
311         }
312     }
313   
314   /* This should always succeed, since its in the buffer */
315   res = g_input_stream_read (G_INPUT_STREAM (stream),
316                              buffer, size,
317                              NULL, NULL);
318   g_warn_if_fail (res == size);
319   return TRUE;
320 }
321
322
323 /**
324  * g_data_input_stream_read_byte:
325  * @stream: a given #GDataInputStream.
326  * @cancellable: optional #GCancellable object, %NULL to ignore.
327  * @error: #GError for error reporting.
328  * 
329  * Reads an unsigned 8-bit/1-byte value from @stream.
330  *
331  * Returns: an unsigned 8-bit/1-byte value read from the @stream or %0 
332  * if an error occurred.
333  **/
334 guchar
335 g_data_input_stream_read_byte (GDataInputStream  *stream,
336                                GCancellable       *cancellable,
337                                GError            **error)
338 {
339   guchar c;
340   
341   g_return_val_if_fail (G_IS_DATA_INPUT_STREAM (stream), '\0');
342   
343   if (read_data (stream, &c, 1, cancellable, error))
344       return c;
345   
346   return 0;
347 }
348
349
350 /**
351  * g_data_input_stream_read_int16:
352  * @stream: a given #GDataInputStream.
353  * @cancellable: optional #GCancellable object, %NULL to ignore.
354  * @error: #GError for error reporting.
355  * 
356  * Reads a 16-bit/2-byte value from @stream.
357  *
358  * In order to get the correct byte order for this read operation, 
359  * see g_data_stream_get_byte_order() and g_data_stream_set_byte_order().
360  * 
361  * Returns: a signed 16-bit/2-byte value read from @stream or %0 if 
362  * an error occurred.
363  **/
364 gint16
365 g_data_input_stream_read_int16 (GDataInputStream  *stream,
366                                GCancellable       *cancellable,
367                                GError            **error)
368 {
369   gint16 v;
370   
371   g_return_val_if_fail (G_IS_DATA_INPUT_STREAM (stream), 0);
372   
373   if (read_data (stream, &v, 2, cancellable, error))
374     {
375       switch (stream->priv->byte_order)
376         {
377         case G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN:
378           v = GINT16_FROM_BE (v);
379           break;
380         case G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN:
381           v = GINT16_FROM_LE (v);
382           break;
383         case G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN:
384         default:
385           break;
386         }
387       return v;
388     }
389   
390   return 0;
391 }
392
393
394 /**
395  * g_data_input_stream_read_uint16:
396  * @stream: a given #GDataInputStream.
397  * @cancellable: optional #GCancellable object, %NULL to ignore.
398  * @error: #GError for error reporting.
399  *
400  * Reads an unsigned 16-bit/2-byte value from @stream.
401  *
402  * In order to get the correct byte order for this read operation, 
403  * see g_data_stream_get_byte_order() and g_data_stream_set_byte_order(). 
404  * 
405  * Returns: an unsigned 16-bit/2-byte value read from the @stream or %0 if 
406  * an error occurred. 
407  **/
408 guint16
409 g_data_input_stream_read_uint16 (GDataInputStream  *stream,
410                                  GCancellable       *cancellable,
411                                  GError            **error)
412 {
413   guint16 v;
414   
415   g_return_val_if_fail (G_IS_DATA_INPUT_STREAM (stream), 0);
416   
417   if (read_data (stream, &v, 2, cancellable, error))
418     {
419       switch (stream->priv->byte_order)
420         {
421         case G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN:
422           v = GUINT16_FROM_BE (v);
423           break;
424         case G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN:
425           v = GUINT16_FROM_LE (v);
426           break;
427         case G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN:
428         default:
429           break;
430         }
431       return v;
432     }
433   
434   return 0;
435 }
436
437
438 /**
439  * g_data_input_stream_read_int32:
440  * @stream: a given #GDataInputStream.
441  * @cancellable: optional #GCancellable object, %NULL to ignore.
442  * @error: #GError for error reporting.
443  * 
444  * Reads a signed 32-bit/4-byte value from @stream.
445  *
446  * In order to get the correct byte order for this read operation, 
447  * see g_data_stream_get_byte_order() and g_data_stream_set_byte_order().
448  *
449  * If @cancellable is not %NULL, then the operation can be cancelled by
450  * triggering the cancellable object from another thread. If the operation
451  * was cancelled, the error %G_IO_ERROR_CANCELLED will be returned. 
452  *   
453  * Returns: a signed 32-bit/4-byte value read from the @stream or %0 if 
454  * an error occurred. 
455  **/
456 gint32
457 g_data_input_stream_read_int32 (GDataInputStream  *stream,
458                                 GCancellable       *cancellable,
459                                 GError            **error)
460 {
461   gint32 v;
462   
463   g_return_val_if_fail (G_IS_DATA_INPUT_STREAM (stream), 0);
464   
465   if (read_data (stream, &v, 4, cancellable, error))
466     {
467       switch (stream->priv->byte_order)
468         {
469         case G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN:
470           v = GINT32_FROM_BE (v);
471           break;
472         case G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN:
473           v = GINT32_FROM_LE (v);
474           break;
475         case G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN:
476         default:
477           break;
478         }
479       return v;
480     }
481   
482   return 0;
483 }
484
485
486 /**
487  * g_data_input_stream_read_uint32:
488  * @stream: a given #GDataInputStream.
489  * @cancellable: optional #GCancellable object, %NULL to ignore.
490  * @error: #GError for error reporting.
491  * 
492  * Reads an unsigned 32-bit/4-byte value from @stream.
493  *
494  * In order to get the correct byte order for this read operation, 
495  * see g_data_stream_get_byte_order() and g_data_stream_set_byte_order().
496  *
497  * If @cancellable is not %NULL, then the operation can be cancelled by
498  * triggering the cancellable object from another thread. If the operation
499  * was cancelled, the error %G_IO_ERROR_CANCELLED will be returned. 
500  * 
501  * Returns: an unsigned 32-bit/4-byte value read from the @stream or %0 if 
502  * an error occurred. 
503  **/
504 guint32
505 g_data_input_stream_read_uint32 (GDataInputStream  *stream,
506                                  GCancellable       *cancellable,
507                                  GError            **error)
508 {
509   guint32 v;
510   
511   g_return_val_if_fail (G_IS_DATA_INPUT_STREAM (stream), 0);
512   
513   if (read_data (stream, &v, 4, cancellable, error))
514     {
515       switch (stream->priv->byte_order)
516         {
517         case G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN:
518           v = GUINT32_FROM_BE (v);
519           break;
520         case G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN:
521           v = GUINT32_FROM_LE (v);
522           break;
523         case G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN:
524         default:
525           break;
526         }
527       return v;
528     }
529   
530   return 0;
531 }
532
533
534 /**
535  * g_data_input_stream_read_int64:
536  * @stream: a given #GDataInputStream.
537  * @cancellable: optional #GCancellable object, %NULL to ignore.
538  * @error: #GError for error reporting.
539  * 
540  * Reads a 64-bit/8-byte value from @stream.
541  *
542  * In order to get the correct byte order for this read operation, 
543  * see g_data_stream_get_byte_order() and g_data_stream_set_byte_order().
544  *
545  * If @cancellable is not %NULL, then the operation can be cancelled by
546  * triggering the cancellable object from another thread. If the operation
547  * was cancelled, the error %G_IO_ERROR_CANCELLED will be returned. 
548  * 
549  * Returns: a signed 64-bit/8-byte value read from @stream or %0 if 
550  * an error occurred.  
551  **/
552 gint64
553 g_data_input_stream_read_int64 (GDataInputStream  *stream,
554                                GCancellable       *cancellable,
555                                GError            **error)
556 {
557   gint64 v;
558   
559   g_return_val_if_fail (G_IS_DATA_INPUT_STREAM (stream), 0);
560   
561   if (read_data (stream, &v, 8, cancellable, error))
562     {
563       switch (stream->priv->byte_order)
564         {
565         case G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN:
566           v = GINT64_FROM_BE (v);
567           break;
568         case G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN:
569           v = GINT64_FROM_LE (v);
570           break;
571         case G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN:
572         default:
573           break;
574         }
575       return v;
576     }
577   
578   return 0;
579 }
580
581
582 /**
583  * g_data_input_stream_read_uint64:
584  * @stream: a given #GDataInputStream.
585  * @cancellable: optional #GCancellable object, %NULL to ignore.
586  * @error: #GError for error reporting.
587  * 
588  * Reads an unsigned 64-bit/8-byte value from @stream.
589  *
590  * In order to get the correct byte order for this read operation, 
591  * see g_data_stream_get_byte_order().
592  *
593  * If @cancellable is not %NULL, then the operation can be cancelled by
594  * triggering the cancellable object from another thread. If the operation
595  * was cancelled, the error %G_IO_ERROR_CANCELLED will be returned. 
596  * 
597  * Returns: an unsigned 64-bit/8-byte read from @stream or %0 if 
598  * an error occurred. 
599  **/
600 guint64
601 g_data_input_stream_read_uint64 (GDataInputStream  *stream,
602                                 GCancellable       *cancellable,
603                                 GError            **error)
604 {
605   guint64 v;
606   
607   g_return_val_if_fail (G_IS_DATA_INPUT_STREAM (stream), 0);
608   
609   if (read_data (stream, &v, 8, cancellable, error))
610     {
611       switch (stream->priv->byte_order)
612         {
613         case G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN:
614           v = GUINT64_FROM_BE (v);
615           break;
616         case G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN:
617           v = GUINT64_FROM_LE (v);
618           break;
619         case G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN:
620         default:
621           break;
622         }
623       return v;
624     }
625   
626   return 0;
627 }
628
629 static gssize
630 scan_for_newline (GDataInputStream *stream,
631                   gsize            *checked_out,
632                   gboolean         *last_saw_cr_out,
633                   int              *newline_len_out)
634 {
635   GBufferedInputStream *bstream;
636   GDataInputStreamPrivate *priv;
637   const char *buffer;
638   gsize start, end, peeked;
639   int i;
640   gssize found_pos;
641   int newline_len;
642   gsize available, checked;
643   gboolean last_saw_cr;
644
645   priv = stream->priv;
646   
647   bstream = G_BUFFERED_INPUT_STREAM (stream);
648
649   checked = *checked_out;
650   last_saw_cr = *last_saw_cr_out;
651   found_pos = -1;
652   newline_len = 0;
653   
654   start = checked;
655   buffer = (const char*)g_buffered_input_stream_peek_buffer (bstream, &available) + start;
656   end = available;
657   peeked = end - start;
658
659   for (i = 0; checked < available && i < peeked; i++)
660     {
661       switch (priv->newline_type)
662         {
663         case G_DATA_STREAM_NEWLINE_TYPE_LF:
664           if (buffer[i] == 10)
665             {
666               found_pos = start + i;
667               newline_len = 1;
668             }
669           break;
670         case G_DATA_STREAM_NEWLINE_TYPE_CR:
671           if (buffer[i] == 13)
672             {
673               found_pos = start + i;
674               newline_len = 1;
675             }
676           break;
677         case G_DATA_STREAM_NEWLINE_TYPE_CR_LF:
678           if (last_saw_cr && buffer[i] == 10)
679             {
680               found_pos = start + i - 1;
681               newline_len = 2;
682             }
683           break;
684         default:
685         case G_DATA_STREAM_NEWLINE_TYPE_ANY:
686           if (buffer[i] == 10) /* LF */
687             {
688               if (last_saw_cr)
689                 {
690                   /* CR LF */
691                   found_pos = start + i - 1;
692                   newline_len = 2;
693                 }
694               else
695                 {
696                   /* LF */
697                   found_pos = start + i;
698                   newline_len = 1;
699                 }
700             }
701           else if (last_saw_cr)
702             {
703               /* Last was cr, this is not LF, end is CR */
704               found_pos = start + i - 1;
705               newline_len = 1;
706             }
707           /* Don't check for CR here, instead look at last_saw_cr on next byte */
708           break;
709         }
710         
711       last_saw_cr = (buffer[i] == 13);
712
713       if (found_pos != -1)
714         {
715           *newline_len_out = newline_len;
716           return found_pos;
717         }
718     }
719
720   checked = end;
721
722   *checked_out = checked;
723   *last_saw_cr_out = last_saw_cr;
724   return -1;
725 }
726                   
727
728 /**
729  * g_data_input_stream_read_line:
730  * @stream: a given #GDataInputStream.
731  * @length: a #gsize to get the length of the data read in.
732  * @cancellable: optional #GCancellable object, %NULL to ignore.
733  * @error: #GError for error reporting.
734  *
735  * Reads a line from the data input stream.
736  * 
737  * If @cancellable is not %NULL, then the operation can be cancelled by
738  * triggering the cancellable object from another thread. If the operation
739  * was cancelled, the error %G_IO_ERROR_CANCELLED will be returned. 
740  * 
741  * Returns: a string with the line that was read in (including the newlines).
742  * Set @length to a #gsize to get the length of the read line. Returns %NULL on an error.
743  **/
744 char *
745 g_data_input_stream_read_line (GDataInputStream  *stream,
746                                gsize             *length,
747                                GCancellable      *cancellable,
748                                GError           **error)
749 {
750   GBufferedInputStream *bstream;
751   gsize checked;
752   gboolean last_saw_cr;
753   gssize found_pos;
754   gssize res;
755   int newline_len;
756   char *line;
757   
758   g_return_val_if_fail (G_IS_DATA_INPUT_STREAM (stream), NULL);  
759
760   bstream = G_BUFFERED_INPUT_STREAM (stream);
761
762   newline_len = 0;
763   checked = 0;
764   last_saw_cr = FALSE;
765
766   while ((found_pos = scan_for_newline (stream, &checked, &last_saw_cr, &newline_len)) == -1)
767     {
768       if (g_buffered_input_stream_get_available (bstream) ==
769           g_buffered_input_stream_get_buffer_size (bstream))
770         g_buffered_input_stream_set_buffer_size (bstream,
771                                                  2 * g_buffered_input_stream_get_buffer_size (bstream));
772
773       res = g_buffered_input_stream_fill (bstream, -1, cancellable, error);
774       if (res < 0)
775         return NULL;
776       if (res == 0)
777         {
778           /* End of stream */
779           if (g_buffered_input_stream_get_available (bstream) == 0)
780             {
781               if (length)
782                 *length = 0;
783               return NULL;
784             }
785           else
786             {
787               found_pos = checked;
788               newline_len = 0;
789               break;
790             }
791         }
792     }
793
794   line = g_malloc (found_pos + newline_len + 1);
795
796   res = g_input_stream_read (G_INPUT_STREAM (stream),
797                              line,
798                              found_pos + newline_len,
799                              NULL, NULL);
800   if (length)
801     *length = (gsize)found_pos;
802   g_warn_if_fail (res == found_pos + newline_len);
803   line[found_pos] = 0;
804   
805   return line;
806 }
807
808
809 static gssize
810 scan_for_chars (GDataInputStream *stream,
811                 gsize            *checked_out,
812                 const char       *stop_chars)
813 {
814   GBufferedInputStream *bstream;
815   GDataInputStreamPrivate *priv;
816   const char *buffer;
817   gsize start, end, peeked;
818   int i;
819   gssize found_pos;
820   gsize available, checked;
821   const char *stop_char;
822
823   priv = stream->priv;
824   
825   bstream = G_BUFFERED_INPUT_STREAM (stream);
826
827   checked = *checked_out;
828   found_pos = -1;
829   
830   start = checked;
831   buffer = (const char *)g_buffered_input_stream_peek_buffer (bstream, &available) + start;
832   end = available;
833   peeked = end - start;
834
835   for (i = 0; checked < available && i < peeked; i++)
836     {
837       for (stop_char = stop_chars; *stop_char != '\0'; stop_char++)
838         {
839           if (buffer[i] == *stop_char)
840             return (start + i);
841         }
842     }
843
844   checked = end;
845
846   *checked_out = checked;
847   return -1;
848 }
849
850 /**
851  * g_data_input_stream_read_until:
852  * @stream: a given #GDataInputStream.
853  * @stop_chars: characters to terminate the read.
854  * @length: a #gsize to get the length of the data read in.
855  * @cancellable: optional #GCancellable object, %NULL to ignore.
856  * @error: #GError for error reporting.
857  * 
858  * Reads a string from the data input stream, up to the first 
859  * occurrance of any of the stop characters.
860  *
861  * Returns: a string with the data that was read before encountering 
862  * any of the stop characters. Set @length to a #gsize to get the length 
863  * of the string. This function will return %NULL on an error.
864  **/
865 char *
866 g_data_input_stream_read_until (GDataInputStream  *stream,
867                                const gchar        *stop_chars,
868                                gsize              *length,
869                                GCancellable       *cancellable,
870                                GError            **error)
871 {
872   GBufferedInputStream *bstream;
873   gsize checked;
874   gssize found_pos;
875   gssize res;
876   int stop_char_len;
877   char *data_until;
878   
879   g_return_val_if_fail (G_IS_DATA_INPUT_STREAM (stream), NULL);  
880
881   bstream = G_BUFFERED_INPUT_STREAM (stream);
882
883   stop_char_len = 1;
884   checked = 0;
885
886   while ((found_pos = scan_for_chars (stream, &checked, stop_chars)) == -1)
887     {
888       if (g_buffered_input_stream_get_available (bstream) ==
889           g_buffered_input_stream_get_buffer_size (bstream))
890         g_buffered_input_stream_set_buffer_size (bstream,
891                                                  2 * g_buffered_input_stream_get_buffer_size (bstream));
892
893       res = g_buffered_input_stream_fill (bstream, -1, cancellable, error);
894       if (res < 0)
895         return NULL;
896       if (res == 0)
897         {
898           /* End of stream */
899           if (g_buffered_input_stream_get_available (bstream) == 0)
900             {
901               if (length)
902                 *length = 0;
903               return NULL;
904             }
905           else
906             {
907               found_pos = checked;
908               stop_char_len = 0;
909               break;
910             }
911         }
912     }
913
914   data_until = g_malloc (found_pos + stop_char_len + 1);
915
916   res = g_input_stream_read (G_INPUT_STREAM (stream),
917                              data_until,
918                              found_pos + stop_char_len,
919                              NULL, NULL);
920   if (length)
921     *length = (gsize)found_pos;
922   g_warn_if_fail (res == found_pos + stop_char_len);
923   data_until[found_pos] = 0;
924   
925   return data_until;
926 }
927
928 #define __G_DATA_INPUT_STREAM_C__
929 #include "gioaliasdef.c"