Coverage Report

Created: 2025-07-12 06:30

/src/tinysparql/subprojects/glib-2.80.3/gio/gbufferedinputstream.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
 *
6
 * SPDX-License-Identifier: LGPL-2.1-or-later
7
 *
8
 * This library is free software; you can redistribute it and/or
9
 * modify it under the terms of the GNU Lesser General Public
10
 * License as published by the Free Software Foundation; either
11
 * version 2.1 of the License, or (at your option) any later version.
12
 *
13
 * This library is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16
 * Lesser General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU Lesser General
19
 * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
20
 *
21
 * Author: Christian Kellner <gicmo@gnome.org>
22
 */
23
24
#include "config.h"
25
#include "gbufferedinputstream.h"
26
#include "ginputstream.h"
27
#include "gcancellable.h"
28
#include "gasyncresult.h"
29
#include "gtask.h"
30
#include "gseekable.h"
31
#include "gioerror.h"
32
#include <string.h>
33
#include "glibintl.h"
34
35
36
/**
37
 * GBufferedInputStream:
38
 *
39
 * Buffered input stream implements #GFilterInputStream and provides
40
 * for buffered reads.
41
 *
42
 * By default, `GBufferedInputStream`'s buffer size is set at 4 kilobytes.
43
 *
44
 * To create a buffered input stream, use [ctor@Gio.BufferedInputStream.new],
45
 * or [ctor@Gio.BufferedInputStream.new_sized] to specify the buffer's size at
46
 * construction.
47
 *
48
 * To get the size of a buffer within a buffered input stream, use
49
 * [method@Gio.BufferedInputStream.get_buffer_size]. To change the size of a
50
 * buffered input stream's buffer, use [method@Gio.BufferedInputStream.set_buffer_size].
51
 * Note that the buffer's size cannot be reduced below the size of the data within the buffer.
52
 */
53
54
55
1
#define DEFAULT_BUFFER_SIZE 4096
56
57
struct _GBufferedInputStreamPrivate {
58
  guint8 *buffer;
59
  gsize   len;
60
  gsize   pos;
61
  gsize   end;
62
  GAsyncReadyCallback outstanding_callback;
63
};
64
65
enum {
66
  PROP_0,
67
  PROP_BUFSIZE
68
};
69
70
static void g_buffered_input_stream_set_property  (GObject      *object,
71
                                                   guint         prop_id,
72
                                                   const GValue *value,
73
                                                   GParamSpec   *pspec);
74
75
static void g_buffered_input_stream_get_property  (GObject      *object,
76
                                                   guint         prop_id,
77
                                                   GValue       *value,
78
                                                   GParamSpec   *pspec);
79
static void g_buffered_input_stream_finalize      (GObject *object);
80
81
82
static gssize g_buffered_input_stream_skip             (GInputStream          *stream,
83
                                                        gsize                  count,
84
                                                        GCancellable          *cancellable,
85
                                                        GError               **error);
86
static void   g_buffered_input_stream_skip_async       (GInputStream          *stream,
87
                                                        gsize                  count,
88
                                                        int                    io_priority,
89
                                                        GCancellable          *cancellable,
90
                                                        GAsyncReadyCallback    callback,
91
                                                        gpointer               user_data);
92
static gssize g_buffered_input_stream_skip_finish      (GInputStream          *stream,
93
                                                        GAsyncResult          *result,
94
                                                        GError               **error);
95
static gssize g_buffered_input_stream_read             (GInputStream          *stream,
96
                                                        void                  *buffer,
97
                                                        gsize                  count,
98
                                                        GCancellable          *cancellable,
99
                                                        GError               **error);
100
static gssize g_buffered_input_stream_real_fill        (GBufferedInputStream  *stream,
101
                                                        gssize                 count,
102
                                                        GCancellable          *cancellable,
103
                                                        GError               **error);
104
static void   g_buffered_input_stream_real_fill_async  (GBufferedInputStream  *stream,
105
                                                        gssize                 count,
106
                                                        int                    io_priority,
107
                                                        GCancellable          *cancellable,
108
                                                        GAsyncReadyCallback    callback,
109
                                                        gpointer               user_data);
110
static gssize g_buffered_input_stream_real_fill_finish (GBufferedInputStream  *stream,
111
                                                        GAsyncResult          *result,
112
                                                        GError               **error);
113
114
static void     g_buffered_input_stream_seekable_iface_init (GSeekableIface  *iface);
115
static goffset  g_buffered_input_stream_tell                (GSeekable       *seekable);
116
static gboolean g_buffered_input_stream_can_seek            (GSeekable       *seekable);
117
static gboolean g_buffered_input_stream_seek                (GSeekable       *seekable,
118
                   goffset          offset,
119
                   GSeekType        type,
120
                   GCancellable    *cancellable,
121
                   GError         **error);
122
static gboolean g_buffered_input_stream_can_truncate        (GSeekable       *seekable);
123
static gboolean g_buffered_input_stream_truncate            (GSeekable       *seekable,
124
                   goffset          offset,
125
                   GCancellable    *cancellable,
126
                   GError         **error);
127
128
static void compact_buffer (GBufferedInputStream *stream);
129
130
G_DEFINE_TYPE_WITH_CODE (GBufferedInputStream,
131
       g_buffered_input_stream,
132
       G_TYPE_FILTER_INPUT_STREAM,
133
                         G_ADD_PRIVATE (GBufferedInputStream)
134
       G_IMPLEMENT_INTERFACE (G_TYPE_SEEKABLE,
135
            g_buffered_input_stream_seekable_iface_init))
