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