Coverage Report

Created: 2025-06-13 06:55

/src/glib/gio/gdatainputstream.c
Line
Count
Source (jump to first uncovered line)
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
 * SPDX-License-Identifier: LGPL-2.1-or-later
8
 *
9
 * This library is free software; you can redistribute it and/or
10
 * modify it under the terms of the GNU Lesser General Public
11
 * License as published by the Free Software Foundation; either
12
 * version 2.1 of the License, or (at your option) any later version.
13
 *
14
 * This library is distributed in the hope that it will be useful,
15
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17
 * Lesser General Public License for more details.
18
 *
19
 * You should have received a copy of the GNU Lesser General
20
 * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
21
 *
22
 * Author: Alexander Larsson <alexl@redhat.com>
23
 */
24
25
#include "config.h"
26
#include "gdatainputstream.h"
27
#include "gtask.h"
28
#include "gcancellable.h"
29
#include "gioenumtypes.h"
30
#include "gioerror.h"
31
#include "glibintl.h"
32
33
#include <string.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_WITH_PRIVATE (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
0
{
74
0
  GObjectClass *object_class;
75
76
0
  object_class = G_OBJECT_CLASS (klass);
77
0
  object_class->get_property = g_data_input_stream_get_property;
78
0
  object_class->set_property = g_data_input_stream_set_property;
79
80
  /**
81
   * GDataInputStream:byte-order:
82
   *
83
   * The :byte-order property determines the byte ordering that
84
   * is used when reading multi-byte entities (such as integers)
85
   * from the stream.
86
   */ 
87
0
  g_object_class_install_property (object_class,
88
0
                                   PROP_BYTE_ORDER,
89
0
                                   g_param_spec_enum ("byte-order",
90
0
                                                      P_("Byte order"),
91
0
                                                      P_("The byte order"),
92
0
                                                      G_TYPE_DATA_STREAM_BYTE_ORDER,
93
0
                                                      G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN,
94
0
                                                      G_PARAM_READWRITE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_BLURB));
95
96
  /**
97
   * GDataInputStream:newline-type:
98
   *
99
   * The :newline-type property determines what is considered
100
   * as a line ending when reading complete lines from the stream.
101
   */ 
102
0
  g_object_class_install_property (object_class,
103
0
                                   PROP_NEWLINE_TYPE,
104
0
                                   g_param_spec_enum ("newline-type",
105
0
                                                      P_("Newline type"),
106
0
                                                      P_("The accepted types of line ending"),
107
0
                                                      G_TYPE_DATA_STREAM_NEWLINE_TYPE,
108
0
                                                      G_DATA_STREAM_NEWLINE_TYPE_LF,
109
0
                                                      G_PARAM_READWRITE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_BLURB));
110
0
}
111
112
static void
113
g_data_input_stream_set_property (GObject      *object,
114
          guint         prop_id,
115
          const GValue *value,
116
          GParamSpec   *pspec)
117
0
{
118
0
  GDataInputStream        *dstream;
119
120
0
  dstream = G_DATA_INPUT_STREAM (object);
121
122
0
   switch (prop_id)
123
0
    {
124
0
    case PROP_BYTE_ORDER:
125
0
      g_data_input_stream_set_byte_order (dstream, g_value_get_enum (value));
126
0
      break;
127
128
0
    case PROP_NEWLINE_TYPE:
129
0
      g_data_input_stream_set_newline_type (dstream, g_value_get_enum (value));
130
0
      break;
131
132
0
    default:
133
0
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
134
0
      break;
135
0
    }
136
137
0
}
138
139
static void
140
g_data_input_stream_get_property (GObject    *object,
141
                                  guint       prop_id,
142
                                  GValue     *value,
143
                                  GParamSpec *pspec)
144
0
{
145
0
  GDataInputStreamPrivate *priv;
146
0
  GDataInputStream        *dstream;
147
148
0
  dstream = G_DATA_INPUT_STREAM (object);
149
0
  priv = dstream->priv;
150
151
0
  switch (prop_id)
152
0
    { 
153
0
    case PROP_BYTE_ORDER:
154
0
      g_value_set_enum (value, priv->byte_order);
155
0
      break;
156
157
0
    case PROP_NEWLINE_TYPE:
158
0
      g_value_set_enum (value, priv->newline_type);
159
0
      break;
160
161
0
    default:
162
0
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
163
0
      break;
164
0
    }
165
166
0
}
167
static void
168
g_data_input_stream_init (GDataInputStream *stream)
169
0
{
170
0
  stream->priv = g_data_input_stream_get_instance_private (stream);
171
0
  stream->priv->byte_order = G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN;
172
0
  stream->priv->newline_type = G_DATA_STREAM_NEWLINE_TYPE_LF;
173
0
}
174
175
/**
176
 * g_data_input_stream_new:
177
 * @base_stream: a #GInputStream.
178
 * 
179
 * Creates a new data input stream for the @base_stream.
180
 * 
181
 * Returns: a new #GDataInputStream.
182
 **/
183
GDataInputStream *
184
g_data_input_stream_new (GInputStream *base_stream)
185
0
{
186
0
  GDataInputStream *stream;
187
188
0
  g_return_val_if_fail (G_IS_INPUT_STREAM (base_stream), NULL);
189
190
0
  stream = g_object_new (G_TYPE_DATA_INPUT_STREAM,
191
0
                         "base-stream", base_stream,
192
0
                         NULL);
193
194
0
  return stream;
195
0
}
196
197
/**
198
 * g_data_input_stream_set_byte_order:
199
 * @stream: a given #GDataInputStream.
200
 * @order: a #GDataStreamByteOrder to set.
201
 * 
202
 * This function sets the byte order for the given @stream. All subsequent
203
 * reads from the @stream will be read in the given @order.
204
 *  
205
 **/
206
void
207
g_data_input_stream_set_byte_order (GDataInputStream     *stream,
208
            GDataStreamByteOrder  order)
209
0
{
210
0
  GDataInputStreamPrivate *priv;
211
212
0
  g_return_if_fail (G_IS_DATA_INPUT_STREAM (stream));
213
214
0
  priv = stream->priv;
215
216
0
  if (priv->byte_order != order)
217
0
    {
218
0
      priv->byte_order = order;
219
      
220
0
      g_object_notify (G_OBJECT (stream), "byte-order");
221
0
    }
222
0
}
223
224
/**
225
 * g_data_input_stream_get_byte_order:
226
 * @stream: a given #GDataInputStream.
227
 * 
228
 * Gets the byte order for the data input stream.
229
 * 
230
 * Returns: the @stream's current #GDataStreamByteOrder. 
231
 **/