136
137
static void
138
g_buffered_input_stream_class_init (GBufferedInputStreamClass *klass)
139
1
{
140
1
  GObjectClass *object_class;
141
1
  GInputStreamClass *istream_class;
142
1
  GBufferedInputStreamClass *bstream_class;
143
144
1
  object_class = G_OBJECT_CLASS (klass);
145
1
  object_class->get_property = g_buffered_input_stream_get_property;
146
1
  object_class->set_property = g_buffered_input_stream_set_property;
147
1
  object_class->finalize     = g_buffered_input_stream_finalize;
148
149
1
  istream_class = G_INPUT_STREAM_CLASS (klass);
150
1
  istream_class->skip = g_buffered_input_stream_skip;
151
1
  istream_class->skip_async  = g_buffered_input_stream_skip_async;
152
1
  istream_class->skip_finish = g_buffered_input_stream_skip_finish;
153
1
  istream_class->read_fn = g_buffered_input_stream_read;
154
155
1
  bstream_class = G_BUFFERED_INPUT_STREAM_CLASS (klass);
156
1
  bstream_class->fill = g_buffered_input_stream_real_fill;
157
1
  bstream_class->fill_async = g_buffered_input_stream_real_fill_async;
158
1
  bstream_class->fill_finish = g_buffered_input_stream_real_fill_finish;
159
160
  /**
161
   * GBufferedInputStream:buffer-size:
162
   *
163
   * The size of the backend buffer, in bytes.
164
   */
165
1
  g_object_class_install_property (object_class,
166
1
                                   PROP_BUFSIZE,
167
1
                                   g_param_spec_uint ("buffer-size", NULL, NULL,
168
1
                                                      1,
169
1
                                                      G_MAXUINT,
170
1
                                                      DEFAULT_BUFFER_SIZE,
171
1
                                                      G_PARAM_READWRITE | G_PARAM_CONSTRUCT |
172
1
                                                      G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB));
173
174
175
1
}
176
177
/**
178
 * g_buffered_input_stream_get_buffer_size:
179
 * @stream: a #GBufferedInputStream
180
 *
181
 * Gets the size of the input buffer.
182
 *
183
 * Returns: the current buffer size.
184
 */
185
gsize
186
g_buffered_input_stream_get_buffer_size (GBufferedInputStream  *stream)
187
0
{
188
0
  g_return_val_if_fail (G_IS_BUFFERED_INPUT_STREAM (stream), 0);
189
190
0
  return stream->priv->len;
191
0
}
192
193
/**
194
 * g_buffered_input_stream_set_buffer_size:
195
 * @stream: a #GBufferedInputStream
196
 * @size: a #gsize
197
 *
198
 * Sets the size of the internal buffer of @stream to @size, or to the
199
 * size of the contents of the buffer. The buffer can never be resized
200
 * smaller than its current contents.
201
 */
202
void
203
g_buffered_input_stream_set_buffer_size (GBufferedInputStream *stream,
204
                                         gsize                 size)
205
8
{
206
8
  GBufferedInputStreamPrivate *priv;
207
8
  gsize in_buffer;
208
8
  guint8 *buffer;
209
210
8
  g_return_if_fail (G_IS_BUFFERED_INPUT_STREAM (stream));
211
212
8
  priv = stream->priv;
213
214
8
  if (priv->len == size)
215
0
    return;
216
217
8
  if (priv->buffer)
218
0
    {
219
0
      in_buffer = priv->end - priv->pos;
220
221
      /* Never resize smaller than current buffer contents */
222
0
      size = MAX (size, in_buffer);
223
224
0
      buffer = g_malloc (size);
225
0
      memcpy (buffer, priv->buffer + priv->pos, in_buffer);
226
0
      priv->len = size;
227
0
      priv->pos = 0;
228
0
      priv->end = in_buffer;
229
0
      g_free (priv->buffer);
230
0
      priv->buffer = buffer;
231
0
    }
232
8
  else
233
8
    {
234
8
      priv->len = size;
235
8
      priv->pos = 0;
236
8
      priv->end = 0;
237
8
      priv->buffer = g_malloc (size);
238
8
    }
239
240
8
  g_object_notify (G_OBJECT (stream), "buffer-size");
241
8
}
242
243
static void
244
g_buffered_input_stream_set_property (GObject      *object,
245
                                      guint         prop_id,
246
                                      const GValue *value,
247
                                      GParamSpec   *pspec)
248
8
{
249
8
  GBufferedInputStream        *bstream;
250
251
8
  bstream = G_BUFFERED_INPUT_STREAM (object);
252
253
8
  switch (prop_id)
254
8
    {
255
8
    case PROP_BUFSIZE:
256
8
      g_buffered_input_stream_set_buffer_size (bstream, g_value_get_uint (value));
257
8
      break;
258
259
0
    default:
260
0
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
261
0
      break;
262
8
    }
263
8
}
264
265
static void
266
g_buffered_input_stream_get_property (GObject    *object,
267
                                      guint       prop_id,
268
                                      GValue     *value,
269
                                      GParamSpec *pspec)
270
0
{
271
0
  GBufferedInputStreamPrivate *priv;
272
0
  GBufferedInputStream        *bstream;
273
274
0
  bstream = G_BUFFERED_INPUT_STREAM (object);
275
0
  priv = bstream->priv;
276
277
0
  switch (prop_id)
278
0
    {
279
0
    case PROP_BUFSIZE:
280
0
      g_value_set_uint (value, priv->len);
281
0
      break;
282
283
0
    default:
284
0
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
285
0
      break;
286
0
    }
287
0
}
288
289
static void
290
g_buffered_input_stream_finalize (GObject *object)
291
8
{
292
8
  GBufferedInputStreamPrivate *priv;
293
8
  GBufferedInputStream        *stream;
294
295
8
  stream = G_BUFFERED_INPUT_STREAM (object);
296
8
  priv = stream->priv;
297
298
8
  g_free (priv->buffer);
299
300
8
  G_OBJECT_CLASS (g_buffered_input_stream_parent_class)->finalize (object);
301
8
}
302
303
static void
304
g_buffered_input_stream_seekable_iface_init (GSeekableIface *iface)
305
1
{
306
1
  iface->tell         = g_buffered_input_stream_tell;
307
1
  iface->can_seek     = g_buffered_input_stream_can_seek;
308
1
  iface->seek         = g_buffered_input_stream_seek;
309
1
  iface->can_truncate = g_buffered_input_stream_can_truncate;
310
1
  iface->truncate_fn  = g_buffered_input_stream_truncate;
311
1
}
312
313
static void
314
g_buffered_input_stream_init (GBufferedInputStream *stream)
315
8
{
316
8
  stream->priv = g_buffered_input_stream_get_instance_private (stream);
317
8
}
318
319
320
/**
321
 * g_buffered_input_stream_new:
322
 * @base_stream: a #GInputStream
323
 *
324
 * Creates a new #GInputStream from the given @base_stream, with
325
 * a buffer set to the default size (4 kilobytes).
326
 *
327
 * Returns: a #GInputStream for the given @base_stream.
328
 */
