Coverage Report

Created: 2025-07-23 08:13

/src/pango/subprojects/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
 * 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
G_DEFINE_TYPE_WITH_PRIVATE (GDataInputStream,
63
                            g_data_input_stream,
64
                            G_TYPE_BUFFERED_INPUT_STREAM)
65
66
67
static void
68
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
844
0
      if (length != NULL)
845
0
        *length = 0;
846
0
      g_free (res);
847
848
0
      return NULL;
849
0
    }
850
0
  return res;
851
0
}
852
853
static gssize
854
scan_for_chars (GDataInputStream *stream,
855
    gsize            *checked_out,
856
    const char       *stop_chars,
857
                gsize             stop_chars_len)
858
0
{
859
0
  GBufferedInputStream *bstream;
860
0
  const char *buffer;
861
0
  gsize start, end, peeked;
862
0
  gsize i;
863
0
  gsize available, checked;
864
865
0
  bstream = G_BUFFERED_INPUT_STREAM (stream);
866
867
0
  checked = *checked_out;
868
869
0
  start = checked;
870
0
  buffer = (const char *)g_buffered_input_stream_peek_buffer (bstream, &available) + start;
871
0
  end = available;
872
0
  peeked = end - start;
873
874
  /* For single-char case such as \0, defer the entire operation to memchr which
875
   * can take advantage of simd/etc.
876
   */
877
0
  if (stop_chars_len == 1)
878
0
    {
879
0
      const char *p = memchr (buffer, stop_chars[0], peeked);
880
881
0
      if (p != NULL)
882
0
        return start + (p - buffer);
883
0
    }
884
0
  else
885
0
    {
886
0
      for (i = 0; checked < available && i < peeked; i++)
887
0
        {
888
          /* We can use memchr() the other way round. Less fast than the
889
           * single-char case above, but still faster than doing our own inner
890
           * loop. */
891
0
          const char *p = memchr (stop_chars, buffer[i], stop_chars_len);
892
893
0
          if (p != NULL)
894
0
            return (start + i);
895
0
        }
896
0
    }
897
898
0
  checked = end;
899
900
0
  *checked_out = checked;
901
0
  return -1;
902
0
}
903
904
/**
905
 * g_data_input_stream_read_until:
906
 * @stream: a given #GDataInputStream.
907
 * @stop_chars: characters to terminate the read.
908
 * @length: (out) (optional): a #gsize to get the length of the data read in.
909
 * @cancellable: (nullable): optional #GCancellable object, %NULL to ignore.
910
 * @error: #GError for error reporting.
911
 *
912
 * Reads a string from the data input stream, up to the first
913
 * occurrence of any of the stop characters.
914
 *
915
 * Note that, in contrast to g_data_input_stream_read_until_async(),
916
 * this function consumes the stop character that it finds.
917
 *
918
 * Don't use this function in new code.  Its functionality is
919
 * inconsistent with g_data_input_stream_read_until_async().  Both
920
 * functions will be marked as deprecated in a future release.  Use
921
 * g_data_input_stream_read_upto() instead, but note that that function
922
 * does not consume the stop character.
923
 *
924
 * Returns: (transfer full): a string with the data that was read
925
 *     before encountering any of the stop characters. Set @length to
926
 *     a #gsize to get the length of the string. This function will
927
 *     return %NULL on an error.
928
 * Deprecated: 2.56: Use g_data_input_stream_read_upto() instead, which has more
929
 *     consistent behaviour regarding the stop character.
930
 */
931
char *
932
g_data_input_stream_read_until (GDataInputStream  *stream,
933
             const gchar        *stop_chars,
934
             gsize              *length,
935
             GCancellable       *cancellable,
936
             GError            **error)
937
0
{
938
0
  GBufferedInputStream *bstream;
939
0
  gchar *result;
940
941
0
  bstream = G_BUFFERED_INPUT_STREAM (stream);
942
943
0
  result = g_data_input_stream_read_upto (stream, stop_chars, -1,
944
0
                                          length, cancellable, error);
945
946
  /* If we're not at end of stream then we have a stop_char to consume. */
947
0
  if (result != NULL && g_buffered_input_stream_get_available (bstream) > 0)
948
0
    {
949
0
      gsize res G_GNUC_UNUSED  /* when compiling with G_DISABLE_ASSERT */;
950
0
      gchar b;
951
952
0
      res = g_input_stream_read (G_INPUT_STREAM (stream), &b, 1, NULL, NULL);
953
0
      g_assert (res == 1);
954
0
    }
955
956
0
  return result;
957
0
}
958
959
typedef struct
960
{
961
  gboolean last_saw_cr;
962
  gsize checked;
963
964
  gchar *stop_chars;
965
  gsize stop_chars_len;
966
  gsize length;
967
} GDataInputStreamReadData;
968
969
static void
970
g_data_input_stream_read_complete (GTask *task,
971
                                   gsize  read_length,
972
                                   gsize  skip_length)