232
GDataStreamByteOrder
233
g_data_input_stream_get_byte_order (GDataInputStream *stream)
234
0
{
235
0
  g_return_val_if_fail (G_IS_DATA_INPUT_STREAM (stream), G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN);
236
237
0
  return stream->priv->byte_order;
238
0
}
239
240
/**
241
 * g_data_input_stream_set_newline_type:
242
 * @stream: a #GDataInputStream.
243
 * @type: the type of new line return as #GDataStreamNewlineType.
244
 * 
245
 * Sets the newline type for the @stream.
246
 * 
247
 * Note that using G_DATA_STREAM_NEWLINE_TYPE_ANY is slightly unsafe. If a read
248
 * chunk ends in "CR" we must read an additional byte to know if this is "CR" or
249
 * "CR LF", and this might block if there is no more data available.
250
 *  
251
 **/
252
void
253
g_data_input_stream_set_newline_type (GDataInputStream       *stream,
254
              GDataStreamNewlineType  type)
255
0
{
256
0
  GDataInputStreamPrivate *priv;
257
258
0
  g_return_if_fail (G_IS_DATA_INPUT_STREAM (stream));
259
260
0
  priv = stream->priv;
261
  
262
0
  if (priv->newline_type != type)
263
0
    {
264
0
      priv->newline_type = type;
265
266
0
      g_object_notify (G_OBJECT (stream), "newline-type");
267
0
    }
268
0
}
269
270
/**
271
 * g_data_input_stream_get_newline_type:
272
 * @stream: a given #GDataInputStream.
273
 * 
274
 * Gets the current newline type for the @stream.
275
 * 
276
 * Returns: #GDataStreamNewlineType for the given @stream.
277
 **/
278
GDataStreamNewlineType
279
g_data_input_stream_get_newline_type (GDataInputStream *stream)
280
0
{
281
0
  g_return_val_if_fail (G_IS_DATA_INPUT_STREAM (stream), G_DATA_STREAM_NEWLINE_TYPE_ANY);
282
283
0
  return stream->priv->newline_type;
284
0
}
285
286
static gboolean
287
read_data (GDataInputStream  *stream,
288
           void              *buffer,
289
           gsize              size,
290
           GCancellable      *cancellable,
291
           GError           **error)
292
0
{
293
0
  gsize available;
294
0
  gssize res;
295
296
0
  while ((available = g_buffered_input_stream_get_available (G_BUFFERED_INPUT_STREAM (stream))) < size)
297
0
    {
298
0
      res = g_buffered_input_stream_fill (G_BUFFERED_INPUT_STREAM (stream),
299
0
            size - available,
300
0
            cancellable, error);
301
0
      if (res < 0)
302
0
  return FALSE;
303
0
      if (res == 0)
304
0
  {
305
0
    g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
306
0
                               _("Unexpected early end-of-stream"));
307
0
    return FALSE;
308
0
  }
309
0
    }
310
  
311
  /* This should always succeed, since it's in the buffer */
312
0
  res = g_input_stream_read (G_INPUT_STREAM (stream),
313
0
           buffer, size,
314
0
           NULL, NULL);
315
0
  g_warn_if_fail (res >= 0 && (gsize) res == size);
316
0
  return TRUE;
317
0
}
318
319
320
/**
321
 * g_data_input_stream_read_byte:
322
 * @stream: a given #GDataInputStream.
323
 * @cancellable: (nullable): optional #GCancellable object, %NULL to ignore.
324
 * @error: #GError for error reporting.
325
 * 
326
 * Reads an unsigned 8-bit/1-byte value from @stream.
327
 *
328
 * Returns: an unsigned 8-bit/1-byte value read from the @stream or `0`
329
 * if an error occurred.
330
 **/
331
guchar
332
g_data_input_stream_read_byte (GDataInputStream  *stream,
333
             GCancellable       *cancellable,
334
             GError            **error)
335
0
{
336
0
  guchar c;
337
  
338
0
  g_return_val_if_fail (G_IS_DATA_INPUT_STREAM (stream), '\0');
339
  
340
0
  if (read_data (stream, &c, 1, cancellable, error))
341
0
      return c;
342
  
343
0
  return 0;
344
0
}
345
346
347
/**
348
 * g_data_input_stream_read_int16:
349
 * @stream: a given #GDataInputStream.
350
 * @cancellable: (nullable): optional #GCancellable object, %NULL to ignore.
351
 * @error: #GError for error reporting.
352
 * 
353
 * Reads a 16-bit/2-byte value from @stream.
354
 *
355
 * In order to get the correct byte order for this read operation, 
356
 * see g_data_input_stream_get_byte_order() and g_data_input_stream_set_byte_order().
357
 * 
358
 * Returns: a signed 16-bit/2-byte value read from @stream or `0` if
359
 * an error occurred.
360
 **/
361
gint16
362
g_data_input_stream_read_int16 (GDataInputStream  *stream,
363
             GCancellable       *cancellable,
364
             GError            **error)
365
0
{
366
0
  gint16 v;
367
  
368
0
  g_return_val_if_fail (G_IS_DATA_INPUT_STREAM (stream), 0);
369
  
370
0
  if (read_data (stream, &v, 2, cancellable, error))
371
0
    {
372
0
      switch (stream->priv->byte_order)
373
0
  {
374
0
  case G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN:
375
0
    v = GINT16_FROM_BE (v);
376
0
    break;
377
0
  case G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN:
378
0
    v = GINT16_FROM_LE (v);
379
0
    break;
380
0
  case G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN:
381
0
  default:
382
0
    break;
383
0
  }
384
0
      return v;
385
0
    }
386
  
387
0
  return 0;
388
0
}
389
390
391
/**
392
 * g_data_input_stream_read_uint16:
393
 * @stream: a given #GDataInputStream.
394
 * @cancellable: (nullable): optional #GCancellable object, %NULL to ignore.
395
 * @error: #GError for error reporting.
396
 *
397
 * Reads an unsigned 16-bit/2-byte value from @stream.
398
 *
399
 * In order to get the correct byte order for this read operation, 
400
 * see g_data_input_stream_get_byte_order() and g_data_input_stream_set_byte_order(). 
401
 * 
402
 * Returns: an unsigned 16-bit/2-byte value read from the @stream or `0` if
403
 * an error occurred. 
404
 **/
405
guint16
406
g_data_input_stream_read_uint16 (GDataInputStream  *stream,
407
         GCancellable       *cancellable,
408
         GError            **error)