329
GInputStream *
330
g_buffered_input_stream_new (GInputStream *base_stream)
331
8
{
332
8
  GInputStream *stream;
333
334
8
  g_return_val_if_fail (G_IS_INPUT_STREAM (base_stream), NULL);
335
336
8
  stream = g_object_new (G_TYPE_BUFFERED_INPUT_STREAM,
337
8
                         "base-stream", base_stream,
338
8
                         NULL);
339
340
8
  return stream;
341
8
}
342
343
/**
344
 * g_buffered_input_stream_new_sized:
345
 * @base_stream: a #GInputStream
346
 * @size: a #gsize
347
 *
348
 * Creates a new #GBufferedInputStream from the given @base_stream,
349
 * with a buffer set to @size.
350
 *
351
 * Returns: a #GInputStream.
352
 */
353
GInputStream *
354
g_buffered_input_stream_new_sized (GInputStream *base_stream,
355
                                   gsize         size)
356
0
{
357
0
  GInputStream *stream;
358
359
0
  g_return_val_if_fail (G_IS_INPUT_STREAM (base_stream), NULL);
360
361
0
  stream = g_object_new (G_TYPE_BUFFERED_INPUT_STREAM,
362
0
                         "base-stream", base_stream,
363
0
                         "buffer-size", (guint)size,
364
0
                         NULL);
365
366
0
  return stream;
367
0
}
368
369
/**
370
 * g_buffered_input_stream_fill:
371
 * @stream: a #GBufferedInputStream
372
 * @count: the number of bytes that will be read from the stream
373
 * @cancellable: (nullable): optional #GCancellable object, %NULL to ignore
374
 * @error: location to store the error occurring, or %NULL to ignore
375
 *
376
 * Tries to read @count bytes from the stream into the buffer.
377
 * Will block during this read.
378
 *
379
 * If @count is zero, returns zero and does nothing. A value of @count
380
 * larger than %G_MAXSSIZE will cause a %G_IO_ERROR_INVALID_ARGUMENT error.
381
 *
382
 * On success, the number of bytes read into the buffer is returned.
383
 * It is not an error if this is not the same as the requested size, as it
384
 * can happen e.g. near the end of a file. Zero is returned on end of file
385
 * (or if @count is zero),  but never otherwise.
386
 *
387
 * If @count is -1 then the attempted read size is equal to the number of
388
 * bytes that are required to fill the buffer.
389
 *
390
 * If @cancellable is not %NULL, then the operation can be cancelled by
391
 * triggering the cancellable object from another thread. If the operation
392
 * was cancelled, the error %G_IO_ERROR_CANCELLED will be returned. If an
393
 * operation was partially finished when the operation was cancelled the
394
 * partial result will be returned, without an error.
395
 *
396
 * On error -1 is returned and @error is set accordingly.
397
 *
398
 * For the asynchronous, non-blocking, version of this function, see
399
 * g_buffered_input_stream_fill_async().
400
 *
401
 * Returns: the number of bytes read into @stream's buffer, up to @count,
402
 *     or -1 on error.
403
 */
404
gssize
405
g_buffered_input_stream_fill (GBufferedInputStream  *stream,
406
                              gssize                 count,
407
                              GCancellable          *cancellable,
408
                              GError               **error)
409
2.15k
{
410
2.15k
  GBufferedInputStreamClass *class;
411
2.15k
  GInputStream *input_stream;
412
2.15k
  gssize res;
413
414
2.15k
  g_return_val_if_fail (G_IS_BUFFERED_INPUT_STREAM (stream), -1);
415
416
2.15k
  input_stream = G_INPUT_STREAM (stream);
417
418
2.15k
  if (count < -1)
419
0
    {
420
0
      g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT,
421
0
                   _("Too large count value passed to %s"), G_STRFUNC);
422
0
      return -1;
423
0
    }
424
425
2.15k
  if (!g_input_stream_set_pending (input_stream, error))
426
0
    return -1;
427
428
2.15k
  if (cancellable)
429
0
    g_cancellable_push_current (cancellable);
430
431
2.15k
  class = G_BUFFERED_INPUT_STREAM_GET_CLASS (stream);
432
2.15k
  res = class->fill (stream, count, cancellable, error);
433
434
2.15k
  if (cancellable)
435
0
    g_cancellable_pop_current (cancellable);
436
437
2.15k
  g_input_stream_clear_pending (input_stream);
438
439
2.15k
  return res;
440
2.15k
}
441
442
static void
443
async_fill_callback_wrapper (GObject      *source_object,
444
                             GAsyncResult *res,
445
                             gpointer      user_data)
446
0
{
447
0
  GBufferedInputStream *stream = G_BUFFERED_INPUT_STREAM (source_object);
448
449
0
  g_input_stream_clear_pending (G_INPUT_STREAM (stream));
450
0
  (*stream->priv->outstanding_callback) (source_object, res, user_data);
451
0
  g_object_unref (stream);
452
0
}
453
454
/**
455
 * g_buffered_input_stream_fill_async:
456
 * @stream: a #GBufferedInputStream
457
 * @count: the number of bytes that will be read from the stream
458
 * @io_priority: the [I/O priority][io-priority] of the request
459
 * @cancellable: (nullable): optional #GCancellable object
460
 * @callback: (scope async) (closure user_data): a #GAsyncReadyCallback
461
 * @user_data: a #gpointer
462
 *
463
 * Reads data into @stream's buffer asynchronously, up to @count size.
464
 * @io_priority can be used to prioritize reads. For the synchronous
465
 * version of this function, see g_buffered_input_stream_fill().
466
 *
467
 * If @count is -1 then the attempted read size is equal to the number
468
 * of bytes that are required to fill the buffer.
469
 */