973
0
{
974
0
  GDataInputStreamReadData *data = g_task_get_task_data (task);
975
0
  GInputStream *stream = g_task_get_source_object (task);
976
0
  char *line = NULL;
977
978
0
  if (read_length || skip_length)
979
0
    {
980
0
      gssize bytes;
981
982
0
      data->length = read_length;
983
0
      line = g_malloc (read_length + 1);
984
0
      line[read_length] = '\0';
985
986
      /* we already checked the buffer.  this shouldn't fail. */
987
0
      bytes = g_input_stream_read (stream, line, read_length, NULL, NULL);
988
0
      g_assert_cmpint (bytes, ==, read_length);
989
990
0
      bytes = g_input_stream_skip (stream, skip_length, NULL, NULL);
991
0
      g_assert_cmpint (bytes, ==, skip_length);
992
0
    }
993
994
0
  g_task_return_pointer (task, line, g_free);
995
0
  g_object_unref (task);
996
0
}
997
998
static void
999
g_data_input_stream_read_line_ready (GObject      *object,
1000
                                     GAsyncResult *result,
1001
                                     gpointer      user_data)
1002
0
{
1003
0
  GTask *task = user_data;
1004
0
  GDataInputStreamReadData *data = g_task_get_task_data (task);
1005
0
  GBufferedInputStream *buffer = g_task_get_source_object (task);
1006
0
  gssize found_pos;
1007
0
  gint newline_len;
1008
1009
0
  if (result)
1010
    /* this is a callback.  finish the async call. */
1011
0
    {
1012
0
      GError *error = NULL;
1013
0
      gssize bytes;
1014
1015
0
      bytes = g_buffered_input_stream_fill_finish (buffer, result, &error);
1016
1017
0
      if (bytes <= 0)
1018
0
        {
1019
0
          if (bytes < 0)
1020
            /* stream error. */
1021
0
            {
1022
0
              g_task_return_error (task, error);
1023
0
              g_object_unref (task);
1024
0
              return;
1025
0
            }
1026
1027
0
          g_data_input_stream_read_complete (task, data->checked, 0);
1028
0
          return;
1029
0
        }
1030
1031
      /* only proceed if we got more bytes... */
1032
0
    }
1033
1034
0
  if (data->stop_chars)
1035
0
    {
1036
0
      found_pos = scan_for_chars (G_DATA_INPUT_STREAM (buffer),
1037
0
                                  &data->checked,
1038
0
                                  data->stop_chars,
1039
0
                                  data->stop_chars_len);
1040
0
      newline_len = 0;
1041
0
    }
1042
0
  else
1043
0
    found_pos = scan_for_newline (G_DATA_INPUT_STREAM (buffer), &data->checked,
1044
0
                                  &data->last_saw_cr, &newline_len);
1045
1046
0
  if (found_pos == -1)
1047
    /* didn't find a full line; need to buffer some more bytes */
1048
0
    {
1049
0
      gsize size;
1050
1051
0
      size = g_buffered_input_stream_get_buffer_size (buffer);
1052
1053
0
      if (g_buffered_input_stream_get_available (buffer) == size)
1054
        /* need to grow the buffer */
1055
0
        g_buffered_input_stream_set_buffer_size (buffer, size * 2);
1056
1057
      /* try again */
1058
0
      g_buffered_input_stream_fill_async (buffer, -1,
1059
0
                                          g_task_get_priority (task),
1060
0
                                          g_task_get_cancellable (task),
1061
0
                                          g_data_input_stream_read_line_ready,
1062
0
                                          user_data);
1063
0
    }
1064
0
  else
1065
0
    {
1066
      /* read the line and the EOL.  no error is possible. */
1067
0
      g_data_input_stream_read_complete (task, found_pos, newline_len);
1068
0
    }
1069
0
}
1070
1071
static void
1072
g_data_input_stream_read_data_free (gpointer user_data)
1073
0
{
1074
0
  GDataInputStreamReadData *data = user_data;
1075
1076
0
  g_free (data->stop_chars);
1077
0
  g_slice_free (GDataInputStreamReadData, data);
1078
0
}
1079
1080
static void
1081
g_data_input_stream_read_async (GDataInputStream    *stream,
1082
                                const gchar         *stop_chars,
1083
                                gssize               stop_chars_len,
1084
                                gint                 io_priority,
1085
                                GCancellable        *cancellable,
1086
                                GAsyncReadyCallback  callback,
1087
                                gpointer             user_data)
