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
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
G_DEFINE_TYPE(GDataInputStream,g_data_input_stream,G_TYPE_BUFFERED_INPUT_STREAM)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
g_data_input_stream_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)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
g_data_input_stream_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)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
g_data_input_stream_init(GDataInputStream * stream)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 *
g_data_input_stream_new(GInputStream * base_stream)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
g_data_input_stream_set_byte_order(GDataInputStream * stream,GDataStreamByteOrder order)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
g_data_input_stream_get_byte_order(GDataInputStream * stream)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
g_data_input_stream_set_newline_type(GDataInputStream * stream,GDataStreamNewlineType type)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
g_data_input_stream_get_newline_type(GDataInputStream * stream)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
read_data(GDataInputStream * stream,void * buffer,gsize size,GCancellable * cancellable,GError ** error)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
g_data_input_stream_read_byte(GDataInputStream * stream,GCancellable * cancellable,GError ** error)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
g_data_input_stream_read_int16(GDataInputStream * stream,GCancellable * cancellable,GError ** error)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
g_data_input_stream_read_uint16(GDataInputStream * stream,GCancellable * cancellable,GError ** error)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
g_data_input_stream_read_int32(GDataInputStream * stream,GCancellable * cancellable,GError ** error)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
g_data_input_stream_read_uint32(GDataInputStream * stream,GCancellable * cancellable,GError ** error)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
g_data_input_stream_read_int64(GDataInputStream * stream,GCancellable * cancellable,GError ** error)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
g_data_input_stream_read_uint64(GDataInputStream * stream,GCancellable * cancellable,GError ** error)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
scan_for_newline(GDataInputStream * stream,gsize * checked_out,gboolean * last_saw_cr_out,int * newline_len_out)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 *
g_data_input_stream_read_line(GDataInputStream * stream,gsize * length,GCancellable * cancellable,GError ** error)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
scan_for_chars(GDataInputStream * stream,gsize * checked_out,const char * stop_chars)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 *
g_data_input_stream_read_until(GDataInputStream * stream,const gchar * stop_chars,gsize * length,GCancellable * cancellable,GError ** error)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
g_data_input_stream_read_complete(GDataInputStreamReadData * data,gsize read_length,gsize skip_length,gboolean need_idle_dispatch)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
g_data_input_stream_read_line_ready(GObject * object,GAsyncResult * result,gpointer user_data)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
g_data_input_stream_read_data_free(gpointer user_data)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
g_data_input_stream_read_async(GDataInputStream * stream,const gchar * stop_chars,gint io_priority,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data,gpointer source_tag)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 *
g_data_input_stream_read_finish(GDataInputStream * stream,GAsyncResult * result,gsize * length,GError ** error)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
g_data_input_stream_read_line_async(GDataInputStream * stream,gint io_priority,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)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
g_data_input_stream_read_until_async(GDataInputStream * stream,const gchar * stop_chars,gint io_priority,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)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 *
g_data_input_stream_read_line_finish(GDataInputStream * stream,GAsyncResult * result,gsize * length,GError ** error)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 *
g_data_input_stream_read_until_finish(GDataInputStream * stream,GAsyncResult * result,gsize * length,GError ** error)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