470
void
471
g_buffered_input_stream_fill_async (GBufferedInputStream *stream,
472
                                    gssize                count,
473
                                    int                   io_priority,
474
                                    GCancellable         *cancellable,
475
                                    GAsyncReadyCallback   callback,
476
                                    gpointer              user_data)
477
0
{
478
0
  GBufferedInputStreamClass *class;
479
0
  GError *error = NULL;
480
481
0
  g_return_if_fail (G_IS_BUFFERED_INPUT_STREAM (stream));
482
483
0
  if (count == 0)
484
0
    {
485
0
      GTask *task;
486
487
0
      task = g_task_new (stream, cancellable, callback, user_data);
488
0
      g_task_set_source_tag (task, g_buffered_input_stream_fill_async);
489
0
      g_task_return_int (task, 0);
490
0
      g_object_unref (task);
491
0
      return;
492
0
    }
493
494
0
  if (count < -1)
495
0
    {
496
0
      g_task_report_new_error (stream, callback, user_data,
497
0
                               g_buffered_input_stream_fill_async,
498
0
                               G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT,
499
0
             _("Too large count value passed to %s"),
500
0
             G_STRFUNC);
501
0
      return;
502
0
    }
503
504
0
  if (!g_input_stream_set_pending (G_INPUT_STREAM (stream), &error))
505
0
    {
506
0
      g_task_report_error (stream, callback, user_data,
507
0
                           g_buffered_input_stream_fill_async,
508
0
                           error);
509
0
      return;
510
0
    }
511
512
0
  class = G_BUFFERED_INPUT_STREAM_GET_CLASS (stream);
513
514
0
  stream->priv->outstanding_callback = callback;
515
0
  g_object_ref (stream);
516
0
  class->fill_async (stream, count, io_priority, cancellable,
517
0
                     async_fill_callback_wrapper, user_data);
518
0
}
519
520
/**
521
 * g_buffered_input_stream_fill_finish:
522
 * @stream: a #GBufferedInputStream
523
 * @result: a #GAsyncResult
524
 * @error: a #GError
525
 *
526
 * Finishes an asynchronous read.
527
 *
528
 * Returns: a #gssize of the read stream, or `-1` on an error.
529
 */
530
gssize
531
g_buffered_input_stream_fill_finish (GBufferedInputStream  *stream,
532
                                     GAsyncResult          *result,
533
                                     GError               **error)
534
0
{
535
0
  GBufferedInputStreamClass *class;
536
537
0
  g_return_val_if_fail (G_IS_BUFFERED_INPUT_STREAM (stream), -1);
538
0
  g_return_val_if_fail (G_IS_ASYNC_RESULT (result), -1);
539
540
0
  if (g_async_result_legacy_propagate_error (result, error))
541
0
    return -1;
542
0
  else if (g_async_result_is_tagged (result, g_buffered_input_stream_fill_async))
543
0
    return g_task_propagate_int (G_TASK (result), error);
544
545
0
  class = G_BUFFERED_INPUT_STREAM_GET_CLASS (stream);
546
0
  return class->fill_finish (stream, result, error);
547
0
}
548
549
/**
550
 * g_buffered_input_stream_get_available:
551
 * @stream: #GBufferedInputStream
552
 *
553
 * Gets the size of the available data within the stream.
554
 *
555
 * Returns: size of the available stream.
556
 */
557
gsize
558
g_buffered_input_stream_get_available (GBufferedInputStream *stream)
559
2.28k
{
560
2.28k
  g_return_val_if_fail (G_IS_BUFFERED_INPUT_STREAM (stream), -1);
561
562
2.28k
  return stream->priv->end - stream->priv->pos;
563
2.28k
}
564
565
/**
566
 * g_buffered_input_stream_peek:
567
 * @stream: a #GBufferedInputStream
568
 * @buffer: (array length=count) (element-type guint8): a pointer to
569
 *   an allocated chunk of memory
570
 * @offset: a #gsize
571
 * @count: a #gsize
572
 *
573
 * Peeks in the buffer, copying data of size @count into @buffer,
574
 * offset @offset bytes.
575
 *
576
 * Returns: a #gsize of the number of bytes peeked, or -1 on error.
577
 */
578
gsize
579
g_buffered_input_stream_peek (GBufferedInputStream *stream,
580
                              void                 *buffer,
581
                              gsize                 offset,
582
                              gsize                 count)
583
0
{
584
0
  gsize available;
585
0
  gsize end;
586
587
0
  g_return_val_if_fail (G_IS_BUFFERED_INPUT_STREAM (stream), -1);
588
0
  g_return_val_if_fail (buffer != NULL, -1);
589
590
0
  available = g_buffered_input_stream_get_available (stream);
591
592
0
  if (offset > available)
593
0
    return 0;
594
595
0
  end = MIN (offset + count, available);
596
0
  count = end - offset;
597
598
0
  memcpy (buffer, stream->priv->buffer + stream->priv->pos + offset, count);
599
0
  return count;
600
0
}
601
602
/**
603
 * g_buffered_input_stream_peek_buffer:
604
 * @stream: a #GBufferedInputStream
605
 * @count: (out): a #gsize to get the number of bytes available in the buffer
606
 *
607
 * Returns the buffer with the currently available bytes. The returned
608
 * buffer must not be modified and will become invalid when reading from
609
 * the stream or filling the buffer.
610
 *
611
 * Returns: (array length=count) (element-type guint8) (transfer none):
612
 *          read-only buffer
613
 */
