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 * 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@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 46struct _GDataInputStreamPrivate { 47 GDataStreamByteOrder byte_order; 48 GDataStreamNewlineType newline_type; 49}; 50 51enum { 52 PROP_0, 53 PROP_BYTE_ORDER, 54 PROP_NEWLINE_TYPE 55}; 56 57static void g_data_input_stream_set_property (GObject *object, 58 guint prop_id, 59 const GValue *value, 60 GParamSpec *pspec); 61static void g_data_input_stream_get_property (GObject *object, 62 guint prop_id, 63 GValue *value, 64 GParamSpec *pspec); 65 66G_DEFINE_TYPE (GDataInputStream, 67 g_data_input_stream, 68 G_TYPE_BUFFERED_INPUT_STREAM) 69 70 71static void 72g_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 114static void 115g_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 143static void 144g_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} 171static void 172g_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 **/ 190GDataInputStream * 191g_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 **/ 213void 214g_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 **/ 239GDataStreamByteOrder 240g_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 **/ 259void 260g_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 **/ 285GDataStreamNewlineType 286g_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 293static gboolean 294read_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 **/ 338guchar 339g_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 **/ 368gint16 369g_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 **/ 412guint16 413g_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 **/ 460gint32 461g_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 **/ 508guint32 509g_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 **/ 556gint64 557g_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 **/ 604guint64 605g_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 633static gssize 634scan_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 **/ 750char * 751g_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 814static gssize 815scan_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 */ 870char * 871g_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 933typedef 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 947static void 948g_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 979static void 980g_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 1051static void 1052g_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 1067static void 1068g_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 1096static gchar * 1097g_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 */ 1140void 1141g_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 */ 1174void 1175g_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 */ 1208gchar * 1209g_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 */ 1237gchar * 1238g_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