409
0
{
410
0
  guint16 v;
411
  
412
0
  g_return_val_if_fail (G_IS_DATA_INPUT_STREAM (stream), 0);
413
  
414
0
  if (read_data (stream, &v, 2, cancellable, error))
415
0
    {
416
0
      switch (stream->priv->byte_order)
417
0
  {
418
0
  case G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN:
419
0
    v = GUINT16_FROM_BE (v);
420
0
    break;
421
0
  case G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN:
422
0
    v = GUINT16_FROM_LE (v);
423
0
    break;
424
0
  case G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN:
425
0
  default:
426
0
    break;
427
0
  }
428
0
      return v;
429
0
    }
430
  
431
0
  return 0;
432
0
}
433
434
435
/**
436
 * g_data_input_stream_read_int32:
437
 * @stream: a given #GDataInputStream.
438
 * @cancellable: (nullable): optional #GCancellable object, %NULL to ignore.
439
 * @error: #GError for error reporting.
440
 * 
441
 * Reads a signed 32-bit/4-byte value from @stream.
442
 *
443
 * In order to get the correct byte order for this read operation, 
444
 * see g_data_input_stream_get_byte_order() and g_data_input_stream_set_byte_order().
445
 *
446
 * If @cancellable is not %NULL, then the operation can be cancelled by
447
 * triggering the cancellable object from another thread. If the operation
448
 * was cancelled, the error %G_IO_ERROR_CANCELLED will be returned. 
449
 *   
450
 * Returns: a signed 32-bit/4-byte value read from the @stream or `0` if
451
 * an error occurred. 
452
 **/
453
gint32
454
g_data_input_stream_read_int32 (GDataInputStream  *stream,
455
        GCancellable       *cancellable,
456
        GError            **error)
457
0
{
458
0
  gint32 v;
459
  
460
0
  g_return_val_if_fail (G_IS_DATA_INPUT_STREAM (stream), 0);
461
  
462
0
  if (read_data (stream, &v, 4, cancellable, error))
463
0
    {
464
0
      switch (stream->priv->byte_order)
465
0
  {
466
0
  case G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN:
467
0
    v = GINT32_FROM_BE (v);
468
0
    break;
469
0
  case G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN:
470
0
    v = GINT32_FROM_LE (v);
471
0
    break;
472
0
  case G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN:
473
0
  default:
474
0
    break;
475
0
  }
476
0
      return v;
477
0
    }
478
  
479
0
  return 0;
480
0
}
481
482
483
/**
484
 * g_data_input_stream_read_uint32:
485
 * @stream: a given #GDataInputStream.
486
 * @cancellable: (nullable): optional #GCancellable object, %NULL to ignore.
487
 * @error: #GError for error reporting.
488
 * 
489
 * Reads an unsigned 32-bit/4-byte value from @stream.
490
 *
491
 * In order to get the correct byte order for this read operation, 
492
 * see g_data_input_stream_get_byte_order() and g_data_input_stream_set_byte_order().
493
 *
494
 * If @cancellable is not %NULL, then the operation can be cancelled by
495
 * triggering the cancellable object from another thread. If the operation
496
 * was cancelled, the error %G_IO_ERROR_CANCELLED will be returned. 
497
 * 
498
 * Returns: an unsigned 32-bit/4-byte value read from the @stream or `0` if
499
 * an error occurred. 
500
 **/
501
guint32
502
g_data_input_stream_read_uint32 (GDataInputStream  *stream,
503
         GCancellable       *cancellable,
504
         GError            **error)
505
0
{
506
0
  guint32 v;
507
  
508
0
  g_return_val_if_fail (G_IS_DATA_INPUT_STREAM (stream), 0);
509
  
510
0
  if (read_data (stream, &v, 4, cancellable, error))
511
0
    {
512
0
      switch (stream->priv->byte_order)
513
0
  {
514
0
  case G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN:
515
0
    v = GUINT32_FROM_BE (v);
516
0
    break;
517
0
  case G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN:
518
0
    v = GUINT32_FROM_LE (v);
519
0
    break;
520
0
  case G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN:
521
0
  default:
522
0
    break;
523
0
  }
524
0
      return v;
525
0
    }
526
  
527
0
  return 0;
528
0
}
529
530
531
/**
532
 * g_data_input_stream_read_int64:
533
 * @stream: a given #GDataInputStream.
534
 * @cancellable: (nullable): optional #GCancellable object, %NULL to ignore.
535
 * @error: #GError for error reporting.
536
 * 
537
 * Reads a 64-bit/8-byte value from @stream.
538
 *
539
 * In order to get the correct byte order for this read operation, 
540
 * see g_data_input_stream_get_byte_order() and g_data_input_stream_set_byte_order().
541
 *
542
 * If @cancellable is not %NULL, then the operation can be cancelled by
543
 * triggering the cancellable object from another thread. If the operation
544
 * was cancelled, the error %G_IO_ERROR_CANCELLED will be returned. 
545
 * 
546
 * Returns: a signed 64-bit/8-byte value read from @stream or `0` if
547
 * an error occurred.  
548
 **/
549
gint64
550
g_data_input_stream_read_int64 (GDataInputStream  *stream,
551
             GCancellable       *cancellable,
552
             GError            **error)
553
0
{
554
0
  gint64 v;
555
  
556
0
  g_return_val_if_fail (G_IS_DATA_INPUT_STREAM (stream), 0);
557
  
558
0
  if (read_data (stream, &v, 8, cancellable, error))
559
0
    {
560
0
      switch (stream->priv->byte_order)
561
0
  {
562
0
  case G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN:
563
0
    v = GINT64_FROM_BE (v);
564
0
    break;
565
0
  case G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN:
566
0
    v = GINT64_FROM_LE (v);
567
0
    break;
568
0
  case G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN:
569
0
  default:
570
0
    break;
571
0
  }
572
0
      return v;
573
0
    }
574
  
575
0
  return 0;
576
0
}
577
578
579
/**
580
 * g_data_input_stream_read_uint64:
581
 * @stream: a given #GDataInputStream.
582
 * @cancellable: (nullable): optional #GCancellable object, %NULL to ignore.
583
 * @error: #GError for error reporting.
584
 * 
585
 * Reads an unsigned 64-bit/8-byte value from @stream.
586
 *
587
 * In order to get the correct byte order for this read operation, 
588
 * see g_data_input_stream_get_byte_order().
589
 *
590
 * If @cancellable is not %NULL, then the operation can be cancelled by
591
 * triggering the cancellable object from another thread. If the operation
592
 * was cancelled, the error %G_IO_ERROR_CANCELLED will be returned. 
593
 * 
594
 * Returns: an unsigned 64-bit/8-byte read from @stream or `0` if
595
 * an error occurred. 
596
 **/
597
guint64
598
g_data_input_stream_read_uint64 (GDataInputStream  *stream,
599
        GCancellable       *cancellable,
600
        GError            **error)
601
0
{
602
0
  guint64 v;
603
  
604
0
  g_return_val_if_fail (G_IS_DATA_INPUT_STREAM (stream), 0);
605
  
606
0
  if (read_data (stream, &v, 8, cancellable, error))
607
0
    {
608
0
      switch (stream->priv->byte_order)
609
0
  {
610
0
  case G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN:
611
0
    v = GUINT64_FROM_BE (v);
612
0
    break;
613
0
  case G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN:
614
0
    v = GUINT64_FROM_LE (v);
615
0
    break;
616
0
  case G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN:
617
0
  default:
618
0
    break;
619
0
  }
620
0
      return v;
621
0
    }
622
  
623
0
  return 0;
624
0
}
625
626
static gssize
627
scan_for_newline (GDataInputStream *stream,
628
      gsize            *checked_out,
629
      gboolean         *last_saw_cr_out,
630
      int              *newline_len_out)