614
const void*
615
g_buffered_input_stream_peek_buffer (GBufferedInputStream *stream,
616
                                     gsize                *count)
617
23.0k
{
618
23.0k
  GBufferedInputStreamPrivate *priv;
619
620
23.0k
  g_return_val_if_fail (G_IS_BUFFERED_INPUT_STREAM (stream), NULL);
621
622
23.0k
  priv = stream->priv;
623
624
23.0k
  if (count)
625
23.0k
    *count = priv->end - priv->pos;
626
627
23.0k
  return priv->buffer + priv->pos;
628
23.0k
}
629
630
static void
631
compact_buffer (GBufferedInputStream *stream)
632
2.01k
{
633
2.01k
  GBufferedInputStreamPrivate *priv;
634
2.01k
  gsize current_size;
635
636
2.01k
  priv = stream->priv;
637
638
2.01k
  current_size = priv->end - priv->pos;
639
640
2.01k
  memmove (priv->buffer, priv->buffer + priv->pos, current_size);
641
642
2.01k
  priv->pos = 0;
643
2.01k
  priv->end = current_size;
644
2.01k
}
645
646
static gssize
647
g_buffered_input_stream_real_fill (GBufferedInputStream  *stream,
648
                                   gssize                 count,
649
                                   GCancellable          *cancellable,
650
                                   GError               **error)
651
2.15k
{
652
2.15k
  GBufferedInputStreamPrivate *priv;
653
2.15k
  GInputStream *base_stream;
654
2.15k
  gssize nread;
655
2.15k
  gsize in_buffer;
656
657
2.15k
  priv = stream->priv;
658
659
2.15k
  if (count == -1)
660
0
    count = priv->len;
661
662
2.15k
  in_buffer = priv->end - priv->pos;
663
664
  /* Never fill more than can fit in the buffer */
665
2.15k
  count = MIN ((gsize) count, priv->len - in_buffer);
666
667
  /* If requested length does not fit at end, compact */
668
2.15k
  if (priv->len - priv->end < (gsize) count)
669
2.01k
    compact_buffer (stream);
670
671
2.15k
  base_stream = G_FILTER_INPUT_STREAM (stream)->base_stream;
672
2.15k
  nread = g_input_stream_read (base_stream,
673
2.15k
                               priv->buffer + priv->end,
674
2.15k
                               count,
675
2.15k
                               cancellable,
676
2.15k
                               error);
677
678
2.15k
  if (nread > 0)
679
10
    priv->end += nread;
680
681
2.15k
  return nread;
682
2.15k
}
683
684
static gssize
685
g_buffered_input_stream_skip (GInputStream  *stream,
686
                              gsize          count,
687
                              GCancellable  *cancellable,
688
                              GError       **error)
689
4.83k
{
690
4.83k
  GBufferedInputStream        *bstream;
691
4.83k
  GBufferedInputStreamPrivate *priv;
692
4.83k
  GBufferedInputStreamClass *class;
693
4.83k
  GInputStream *base_stream;
694
4.83k
  gsize available, bytes_skipped;
695
4.83k
  gssize nread;
696
697
4.83k
  bstream = G_BUFFERED_INPUT_STREAM (stream);
698
4.83k
  priv = bstream->priv;
699
700
4.83k
  available = priv->end - priv->pos;
701
702
4.83k
  if (count <= available)
703
4.83k
    {
704
4.83k
      priv->pos += count;
705
4.83k
      return count;
706
4.83k
    }
707
708
  /* Full request not available, skip all currently available and
709
   * request refill for more
710
   */
711
712
0
  priv->pos = 0;
713
0
  priv->end = 0;
714
0
  bytes_skipped = available;
715
0
  count -= available;
716
717
0
  if (bytes_skipped > 0)
718
0
    error = NULL; /* Ignore further errors if we already read some data */
719
720
0
  if (count > priv->len)
721
0
    {
722
      /* Large request, shortcut buffer */
723
724
0
      base_stream = G_FILTER_INPUT_STREAM (stream)->base_stream;
725
726
0
      nread = g_input_stream_skip (base_stream,
727
0
                                   count,
728
0
                                   cancellable,
729
0
                                   error);
730
731
0
      if (nread < 0 && bytes_skipped == 0)
732
0
        return -1;
733
734
0
      if (nread > 0)
735
0
        bytes_skipped += nread;
736
737
0
      return bytes_skipped;
738
0
    }
739
740
0
  class = G_BUFFERED_INPUT_STREAM_GET_CLASS (stream);
741
0
  nread = class->fill (bstream, priv->len, cancellable, error);
742
743
0
  if (nread < 0)
744
0
    {
745
0
      if (bytes_skipped == 0)
746
0
        return -1;
747
0
      else
748
0
        return bytes_skipped;
749
0
    }
750
751
0
  available = priv->end - priv->pos;
752
0
  count = MIN (count, available);
753
754
0
  bytes_skipped += count;
755
0
  priv->pos += count;
756
757
0
  return bytes_skipped;
758
0
}
759
760
static gssize
761
g_buffered_input_stream_read (GInputStream *stream,
762
                              void         *buffer,
763
                              gsize         count,
764
                              GCancellable *cancellable,
765
                              GError      **error)
