Coverage Report

Created: 2025-07-01 07:09

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