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