1088
0
{
1089
0
  GDataInputStreamReadData *data;
1090
0
  GTask *task;
1091
0
  gsize stop_chars_len_unsigned;
1092
1093
0
  data = g_slice_new0 (GDataInputStreamReadData);
1094
1095
0
  if (stop_chars_len < 0)
1096
0
    stop_chars_len_unsigned = strlen (stop_chars);
1097
0
  else
1098
0
    stop_chars_len_unsigned = (gsize) stop_chars_len;
1099
1100
0
  data->stop_chars = g_memdup2 (stop_chars, stop_chars_len_unsigned);
1101
0
  data->stop_chars_len = stop_chars_len_unsigned;
1102
0
  data->last_saw_cr = FALSE;
1103
1104
0
  task = g_task_new (stream, cancellable, callback, user_data);
1105
0
  g_task_set_source_tag (task, g_data_input_stream_read_async);
1106
0
  g_task_set_task_data (task, data, g_data_input_stream_read_data_free);
1107
0
  g_task_set_priority (task, io_priority);
1108
1109
0
  g_data_input_stream_read_line_ready (NULL, NULL, task);
1110
0
}
1111
1112
static gchar *
1113
g_data_input_stream_read_finish (GDataInputStream  *stream,
1114
                                 GAsyncResult      *result,
1115
                                 gsize             *length,
1116
                                 GError           **error)
1117
0
{
1118
0
  GTask *task = G_TASK (result);
1119
0
  gchar *line;
1120
1121
0
  line = g_task_propagate_pointer (task, error);
1122
1123
0
  if (length && line)
1124
0
    {
1125
0
      GDataInputStreamReadData *data = g_task_get_task_data (task);
1126
1127
0
      *length = data->length;
1128
0
    }
1129
1130
0
  return line;
1131
0
}
1132
1133
/**
1134
 * g_data_input_stream_read_line_async:
1135
 * @stream: a given #GDataInputStream.
1136
 * @io_priority: the [I/O priority](iface.AsyncResult.html#io-priority) of the request
1137
 * @cancellable: (nullable): optional #GCancellable object, %NULL to ignore.
1138
 * @callback: (scope async) (closure user_data): callback to call when the request is satisfied.
1139
 * @user_data: the data to pass to callback function.
1140
 *
1141
 * The asynchronous version of g_data_input_stream_read_line().  It is
1142
 * an error to have two outstanding calls to this function.
1143
 *
1144
 * When the operation is finished, @callback will be called. You
1145
 * can then call g_data_input_stream_read_line_finish() to get
1146
 * the result of the operation.
1147
 *
1148
 * Since: 2.20
1149
 */
1150
void
1151
g_data_input_stream_read_line_async (GDataInputStream    *stream,
1152
                                     gint                 io_priority,
1153
                                     GCancellable        *cancellable,
1154
                                     GAsyncReadyCallback  callback,
1155
                                     gpointer             user_data)
1156
0
{
1157
0
  g_return_if_fail (G_IS_DATA_INPUT_STREAM (stream));
1158
0
  g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
1159
1160
0
  g_data_input_stream_read_async (stream, NULL, 0, io_priority,
1161
0
                                  cancellable, callback, user_data);
1162
0
}
1163
1164
/**
1165
 * g_data_input_stream_read_until_async:
1166
 * @stream: a given #GDataInputStream.
1167
 * @stop_chars: characters to terminate the read.
1168
 * @io_priority: the [I/O priority](iface.AsyncResult.html#io-priority) of the request
1169
 * @cancellable: (nullable): optional #GCancellable object, %NULL to ignore.
1170
 * @callback: (scope async): callback to call when the request is satisfied.
1171
 * @user_data: (closure): the data to pass to callback function.
1172
 *
1173
 * The asynchronous version of g_data_input_stream_read_until().
1174
 * It is an error to have two outstanding calls to this function.
1175
 *
1176
 * Note that, in contrast to g_data_input_stream_read_until(),
1177
 * this function does not consume the stop character that it finds.  You
1178
 * must read it for yourself.
1179
 *
1180
 * When the operation is finished, @callback will be called. You
1181
 * can then call g_data_input_stream_read_until_finish() to get
1182
 * the result of the operation.
1183
 *
1184
 * Don't use this function in new code.  Its functionality is
1185
 * inconsistent with g_data_input_stream_read_until().  Both functions
1186
 * will be marked as deprecated in a future release.  Use
1187
 * g_data_input_stream_read_upto_async() instead.
1188
 *
1189
 * Since: 2.20
1190
 * Deprecated: 2.56: Use g_data_input_stream_read_upto_async() instead, which
1191
 *     has more consistent behaviour regarding the stop character.
1192
 */