766
0
{
767
0
  GBufferedInputStream        *bstream;
768
0
  GBufferedInputStreamPrivate *priv;
769
0
  GBufferedInputStreamClass *class;
770
0
  GInputStream *base_stream;
771
0
  gsize available, bytes_read;
772
0
  gssize nread;
773
774
0
  bstream = G_BUFFERED_INPUT_STREAM (stream);
775
0
  priv = bstream->priv;
776
777
0
  available = priv->end - priv->pos;
778
779
0
  if (count <= available)
780
0
    {
781
0
      memcpy (buffer, priv->buffer + priv->pos, count);
782
0
      priv->pos += count;
783
0
      return count;
784
0
    }
785
786
  /* Full request not available, read all currently available and
787
   * request refill for more
788
   */
789
790
0
  memcpy (buffer, priv->buffer + priv->pos, available);
791
0
  priv->pos = 0;
792
0
  priv->end = 0;
793
0
  bytes_read = available;
794
0
  count -= available;
795
796
0
  if (bytes_read > 0)
797
0
    error = NULL; /* Ignore further errors if we already read some data */
798
799
0
  if (count > priv->len)
800
0
    {
801
      /* Large request, shortcut buffer */
802
803
0
      base_stream = G_FILTER_INPUT_STREAM (stream)->base_stream;
804
805
0
      nread = g_input_stream_read (base_stream,
806
0
                                   (char *)buffer + bytes_read,
807
0
                                   count,
808
0
                                   cancellable,
809
0
                                   error);
810
811
0
      if (nread < 0 && bytes_read == 0)
812
0
        return -1;
813
814
0
      if (nread > 0)
815
0
        bytes_read += nread;
816
817
0
      return bytes_read;
818
0
    }
819
820
0
  class = G_BUFFERED_INPUT_STREAM_GET_CLASS (stream);
821
0
  nread = class->fill (bstream, priv->len, cancellable, error);
822
0
  if (nread < 0)
823
0
    {
824
0
      if (bytes_read == 0)
825
0
        return -1;
826
0
      else
827
0
        return bytes_read;
828
0
    }
829
830
0
  available = priv->end - priv->pos;
831
0
  count = MIN (count, available);
832
833
0
  memcpy ((char *)buffer + bytes_read, (char *)priv->buffer + priv->pos, count);
834
0
  bytes_read += count;
835
0
  priv->pos += count;
836
837
0
  return bytes_read;
838
0
}
839
840
static goffset
841
g_buffered_input_stream_tell (GSeekable *seekable)
842
0
{
843
0
  GBufferedInputStream        *bstream;
844
0
  GBufferedInputStreamPrivate *priv;
845
0
  GInputStream *base_stream;
846
0
  GSeekable    *base_stream_seekable;
847
0
  gsize available;
848
0
  goffset base_offset;
849
  
850
0
  bstream = G_BUFFERED_INPUT_STREAM (seekable);
851
0
  priv = bstream->priv;
852
853
0
  base_stream = G_FILTER_INPUT_STREAM (seekable)->base_stream;
854
0
  if (!G_IS_SEEKABLE (base_stream))
855
0
    return 0;
856
0
  base_stream_seekable = G_SEEKABLE (base_stream);
857
  
858
0
  available = priv->end - priv->pos;
859
0
  base_offset = g_seekable_tell (base_stream_seekable);
860
861
0
  return base_offset - available;
862
0
}
863
864
static gboolean
865
g_buffered_input_stream_can_seek (GSeekable *seekable)
866
0
{
867
0
  GInputStream *base_stream;
868
  
869
0
  base_stream = G_FILTER_INPUT_STREAM (seekable)->base_stream;
870
0
  return G_IS_SEEKABLE (base_stream) && g_seekable_can_seek (G_SEEKABLE (base_stream));
871
0
}
872
873
static gboolean
874
g_buffered_input_stream_seek (GSeekable     *seekable,
875
            goffset        offset,
876
            GSeekType      type,
877
            GCancellable  *cancellable,
878
            GError       **error)
879
0
{
880
0
  GBufferedInputStream        *bstream;
881
0
  GBufferedInputStreamPrivate *priv;
882
0
  GInputStream *base_stream;
883
0
  GSeekable *base_stream_seekable;
884
885
0
  bstream = G_BUFFERED_INPUT_STREAM (seekable);
886
0
  priv = bstream->priv;
887
888
0
  base_stream = G_FILTER_INPUT_STREAM (seekable)->base_stream;
889
0
  if (!G_IS_SEEKABLE (base_stream))
890
0
    {
891
0
      g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
892
0
                           _("Seek not supported on base stream"));
893
0
      return FALSE;
894
0
    }
895
896
0
  base_stream_seekable = G_SEEKABLE (base_stream);
897
  
898
0
  if (type == G_SEEK_CUR)
899
0
    {
900
0
      if (offset <= (goffset) (priv->end - priv->pos) &&
901
0
          offset >= (goffset) -priv->pos)
902
0
  {
903
0
    priv->pos += offset;
904
0
    return TRUE;
905
0
  }
906
0
      else
907
0
  {
908
0
    offset -= priv->end - priv->pos;
909
0
  }
910
0
    }
911
912
0
  if (g_seekable_seek (base_stream_seekable, offset, type, cancellable, error))
913
0
    {
914
0
      priv->pos = 0;
915
0
      priv->end = 0;
916
0
      return TRUE;
917
0
    }
918
0
  else
919
0
    {
920
0
      return FALSE;
921
0
    }
922
0
}
923
924
static gboolean
925
g_buffered_input_stream_can_truncate (GSeekable *seekable)
926
0
{
927
0
  return FALSE;
928
0
}
929
930
static gboolean
931
g_buffered_input_stream_truncate (GSeekable     *seekable,
932
          goffset        offset,
933
          GCancellable  *cancellable,
934
          GError       **error)
935
0
{
936
0
  g_set_error_literal (error,
937
0
           G_IO_ERROR,
938
0
           G_IO_ERROR_NOT_SUPPORTED,
939
0
           _("Cannot truncate GBufferedInputStream"));
940
0
  return FALSE;
941
0
}
942
943
/**
944
 * g_buffered_input_stream_read_byte:
945
 * @stream: a #GBufferedInputStream
946
 * @cancellable: (nullable): optional #GCancellable object, %NULL to ignore
947
 * @error: location to store the error occurring, or %NULL to ignore
948
 *
949
 * Tries to read a single byte from the stream or the buffer. Will block
950
 * during this read.
951
 *
952
 * On success, the byte read from the stream is returned. On end of stream
953
 * -1 is returned but it's not an exceptional error and @error is not set.
954
 *
955
 * If @cancellable is not %NULL, then the operation can be cancelled by
956
 * triggering the cancellable object from another thread. If the operation
957
 * was cancelled, the error %G_IO_ERROR_CANCELLED will be returned. If an
958
 * operation was partially finished when the operation was cancelled the
959
 * partial result will be returned, without an error.
960
 *
961
 * On error -1 is returned and @error is set accordingly.
962
 *
963
 * Returns: the byte read from the @stream, or -1 on end of stream or error.
964
 */
