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