631
0
{
632
0
  GBufferedInputStream *bstream;
633
0
  GDataInputStreamPrivate *priv;
634
0
  const char *buffer;
635
0
  gsize start, end, peeked;
636
0
  gsize i;
637
0
  gssize found_pos;
638
0
  int newline_len;
639
0
  gsize available, checked;
640
0
  gboolean last_saw_cr;
641
642
0
  priv = stream->priv;
643
  
644
0
  bstream = G_BUFFERED_INPUT_STREAM (stream);
645
646
0
  checked = *checked_out;
647
0
  last_saw_cr = *last_saw_cr_out;
648
0
  found_pos = -1;
649
0
  newline_len = 0;
650
  
651
0
  start = checked;
652
0
  buffer = (const char*)g_buffered_input_stream_peek_buffer (bstream, &available) + start;
653
0
  end = available;
654
0
  peeked = end - start;
655
656
0
  for (i = 0; checked < available && i < peeked; i++)
657
0
    {
658
0
      switch (priv->newline_type)
659
0
  {
660
0
  case G_DATA_STREAM_NEWLINE_TYPE_LF:
661
0
    if (buffer[i] == 10)
662
0
      {
663
0
        found_pos = start + i;
664
0
        newline_len = 1;
665
0
      }
666
0
    break;
667
0
  case G_DATA_STREAM_NEWLINE_TYPE_CR:
668
0
    if (buffer[i] == 13)
669
0
      {
670
0
        found_pos = start + i;
671
0
        newline_len = 1;
672
0
      }
673
0
    break;
674
0
  case G_DATA_STREAM_NEWLINE_TYPE_CR_LF:
675
0
    if (last_saw_cr && buffer[i] == 10)
676
0
      {
677
0
        found_pos = start + i - 1;
678
0
        newline_len = 2;
679
0
      }
680
0
    break;
681
0
  default:
682
0
  case G_DATA_STREAM_NEWLINE_TYPE_ANY:
683
0
    if (buffer[i] == 10) /* LF */
684
0
      {
685
0
        if (last_saw_cr)
686
0
    {
687
      /* CR LF */
688
0
      found_pos = start + i - 1;
689
0
      newline_len = 2;
690
0
    }
691
0
        else
692
0
    {
693
      /* LF */
694
0
      found_pos = start + i;
695
0
      newline_len = 1;
696
0
    }
697
0
      }
698
0
    else if (last_saw_cr)
699
0
      {
700
        /* Last was cr, this is not LF, end is CR */
701
0
        found_pos = start + i - 1;
702
0
        newline_len = 1;
703
0
      }
704
    /* Don't check for CR here, instead look at last_saw_cr on next byte */
705
0
    break;
706
0
  }
707
  
708
0
      last_saw_cr = (buffer[i] == 13);
709
710
0
      if (found_pos != -1)
711
0
  {
712
0
    *newline_len_out = newline_len;
713
0
    return found_pos;
714
0
  }
715
0
    }
716
717
0
  checked = end;
718
719
0
  *checked_out = checked;
720
0
  *last_saw_cr_out = last_saw_cr;
721
0
  return -1;
722
0
}
723
      
724
725
/**
726
 * g_data_input_stream_read_line:
727
 * @stream: a given #GDataInputStream.
728
 * @length: (out) (optional): a #gsize to get the length of the data read in.
729
 * @cancellable: (nullable): optional #GCancellable object, %NULL to ignore.
730
 * @error: #GError for error reporting.
731
 *
732
 * Reads a line from the data input stream.  Note that no encoding
733
 * checks or conversion is performed; the input is not guaranteed to
734
 * be UTF-8, and may in fact have embedded NUL characters.
735
 *
736
 * If @cancellable is not %NULL, then the operation can be cancelled by
737
 * triggering the cancellable object from another thread. If the operation
738
 * was cancelled, the error %G_IO_ERROR_CANCELLED will be returned.
739
 *
740
 * Returns: (nullable) (transfer full) (array zero-terminated=1) (element-type guint8):
741
 *  a NUL terminated byte array with the line that was read in
742
 *  (without the newlines).  Set @length to a #gsize to get the length
743
 *  of the read line.  On an error, it will return %NULL and @error
744
 *  will be set. If there's no content to read, it will still return
745
 *  %NULL, but @error won't be set.
746
 **/
747
char *
748
g_data_input_stream_read_line (GDataInputStream  *stream,
749
             gsize             *length,
750
             GCancellable      *cancellable,
751
             GError           **error)
752
0
{
753
0
  GBufferedInputStream *bstream;
754
0
  gsize checked;
755
0
  gboolean last_saw_cr;
756
0
  gssize found_pos;
757
0
  gssize res;
758
0
  int newline_len;
759
0
  char *line;
760
  
761
0
  g_return_val_if_fail (G_IS_DATA_INPUT_STREAM (stream), NULL);  
762
763
0
  bstream = G_BUFFERED_INPUT_STREAM (stream);
764
765
0
  newline_len = 0;
766
0
  checked = 0;
767
0
  last_saw_cr = FALSE;
768
769
0
  while ((found_pos = scan_for_newline (stream, &checked, &last_saw_cr, &newline_len)) == -1)
770
0
    {
771
0
      if (g_buffered_input_stream_get_available (bstream) ==
772
0
    g_buffered_input_stream_get_buffer_size (bstream))
773
0
  g_buffered_input_stream_set_buffer_size (bstream,
774
0
             2 * g_buffered_input_stream_get_buffer_size (bstream));
775
776
0
      res = g_buffered_input_stream_fill (bstream, -1, cancellable, error);
777
0
      if (res < 0)
778
0
  return NULL;
779
0
      if (res == 0)
780
0
  {
781
    /* End of stream */
782
0
    if (g_buffered_input_stream_get_available (bstream) == 0)
783
0
      {
784
0
        if (length)
785
0
    *length = 0;
786
0
        return NULL;
787
0
      }
788
0
    else
789
0
      {
790
0
        found_pos = checked;
791
0
        newline_len = 0;
792
0
        break;
793
0
      }
794
0
  }
795
0
    }
796
797
0
  line = g_malloc (found_pos + newline_len + 1);
798
799
0
  res = g_input_stream_read (G_INPUT_STREAM (stream),
800
0
           line,
801
0
           found_pos + newline_len,
802
0
           NULL, NULL);
803
0
  if (length)
804
0
    *length = (gsize)found_pos;
805
0
  g_warn_if_fail (res == found_pos + newline_len);
806
0
  line[found_pos] = 0;
807
  
808
0
  return line;
809
0
}
810
811
/**
812
 * g_data_input_stream_read_line_utf8:
813
 * @stream: a given #GDataInputStream.
814
 * @length: (out) (optional): a #gsize to get the length of the data read in.
815
 * @cancellable: (nullable): optional #GCancellable object, %NULL to ignore.
816
 * @error: #GError for error reporting.
817
 *
818
 * Reads a UTF-8 encoded line from the data input stream.
819
 *
820
 * If @cancellable is not %NULL, then the operation can be cancelled by
821
 * triggering the cancellable object from another thread. If the operation
822
 * was cancelled, the error %G_IO_ERROR_CANCELLED will be returned.
823
 *
824
 * Returns: (nullable) (transfer full): a NUL terminated UTF-8 string
825
 *  with the line that was read in (without the newlines).  Set
826
 *  @length to a #gsize to get the length of the read line.  On an
827
 *  error, it will return %NULL and @error will be set.  For UTF-8
828
 *  conversion errors, the set error domain is %G_CONVERT_ERROR.  If
829
 *  there's no content to read, it will still return %NULL, but @error
830
 *  won't be set.
831
 *
832
 * Since: 2.30
833
 **/