1193
void
1194
g_data_input_stream_read_until_async (GDataInputStream    *stream,
1195
                                      const gchar         *stop_chars,
1196
                                      gint                 io_priority,
1197
                                      GCancellable        *cancellable,
1198
                                      GAsyncReadyCallback  callback,
1199
                                      gpointer             user_data)
1200
0
{
1201
0
  g_return_if_fail (G_IS_DATA_INPUT_STREAM (stream));
1202
0
  g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
1203
0
  g_return_if_fail (stop_chars != NULL);
1204
1205
0
  g_data_input_stream_read_async (stream, stop_chars, -1, io_priority,
1206
0
                                  cancellable, callback, user_data);
1207
0
}
1208
1209
/**
1210
 * g_data_input_stream_read_line_finish:
1211
 * @stream: a given #GDataInputStream.
1212
 * @result: the #GAsyncResult that was provided to the callback.
1213
 * @length: (out) (optional): a #gsize to get the length of the data read in.
1214
 * @error: #GError for error reporting.
1215
 *
1216
 * Finish an asynchronous call started by
1217
 * g_data_input_stream_read_line_async().  Note the warning about
1218
 * string encoding in g_data_input_stream_read_line() applies here as
1219
 * well.
1220
 *
1221
 * Returns: (nullable) (transfer full) (array zero-terminated=1) (element-type guint8):
1222
 *  a NUL-terminated byte array with the line that was read in
1223
 *  (without the newlines).  Set @length to a #gsize to get the length
1224
 *  of the read line.  On an error, it will return %NULL and @error
1225
 *  will be set. If there's no content to read, it will still return
1226
 *  %NULL, but @error won't be set.
1227
 *
1228
 * Since: 2.20
1229
 */
1230
gchar *
1231
g_data_input_stream_read_line_finish (GDataInputStream  *stream,
1232
                                      GAsyncResult      *result,
1233
                                      gsize             *length,
1234
                                      GError           **error)
1235
0
{
1236
0
  g_return_val_if_fail (g_task_is_valid (result, stream), NULL);
1237
1238
0
  return g_data_input_stream_read_finish (stream, result, length, error);
1239
0
}
1240
1241
/**
1242
 * g_data_input_stream_read_line_finish_utf8:
1243
 * @stream: a given #GDataInputStream.
1244
 * @result: the #GAsyncResult that was provided to the callback.
1245
 * @length: (out) (optional): a #gsize to get the length of the data read in.
1246
 * @error: #GError for error reporting.
1247
 *
1248
 * Finish an asynchronous call started by
1249
 * g_data_input_stream_read_line_async().
1250
 *
1251
 * Returns: (nullable) (transfer full): a string with the line that
1252
 *  was read in (without the newlines).  Set @length to a #gsize to
1253
 *  get the length of the read line.  On an error, it will return
1254
 *  %NULL and @error will be set. For UTF-8 conversion errors, the set
1255
 *  error domain is %G_CONVERT_ERROR.  If there's no content to read,
1256
 *  it will still return %NULL, but @error won't be set.
1257
 *
1258
 * Since: 2.30
1259
 */
1260
gchar *
1261
g_data_input_stream_read_line_finish_utf8 (GDataInputStream  *stream,
1262
             GAsyncResult      *result,
1263
             gsize             *length,
1264
             GError           **error)
