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