834
char *
835
g_data_input_stream_read_line_utf8 (GDataInputStream  *stream,
836
            gsize             *length,
837
            GCancellable      *cancellable,
838
            GError           **error)
839
0
{
840
0
  char *res;
841
842
0
  res = g_data_input_stream_read_line (stream, length, cancellable, error);
843
0
  if (!res)
844
0
    return NULL;
845
  
846
0
  if (!g_utf8_validate (res, -1, NULL))
847
0
    {
848
0
      g_set_error_literal (error, G_CONVERT_ERROR,
849
0
         G_CONVERT_ERROR_ILLEGAL_SEQUENCE,
850
0
         _("Invalid byte sequence in conversion input"));
851
0
      g_free (res);
852
0
      return NULL;
853
0
    }
854
0
  return res;
855
0
}
856
857
static gssize
858
scan_for_chars (GDataInputStream *stream,
859
    gsize            *checked_out,
860
    const char       *stop_chars,
861
                gsize             stop_chars_len)
862
0
{
863
0
  GBufferedInputStream *bstream;
864
0
  const char *buffer;
865
0
  gsize start, end, peeked;
866
0
  gsize i;
867
0
  gsize available, checked;
868
0
  const char *stop_char;
869
0
  const char *stop_end;
870
871
0
  bstream = G_BUFFERED_INPUT_STREAM (stream);
872
0
  stop_end = stop_chars + stop_chars_len;
873
874
0
  checked = *checked_out;
875
876
0
  start = checked;
877
0
  buffer = (const char *)g_buffered_input_stream_peek_buffer (bstream, &available) + start;
878
0
  end = available;
879
0
  peeked = end - start;
880
881
0
  for (i = 0; checked < available && i < peeked; i++)
882
0
    {
883
0
      for (stop_char = stop_chars; stop_char != stop_end; stop_char++)
884
0
  {
885
0
    if (buffer[i] == *stop_char)
886
0
      return (start + i);
887
0
  }
888
0
    }
889
890
0
  checked = end;
891
892
0
  *checked_out = checked;
893
0
  return -1;
894
0
}
895
896
/**
897
 * g_data_input_stream_read_until:
898
 * @stream: a given #GDataInputStream.
899
 * @stop_chars: characters to terminate the read.
900
 * @length: (out) (optional): a #gsize to get the length of the data read in.
901
 * @cancellable: (nullable): optional #GCancellable object, %NULL to ignore.
902
 * @error: #GError for error reporting.
903
 *
904
 * Reads a string from the data input stream, up to the first
905
 * occurrence of any of the stop characters.
906
 *
907
 * Note that, in contrast to g_data_input_stream_read_until_async(),
908
 * this function consumes the stop character that it finds.
909
 *
910
 * Don't use this function in new code.  Its functionality is
911
 * inconsistent with g_data_input_stream_read_until_async().  Both
912
 * functions will be marked as deprecated in a future release.  Use
913
 * g_data_input_stream_read_upto() instead, but note that that function
914
 * does not consume the stop character.
915
 *
916
 * Returns: (transfer full): a string with the data that was read
917
 *     before encountering any of the stop characters. Set @length to
918
 *     a #gsize to get the length of the string. This function will
919
 *     return %NULL on an error.
920
 * Deprecated: 2.56: Use g_data_input_stream_read_upto() instead, which has more
921
 *     consistent behaviour regarding the stop character.
922
 */
923
char *
924
g_data_input_stream_read_until (GDataInputStream  *stream,
925
             const gchar        *stop_chars,
926
             gsize              *length,
927
             GCancellable       *cancellable,
928
             GError            **error)
929
0
{
930
0
  GBufferedInputStream *bstream;
931
0
  gchar *result;
932
933
0
  bstream = G_BUFFERED_INPUT_STREAM (stream);
934
935
0
  result = g_data_input_stream_read_upto (stream, stop_chars, -1,
936
0
                                          length, cancellable, error);
937
938
  /* If we're not at end of stream then we have a stop_char to consume. */
939
0
  if (result != NULL && g_buffered_input_stream_get_available (bstream) > 0)
940
0
    {
941
0
      gsize res G_GNUC_UNUSED  /* when compiling with G_DISABLE_ASSERT */;
942
0
      gchar b;
943
944
0
      res = g_input_stream_read (G_INPUT_STREAM (stream), &b, 1, NULL, NULL);
945
0
      g_assert (res == 1);
946
0
    }
947
948
0
  return result;
949
0
}
950
951
typedef struct
952
{
953
  gboolean last_saw_cr;
954
  gsize checked;
955
956
  gchar *stop_chars;
957
  gsize stop_chars_len;
958
  gsize length;
959
} GDataInputStreamReadData;
960
961
static void
962
g_data_input_stream_read_complete (GTask *task,
963
                                   gsize  read_length,
964
                                   gsize  skip_length)
965
0
{
966
0
  GDataInputStreamReadData *data = g_task_get_task_data (task);
967
0
  GInputStream *stream = g_task_get_source_object (task);
968
0
  char *line = NULL;
969
970
0
  if (read_length || skip_length)
971
0
    {
972
0
      gssize bytes;
973
974
0
      data->length = read_length;
975
0
      line = g_malloc (read_length + 1);
976
0
      line[read_length] = '\0';
977
978
      /* we already checked the buffer.  this shouldn't fail. */
979
0
      bytes = g_input_stream_read (stream, line, read_length, NULL, NULL);
980
0
      g_assert_cmpint (bytes, ==, read_length);
981
982
0
      bytes = g_input_stream_skip (stream, skip_length, NULL, NULL);
983
0
      g_assert_cmpint (bytes, ==, skip_length);
984
0
    }
985
986
0
  g_task_return_pointer (task, line, g_free);
987
0
  g_object_unref (task);
988
0
}
989
990
static void
991
g_data_input_stream_read_line_ready (GObject      *object,
992
                                     GAsyncResult *result,
993
                                     gpointer      user_data)