965
int
966
g_buffered_input_stream_read_byte (GBufferedInputStream  *stream,
967
                                   GCancellable          *cancellable,
968
                                   GError               **error)
969
0
{
970
0
  GBufferedInputStreamPrivate *priv;
971
0
  GBufferedInputStreamClass *class;
972
0
  GInputStream *input_stream;
973
0
  gsize available;
974
0
  gssize nread;
975
976
0
  g_return_val_if_fail (G_IS_BUFFERED_INPUT_STREAM (stream), -1);
977
978
0
  priv = stream->priv;
979
0
  input_stream = G_INPUT_STREAM (stream);
980
981
0
  if (g_input_stream_is_closed (input_stream))
982
0
    {
983
0
      g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_CLOSED,
984
0
                           _("Stream is already closed"));
985
0
      return -1;
986
0
    }
987
988
0
  if (!g_input_stream_set_pending (input_stream, error))
989
0
    return -1;
990
991
0
  available = priv->end - priv->pos;
992
993
0
  if (available != 0)
994
0
    {
995
0
      g_input_stream_clear_pending (input_stream);
996
0
      return priv->buffer[priv->pos++];
997
0
    }
998
999
  /* Byte not available, request refill for more */
1000
1001
0
  if (cancellable)
1002
0
    g_cancellable_push_current (cancellable);
1003
1004
0
  priv->pos = 0;
1005
0
  priv->end = 0;
1006
1007
0
  class = G_BUFFERED_INPUT_STREAM_GET_CLASS (stream);
1008
0
  nread = class->fill (stream, priv->len, cancellable, error);
1009
1010
0
  if (cancellable)
1011
0
    g_cancellable_pop_current (cancellable);
1012
1013
0
  g_input_stream_clear_pending (input_stream);
1014
1015
0
  if (nread <= 0)
1016
0
    return -1; /* error or end of stream */
1017
1018
0
  return priv->buffer[priv->pos++];
1019
0
}
1020
1021
/* ************************** */
1022
/* Async stuff implementation */
1023
/* ************************** */
1024
1025
static void
1026
fill_async_callback (GObject      *source_object,
1027
                     GAsyncResult *result,
1028
                     gpointer      user_data)
1029
0
{
1030
0
  GError *error;
1031
0
  gssize res;
1032
0
  GTask *task = user_data;
1033
1034
0
  error = NULL;
1035
0
  res = g_input_stream_read_finish (G_INPUT_STREAM (source_object),
1036
0
                                    result, &error);
1037
0
  if (res == -1)
1038
0
    g_task_return_error (task, error);
1039
0
  else
1040
0
    {
1041
0
      GBufferedInputStream *stream;
1042
0
      GBufferedInputStreamPrivate *priv;
1043
1044
0
      stream = g_task_get_source_object (task);
1045
0
      priv = G_BUFFERED_INPUT_STREAM (stream)->priv;
1046
1047
0
      g_assert_cmpint (priv->end + res, <=, priv->len);
1048
0
      priv->end += res;
1049
1050
0
      g_task_return_int (task, res);
1051
0
    }
1052
1053
0
  g_object_unref (task);
1054
0
}
1055
1056
static void
1057
g_buffered_input_stream_real_fill_async (GBufferedInputStream *stream,
1058
                                         gssize                count,
1059
                                         int                   io_priority,
1060
                                         GCancellable         *cancellable,
1061
                                         GAsyncReadyCallback   callback,
1062
                                         gpointer              user_data)
1063
0
{
1064
0
  GBufferedInputStreamPrivate *priv;
1065
0
  GInputStream *base_stream;
1066
0
  GTask *task;
1067
0
  gsize in_buffer;
1068
1069
0
  priv = stream->priv;
1070
1071
0
  if (count == -1)
1072
0
    count = priv->len;
1073
1074
0
  in_buffer = priv->end - priv->pos;
1075
1076
  /* Never fill more than can fit in the buffer */
1077
0
  count = MIN ((gsize) count, priv->len - in_buffer);
1078
1079
  /* If requested length does not fit at end, compact */
1080
0
  if (priv->len - priv->end < (gsize) count)
1081
0
    compact_buffer (stream);
1082
1083
0
  task = g_task_new (stream, cancellable, callback, user_data);
1084
0
  g_task_set_source_tag (task, g_buffered_input_stream_real_fill_async);
1085
1086
0
  base_stream = G_FILTER_INPUT_STREAM (stream)->base_stream;
1087
0
  g_input_stream_read_async (base_stream,
1088
0
                             priv->buffer + priv->end,
1089
0
                             count,
1090
0
                             io_priority,
1091
0
                             cancellable,
1092
0
                             fill_async_callback,
1093
0
                             task);
1094
0
}
1095
1096
static gssize
1097
g_buffered_input_stream_real_fill_finish (GBufferedInputStream *stream,
1098
                                          GAsyncResult         *result,
1099
                                          GError              **error)
1100
0
{
1101
0
  g_return_val_if_fail (g_task_is_valid (result, stream), -1);
1102
1103
0
  return g_task_propagate_int (G_TASK (result), error);
1104
0
}
1105
1106
typedef struct
1107
{
1108
  gsize bytes_skipped;
1109
  gsize count;
1110
} SkipAsyncData;
1111
1112
static void
1113
free_skip_async_data (gpointer _data)
1114
0
{
1115
0
  SkipAsyncData *data = _data;
1116
0
  g_slice_free (SkipAsyncData, data);
1117
0
}
1118
1119
static void
1120
large_skip_callback (GObject      *source_object,
1121
                     GAsyncResult *result,
1122
                     gpointer      user_data)