1265
0
{
1266
0
  gchar *res;
1267
1268
0
  res = g_data_input_stream_read_line_finish (stream, result, length, error);
1269
0
  if (!res)
1270
0
    return NULL;
1271
1272
0
  if (!g_utf8_validate (res, -1, NULL))
1273
0
    {
1274
0
      g_set_error_literal (error, G_CONVERT_ERROR,
1275
0
         G_CONVERT_ERROR_ILLEGAL_SEQUENCE,
1276
0
         _("Invalid byte sequence in conversion input"));
1277
0
      g_free (res);
1278
0
      return NULL;
1279
0
    }
1280
0
  return res;
1281
0
}
1282
1283
/**
1284
 * g_data_input_stream_read_until_finish:
1285
 * @stream: a given #GDataInputStream.
1286
 * @result: the #GAsyncResult that was provided to the callback.
1287
 * @length: (out) (optional): a #gsize to get the length of the data read in.
1288
 * @error: #GError for error reporting.
1289
 *
1290
 * Finish an asynchronous call started by
1291
 * g_data_input_stream_read_until_async().
1292
 *
1293
 * Since: 2.20
1294
 *
1295
 * Returns: (transfer full): a string with the data that was read
1296
 *     before encountering any of the stop characters. Set @length to
1297
 *     a #gsize to get the length of the string. This function will
1298
 *     return %NULL on an error.
1299
 * Deprecated: 2.56: Use g_data_input_stream_read_upto_finish() instead, which
1300
 *     has more consistent behaviour regarding the stop character.
1301
 */
1302
gchar *
1303
g_data_input_stream_read_until_finish (GDataInputStream  *stream,
1304
                                       GAsyncResult      *result,
1305
                                       gsize             *length,
1306
                                       GError           **error)
1307
0
{
1308
0
  g_return_val_if_fail (g_task_is_valid (result, stream), NULL);
1309
1310
0
  return g_data_input_stream_read_finish (stream, result, length, error);
1311
0
}
1312
1313
/**
1314
 * g_data_input_stream_read_upto:
1315
 * @stream: a #GDataInputStream
1316
 * @stop_chars: characters to terminate the read
1317
 * @stop_chars_len: length of @stop_chars. May be -1 if @stop_chars is
1318
 *     nul-terminated
1319
 * @length: (out) (optional): a #gsize to get the length of the data read in
1320
 * @cancellable: (nullable): optional #GCancellable object, %NULL to ignore
1321
 * @error: #GError for error reporting
1322
 *
1323
 * Reads a string from the data input stream, up to the first
1324
 * occurrence of any of the stop characters.
1325
 *
1326
 * In contrast to g_data_input_stream_read_until(), this function
1327
 * does not consume the stop character. You have to use
1328
 * g_data_input_stream_read_byte() to get it before calling
1329
 * g_data_input_stream_read_upto() again.
1330
 *
1331
 * Note that @stop_chars may contain '\0' if @stop_chars_len is
1332
 * specified.
1333
 *
1334
 * The returned string will always be nul-terminated on success.
1335
 *
1336
 * Returns: (transfer full): a string with the data that was read
1337
 *     before encountering any of the stop characters. Set @length to
1338
 *     a #gsize to get the length of the string. This function will
1339
 *     return %NULL on an error
1340
 *
1341
 * Since: 2.26
1342
 */
1343
char *
1344
g_data_input_stream_read_upto (GDataInputStream  *stream,
1345
                               const gchar       *stop_chars,
1346
                               gssize             stop_chars_len,
1347
                               gsize             *length,
1348
                               GCancellable      *cancellable,
1349
                               GError           **error)