994
0
{
995
0
  GTask *task = user_data;
996
0
  GDataInputStreamReadData *data = g_task_get_task_data (task);
997
0
  GBufferedInputStream *buffer = g_task_get_source_object (task);
998
0
  gssize found_pos;
999
0
  gint newline_len;
1000
1001
0
  if (result)
1002
    /* this is a callback.  finish the async call. */
1003
0
    {
1004
0
      GError *error = NULL;
1005
0
      gssize bytes;
1006
1007
0
      bytes = g_buffered_input_stream_fill_finish (buffer, result, &error);
1008
1009
0
      if (bytes <= 0)
1010
0
        {
1011
0
          if (bytes < 0)
1012
            /* stream error. */
1013
0
            {
1014
0
              g_task_return_error (task, error);
1015
0
              g_object_unref (task);
1016
0
              return;
1017
0
            }
1018
1019
0
          g_data_input_stream_read_complete (task, data->checked, 0);
1020
0
          return;
1021
0
        }
1022
1023
      /* only proceed if we got more bytes... */
1024
0
    }
1025
1026
0
  if (data->stop_chars)
1027
0
    {
1028
0
      found_pos = scan_for_chars (G_DATA_INPUT_STREAM (buffer),
1029
0
                                  &data->checked,
1030
0
                                  data->stop_chars,
1031
0
                                  data->stop_chars_len);
1032
0
      newline_len = 0;
1033
0
    }
1034
0
  else
1035
0
    found_pos = scan_for_newline (G_DATA_INPUT_STREAM (buffer), &data->checked,
1036
0
                                  &data->last_saw_cr, &newline_len);
1037
1038
0
  if (found_pos == -1)
1039
    /* didn't find a full line; need to buffer some more bytes */
1040
0
    {
1041
0
      gsize size;
1042
1043
0
      size = g_buffered_input_stream_get_buffer_size (buffer);
1044
1045
0
      if (g_buffered_input_stream_get_available (buffer) == size)
1046
        /* need to grow the buffer */
1047
0
        g_buffered_input_stream_set_buffer_size (buffer, size * 2);
1048
1049
      /* try again */
1050
0
      g_buffered_input_stream_fill_async (buffer, -1,
1051
0
                                          g_task_get_priority (task),
1052
0
                                          g_task_get_cancellable (task),
1053
0
                                          g_data_input_stream_read_line_ready,
1054
0
                                          user_data);
1055
0
    }
1056
0
  else
1057
0
    {
1058
      /* read the line and the EOL.  no error is possible. */
1059
0
      g_data_input_stream_read_complete (task, found_pos, newline_len);
1060
0
    }
1061
0
}
1062
1063
static void
1064
g_data_input_stream_read_data_free (gpointer user_data)
1065
0
{
1066
0
  GDataInputStreamReadData *data = user_data;
1067
1068
0
  g_free (data->stop_chars);
1069
0
  g_slice_free (GDataInputStreamReadData, data);
1070
0
}
1071
1072
static void
1073
g_data_input_stream_read_async (GDataInputStream    *stream,
1074
                                const gchar         *stop_chars,
1075
                                gssize               stop_chars_len,
1076
                                gint                 io_priority,
1077
                                GCancellable        *cancellable,
1078
                                GAsyncReadyCallback  callback,
1079
                                gpointer             user_data)
1080
0
{
1081
0
  GDataInputStreamReadData *data;
1082
0
  GTask *task;
1083
0
  gsize stop_chars_len_unsigned;
1084
1085
0
  data = g_slice_new0 (GDataInputStreamReadData);
1086
1087
0
  if (stop_chars_len < 0)
1088
0
    stop_chars_len_unsigned = strlen (stop_chars);
1089
0
  else
1090
0
    stop_chars_len_unsigned = (gsize) stop_chars_len;
1091
1092
0
  data->stop_chars = g_memdup2 (stop_chars, stop_chars_len_unsigned);
1093
0
  data->stop_chars_len = stop_chars_len_unsigned;
1094
0
  data->last_saw_cr = FALSE;
1095
1096
0
  task = g_task_new (stream, cancellable, callback, user_data);
1097
0
  g_task_set_source_tag (task, g_data_input_stream_read_async);
1098
0
  g_task_set_task_data (task, data, g_data_input_stream_read_data_free);
1099
0
  g_task_set_priority (task, io_priority);
1100
1101
0
  g_data_input_stream_read_line_ready (NULL, NULL, task);
1102
0
}
1103
1104
static gchar *
1105
g_data_input_stream_read_finish (GDataInputStream  *stream,
1106
                                 GAsyncResult      *result,
1107
                                 gsize             *length,
1108
                                 GError           **error)
1109
0
{
1110
0
  GTask *task = G_TASK (result);
1111
0
  gchar *line;
1112
1113
0
  line = g_task_propagate_pointer (task, error);
1114
1115
0
  if (length && line)
1116
0
    {
1117
0
      GDataInputStreamReadData *data = g_task_get_task_data (task);
1118
1119
0
      *length = data->length;
1120
0
    }
1121
1122
0
  return line;
1123
0
}
1124
1125
/**
1126
 * g_data_input_stream_read_line_async:
1127
 * @stream: a given #GDataInputStream.
1128
 * @io_priority: the [I/O priority][io-priority] of the request
1129
 * @cancellable: (nullable): optional #GCancellable object, %NULL to ignore.
1130
 * @callback: (scope async) (closure user_data): callback to call when the request is satisfied.
1131
 * @user_data: the data to pass to callback function.
1132
 *
1133
 * The asynchronous version of g_data_input_stream_read_line().  It is
1134
 * an error to have two outstanding calls to this function.
1135
 *
1136
 * When the operation is finished, @callback will be called. You
1137
 * can then call g_data_input_stream_read_line_finish() to get
1138
 * the result of the operation.
1139
 *
1140
 * Since: 2.20
1141
 */
1142
void
1143
g_data_input_stream_read_line_async (GDataInputStream    *stream,
1144
                                     gint                 io_priority,
1145
                                     GCancellable        *cancellable,
1146
                                     GAsyncReadyCallback  callback,
1147
                                     gpointer             user_data)