1123
0
{
1124
0
  GTask *task = G_TASK (user_data);
1125
0
  SkipAsyncData *data;
1126
0
  GError *error;
1127
0
  gssize nread;
1128
1129
0
  data = g_task_get_task_data (task);
1130
1131
0
  error = NULL;
1132
0
  nread = g_input_stream_skip_finish (G_INPUT_STREAM (source_object),
1133
0
                                      result, &error);
1134
1135
  /* Only report the error if we've not already read some data */
1136
0
  if (nread < 0 && data->bytes_skipped == 0)
1137
0
    g_task_return_error (task, error);
1138
0
  else
1139
0
    {
1140
0
      if (error)
1141
0
  g_error_free (error);
1142
1143
0
      if (nread > 0)
1144
0
  data->bytes_skipped += nread;
1145
1146
0
      g_task_return_int (task, data->bytes_skipped);
1147
0
    }
1148
1149
0
  g_object_unref (task);
1150
0
}
1151
1152
static void
1153
skip_fill_buffer_callback (GObject      *source_object,
1154
                           GAsyncResult *result,
1155
                           gpointer      user_data)
1156
0
{
1157
0
  GTask *task = G_TASK (user_data);
1158
0
  GBufferedInputStream *bstream;
1159
0
  GBufferedInputStreamPrivate *priv;
1160
0
  SkipAsyncData *data;
1161
0
  GError *error;
1162
0
  gssize nread;
1163
0
  gsize available;
1164
1165
0
  bstream = G_BUFFERED_INPUT_STREAM (source_object);
1166
0
  priv = bstream->priv;
1167
1168
0
  data = g_task_get_task_data (task);
1169
1170
0
  error = NULL;
1171
0
  nread = g_buffered_input_stream_fill_finish (bstream,
1172
0
                                               result, &error);
1173
1174
0
  if (nread < 0 && data->bytes_skipped == 0)
1175
0
    g_task_return_error (task, error);
1176
0
  else
1177
0
    {
1178
0
      if (error)
1179
0
  g_error_free (error);
1180
1181
0
      if (nread > 0)
1182
0
  {
1183
0
    available = priv->end - priv->pos;
1184
0
    data->count = MIN (data->count, available);
1185
1186
0
    data->bytes_skipped += data->count;
1187
0
    priv->pos += data->count;
1188
0
  }
1189
1190
0
      g_assert (data->bytes_skipped <= G_MAXSSIZE);
1191
0
      g_task_return_int (task, data->bytes_skipped);
1192
0
    }
1193
1194
0
  g_object_unref (task);
1195
0
}
1196
1197
static void
1198
g_buffered_input_stream_skip_async (GInputStream        *stream,
1199
                                    gsize                count,
1200
                                    int                  io_priority,
1201
                                    GCancellable        *cancellable,
1202
                                    GAsyncReadyCallback  callback,
1203
                                    gpointer             user_data)
1204
0
{
1205
0
  GBufferedInputStream *bstream;
1206
0
  GBufferedInputStreamPrivate *priv;
1207
0
  GBufferedInputStreamClass *class;
1208
0
  GInputStream *base_stream;
1209
0
  gsize available;
1210
0
  GTask *task;
1211
0
  SkipAsyncData *data;
1212
1213
0
  bstream = G_BUFFERED_INPUT_STREAM (stream);
1214
0
  priv = bstream->priv;
1215
1216
0
  data = g_slice_new (SkipAsyncData);
1217
0
  data->bytes_skipped = 0;
1218
0
  task = g_task_new (stream, cancellable, callback, user_data);
1219
0
  g_task_set_source_tag (task, g_buffered_input_stream_skip_async);
1220
0
  g_task_set_task_data (task, data, free_skip_async_data);
1221
1222
0
  available = priv->end - priv->pos;
1223
1224
0
  if (count <= available)
1225
0
    {
1226
0
      priv->pos += count;
1227
1228
0
      g_task_return_int (task, count);
1229
0
      g_object_unref (task);
1230
0
      return;
1231
0
    }
1232
1233
  /* Full request not available, skip all currently available
1234
   * and request refill for more
1235
   */
1236
1237
0
  priv->pos = 0;
1238
0
  priv->end = 0;
1239
1240
0
  count -= available;
1241
1242
0
  data->bytes_skipped = available;
1243
0
  data->count = count;
1244
1245
0
  if (count > priv->len)
1246
0
    {
1247
      /* Large request, shortcut buffer */
1248
0
      base_stream = G_FILTER_INPUT_STREAM (stream)->base_stream;
1249
1250
      /* If 'count > G_MAXSSIZE then 'g_input_stream_skip_async()'
1251
       * will return an error anyway before calling this.
1252
       * Assert that this is never called for too big `count` for clarity. */
1253
0
      g_assert ((gssize) count >= 0);
1254
0
      g_input_stream_skip_async (base_stream,
1255
0
                                 count,
1256
0
                                 io_priority, cancellable,
1257
0
                                 large_skip_callback,
1258
0
                                 task);
1259
0
    }
1260
0
  else
1261
0
    {
1262
0
      class = G_BUFFERED_INPUT_STREAM_GET_CLASS (stream);
1263
0
      class->fill_async (bstream, priv->len, io_priority, cancellable,
1264
0
                         skip_fill_buffer_callback, task);
1265
0
    }
1266
0
}
1267
1268
static gssize
1269
g_buffered_input_stream_skip_finish (GInputStream   *stream,
1270
                                     GAsyncResult   *result,
1271
                                     GError        **error)
1272
0
{
1273
0
  g_return_val_if_fail (g_task_is_valid (result, stream), -1);
1274
1275
0
  return g_task_propagate_int (G_TASK (result), error);
1276
0
}