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