1148
0
{
1149
0
  g_return_if_fail (G_IS_DATA_INPUT_STREAM (stream));
1150
0
  g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
1151
1152
0
  g_data_input_stream_read_async (stream, NULL, 0, io_priority,
1153
0
                                  cancellable, callback, user_data);
1154
0
}
1155
1156
/**
1157
 * g_data_input_stream_read_until_async:
1158
 * @stream: a given #GDataInputStream.
1159
 * @stop_chars: characters to terminate the read.
1160
 * @io_priority: the [I/O priority][io-priority] of the request
1161
 * @cancellable: (nullable): optional #GCancellable object, %NULL to ignore.
1162
 * @callback: (scope async): callback to call when the request is satisfied.
1163
 * @user_data: (closure): 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
 * Note that, in contrast to g_data_input_stream_read_until(),
1169
 * this function does not consume the stop character that it finds.  You
1170
 * must read it for yourself.
1171
 *
1172
 * When the operation is finished, @callback will be called. You
1173
 * can then call g_data_input_stream_read_until_finish() to get
1174
 * the result of the operation.
1175
 *
1176
 * Don't use this function in new code.  Its functionality is
1177
 * inconsistent with g_data_input_stream_read_until().  Both functions
1178
 * will be marked as deprecated in a future release.  Use
1179
 * g_data_input_stream_read_upto_async() instead.
1180
 *
1181
 * Since: 2.20
1182
 * Deprecated: 2.56: Use g_data_input_stream_read_upto_async() instead, which
1183
 *     has more consistent behaviour regarding the stop character.
1184
 */
1185
void
1186
g_data_input_stream_read_until_async (GDataInputStream    *stream,
1187
                                      const gchar         *stop_chars,
1188
                                      gint                 io_priority,
1189
                                      GCancellable        *cancellable,
1190
                                      GAsyncReadyCallback  callback,
1191
                                      gpointer             user_data)
1192
0
{
1193
0
  g_return_if_fail (G_IS_DATA_INPUT_STREAM (stream));
1194
0
  g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
1195
0
  g_return_if_fail (stop_chars != NULL);
1196
1197
0
  g_data_input_stream_read_async (stream, stop_chars, -1, io_priority,
1198
0
                                  cancellable, callback, user_data);
1199
0
}
1200
1201
/**
1202
 * g_data_input_stream_read_line_finish:
1203
 * @stream: a given #GDataInputStream.
1204
 * @result: the #GAsyncResult that was provided to the callback.
1205
 * @length: (out) (optional): a #gsize to get the length of the data read in.
1206
 * @error: #GError for error reporting.
1207
 *
1208
 * Finish an asynchronous call started by
1209
 * g_data_input_stream_read_line_async().  Note the warning about
1210
 * string encoding in g_data_input_stream_read_line() applies here as
1211
 * well.
1212
 *
1213
 * Returns: (nullable) (transfer full) (array zero-terminated=1) (element-type guint8):
1214
 *  a NUL-terminated byte array with the line that was read in
1215
 *  (without the newlines).  Set @length to a #gsize to get the length
1216
 *  of the read line.  On an error, it will return %NULL and @error
1217
 *  will be set. If there's no content to read, it will still return
1218
 *  %NULL, but @error won't be set.
1219
 *
1220
 * Since: 2.20
1221
 */
1222
gchar *
1223
g_data_input_stream_read_line_finish (GDataInputStream  *stream,
1224
                                      GAsyncResult      *result,
1225
                                      gsize             *length,
1226
                                      GError           **error)
1227
0
{
1228
0
  g_return_val_if_fail (g_task_is_valid (result, stream), NULL);
1229
1230
0
  return g_data_input_stream_read_finish (stream, result, length, error);
1231
0
}
1232
1233
/**
1234
 * g_data_input_stream_read_line_finish_utf8:
1235
 * @stream: a given #GDataInputStream.
1236
 * @result: the #GAsyncResult that was provided to the callback.
1237
 * @length: (out) (optional): a #gsize to get the length of the data read in.
1238
 * @error: #GError for error reporting.
1239
 *
1240
 * Finish an asynchronous call started by
1241
 * g_data_input_stream_read_line_async().
1242
 *
1243
 * Returns: (nullable) (transfer full): a string with the line that
1244
 *  was read in (without the newlines).  Set @length to a #gsize to
1245
 *  get the length of the read line.  On an error, it will return
1246
 *  %NULL and @error will be set. For UTF-8 conversion errors, the set
1247
 *  error domain is %G_CONVERT_ERROR.  If there's no content to read,
1248
 *  it will still return %NULL, but @error won't be set.
1249
 *
1250
 * Since: 2.30
1251
 */
1252
gchar *
1253
g_data_input_stream_read_line_finish_utf8 (GDataInputStream  *stream,
1254
             GAsyncResult      *result,
1255
             gsize             *length,
1256
             GError           **error)
1257
0
{
1258
0
  gchar *res;
1259
1260
0
  res = g_data_input_stream_read_line_finish (stream, result, length, error);
1261
0
  if (!res)
1262
0
    return NULL;
1263
1264
0
  if (!g_utf8_validate (res, -1, NULL))
1265
0
    {
1266
0
      g_set_error_literal (error, G_CONVERT_ERROR,
1267
0
         G_CONVERT_ERROR_ILLEGAL_SEQUENCE,
1268
0
         _("Invalid byte sequence in conversion input"));
1269
0
      g_free (res);
1270
0
      return NULL;
1271
0
    }
1272
0
  return res;
1273
0
}
1274
1275
/**
1276
 * g_data_input_stream_read_until_finish:
1277
 * @stream: a given #GDataInputStream.
1278
 * @result: the #GAsyncResult that was provided to the callback.
1279
 * @length: (out) (optional): a #gsize to get the length of the data read in.
1280
 * @error: #GError for error reporting.
1281
 *
1282
 * Finish an asynchronous call started by
1283
 * g_data_input_stream_read_until_async().
1284
 *
1285
 * Since: 2.20
1286
 *
1287
 * Returns: (transfer full): a string with the data that was read
1288
 *     before encountering any of the stop characters. Set @length to
1289
 *     a #gsize to get the length of the string. This function will
1290
 *     return %NULL on an error.
1291
 * Deprecated: 2.56: Use g_data_input_stream_read_upto_finish() instead, which
1292
 *     has more consistent behaviour regarding the stop character.
1293
 */
1294
gchar *
1295
g_data_input_stream_read_until_finish (GDataInputStream  *stream,
1296
                                       GAsyncResult      *result,
1297
                                       gsize             *length,
1298
                                       GError           **error)
1299
0
{
1300
0
  g_return_val_if_fail (g_task_is_valid (result, stream), NULL);
1301
1302
0
  return g_data_input_stream_read_finish (stream, result, length, error);
1303
0
}
1304
1305
/**
1306
 * g_data_input_stream_read_upto:
1307
 * @stream: a #GDataInputStream
1308
 * @stop_chars: characters to terminate the read
1309
 * @stop_chars_len: length of @stop_chars. May be -1 if @stop_chars is
1310
 *     nul-terminated
1311
 * @length: (out) (optional): a #gsize to get the length of the data read in
1312
 * @cancellable: (nullable): optional #GCancellable object, %NULL to ignore
1313
 * @error: #GError for error reporting
1314
 *
1315
 * Reads a string from the data input stream, up to the first
1316
 * occurrence of any of the stop characters.
1317
 *
1318
 * In contrast to g_data_input_stream_read_until(), this function
1319
 * does not consume the stop character. You have to use
1320
 * g_data_input_stream_read_byte() to get it before calling
1321
 * g_data_input_stream_read_upto() again.
1322
 *
1323
 * Note that @stop_chars may contain '\0' if @stop_chars_len is
1324
 * specified.
1325
 *
1326
 * The returned string will always be nul-terminated on success.
1327
 *
1328
 * Returns: (transfer full): a string with the data that was read
1329
 *     before encountering any of the stop characters. Set @length to
1330
 *     a #gsize to get the length of the string. This function will
1331
 *     return %NULL on an error
1332
 *
1333
 * Since: 2.26
1334
 */
