Home | History | Annotate | Download | only in gio
      1 /* GIO - GLib Input, Output and Streaming Library
      2  *
      3  * Copyright (C) 2006-2007 Red Hat, Inc.
      4  * Copyright (C) 2007 Jrg Billeter
      5  * Copyright  2009 Codethink Limited
      6  *
      7  * This library is free software; you can redistribute it and/or
      8  * modify it under the terms of the GNU Lesser General Public
      9  * License as published by the Free Software Foundation; either
     10  * version 2 of the License, or (at your option) any later version.
     11  *
     12  * This library is distributed in the hope that it will be useful,
     13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     15  * Lesser General Public License for more details.
     16  *
     17  * You should have received a copy of the GNU Lesser General
     18  * Public License along with this library; if not, write to the
     19  * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
     20  * Boston, MA 02111-1307, USA.
     21  *
     22  * Author: Alexander Larsson <alexl (at) redhat.com>
     23  */
     24 
     25 #include "config.h"
     26 #include "gdatainputstream.h"
     27 #include "gsimpleasyncresult.h"
     28 #include "gcancellable.h"
     29 #include "gioenumtypes.h"
     30 #include "gioerror.h"
     31 #include "glibintl.h"
     32 
     33 #include "gioalias.h"
     34 
     35 /**
     36  * SECTION:gdatainputstream
     37  * @short_description: Data Input Stream
     38  * @include: gio/gio.h
     39  * @see_also: #GInputStream
     40  *
     41  * Data input stream implements #GInputStream and includes functions for
     42  * reading structured data directly from a binary input stream.
     43  *
     44  **/
     45 
     46 struct _GDataInputStreamPrivate {
     47   GDataStreamByteOrder byte_order;
     48   GDataStreamNewlineType newline_type;
     49 };
     50 
     51 enum {
     52   PROP_0,
     53   PROP_BYTE_ORDER,
     54   PROP_NEWLINE_TYPE
     55 };
     56 
     57 static void g_data_input_stream_set_property (GObject      *object,
     58 					      guint         prop_id,
     59 					      const GValue *value,
     60 					      GParamSpec   *pspec);
     61 static void g_data_input_stream_get_property (GObject      *object,
     62 					      guint         prop_id,
     63 					      GValue       *value,
     64 					      GParamSpec   *pspec);
     65 
     66 G_DEFINE_TYPE (GDataInputStream,
     67                g_data_input_stream,
     68                G_TYPE_BUFFERED_INPUT_STREAM)
     69 
     70 
     71 static void
     72 g_data_input_stream_class_init (GDataInputStreamClass *klass)
     73 {
     74   GObjectClass *object_class;
     75 
     76   g_type_class_add_private (klass, sizeof (GDataInputStreamPrivate));
     77 
     78   object_class = G_OBJECT_CLASS (klass);
     79   object_class->get_property = g_data_input_stream_get_property;
     80   object_class->set_property = g_data_input_stream_set_property;
     81 
     82   /**
     83    * GDataStream:byte-order:
     84    *
     85    * The ::byte-order property determines the byte ordering that
     86    * is used when reading multi-byte entities (such as integers)
     87    * from the stream.
     88    */
     89   g_object_class_install_property (object_class,
     90                                    PROP_BYTE_ORDER,
     91                                    g_param_spec_enum ("byte-order",
     92                                                       P_("Byte order"),
     93                                                       P_("The byte order"),
     94                                                       G_TYPE_DATA_STREAM_BYTE_ORDER,
     95                                                       G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN,
     96                                                       G_PARAM_READWRITE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_BLURB));
     97 
     98   /**
     99    * GDataStream:newline-type:
    100    *
    101    * The :newline-type property determines what is considered
    102    * as a line ending when reading complete lines from the stream.
    103    */
    104   g_object_class_install_property (object_class,
    105                                    PROP_NEWLINE_TYPE,
    106                                    g_param_spec_enum ("newline-type",
    107                                                       P_("Newline type"),
    108                                                       P_("The accepted types of line ending"),
    109                                                       G_TYPE_DATA_STREAM_NEWLINE_TYPE,
    110                                                       G_DATA_STREAM_NEWLINE_TYPE_LF,
    111                                                       G_PARAM_READWRITE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_BLURB));
    112 }
    113 
    114 static void
    115 g_data_input_stream_set_property (GObject      *object,
    116 				  guint         prop_id,
    117 				  const GValue *value,
    118 				  GParamSpec   *pspec)
    119 {
    120   GDataInputStreamPrivate *priv;
    121   GDataInputStream        *dstream;
    122 
    123   dstream = G_DATA_INPUT_STREAM (object);
    124   priv = dstream->priv;
    125 
    126    switch (prop_id)
    127     {
    128     case PROP_BYTE_ORDER:
    129       g_data_input_stream_set_byte_order (dstream, g_value_get_enum (value));
    130       break;
    131 
    132     case PROP_NEWLINE_TYPE:
    133       g_data_input_stream_set_newline_type (dstream, g_value_get_enum (value));
    134       break;
    135 
    136     default:
    137       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
    138       break;
    139     }
    140 
    141 }
    142 
    143 static void
    144 g_data_input_stream_get_property (GObject    *object,
    145                                   guint       prop_id,
    146                                   GValue     *value,
    147                                   GParamSpec *pspec)
    148 {
    149   GDataInputStreamPrivate *priv;
    150   GDataInputStream        *dstream;
    151 
    152   dstream = G_DATA_INPUT_STREAM (object);
    153   priv = dstream->priv;
    154 
    155   switch (prop_id)
    156     {
    157     case PROP_BYTE_ORDER:
    158       g_value_set_enum (value, priv->byte_order);
    159       break;
    160 
    161     case PROP_NEWLINE_TYPE:
    162       g_value_set_enum (value, priv->newline_type);
    163       break;
    164 
    165     default:
    166       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
    167       break;
    168     }
    169 
    170 }
    171 static void
    172 g_data_input_stream_init (GDataInputStream *stream)
    173 {
    174   stream->priv = G_TYPE_INSTANCE_GET_PRIVATE (stream,
    175                                               G_TYPE_DATA_INPUT_STREAM,
    176                                               GDataInputStreamPrivate);
    177 
    178   stream->priv->byte_order = G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN;
    179   stream->priv->newline_type = G_DATA_STREAM_NEWLINE_TYPE_LF;
    180 }
    181 
    182 /**
    183  * g_data_input_stream_new:
    184  * @base_stream: a #GInputStream.
    185  *
    186  * Creates a new data input stream for the @base_stream.
    187  *
    188  * Returns: a new #GDataInputStream.
    189  **/
    190 GDataInputStream *
    191 g_data_input_stream_new (GInputStream *base_stream)
    192 {
    193   GDataInputStream *stream;
    194 
    195   g_return_val_if_fail (G_IS_INPUT_STREAM (base_stream), NULL);
    196 
    197   stream = g_object_new (G_TYPE_DATA_INPUT_STREAM,
    198                          "base-stream", base_stream,
    199                          NULL);
    200 
    201   return stream;
    202 }
    203 
    204 /**
    205  * g_data_input_stream_set_byte_order:
    206  * @stream: a given #GDataInputStream.
    207  * @order: a #GDataStreamByteOrder to set.
    208  *
    209  * This function sets the byte order for the given @stream. All subsequent
    210  * reads from the @stream will be read in the given @order.
    211  *
    212  **/
    213 void
    214 g_data_input_stream_set_byte_order (GDataInputStream     *stream,
    215 				    GDataStreamByteOrder  order)
    216 {
    217   GDataInputStreamPrivate *priv;
    218 
    219   g_return_if_fail (G_IS_DATA_INPUT_STREAM (stream));
    220 
    221   priv = stream->priv;
    222 
    223   if (priv->byte_order != order)
    224     {
    225       priv->byte_order = order;
    226 
    227       g_object_notify (G_OBJECT (stream), "byte-order");
    228     }
    229 }
    230 
    231 /**
    232  * g_data_input_stream_get_byte_order:
    233  * @stream: a given #GDataInputStream.
    234  *
    235  * Gets the byte order for the data input stream.
    236  *
    237  * Returns: the @stream's current #GDataStreamByteOrder.
    238  **/
    239 GDataStreamByteOrder
    240 g_data_input_stream_get_byte_order (GDataInputStream *stream)
    241 {
    242   g_return_val_if_fail (G_IS_DATA_INPUT_STREAM (stream), G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN);
    243 
    244   return stream->priv->byte_order;
    245 }
    246 
    247 /**
    248  * g_data_input_stream_set_newline_type:
    249  * @stream: a #GDataInputStream.
    250  * @type: the type of new line return as #GDataStreamNewlineType.
    251  *
    252  * Sets the newline type for the @stream.
    253  *
    254  * Note that using G_DATA_STREAM_NEWLINE_TYPE_ANY is slightly unsafe. If a read
    255  * chunk ends in "CR" we must read an additional byte to know if this is "CR" or
    256  * "CR LF", and this might block if there is no more data availible.
    257  *
    258  **/
    259 void
    260 g_data_input_stream_set_newline_type (GDataInputStream       *stream,
    261 				      GDataStreamNewlineType  type)
    262 {
    263   GDataInputStreamPrivate *priv;
    264 
    265   g_return_if_fail (G_IS_DATA_INPUT_STREAM (stream));
    266 
    267   priv = stream->priv;
    268 
    269   if (priv->newline_type != type)
    270     {
    271       priv->newline_type = type;
    272 
    273       g_object_notify (G_OBJECT (stream), "newline-type");
    274     }
    275 }
    276 
    277 /**
    278  * g_data_input_stream_get_newline_type:
    279  * @stream: a given #GDataInputStream.
    280  *
    281  * Gets the current newline type for the @stream.
    282  *
    283  * Returns: #GDataStreamNewlineType for the given @stream.
    284  **/
    285 GDataStreamNewlineType
    286 g_data_input_stream_get_newline_type (GDataInputStream *stream)
    287 {
    288   g_return_val_if_fail (G_IS_DATA_INPUT_STREAM (stream), G_DATA_STREAM_NEWLINE_TYPE_ANY);
    289 
    290   return stream->priv->newline_type;
    291 }
    292 
    293 static gboolean
    294 read_data (GDataInputStream  *stream,
    295            void              *buffer,
    296            gsize              size,
    297            GCancellable      *cancellable,
    298            GError           **error)
    299 {
    300   gsize available;
    301   gssize res;
    302 
    303   while ((available = g_buffered_input_stream_get_available (G_BUFFERED_INPUT_STREAM (stream))) < size)
    304     {
    305       res = g_buffered_input_stream_fill (G_BUFFERED_INPUT_STREAM (stream),
    306 					  size - available,
    307 					  cancellable, error);
    308       if (res < 0)
    309 	return FALSE;
    310       if (res == 0)
    311 	{
    312 	  g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
    313                                _("Unexpected early end-of-stream"));
    314 	  return FALSE;
    315 	}
    316     }
    317 
    318   /* This should always succeed, since it's in the buffer */
    319   res = g_input_stream_read (G_INPUT_STREAM (stream),
    320 			     buffer, size,
    321 			     NULL, NULL);
    322   g_warn_if_fail (res == size);
    323   return TRUE;
    324 }
    325 
    326 
    327 /**
    328  * g_data_input_stream_read_byte:
    329  * @stream: a given #GDataInputStream.
    330  * @cancellable: optional #GCancellable object, %NULL to ignore.
    331  * @error: #GError for error reporting.
    332  *
    333  * Reads an unsigned 8-bit/1-byte value from @stream.
    334  *
    335  * Returns: an unsigned 8-bit/1-byte value read from the @stream or %0
    336  * if an error occurred.
    337  **/
    338 guchar
    339 g_data_input_stream_read_byte (GDataInputStream  *stream,
    340 			       GCancellable       *cancellable,
    341 			       GError            **error)
    342 {
    343   guchar c;
    344 
    345   g_return_val_if_fail (G_IS_DATA_INPUT_STREAM (stream), '\0');
    346 
    347   if (read_data (stream, &c, 1, cancellable, error))
    348       return c;
    349 
    350   return 0;
    351 }
    352 
    353 
    354 /**
    355  * g_data_input_stream_read_int16:
    356  * @stream: a given #GDataInputStream.
    357  * @cancellable: optional #GCancellable object, %NULL to ignore.
    358  * @error: #GError for error reporting.
    359  *
    360  * Reads a 16-bit/2-byte value from @stream.
    361  *
    362  * In order to get the correct byte order for this read operation,
    363  * see g_data_stream_get_byte_order() and g_data_stream_set_byte_order().
    364  *
    365  * Returns: a signed 16-bit/2-byte value read from @stream or %0 if
    366  * an error occurred.
    367  **/
    368 gint16
    369 g_data_input_stream_read_int16 (GDataInputStream  *stream,
    370 			       GCancellable       *cancellable,
    371 			       GError            **error)
    372 {
    373   gint16 v;
    374 
    375   g_return_val_if_fail (G_IS_DATA_INPUT_STREAM (stream), 0);
    376 
    377   if (read_data (stream, &v, 2, cancellable, error))
    378     {
    379       switch (stream->priv->byte_order)
    380 	{
    381 	case G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN:
    382 	  v = GINT16_FROM_BE (v);
    383 	  break;
    384 	case G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN:
    385 	  v = GINT16_FROM_LE (v);
    386 	  break;
    387 	case G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN:
    388 	default:
    389 	  break;
    390 	}
    391       return v;
    392     }
    393 
    394   return 0;
    395 }
    396 
    397 
    398 /**
    399  * g_data_input_stream_read_uint16:
    400  * @stream: a given #GDataInputStream.
    401  * @cancellable: optional #GCancellable object, %NULL to ignore.
    402  * @error: #GError for error reporting.
    403  *
    404  * Reads an unsigned 16-bit/2-byte value from @stream.
    405  *
    406  * In order to get the correct byte order for this read operation,
    407  * see g_data_stream_get_byte_order() and g_data_stream_set_byte_order().
    408  *
    409  * Returns: an unsigned 16-bit/2-byte value read from the @stream or %0 if
    410  * an error occurred.
    411  **/
    412 guint16
    413 g_data_input_stream_read_uint16 (GDataInputStream  *stream,
    414 				 GCancellable       *cancellable,
    415 				 GError            **error)
    416 {
    417   guint16 v;
    418 
    419   g_return_val_if_fail (G_IS_DATA_INPUT_STREAM (stream), 0);
    420 
    421   if (read_data (stream, &v, 2, cancellable, error))
    422     {
    423       switch (stream->priv->byte_order)
    424 	{
    425 	case G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN:
    426 	  v = GUINT16_FROM_BE (v);
    427 	  break;
    428 	case G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN:
    429 	  v = GUINT16_FROM_LE (v);
    430 	  break;
    431 	case G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN:
    432 	default:
    433 	  break;
    434 	}
    435       return v;
    436     }
    437 
    438   return 0;
    439 }
    440 
    441 
    442 /**
    443  * g_data_input_stream_read_int32:
    444  * @stream: a given #GDataInputStream.
    445  * @cancellable: optional #GCancellable object, %NULL to ignore.
    446  * @error: #GError for error reporting.
    447  *
    448  * Reads a signed 32-bit/4-byte value from @stream.
    449  *
    450  * In order to get the correct byte order for this read operation,
    451  * see g_data_stream_get_byte_order() and g_data_stream_set_byte_order().
    452  *
    453  * If @cancellable is not %NULL, then the operation can be cancelled by
    454  * triggering the cancellable object from another thread. If the operation
    455  * was cancelled, the error %G_IO_ERROR_CANCELLED will be returned.
    456  *
    457  * Returns: a signed 32-bit/4-byte value read from the @stream or %0 if
    458  * an error occurred.
    459  **/
    460 gint32
    461 g_data_input_stream_read_int32 (GDataInputStream  *stream,
    462 				GCancellable       *cancellable,
    463 				GError            **error)
    464 {
    465   gint32 v;
    466 
    467   g_return_val_if_fail (G_IS_DATA_INPUT_STREAM (stream), 0);
    468 
    469   if (read_data (stream, &v, 4, cancellable, error))
    470     {
    471       switch (stream->priv->byte_order)
    472 	{
    473 	case G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN:
    474 	  v = GINT32_FROM_BE (v);
    475 	  break;
    476 	case G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN:
    477 	  v = GINT32_FROM_LE (v);
    478 	  break;
    479 	case G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN:
    480 	default:
    481 	  break;
    482 	}
    483       return v;
    484     }
    485 
    486   return 0;
    487 }
    488 
    489 
    490 /**
    491  * g_data_input_stream_read_uint32:
    492  * @stream: a given #GDataInputStream.
    493  * @cancellable: optional #GCancellable object, %NULL to ignore.
    494  * @error: #GError for error reporting.
    495  *
    496  * Reads an unsigned 32-bit/4-byte value from @stream.
    497  *
    498  * In order to get the correct byte order for this read operation,
    499  * see g_data_stream_get_byte_order() and g_data_stream_set_byte_order().
    500  *
    501  * If @cancellable is not %NULL, then the operation can be cancelled by
    502  * triggering the cancellable object from another thread. If the operation
    503  * was cancelled, the error %G_IO_ERROR_CANCELLED will be returned.
    504  *
    505  * Returns: an unsigned 32-bit/4-byte value read from the @stream or %0 if
    506  * an error occurred.
    507  **/
    508 guint32
    509 g_data_input_stream_read_uint32 (GDataInputStream  *stream,
    510 				 GCancellable       *cancellable,
    511 				 GError            **error)
    512 {
    513   guint32 v;
    514 
    515   g_return_val_if_fail (G_IS_DATA_INPUT_STREAM (stream), 0);
    516 
    517   if (read_data (stream, &v, 4, cancellable, error))
    518     {
    519       switch (stream->priv->byte_order)
    520 	{
    521 	case G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN:
    522 	  v = GUINT32_FROM_BE (v);
    523 	  break;
    524 	case G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN:
    525 	  v = GUINT32_FROM_LE (v);
    526 	  break;
    527 	case G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN:
    528 	default:
    529 	  break;
    530 	}
    531       return v;
    532     }
    533 
    534   return 0;
    535 }
    536 
    537 
    538 /**
    539  * g_data_input_stream_read_int64:
    540  * @stream: a given #GDataInputStream.
    541  * @cancellable: optional #GCancellable object, %NULL to ignore.
    542  * @error: #GError for error reporting.
    543  *
    544  * Reads a 64-bit/8-byte value from @stream.
    545  *
    546  * In order to get the correct byte order for this read operation,
    547  * see g_data_stream_get_byte_order() and g_data_stream_set_byte_order().
    548  *
    549  * If @cancellable is not %NULL, then the operation can be cancelled by
    550  * triggering the cancellable object from another thread. If the operation
    551  * was cancelled, the error %G_IO_ERROR_CANCELLED will be returned.
    552  *
    553  * Returns: a signed 64-bit/8-byte value read from @stream or %0 if
    554  * an error occurred.
    555  **/
    556 gint64
    557 g_data_input_stream_read_int64 (GDataInputStream  *stream,
    558 			       GCancellable       *cancellable,
    559 			       GError            **error)
    560 {
    561   gint64 v;
    562 
    563   g_return_val_if_fail (G_IS_DATA_INPUT_STREAM (stream), 0);
    564 
    565   if (read_data (stream, &v, 8, cancellable, error))
    566     {
    567       switch (stream->priv->byte_order)
    568 	{
    569 	case G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN:
    570 	  v = GINT64_FROM_BE (v);
    571 	  break;
    572 	case G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN:
    573 	  v = GINT64_FROM_LE (v);
    574 	  break;
    575 	case G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN:
    576 	default:
    577 	  break;
    578 	}
    579       return v;
    580     }
    581 
    582   return 0;
    583 }
    584 
    585 
    586 /**
    587  * g_data_input_stream_read_uint64:
    588  * @stream: a given #GDataInputStream.
    589  * @cancellable: optional #GCancellable object, %NULL to ignore.
    590  * @error: #GError for error reporting.
    591  *
    592  * Reads an unsigned 64-bit/8-byte value from @stream.
    593  *
    594  * In order to get the correct byte order for this read operation,
    595  * see g_data_stream_get_byte_order().
    596  *
    597  * If @cancellable is not %NULL, then the operation can be cancelled by
    598  * triggering the cancellable object from another thread. If the operation
    599  * was cancelled, the error %G_IO_ERROR_CANCELLED will be returned.
    600  *
    601  * Returns: an unsigned 64-bit/8-byte read from @stream or %0 if
    602  * an error occurred.
    603  **/
    604 guint64
    605 g_data_input_stream_read_uint64 (GDataInputStream  *stream,
    606 				GCancellable       *cancellable,
    607 				GError            **error)
    608 {
    609   guint64 v;
    610 
    611   g_return_val_if_fail (G_IS_DATA_INPUT_STREAM (stream), 0);
    612 
    613   if (read_data (stream, &v, 8, cancellable, error))
    614     {
    615       switch (stream->priv->byte_order)
    616 	{
    617 	case G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN:
    618 	  v = GUINT64_FROM_BE (v);
    619 	  break;
    620 	case G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN:
    621 	  v = GUINT64_FROM_LE (v);
    622 	  break;
    623 	case G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN:
    624 	default:
    625 	  break;
    626 	}
    627       return v;
    628     }
    629 
    630   return 0;
    631 }
    632 
    633 static gssize
    634 scan_for_newline (GDataInputStream *stream,
    635 		  gsize            *checked_out,
    636 		  gboolean         *last_saw_cr_out,
    637 		  int              *newline_len_out)
    638 {
    639   GBufferedInputStream *bstream;
    640   GDataInputStreamPrivate *priv;
    641   const char *buffer;
    642   gsize start, end, peeked;
    643   int i;
    644   gssize found_pos;
    645   int newline_len;
    646   gsize available, checked;
    647   gboolean last_saw_cr;
    648 
    649   priv = stream->priv;
    650 
    651   bstream = G_BUFFERED_INPUT_STREAM (stream);
    652 
    653   checked = *checked_out;
    654   last_saw_cr = *last_saw_cr_out;
    655   found_pos = -1;
    656   newline_len = 0;
    657 
    658   start = checked;
    659   buffer = (const char*)g_buffered_input_stream_peek_buffer (bstream, &available) + start;
    660   end = available;
    661   peeked = end - start;
    662 
    663   for (i = 0; checked < available && i < peeked; i++)
    664     {
    665       switch (priv->newline_type)
    666 	{
    667 	case G_DATA_STREAM_NEWLINE_TYPE_LF:
    668 	  if (buffer[i] == 10)
    669 	    {
    670 	      found_pos = start + i;
    671 	      newline_len = 1;
    672 	    }
    673 	  break;
    674 	case G_DATA_STREAM_NEWLINE_TYPE_CR:
    675 	  if (buffer[i] == 13)
    676 	    {
    677 	      found_pos = start + i;
    678 	      newline_len = 1;
    679 	    }
    680 	  break;
    681 	case G_DATA_STREAM_NEWLINE_TYPE_CR_LF:
    682 	  if (last_saw_cr && buffer[i] == 10)
    683 	    {
    684 	      found_pos = start + i - 1;
    685 	      newline_len = 2;
    686 	    }
    687 	  break;
    688 	default:
    689 	case G_DATA_STREAM_NEWLINE_TYPE_ANY:
    690 	  if (buffer[i] == 10) /* LF */
    691 	    {
    692 	      if (last_saw_cr)
    693 		{
    694 		  /* CR LF */
    695 		  found_pos = start + i - 1;
    696 		  newline_len = 2;
    697 		}
    698 	      else
    699 		{
    700 		  /* LF */
    701 		  found_pos = start + i;
    702 		  newline_len = 1;
    703 		}
    704 	    }
    705 	  else if (last_saw_cr)
    706 	    {
    707 	      /* Last was cr, this is not LF, end is CR */
    708 	      found_pos = start + i - 1;
    709 	      newline_len = 1;
    710 	    }
    711 	  /* Don't check for CR here, instead look at last_saw_cr on next byte */
    712 	  break;
    713 	}
    714 
    715       last_saw_cr = (buffer[i] == 13);
    716 
    717       if (found_pos != -1)
    718 	{
    719 	  *newline_len_out = newline_len;
    720 	  return found_pos;
    721 	}
    722     }
    723 
    724   checked = end;
    725 
    726   *checked_out = checked;
    727   *last_saw_cr_out = last_saw_cr;
    728   return -1;
    729 }
    730 
    731 
    732 /**
    733  * g_data_input_stream_read_line:
    734  * @stream: a given #GDataInputStream.
    735  * @length: a #gsize to get the length of the data read in.
    736  * @cancellable: optional #GCancellable object, %NULL to ignore.
    737  * @error: #GError for error reporting.
    738  *
    739  * Reads a line from the data input stream.
    740  *
    741  * If @cancellable is not %NULL, then the operation can be cancelled by
    742  * triggering the cancellable object from another thread. If the operation
    743  * was cancelled, the error %G_IO_ERROR_CANCELLED will be returned.
    744  *
    745  * Returns: a string with the line that was read in (without the newlines).
    746  *     Set @length to a #gsize to get the length of the read line.
    747  *     On an error, it will return %NULL and @error will be set. If there's no
    748  *     content to read, it will still return %NULL, but @error won't be set.
    749  **/
    750 char *
    751 g_data_input_stream_read_line (GDataInputStream  *stream,
    752 			       gsize             *length,
    753 			       GCancellable      *cancellable,
    754 			       GError           **error)
    755 {
    756   GBufferedInputStream *bstream;
    757   gsize checked;
    758   gboolean last_saw_cr;
    759   gssize found_pos;
    760   gssize res;
    761   int newline_len;
    762   char *line;
    763 
    764   g_return_val_if_fail (G_IS_DATA_INPUT_STREAM (stream), NULL);
    765 
    766   bstream = G_BUFFERED_INPUT_STREAM (stream);
    767 
    768   newline_len = 0;
    769   checked = 0;
    770   last_saw_cr = FALSE;
    771 
    772   while ((found_pos = scan_for_newline (stream, &checked, &last_saw_cr, &newline_len)) == -1)
    773     {
    774       if (g_buffered_input_stream_get_available (bstream) ==
    775 	  g_buffered_input_stream_get_buffer_size (bstream))
    776 	g_buffered_input_stream_set_buffer_size (bstream,
    777 						 2 * g_buffered_input_stream_get_buffer_size (bstream));
    778 
    779       res = g_buffered_input_stream_fill (bstream, -1, cancellable, error);
    780       if (res < 0)
    781 	return NULL;
    782       if (res == 0)
    783 	{
    784 	  /* End of stream */
    785 	  if (g_buffered_input_stream_get_available (bstream) == 0)
    786 	    {
    787 	      if (length)
    788 		*length = 0;
    789 	      return NULL;
    790 	    }
    791 	  else
    792 	    {
    793 	      found_pos = checked;
    794 	      newline_len = 0;
    795 	      break;
    796 	    }
    797 	}
    798     }
    799 
    800   line = g_malloc (found_pos + newline_len + 1);
    801 
    802   res = g_input_stream_read (G_INPUT_STREAM (stream),
    803 			     line,
    804 			     found_pos + newline_len,
    805 			     NULL, NULL);
    806   if (length)
    807     *length = (gsize)found_pos;
    808   g_warn_if_fail (res == found_pos + newline_len);
    809   line[found_pos] = 0;
    810 
    811   return line;
    812 }
    813 
    814 static gssize
    815 scan_for_chars (GDataInputStream *stream,
    816 		gsize            *checked_out,
    817 		const char       *stop_chars)
    818 {
    819   GBufferedInputStream *bstream;
    820   GDataInputStreamPrivate *priv;
    821   const char *buffer;
    822   gsize start, end, peeked;
    823   int i;
    824   gssize found_pos;
    825   gsize available, checked;
    826   const char *stop_char;
    827 
    828   priv = stream->priv;
    829 
    830   bstream = G_BUFFERED_INPUT_STREAM (stream);
    831 
    832   checked = *checked_out;
    833   found_pos = -1;
    834 
    835   start = checked;
    836   buffer = (const char *)g_buffered_input_stream_peek_buffer (bstream, &available) + start;
    837   end = available;
    838   peeked = end - start;
    839 
    840   for (i = 0; checked < available && i < peeked; i++)
    841     {
    842       for (stop_char = stop_chars; *stop_char != '\0'; stop_char++)
    843 	{
    844 	  if (buffer[i] == *stop_char)
    845 	    return (start + i);
    846 	}
    847     }
    848 
    849   checked = end;
    850 
    851   *checked_out = checked;
    852   return -1;
    853 }
    854 
    855 /**
    856  * g_data_input_stream_read_until:
    857  * @stream: a given #GDataInputStream.
    858  * @stop_chars: characters to terminate the read.
    859  * @length: a #gsize to get the length of the data read in.
    860  * @cancellable: optional #GCancellable object, %NULL to ignore.
    861  * @error: #GError for error reporting.
    862  *
    863  * Reads a string from the data input stream, up to the first
    864  * occurrence of any of the stop characters.
    865  *
    866  * Returns: a string with the data that was read before encountering
    867  *     any of the stop characters. Set @length to a #gsize to get the length
    868  *     of the string. This function will return %NULL on an error.
    869  */
    870 char *
    871 g_data_input_stream_read_until (GDataInputStream  *stream,
    872 			       const gchar        *stop_chars,
    873 			       gsize              *length,
    874 			       GCancellable       *cancellable,
    875 			       GError            **error)
    876 {
    877   GBufferedInputStream *bstream;
    878   gsize checked;
    879   gssize found_pos;
    880   gssize res;
    881   int stop_char_len;
    882   char *data_until;
    883 
    884   g_return_val_if_fail (G_IS_DATA_INPUT_STREAM (stream), NULL);
    885 
    886   bstream = G_BUFFERED_INPUT_STREAM (stream);
    887 
    888   stop_char_len = 1;
    889   checked = 0;
    890 
    891   while ((found_pos = scan_for_chars (stream, &checked, stop_chars)) == -1)
    892     {
    893       if (g_buffered_input_stream_get_available (bstream) ==
    894 	  g_buffered_input_stream_get_buffer_size (bstream))
    895 	g_buffered_input_stream_set_buffer_size (bstream,
    896 						 2 * g_buffered_input_stream_get_buffer_size (bstream));
    897 
    898       res = g_buffered_input_stream_fill (bstream, -1, cancellable, error);
    899       if (res < 0)
    900 	return NULL;
    901       if (res == 0)
    902 	{
    903 	  /* End of stream */
    904 	  if (g_buffered_input_stream_get_available (bstream) == 0)
    905 	    {
    906 	      if (length)
    907 		*length = 0;
    908 	      return NULL;
    909 	    }
    910 	  else
    911 	    {
    912 	      found_pos = checked;
    913 	      stop_char_len = 0;
    914 	      break;
    915 	    }
    916 	}
    917     }
    918 
    919   data_until = g_malloc (found_pos + stop_char_len + 1);
    920 
    921   res = g_input_stream_read (G_INPUT_STREAM (stream),
    922 			     data_until,
    923 			     found_pos + stop_char_len,
    924 			     NULL, NULL);
    925   if (length)
    926     *length = (gsize)found_pos;
    927   g_warn_if_fail (res == found_pos + stop_char_len);
    928   data_until[found_pos] = 0;
    929 
    930   return data_until;
    931 }
    932 
    933 typedef struct
    934 {
    935   GDataInputStream *stream;
    936   GSimpleAsyncResult *simple;
    937   gboolean last_saw_cr;
    938   gsize checked;
    939   gint io_priority;
    940   GCancellable *cancellable;
    941 
    942   gchar *stop_chars;
    943   gchar *line;
    944   gsize length;
    945 } GDataInputStreamReadData;
    946 
    947 static void
    948 g_data_input_stream_read_complete (GDataInputStreamReadData *data,
    949                                    gsize                     read_length,
    950                                    gsize                     skip_length,
    951                                    gboolean                  need_idle_dispatch)
    952 {
    953   if (read_length || skip_length)
    954     {
    955       gssize bytes;
    956 
    957       data->length = read_length;
    958       data->line = g_malloc (read_length + 1);
    959       data->line[read_length] = '\0';
    960 
    961       /* we already checked the buffer.  this shouldn't fail. */
    962       bytes = g_input_stream_read (G_INPUT_STREAM (data->stream),
    963                                    data->line, read_length, NULL, NULL);
    964       g_assert_cmpint (bytes, ==, read_length);
    965 
    966       bytes = g_input_stream_skip (G_INPUT_STREAM (data->stream),
    967                                    skip_length, NULL, NULL);
    968       g_assert_cmpint (bytes, ==, skip_length);
    969     }
    970 
    971   if (need_idle_dispatch)
    972     g_simple_async_result_complete_in_idle (data->simple);
    973   else
    974     g_simple_async_result_complete (data->simple);
    975 
    976   g_object_unref (data->simple);
    977 }
    978 
    979 static void
    980 g_data_input_stream_read_line_ready (GObject      *object,
    981                                      GAsyncResult *result,
    982                                      gpointer      user_data)
    983 {
    984   GDataInputStreamReadData *data = user_data;
    985   gssize found_pos;
    986   gint newline_len;
    987 
    988   if (result)
    989     /* this is a callback.  finish the async call. */
    990     {
    991       GBufferedInputStream *buffer = G_BUFFERED_INPUT_STREAM (data->stream);
    992       GError *error = NULL;
    993       gssize bytes;
    994 
    995       bytes = g_buffered_input_stream_fill_finish (buffer, result, &error);
    996 
    997       if (bytes <= 0)
    998         {
    999           if (bytes < 0)
   1000             /* stream error. */
   1001             {
   1002               g_simple_async_result_set_from_error (data->simple, error);
   1003               g_error_free (error);
   1004               data->checked = 0;
   1005             }
   1006 
   1007           g_data_input_stream_read_complete (data, data->checked, 0, FALSE);
   1008           return;
   1009         }
   1010 
   1011       /* only proceed if we got more bytes... */
   1012     }
   1013 
   1014   if (data->stop_chars)
   1015     {
   1016       found_pos = scan_for_chars (data->stream,
   1017                                   &data->checked,
   1018                                   data->stop_chars);
   1019       newline_len = 0;
   1020     }
   1021   else
   1022     found_pos = scan_for_newline (data->stream, &data->checked,
   1023                                   &data->last_saw_cr, &newline_len);
   1024 
   1025   if (found_pos == -1)
   1026     /* didn't find a full line; need to buffer some more bytes */
   1027     {
   1028       GBufferedInputStream *buffer = G_BUFFERED_INPUT_STREAM (data->stream);
   1029       gsize size;
   1030 
   1031       size = g_buffered_input_stream_get_buffer_size (buffer);
   1032 
   1033       if (g_buffered_input_stream_get_available (buffer) == size)
   1034         /* need to grow the buffer */
   1035         g_buffered_input_stream_set_buffer_size (buffer, size * 2);
   1036 
   1037       /* try again */
   1038       g_buffered_input_stream_fill_async (buffer, -1, data->io_priority,
   1039                                           data->cancellable,
   1040                                           g_data_input_stream_read_line_ready,
   1041                                           user_data);
   1042     }
   1043   else
   1044     {
   1045       /* read the line and the EOL.  no error is possible. */
   1046       g_data_input_stream_read_complete (data, found_pos,
   1047                                          newline_len, result == NULL);
   1048     }
   1049 }
   1050 
   1051 static void
   1052 g_data_input_stream_read_data_free (gpointer user_data)
   1053 {
   1054   GDataInputStreamReadData *data = user_data;
   1055 
   1056   /* we don't hold a ref to ->simple because it keeps a ref to us.
   1057    * we are called because it is being finalized.
   1058    */
   1059 
   1060   g_free (data->stop_chars);
   1061   if (data->cancellable)
   1062     g_object_unref (data->cancellable);
   1063   g_free (data->line);
   1064   g_slice_free (GDataInputStreamReadData, data);
   1065 }
   1066 
   1067 static void
   1068 g_data_input_stream_read_async (GDataInputStream    *stream,
   1069                                 const gchar         *stop_chars,
   1070                                 gint                 io_priority,
   1071                                 GCancellable        *cancellable,
   1072                                 GAsyncReadyCallback  callback,
   1073                                 gpointer             user_data,
   1074                                 gpointer             source_tag)
   1075 {
   1076   GDataInputStreamReadData *data;
   1077 
   1078   data = g_slice_new (GDataInputStreamReadData);
   1079   data->stream = stream;
   1080   if (cancellable)
   1081     g_object_ref (cancellable);
   1082   data->cancellable = cancellable;
   1083   data->stop_chars = g_strdup (stop_chars);
   1084   data->io_priority = io_priority;
   1085   data->last_saw_cr = FALSE;
   1086   data->checked = 0;
   1087   data->line = NULL;
   1088 
   1089   data->simple = g_simple_async_result_new (G_OBJECT (stream), callback,
   1090                                             user_data, source_tag);
   1091   g_simple_async_result_set_op_res_gpointer (data->simple, data,
   1092                                              g_data_input_stream_read_data_free);
   1093   g_data_input_stream_read_line_ready (NULL, NULL, data);
   1094 }
   1095 
   1096 static gchar *
   1097 g_data_input_stream_read_finish (GDataInputStream  *stream,
   1098                                  GAsyncResult      *result,
   1099                                  gsize             *length,
   1100                                  GError           **error)
   1101 {
   1102   GDataInputStreamReadData *data;
   1103   GSimpleAsyncResult *simple;
   1104   gchar *line;
   1105 
   1106   simple = G_SIMPLE_ASYNC_RESULT (result);
   1107 
   1108   if (g_simple_async_result_propagate_error (simple, error))
   1109     return NULL;
   1110 
   1111   data = g_simple_async_result_get_op_res_gpointer (simple);
   1112 
   1113   line = data->line;
   1114   data->line = NULL;
   1115 
   1116   if (length && line)
   1117     *length = data->length;
   1118 
   1119   return line;
   1120 }
   1121 
   1122 /**
   1123  * g_data_input_stream_read_line_async:
   1124  * @stream: a given #GDataInputStream.
   1125  * @io_priority: the <link linkend="io-priority">I/O priority</link>
   1126  *     of the request.
   1127  * @cancellable: optional #GCancellable object, %NULL to ignore.
   1128  * @callback: callback to call when the request is satisfied.
   1129  * @user_data: the data to pass to callback function.
   1130  *
   1131  * The asynchronous version of g_data_input_stream_read_line().  It is
   1132  * an error to have two outstanding calls to this function.
   1133  *
   1134  * When the operation is finished, @callback will be called. You
   1135  * can then call g_data_input_stream_read_line_finish() to get
   1136  * the result of the operation.
   1137  *
   1138  * Since: 2.20
   1139  */
   1140 void
   1141 g_data_input_stream_read_line_async (GDataInputStream    *stream,
   1142                                      gint                 io_priority,
   1143                                      GCancellable        *cancellable,
   1144                                      GAsyncReadyCallback  callback,
   1145                                      gpointer             user_data)
   1146 {
   1147   g_return_if_fail (G_IS_DATA_INPUT_STREAM (stream));
   1148   g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
   1149 
   1150   g_data_input_stream_read_async (stream, NULL, io_priority,
   1151                                   cancellable, callback, user_data,
   1152                                   g_data_input_stream_read_line_async);
   1153 }
   1154 
   1155 /**
   1156  * g_data_input_stream_read_until_async:
   1157  * @stream: a given #GDataInputStream.
   1158  * @stop_chars: characters to terminate the read.
   1159  * @io_priority: the <link linkend="io-priority">I/O priority</link>
   1160  *     of the request.
   1161  * @cancellable: optional #GCancellable object, %NULL to ignore.
   1162  * @callback: callback to call when the request is satisfied.
   1163  * @user_data: the data to pass to callback function.
   1164  *
   1165  * The asynchronous version of g_data_input_stream_read_until().
   1166  * It is an error to have two outstanding calls to this function.
   1167  *
   1168  * When the operation is finished, @callback will be called. You
   1169  * can then call g_data_input_stream_read_until_finish() to get
   1170  * the result of the operation.
   1171  *
   1172  * Since: 2.20
   1173  */
   1174 void
   1175 g_data_input_stream_read_until_async (GDataInputStream    *stream,
   1176                                       const gchar         *stop_chars,
   1177                                       gint                 io_priority,
   1178                                       GCancellable        *cancellable,
   1179                                       GAsyncReadyCallback  callback,
   1180                                       gpointer             user_data)
   1181 {
   1182   g_return_if_fail (G_IS_DATA_INPUT_STREAM (stream));
   1183   g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
   1184   g_return_if_fail (stop_chars != NULL);
   1185 
   1186   g_data_input_stream_read_async (stream, stop_chars, io_priority,
   1187                                   cancellable, callback, user_data,
   1188                                   g_data_input_stream_read_until_async);
   1189 }
   1190 
   1191 /**
   1192  * g_data_input_stream_read_line_finish:
   1193  * @stream: a given #GDataInputStream.
   1194  * @result: the #GAsyncResult that was provided to the callback.
   1195  * @length: a #gsize to get the length of the data read in.
   1196  * @error: #GError for error reporting.
   1197  *
   1198  * Finish an asynchronous call started by
   1199  * g_data_input_stream_read_line_async().
   1200  *
   1201  * Returns: a string with the line that was read in (without the newlines).
   1202  *     Set @length to a #gsize to get the length of the read line.
   1203  *     On an error, it will return %NULL and @error will be set. If there's no
   1204  *     content to read, it will still return %NULL, but @error won't be set.
   1205  *
   1206  * Since: 2,20
   1207  */
   1208 gchar *
   1209 g_data_input_stream_read_line_finish (GDataInputStream  *stream,
   1210                                       GAsyncResult      *result,
   1211                                       gsize             *length,
   1212                                       GError           **error)
   1213 {
   1214   g_return_val_if_fail (
   1215     g_simple_async_result_is_valid (result, G_OBJECT (stream),
   1216       g_data_input_stream_read_line_async), NULL);
   1217 
   1218   return g_data_input_stream_read_finish (stream, result, length, error);
   1219 }
   1220 
   1221 /**
   1222  * g_data_input_stream_read_until_finish:
   1223  * @stream: a given #GDataInputStream.
   1224  * @result: the #GAsyncResult that was provided to the callback.
   1225  * @length: a #gsize to get the length of the data read in.
   1226  * @error: #GError for error reporting.
   1227  *
   1228  * Finish an asynchronous call started by
   1229  * g_data_input_stream_read_until_async().
   1230  *
   1231  * Since: 2.20
   1232  *
   1233  * Returns: a string with the data that was read before encountering
   1234  *     any of the stop characters. Set @length to a #gsize to get the length
   1235  *     of the string. This function will return %NULL on an error.
   1236  */
   1237 gchar *
   1238 g_data_input_stream_read_until_finish (GDataInputStream  *stream,
   1239                                        GAsyncResult      *result,
   1240                                        gsize             *length,
   1241                                        GError           **error)
   1242 {
   1243   g_return_val_if_fail (
   1244     g_simple_async_result_is_valid (result, G_OBJECT (stream),
   1245       g_data_input_stream_read_until_async), NULL);
   1246 
   1247   return g_data_input_stream_read_finish (stream, result, length, error);
   1248 }
   1249 
   1250 
   1251 #define __G_DATA_INPUT_STREAM_C__
   1252 #include "gioaliasdef.c"
   1253