1350
0
{
1351
0
  GBufferedInputStream *bstream;
1352
0
  gsize checked;
1353
0
  gssize found_pos;
1354
0
  gssize res;
1355
0
  char *data_until;
1356
0
  gsize stop_chars_len_unsigned;
1357
1358
0
  g_return_val_if_fail (G_IS_DATA_INPUT_STREAM (stream), NULL);
1359
1360
0
  if (stop_chars_len < 0)
1361
0
    stop_chars_len_unsigned = strlen (stop_chars);
1362
0
  else
1363
0
    stop_chars_len_unsigned = (gsize) stop_chars_len;
1364
1365
0
  bstream = G_BUFFERED_INPUT_STREAM (stream);
1366
1367
0
  checked = 0;
1368
1369
0
  while ((found_pos = scan_for_chars (stream, &checked, stop_chars, stop_chars_len_unsigned)) == -1)
1370
0
    {
1371
0
      if (g_buffered_input_stream_get_available (bstream) ==
1372
0
          g_buffered_input_stream_get_buffer_size (bstream))
1373
0
        g_buffered_input_stream_set_buffer_size (bstream,
1374
0
                                                 2 * g_buffered_input_stream_get_buffer_size (bstream));
1375
1376
0
      res = g_buffered_input_stream_fill (bstream, -1, cancellable, error);
1377
0
      if (res < 0)
1378
0
        return NULL;
1379
0
      if (res == 0)
1380
0
        {
1381
          /* End of stream */
1382
0
          if (g_buffered_input_stream_get_available (bstream) == 0)
1383
0
            {
1384
0
              if (length)
1385
0
                *length = 0;
1386
0
              return NULL;
1387
0
            }
1388
0
          else
1389
0
            {
1390
0
              found_pos = checked;
1391
0
              break;
1392
0
            }
1393
0
        }
1394
0
    }
1395
1396
0
  data_until = g_malloc (found_pos + 1);
1397
1398
0
  res = g_input_stream_read (G_INPUT_STREAM (stream),
1399
0
                             data_until,
1400
0
                             found_pos,
1401
0
                             NULL, NULL);
1402
0
  if (length)
1403
0
    *length = (gsize)found_pos;
1404
0
  g_warn_if_fail (res == found_pos);
1405
0
  data_until[found_pos] = 0;
1406
1407
0
  return data_until;
1408
0
}
1409
1410
/**
1411
 * g_data_input_stream_read_upto_async:
1412
 * @stream: a #GDataInputStream
1413
 * @stop_chars: characters to terminate the read
1414
 * @stop_chars_len: length of @stop_chars. May be -1 if @stop_chars is
1415
 *     nul-terminated
1416
 * @io_priority: the [I/O priority](iface.AsyncResult.html#io-priority) of the request
1417
 * @cancellable: (nullable): optional #GCancellable object, %NULL to ignore
1418
 * @callback: (scope async): callback to call when the request is satisfied
1419
 * @user_data: (closure): the data to pass to callback function
1420
 *
1421
 * The asynchronous version of g_data_input_stream_read_upto().
1422
 * It is an error to have two outstanding calls to this function.
1423
 *
1424
 * In contrast to g_data_input_stream_read_until(), this function
1425
 * does not consume the stop character. You have to use
1426
 * g_data_input_stream_read_byte() to get it before calling
1427
 * g_data_input_stream_read_upto() again.
1428
 *
1429
 * Note that @stop_chars may contain '\0' if @stop_chars_len is
1430
 * specified.
1431
 *
1432
 * When the operation is finished, @callback will be called. You
1433
 * can then call g_data_input_stream_read_upto_finish() to get
1434
 * the result of the operation.
1435
 *
1436
 * Since: 2.26
1437
 */
1438
void
1439
g_data_input_stream_read_upto_async (GDataInputStream    *stream,
1440
                                     const gchar         *stop_chars,
1441
                                     gssize               stop_chars_len,
1442
                                     gint                 io_priority,
1443
                                     GCancellable        *cancellable,
1444
                                     GAsyncReadyCallback  callback,
1445
                                     gpointer             user_data)
1446
0
{
1447
0
  g_return_if_fail (G_IS_DATA_INPUT_STREAM (stream));
1448
0
  g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
1449
0
  g_return_if_fail (stop_chars != NULL);
1450
1451
0
  g_data_input_stream_read_async (stream, stop_chars, stop_chars_len, io_priority,
1452
0
                                  cancellable, callback, user_data);
1453
0
}
1454
1455
/**
1456
 * g_data_input_stream_read_upto_finish:
1457
 * @stream: a #GDataInputStream
1458
 * @result: the #GAsyncResult that was provided to the callback
1459
 * @length: (out) (optional): a #gsize to get the length of the data read in
1460
 * @error: #GError for error reporting
1461
 *
1462
 * Finish an asynchronous call started by
1463
 * g_data_input_stream_read_upto_async().
1464
 *
1465
 * Note that this function does not consume the stop character. You
1466
 * have to use g_data_input_stream_read_byte() to get it before calling
1467
 * g_data_input_stream_read_upto_async() again.
1468
 *
1469
 * The returned string will always be nul-terminated on success.
1470
 *
1471
 * Returns: (transfer full): a string with the data that was read
1472
 *     before encountering any of the stop characters. Set @length to
1473
 *     a #gsize to get the length of the string. This function will
1474
 *     return %NULL on an error.
1475
 *
1476
 * Since: 2.24
1477
 */
1478
gchar *
1479
g_data_input_stream_read_upto_finish (GDataInputStream  *stream,
1480
                                      GAsyncResult      *result,
1481
                                      gsize             *length,
1482
                                      GError           **error)
1483
0
{
1484
0
  g_return_val_if_fail (g_task_is_valid (result, stream), NULL);
1485
1486
0
  return g_data_input_stream_read_finish (stream, result, length, error);
1487
0
}