1335
char *
1336
g_data_input_stream_read_upto (GDataInputStream  *stream,
1337
                               const gchar       *stop_chars,
1338
                               gssize             stop_chars_len,
1339
                               gsize             *length,
1340
                               GCancellable      *cancellable,
1341
                               GError           **error)
1342
0
{
1343
0
  GBufferedInputStream *bstream;
1344
0
  gsize checked;
1345
0
  gssize found_pos;
1346
0
  gssize res;
1347
0
  char *data_until;
1348
0
  gsize stop_chars_len_unsigned;
1349
1350
0
  g_return_val_if_fail (G_IS_DATA_INPUT_STREAM (stream), NULL);
1351
1352
0
  if (stop_chars_len < 0)
1353
0
    stop_chars_len_unsigned = strlen (stop_chars);
1354
0
  else
1355
0
    stop_chars_len_unsigned = (gsize) stop_chars_len;
1356
1357
0
  bstream = G_BUFFERED_INPUT_STREAM (stream);
1358
1359
0
  checked = 0;
1360
1361
0
  while ((found_pos = scan_for_chars (stream, &checked, stop_chars, stop_chars_len_unsigned)) == -1)
1362
0
    {
1363
0
      if (g_buffered_input_stream_get_available (bstream) ==
1364
0
          g_buffered_input_stream_get_buffer_size (bstream))
1365
0
        g_buffered_input_stream_set_buffer_size (bstream,
1366
0
                                                 2 * g_buffered_input_stream_get_buffer_size (bstream));
1367
1368
0
      res = g_buffered_input_stream_fill (bstream, -1, cancellable, error);
1369
0
      if (res < 0)
1370
0
        return NULL;
1371
0
      if (res == 0)
1372
0
        {
1373
          /* End of stream */
1374
0
          if (g_buffered_input_stream_get_available (bstream) == 0)
1375
0
            {
1376
0
              if (length)
1377
0
                *length = 0;
1378
0
              return NULL;
1379
0
            }
1380
0
          else
1381
0
            {
1382
0
              found_pos = checked;
1383
0
              break;
1384
0
            }
1385
0
        }
1386
0
    }
1387
1388
0
  data_until = g_malloc (found_pos + 1);
1389
1390
0
  res = g_input_stream_read (G_INPUT_STREAM (stream),
1391
0
                             data_until,
1392
0
                             found_pos,
1393
0
                             NULL, NULL);
1394
0
  if (length)
1395
0
    *length = (gsize)found_pos;
1396
0
  g_warn_if_fail (res == found_pos);
1397
0
  data_until[found_pos] = 0;
1398
1399
0
  return data_until;
1400
0
}
1401
1402
/**
1403
 * g_data_input_stream_read_upto_async:
1404
 * @stream: a #GDataInputStream
1405
 * @stop_chars: characters to terminate the read
1406
 * @stop_chars_len: length of @stop_chars. May be -1 if @stop_chars is
1407
 *     nul-terminated
1408
 * @io_priority: the [I/O priority][io-priority] of the request
1409
 * @cancellable: (nullable): optional #GCancellable object, %NULL to ignore
1410
 * @callback: (scope async): callback to call when the request is satisfied
1411
 * @user_data: (closure): the data to pass to callback function
1412
 *
1413
 * The asynchronous version of g_data_input_stream_read_upto().
1414
 * It is an error to have two outstanding calls to this function.
1415
 *
1416
 * In contrast to g_data_input_stream_read_until(), this function
1417
 * does not consume the stop character. You have to use
1418
 * g_data_input_stream_read_byte() to get it before calling
1419
 * g_data_input_stream_read_upto() again.
1420
 *
1421
 * Note that @stop_chars may contain '\0' if @stop_chars_len is
1422
 * specified.
1423
 *
1424
 * When the operation is finished, @callback will be called. You
1425
 * can then call g_data_input_stream_read_upto_finish() to get
1426
 * the result of the operation.
1427
 *
1428
 * Since: 2.26
1429
 */
1430
void
1431
g_data_input_stream_read_upto_async (GDataInputStream    *stream,
1432
                                     const gchar         *stop_chars,
1433
                                     gssize               stop_chars_len,
1434
                                     gint                 io_priority,
1435
                                     GCancellable        *cancellable,
1436
                                     GAsyncReadyCallback  callback,
1437
                                     gpointer             user_data)
1438
0
{
1439
0
  g_return_if_fail (G_IS_DATA_INPUT_STREAM (stream));
1440
0
  g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
1441
0
  g_return_if_fail (stop_chars != NULL);
1442
1443
0
  g_data_input_stream_read_async (stream, stop_chars, stop_chars_len, io_priority,
1444
0
                                  cancellable, callback, user_data);
1445
0
}
1446
1447
/**
1448
 * g_data_input_stream_read_upto_finish:
1449
 * @stream: a #GDataInputStream
1450
 * @result: the #GAsyncResult that was provided to the callback
1451
 * @length: (out) (optional): a #gsize to get the length of the data read in
1452
 * @error: #GError for error reporting
1453
 *
1454
 * Finish an asynchronous call started by
1455
 * g_data_input_stream_read_upto_async().
1456
 *
1457
 * Note that this function does not consume the stop character. You
1458
 * have to use g_data_input_stream_read_byte() to get it before calling
1459
 * g_data_input_stream_read_upto_async() again.
1460
 *
1461
 * The returned string will always be nul-terminated on success.
1462
 *
1463
 * Returns: (transfer full): a string with the data that was read
1464
 *     before encountering any of the stop characters. Set @length to
1465
 *     a #gsize to get the length of the string. This function will
1466
 *     return %NULL on an error.
1467
 *
1468
 * Since: 2.24
1469
 */
1470
gchar *
1471
g_data_input_stream_read_upto_finish (GDataInputStream  *stream,
1472
                                      GAsyncResult      *result,
1473
                                      gsize             *length,
1474
                                      GError           **error)
1475
0
{
1476
0
  g_return_val_if_fail (g_task_is_valid (result, stream), NULL);
1477
1478
0
  return g_data_input_stream_read_finish (stream, result, length, error);
1479
0
}