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