Coverage Report

Created: 2025-11-16 07:45

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