/src/pango/subprojects/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 | | * 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 | | G_DEFINE_TYPE_WITH_PRIVATE (GDataInputStream, |
63 | | g_data_input_stream, |
64 | | G_TYPE_BUFFERED_INPUT_STREAM) |
65 | | |
66 | | |
67 | | static void |
68 | | g_data_input_stream_class_init (GDataInputStreamClass *klass) |
69 | 0 | { |
70 | 0 | GObjectClass *object_class; |
71 | |
|
72 | 0 | object_class = G_OBJECT_CLASS (klass); |
73 | 0 | object_class->get_property = g_data_input_stream_get_property; |
74 | 0 | 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 | 0 | g_object_class_install_property (object_class, |
84 | 0 | PROP_BYTE_ORDER, |
85 | 0 | g_param_spec_enum ("byte-order", NULL, NULL, |
86 | 0 | G_TYPE_DATA_STREAM_BYTE_ORDER, |
87 | 0 | G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN, |
88 | 0 | 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 | 0 | g_object_class_install_property (object_class, |
97 | 0 | PROP_NEWLINE_TYPE, |
98 | 0 | g_param_spec_enum ("newline-type", NULL, NULL, |
99 | 0 | G_TYPE_DATA_STREAM_NEWLINE_TYPE, |
100 | 0 | G_DATA_STREAM_NEWLINE_TYPE_LF, |
101 | 0 | G_PARAM_READWRITE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_BLURB)); |
102 | 0 | } |
103 | | |
104 | | static void |
105 | | g_data_input_stream_set_property (GObject *object, |
106 | | guint prop_id, |
107 | | const GValue *value, |
108 | | GParamSpec *pspec) |
109 | 0 | { |
110 | 0 | GDataInputStream *dstream; |
111 | |
|
112 | 0 | dstream = G_DATA_INPUT_STREAM (object); |
113 | |
|
114 | 0 | switch (prop_id) |
115 | 0 | { |
116 | 0 | case PROP_BYTE_ORDER: |
117 | 0 | g_data_input_stream_set_byte_order (dstream, g_value_get_enum (value)); |
118 | 0 | break; |
119 | | |
120 | 0 | case PROP_NEWLINE_TYPE: |
121 | 0 | g_data_input_stream_set_newline_type (dstream, g_value_get_enum (value)); |
122 | 0 | break; |
123 | | |
124 | 0 | default: |
125 | 0 | G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); |
126 | 0 | break; |
127 | 0 | } |
128 | |
|
129 | 0 | } |
130 | | |
131 | | static void |
132 | | g_data_input_stream_get_property (GObject *object, |
133 | | guint prop_id, |
134 | | GValue *value, |
135 | | GParamSpec *pspec) |
136 | 0 | { |
137 | 0 | GDataInputStreamPrivate *priv; |
138 | 0 | GDataInputStream *dstream; |
139 | |
|
140 | 0 | dstream = G_DATA_INPUT_STREAM (object); |
141 | 0 | priv = dstream->priv; |
142 | |
|
143 | 0 | switch (prop_id) |
144 | 0 | { |
145 | 0 | case PROP_BYTE_ORDER: |
146 | 0 | g_value_set_enum (value, priv->byte_order); |
147 | 0 | break; |
148 | | |
149 | 0 | case PROP_NEWLINE_TYPE: |
150 | 0 | g_value_set_enum (value, priv->newline_type); |
151 | 0 | break; |
152 | | |
153 | 0 | default: |
154 | 0 | G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); |
155 | 0 | break; |
156 | 0 | } |
157 | |
|
158 | 0 | } |
159 | | static void |
160 | | g_data_input_stream_init (GDataInputStream *stream) |
161 | 0 | { |
162 | 0 | stream->priv = g_data_input_stream_get_instance_private (stream); |
163 | 0 | stream->priv->byte_order = G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN; |
164 | 0 | stream->priv->newline_type = G_DATA_STREAM_NEWLINE_TYPE_LF; |
165 | 0 | } |
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 | | g_data_input_stream_new (GInputStream *base_stream) |
177 | 0 | { |
178 | 0 | GDataInputStream *stream; |
179 | |
|
180 | 0 | g_return_val_if_fail (G_IS_INPUT_STREAM (base_stream), NULL); |
181 | | |
182 | 0 | stream = g_object_new (G_TYPE_DATA_INPUT_STREAM, |
183 | 0 | "base-stream", base_stream, |
184 | 0 | NULL); |
185 | |
|
186 | 0 | return stream; |
187 | 0 | } |
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 | | g_data_input_stream_set_byte_order (GDataInputStream *stream, |
200 | | GDataStreamByteOrder order) |
201 | 0 | { |
202 | 0 | GDataInputStreamPrivate *priv; |
203 | |
|
204 | 0 | g_return_if_fail (G_IS_DATA_INPUT_STREAM (stream)); |
205 | | |
206 | 0 | priv = stream->priv; |
207 | |
|
208 | 0 | if (priv->byte_order != order) |
209 | 0 | { |
210 | 0 | priv->byte_order = order; |
211 | | |
212 | 0 | g_object_notify (G_OBJECT (stream), "byte-order"); |
213 | 0 | } |
214 | 0 | } |
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 | | g_data_input_stream_get_byte_order (GDataInputStream *stream) |
226 | 0 | { |
227 | 0 | g_return_val_if_fail (G_IS_DATA_INPUT_STREAM (stream), G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN); |
228 | | |
229 | 0 | return stream->priv->byte_order; |
230 | 0 | } |
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 | | g_data_input_stream_set_newline_type (GDataInputStream *stream, |
246 | | GDataStreamNewlineType type) |
247 | 0 | { |
248 | 0 | GDataInputStreamPrivate *priv; |
249 | |
|
250 | 0 | g_return_if_fail (G_IS_DATA_INPUT_STREAM (stream)); |
251 | | |
252 | 0 | priv = stream->priv; |
253 | | |
254 | 0 | if (priv->newline_type != type) |
255 | 0 | { |
256 | 0 | priv->newline_type = type; |
257 | |
|
258 | 0 | g_object_notify (G_OBJECT (stream), "newline-type"); |
259 | 0 | } |
260 | 0 | } |
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 | | g_data_input_stream_get_newline_type (GDataInputStream *stream) |
272 | 0 | { |
273 | 0 | g_return_val_if_fail (G_IS_DATA_INPUT_STREAM (stream), G_DATA_STREAM_NEWLINE_TYPE_ANY); |
274 | | |
275 | 0 | return stream->priv->newline_type; |
276 | 0 | } |
277 | | |
278 | | static gboolean |
279 | | read_data (GDataInputStream *stream, |
280 | | void *buffer, |
281 | | gsize size, |
282 | | GCancellable *cancellable, |
283 | | GError **error) |
284 | 0 | { |
285 | 0 | gsize available; |
286 | 0 | gssize res; |
287 | |
|
288 | 0 | while ((available = g_buffered_input_stream_get_available (G_BUFFERED_INPUT_STREAM (stream))) < size) |
289 | 0 | { |
290 | 0 | res = g_buffered_input_stream_fill (G_BUFFERED_INPUT_STREAM (stream), |
291 | 0 | size - available, |
292 | 0 | cancellable, error); |
293 | 0 | if (res < 0) |
294 | 0 | return FALSE; |
295 | 0 | if (res == 0) |
296 | 0 | { |
297 | 0 | g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED, |
298 | 0 | _("Unexpected early end-of-stream")); |
299 | 0 | return FALSE; |
300 | 0 | } |
301 | 0 | } |
302 | | |
303 | | /* This should always succeed, since it's in the buffer */ |
304 | 0 | res = g_input_stream_read (G_INPUT_STREAM (stream), |
305 | 0 | buffer, size, |
306 | 0 | NULL, NULL); |
307 | 0 | g_warn_if_fail (res >= 0 && (gsize) res == size); |
308 | 0 | return TRUE; |
309 | 0 | } |
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 | | g_data_input_stream_read_byte (GDataInputStream *stream, |
325 | | GCancellable *cancellable, |
326 | | GError **error) |
327 | 0 | { |
328 | 0 | guchar c; |
329 | | |
330 | 0 | g_return_val_if_fail (G_IS_DATA_INPUT_STREAM (stream), '\0'); |
331 | | |
332 | 0 | if (read_data (stream, &c, 1, cancellable, error)) |
333 | 0 | return c; |
334 | | |
335 | 0 | return 0; |
336 | 0 | } |
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 | | g_data_input_stream_read_int16 (GDataInputStream *stream, |
355 | | GCancellable *cancellable, |
356 | | GError **error) |
357 | 0 | { |
358 | 0 | gint16 v; |
359 | | |
360 | 0 | g_return_val_if_fail (G_IS_DATA_INPUT_STREAM (stream), 0); |
361 | | |
362 | 0 | if (read_data (stream, &v, 2, cancellable, error)) |
363 | 0 | { |
364 | 0 | switch (stream->priv->byte_order) |
365 | 0 | { |
366 | 0 | case G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN: |
367 | 0 | v = GINT16_FROM_BE (v); |
368 | 0 | break; |
369 | 0 | case G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN: |
370 | 0 | v = GINT16_FROM_LE (v); |
371 | 0 | break; |
372 | 0 | case G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN: |
373 | 0 | default: |
374 | 0 | break; |
375 | 0 | } |
376 | 0 | return v; |
377 | 0 | } |
378 | | |
379 | 0 | return 0; |
380 | 0 | } |
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 | | g_data_input_stream_read_uint16 (GDataInputStream *stream, |
399 | | GCancellable *cancellable, |
400 | | GError **error) |
401 | 0 | { |
402 | 0 | guint16 v; |
403 | | |
404 | 0 | g_return_val_if_fail (G_IS_DATA_INPUT_STREAM (stream), 0); |
405 | | |
406 | 0 | if (read_data (stream, &v, 2, cancellable, error)) |
407 | 0 | { |
408 | 0 | switch (stream->priv->byte_order) |
409 | 0 | { |
410 | 0 | case G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN: |
411 | 0 | v = GUINT16_FROM_BE (v); |
412 | 0 | break; |
413 | 0 | case G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN: |
414 | 0 | v = GUINT16_FROM_LE (v); |
415 | 0 | break; |
416 | 0 | case G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN: |
417 | 0 | default: |
418 | 0 | break; |
419 | 0 | } |
420 | 0 | return v; |
421 | 0 | } |
422 | | |
423 | 0 | return 0; |
424 | 0 | } |
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 | | g_data_input_stream_read_int32 (GDataInputStream *stream, |
447 | | GCancellable *cancellable, |
448 | | GError **error) |
449 | 0 | { |
450 | 0 | gint32 v; |
451 | | |
452 | 0 | g_return_val_if_fail (G_IS_DATA_INPUT_STREAM (stream), 0); |
453 | | |
454 | 0 | if (read_data (stream, &v, 4, cancellable, error)) |
455 | 0 | { |
456 | 0 | switch (stream->priv->byte_order) |
457 | 0 | { |
458 | 0 | case G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN: |
459 | 0 | v = GINT32_FROM_BE (v); |
460 | 0 | break; |
461 | 0 | case G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN: |
462 | 0 | v = GINT32_FROM_LE (v); |
463 | 0 | break; |
464 | 0 | case G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN: |
465 | 0 | default: |
466 | 0 | break; |
467 | 0 | } |
468 | 0 | return v; |
469 | 0 | } |
470 | | |
471 | 0 | return 0; |
472 | 0 | } |
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 | | g_data_input_stream_read_uint32 (GDataInputStream *stream, |
495 | | GCancellable *cancellable, |
496 | | GError **error) |
497 | 0 | { |
498 | 0 | guint32 v; |
499 | | |
500 | 0 | g_return_val_if_fail (G_IS_DATA_INPUT_STREAM (stream), 0); |
501 | | |
502 | 0 | if (read_data (stream, &v, 4, cancellable, error)) |
503 | 0 | { |
504 | 0 | switch (stream->priv->byte_order) |
505 | 0 | { |
506 | 0 | case G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN: |
507 | 0 | v = GUINT32_FROM_BE (v); |
508 | 0 | break; |
509 | 0 | case G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN: |
510 | 0 | v = GUINT32_FROM_LE (v); |
511 | 0 | break; |
512 | 0 | case G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN: |
513 | 0 | default: |
514 | 0 | break; |
515 | 0 | } |
516 | 0 | return v; |
517 | 0 | } |
518 | | |
519 | 0 | return 0; |
520 | 0 | } |
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 | | g_data_input_stream_read_int64 (GDataInputStream *stream, |
543 | | GCancellable *cancellable, |
544 | | GError **error) |
545 | 0 | { |
546 | 0 | gint64 v; |
547 | | |
548 | 0 | g_return_val_if_fail (G_IS_DATA_INPUT_STREAM (stream), 0); |
549 | | |
550 | 0 | if (read_data (stream, &v, 8, cancellable, error)) |
551 | 0 | { |
552 | 0 | switch (stream->priv->byte_order) |
553 | 0 | { |
554 | 0 | case G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN: |
555 | 0 | v = GINT64_FROM_BE (v); |
556 | 0 | break; |
557 | 0 | case G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN: |
558 | 0 | v = GINT64_FROM_LE (v); |
559 | 0 | break; |
560 | 0 | case G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN: |
561 | 0 | default: |
562 | 0 | break; |
563 | 0 | } |
564 | 0 | return v; |
565 | 0 | } |
566 | | |
567 | 0 | return 0; |
568 | 0 | } |
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 | | g_data_input_stream_read_uint64 (GDataInputStream *stream, |
591 | | GCancellable *cancellable, |
592 | | GError **error) |
593 | 0 | { |
594 | 0 | guint64 v; |
595 | | |
596 | 0 | g_return_val_if_fail (G_IS_DATA_INPUT_STREAM (stream), 0); |
597 | | |
598 | 0 | if (read_data (stream, &v, 8, cancellable, error)) |
599 | 0 | { |
600 | 0 | switch (stream->priv->byte_order) |
601 | 0 | { |
602 | 0 | case G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN: |
603 | 0 | v = GUINT64_FROM_BE (v); |
604 | 0 | break; |
605 | 0 | case G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN: |
606 | 0 | v = GUINT64_FROM_LE (v); |
607 | 0 | break; |
608 | 0 | case G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN: |
609 | 0 | default: |
610 | 0 | break; |
611 | 0 | } |
612 | 0 | return v; |
613 | 0 | } |
614 | | |
615 | 0 | return 0; |
616 | 0 | } |
617 | | |
618 | | static gssize |
619 | | scan_for_newline (GDataInputStream *stream, |
620 | | gsize *checked_out, |
621 | | gboolean *last_saw_cr_out, |
622 | | int *newline_len_out) |
623 | 0 | { |
624 | 0 | GBufferedInputStream *bstream; |
625 | 0 | GDataInputStreamPrivate *priv; |
626 | 0 | const char *buffer; |
627 | 0 | gsize start, end, peeked; |
628 | 0 | gsize i; |
629 | 0 | gssize found_pos; |
630 | 0 | int newline_len; |
631 | 0 | gsize available, checked; |
632 | 0 | gboolean last_saw_cr; |
633 | |
|
634 | 0 | priv = stream->priv; |
635 | | |
636 | 0 | bstream = G_BUFFERED_INPUT_STREAM (stream); |
637 | |
|
638 | 0 | checked = *checked_out; |
639 | 0 | last_saw_cr = *last_saw_cr_out; |
640 | 0 | found_pos = -1; |
641 | 0 | newline_len = 0; |
642 | | |
643 | 0 | start = checked; |
644 | 0 | buffer = (const char*)g_buffered_input_stream_peek_buffer (bstream, &available) + start; |
645 | 0 | end = available; |
646 | 0 | peeked = end - start; |
647 | |
|
648 | 0 | for (i = 0; checked < available && i < peeked; i++) |
649 | 0 | { |
650 | 0 | switch (priv->newline_type) |
651 | 0 | { |
652 | 0 | case G_DATA_STREAM_NEWLINE_TYPE_LF: |
653 | 0 | if (buffer[i] == 10) |
654 | 0 | { |
655 | 0 | found_pos = start + i; |
656 | 0 | newline_len = 1; |
657 | 0 | } |
658 | 0 | break; |
659 | 0 | case G_DATA_STREAM_NEWLINE_TYPE_CR: |
660 | 0 | if (buffer[i] == 13) |
661 | 0 | { |
662 | 0 | found_pos = start + i; |
663 | 0 | newline_len = 1; |
664 | 0 | } |
665 | 0 | break; |
666 | 0 | case G_DATA_STREAM_NEWLINE_TYPE_CR_LF: |
667 | 0 | if (last_saw_cr && buffer[i] == 10) |
668 | 0 | { |
669 | 0 | found_pos = start + i - 1; |
670 | 0 | newline_len = 2; |
671 | 0 | } |
672 | 0 | break; |
673 | 0 | default: |
674 | 0 | case G_DATA_STREAM_NEWLINE_TYPE_ANY: |
675 | 0 | if (buffer[i] == 10) /* LF */ |
676 | 0 | { |
677 | 0 | if (last_saw_cr) |
678 | 0 | { |
679 | | /* CR LF */ |
680 | 0 | found_pos = start + i - 1; |
681 | 0 | newline_len = 2; |
682 | 0 | } |
683 | 0 | else |
684 | 0 | { |
685 | | /* LF */ |
686 | 0 | found_pos = start + i; |
687 | 0 | newline_len = 1; |
688 | 0 | } |
689 | 0 | } |
690 | 0 | else if (last_saw_cr) |
691 | 0 | { |
692 | | /* Last was cr, this is not LF, end is CR */ |
693 | 0 | found_pos = start + i - 1; |
694 | 0 | newline_len = 1; |
695 | 0 | } |
696 | | /* Don't check for CR here, instead look at last_saw_cr on next byte */ |
697 | 0 | break; |
698 | 0 | } |
699 | | |
700 | 0 | last_saw_cr = (buffer[i] == 13); |
701 | |
|
702 | 0 | if (found_pos != -1) |
703 | 0 | { |
704 | 0 | *newline_len_out = newline_len; |
705 | 0 | return found_pos; |
706 | 0 | } |
707 | 0 | } |
708 | | |
709 | 0 | checked = end; |
710 | |
|
711 | 0 | *checked_out = checked; |
712 | 0 | *last_saw_cr_out = last_saw_cr; |
713 | 0 | return -1; |
714 | 0 | } |
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 | | g_data_input_stream_read_line (GDataInputStream *stream, |
741 | | gsize *length, |
742 | | GCancellable *cancellable, |
743 | | GError **error) |
744 | 0 | { |
745 | 0 | GBufferedInputStream *bstream; |
746 | 0 | gsize checked; |
747 | 0 | gboolean last_saw_cr; |
748 | 0 | gssize found_pos; |
749 | 0 | gssize res; |
750 | 0 | int newline_len; |
751 | 0 | char *line; |
752 | | |
753 | 0 | g_return_val_if_fail (G_IS_DATA_INPUT_STREAM (stream), NULL); |
754 | | |
755 | 0 | bstream = G_BUFFERED_INPUT_STREAM (stream); |
756 | |
|
757 | 0 | newline_len = 0; |
758 | 0 | checked = 0; |
759 | 0 | last_saw_cr = FALSE; |
760 | |
|
761 | 0 | while ((found_pos = scan_for_newline (stream, &checked, &last_saw_cr, &newline_len)) == -1) |
762 | 0 | { |
763 | 0 | if (g_buffered_input_stream_get_available (bstream) == |
764 | 0 | 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 | 0 | res = g_buffered_input_stream_fill (bstream, -1, cancellable, error); |
769 | 0 | if (res < 0) |
770 | 0 | return NULL; |
771 | 0 | if (res == 0) |
772 | 0 | { |
773 | | /* End of stream */ |
774 | 0 | if (g_buffered_input_stream_get_available (bstream) == 0) |
775 | 0 | { |
776 | 0 | if (length) |
777 | 0 | *length = 0; |
778 | 0 | return NULL; |
779 | 0 | } |
780 | 0 | else |
781 | 0 | { |
782 | 0 | found_pos = checked; |
783 | 0 | newline_len = 0; |
784 | 0 | break; |
785 | 0 | } |
786 | 0 | } |
787 | 0 | } |
788 | | |
789 | 0 | line = g_malloc (found_pos + newline_len + 1); |
790 | |
|
791 | 0 | res = g_input_stream_read (G_INPUT_STREAM (stream), |
792 | 0 | line, |
793 | 0 | found_pos + newline_len, |
794 | 0 | NULL, NULL); |
795 | 0 | if (length) |
796 | 0 | *length = (gsize)found_pos; |
797 | 0 | g_warn_if_fail (res == found_pos + newline_len); |
798 | 0 | line[found_pos] = 0; |
799 | | |
800 | 0 | return line; |
801 | 0 | } |
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 | | g_data_input_stream_read_line_utf8 (GDataInputStream *stream, |
828 | | gsize *length, |
829 | | GCancellable *cancellable, |
830 | | GError **error) |
831 | 0 | { |
832 | 0 | char *res; |
833 | |
|
834 | 0 | res = g_data_input_stream_read_line (stream, length, cancellable, error); |
835 | 0 | if (!res) |
836 | 0 | return NULL; |
837 | | |
838 | 0 | if (!g_utf8_validate (res, -1, NULL)) |
839 | 0 | { |
840 | 0 | g_set_error_literal (error, G_CONVERT_ERROR, |
841 | 0 | G_CONVERT_ERROR_ILLEGAL_SEQUENCE, |
842 | 0 | _("Invalid byte sequence in conversion input")); |
843 | |
|
844 | 0 | if (length != NULL) |
845 | 0 | *length = 0; |
846 | 0 | g_free (res); |
847 | |
|
848 | 0 | return NULL; |
849 | 0 | } |
850 | 0 | return res; |
851 | 0 | } |
852 | | |
853 | | static gssize |
854 | | scan_for_chars (GDataInputStream *stream, |
855 | | gsize *checked_out, |
856 | | const char *stop_chars, |
857 | | gsize stop_chars_len) |
858 | 0 | { |
859 | 0 | GBufferedInputStream *bstream; |
860 | 0 | const char *buffer; |
861 | 0 | gsize start, end, peeked; |
862 | 0 | gsize i; |
863 | 0 | gsize available, checked; |
864 | |
|
865 | 0 | bstream = G_BUFFERED_INPUT_STREAM (stream); |
866 | |
|
867 | 0 | checked = *checked_out; |
868 | |
|
869 | 0 | start = checked; |
870 | 0 | buffer = (const char *)g_buffered_input_stream_peek_buffer (bstream, &available) + start; |
871 | 0 | end = available; |
872 | 0 | 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 | 0 | if (stop_chars_len == 1) |
878 | 0 | { |
879 | 0 | const char *p = memchr (buffer, stop_chars[0], peeked); |
880 | |
|
881 | 0 | if (p != NULL) |
882 | 0 | return start + (p - buffer); |
883 | 0 | } |
884 | 0 | else |
885 | 0 | { |
886 | 0 | for (i = 0; checked < available && i < peeked; i++) |
887 | 0 | { |
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 | 0 | const char *p = memchr (stop_chars, buffer[i], stop_chars_len); |
892 | |
|
893 | 0 | if (p != NULL) |
894 | 0 | return (start + i); |
895 | 0 | } |
896 | 0 | } |
897 | | |
898 | 0 | checked = end; |
899 | |
|
900 | 0 | *checked_out = checked; |
901 | 0 | return -1; |
902 | 0 | } |
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 | | g_data_input_stream_read_until (GDataInputStream *stream, |
933 | | const gchar *stop_chars, |
934 | | gsize *length, |
935 | | GCancellable *cancellable, |
936 | | GError **error) |
937 | 0 | { |
938 | 0 | GBufferedInputStream *bstream; |
939 | 0 | gchar *result; |
940 | |
|
941 | 0 | bstream = G_BUFFERED_INPUT_STREAM (stream); |
942 | |
|
943 | 0 | result = g_data_input_stream_read_upto (stream, stop_chars, -1, |
944 | 0 | length, cancellable, error); |
945 | | |
946 | | /* If we're not at end of stream then we have a stop_char to consume. */ |
947 | 0 | if (result != NULL && g_buffered_input_stream_get_available (bstream) > 0) |
948 | 0 | { |
949 | 0 | gsize res G_GNUC_UNUSED /* when compiling with G_DISABLE_ASSERT */; |
950 | 0 | gchar b; |
951 | |
|
952 | 0 | res = g_input_stream_read (G_INPUT_STREAM (stream), &b, 1, NULL, NULL); |
953 | 0 | g_assert (res == 1); |
954 | 0 | } |
955 | | |
956 | 0 | return result; |
957 | 0 | } |
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 | | g_data_input_stream_read_complete (GTask *task, |
971 | | gsize read_length, |
972 | | gsize skip_length) |
973 | 0 | { |
974 | 0 | GDataInputStreamReadData *data = g_task_get_task_data (task); |
975 | 0 | GInputStream *stream = g_task_get_source_object (task); |
976 | 0 | char *line = NULL; |
977 | |
|
978 | 0 | if (read_length || skip_length) |
979 | 0 | { |
980 | 0 | gssize bytes; |
981 | |
|
982 | 0 | data->length = read_length; |
983 | 0 | line = g_malloc (read_length + 1); |
984 | 0 | line[read_length] = '\0'; |
985 | | |
986 | | /* we already checked the buffer. this shouldn't fail. */ |
987 | 0 | bytes = g_input_stream_read (stream, line, read_length, NULL, NULL); |
988 | 0 | g_assert_cmpint (bytes, ==, read_length); |
989 | |
|
990 | 0 | bytes = g_input_stream_skip (stream, skip_length, NULL, NULL); |
991 | 0 | g_assert_cmpint (bytes, ==, skip_length); |
992 | 0 | } |
993 | |
|
994 | 0 | g_task_return_pointer (task, line, g_free); |
995 | 0 | g_object_unref (task); |
996 | 0 | } |
997 | | |
998 | | static void |
999 | | g_data_input_stream_read_line_ready (GObject *object, |
1000 | | GAsyncResult *result, |
1001 | | gpointer user_data) |
1002 | 0 | { |
1003 | 0 | GTask *task = user_data; |
1004 | 0 | GDataInputStreamReadData *data = g_task_get_task_data (task); |
1005 | 0 | GBufferedInputStream *buffer = g_task_get_source_object (task); |
1006 | 0 | gssize found_pos; |
1007 | 0 | gint newline_len; |
1008 | |
|
1009 | 0 | if (result) |
1010 | | /* this is a callback. finish the async call. */ |
1011 | 0 | { |
1012 | 0 | GError *error = NULL; |
1013 | 0 | gssize bytes; |
1014 | |
|
1015 | 0 | bytes = g_buffered_input_stream_fill_finish (buffer, result, &error); |
1016 | |
|
1017 | 0 | if (bytes <= 0) |
1018 | 0 | { |
1019 | 0 | if (bytes < 0) |
1020 | | /* stream error. */ |
1021 | 0 | { |
1022 | 0 | g_task_return_error (task, error); |
1023 | 0 | g_object_unref (task); |
1024 | 0 | return; |
1025 | 0 | } |
1026 | | |
1027 | 0 | g_data_input_stream_read_complete (task, data->checked, 0); |
1028 | 0 | return; |
1029 | 0 | } |
1030 | | |
1031 | | /* only proceed if we got more bytes... */ |
1032 | 0 | } |
1033 | | |
1034 | 0 | if (data->stop_chars) |
1035 | 0 | { |
1036 | 0 | found_pos = scan_for_chars (G_DATA_INPUT_STREAM (buffer), |
1037 | 0 | &data->checked, |
1038 | 0 | data->stop_chars, |
1039 | 0 | data->stop_chars_len); |
1040 | 0 | newline_len = 0; |
1041 | 0 | } |
1042 | 0 | else |
1043 | 0 | found_pos = scan_for_newline (G_DATA_INPUT_STREAM (buffer), &data->checked, |
1044 | 0 | &data->last_saw_cr, &newline_len); |
1045 | |
|
1046 | 0 | if (found_pos == -1) |
1047 | | /* didn't find a full line; need to buffer some more bytes */ |
1048 | 0 | { |
1049 | 0 | gsize size; |
1050 | |
|
1051 | 0 | size = g_buffered_input_stream_get_buffer_size (buffer); |
1052 | |
|
1053 | 0 | 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 | 0 | g_buffered_input_stream_fill_async (buffer, -1, |
1059 | 0 | g_task_get_priority (task), |
1060 | 0 | g_task_get_cancellable (task), |
1061 | 0 | g_data_input_stream_read_line_ready, |
1062 | 0 | user_data); |
1063 | 0 | } |
1064 | 0 | else |
1065 | 0 | { |
1066 | | /* read the line and the EOL. no error is possible. */ |
1067 | 0 | g_data_input_stream_read_complete (task, found_pos, newline_len); |
1068 | 0 | } |
1069 | 0 | } |
1070 | | |
1071 | | static void |
1072 | | g_data_input_stream_read_data_free (gpointer user_data) |
1073 | 0 | { |
1074 | 0 | GDataInputStreamReadData *data = user_data; |
1075 | |
|
1076 | 0 | g_free (data->stop_chars); |
1077 | 0 | g_slice_free (GDataInputStreamReadData, data); |
1078 | 0 | } |
1079 | | |
1080 | | static void |
1081 | | 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 | 0 | { |
1089 | 0 | GDataInputStreamReadData *data; |
1090 | 0 | GTask *task; |
1091 | 0 | gsize stop_chars_len_unsigned; |
1092 | |
|
1093 | 0 | data = g_slice_new0 (GDataInputStreamReadData); |
1094 | |
|
1095 | 0 | if (stop_chars_len < 0) |
1096 | 0 | stop_chars_len_unsigned = strlen (stop_chars); |
1097 | 0 | else |
1098 | 0 | stop_chars_len_unsigned = (gsize) stop_chars_len; |
1099 | |
|
1100 | 0 | data->stop_chars = g_memdup2 (stop_chars, stop_chars_len_unsigned); |
1101 | 0 | data->stop_chars_len = stop_chars_len_unsigned; |
1102 | 0 | data->last_saw_cr = FALSE; |
1103 | |
|
1104 | 0 | task = g_task_new (stream, cancellable, callback, user_data); |
1105 | 0 | g_task_set_source_tag (task, g_data_input_stream_read_async); |
1106 | 0 | g_task_set_task_data (task, data, g_data_input_stream_read_data_free); |
1107 | 0 | g_task_set_priority (task, io_priority); |
1108 | |
|
1109 | 0 | g_data_input_stream_read_line_ready (NULL, NULL, task); |
1110 | 0 | } |
1111 | | |
1112 | | static gchar * |
1113 | | g_data_input_stream_read_finish (GDataInputStream *stream, |
1114 | | GAsyncResult *result, |
1115 | | gsize *length, |
1116 | | GError **error) |
1117 | 0 | { |
1118 | 0 | GTask *task = G_TASK (result); |
1119 | 0 | gchar *line; |
1120 | |
|
1121 | 0 | line = g_task_propagate_pointer (task, error); |
1122 | |
|
1123 | 0 | if (length && line) |
1124 | 0 | { |
1125 | 0 | GDataInputStreamReadData *data = g_task_get_task_data (task); |
1126 | |
|
1127 | 0 | *length = data->length; |
1128 | 0 | } |
1129 | |
|
1130 | 0 | return line; |
1131 | 0 | } |
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 | | g_data_input_stream_read_line_async (GDataInputStream *stream, |
1152 | | gint io_priority, |
1153 | | GCancellable *cancellable, |
1154 | | GAsyncReadyCallback callback, |
1155 | | gpointer user_data) |
1156 | 0 | { |
1157 | 0 | g_return_if_fail (G_IS_DATA_INPUT_STREAM (stream)); |
1158 | 0 | g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable)); |
1159 | | |
1160 | 0 | g_data_input_stream_read_async (stream, NULL, 0, io_priority, |
1161 | 0 | cancellable, callback, user_data); |
1162 | 0 | } |
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 | | 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 | 0 | { |
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 | 0 | cancellable, callback, user_data); |
1207 | 0 | } |
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 | | g_data_input_stream_read_line_finish (GDataInputStream *stream, |
1232 | | GAsyncResult *result, |
1233 | | gsize *length, |
1234 | | GError **error) |
1235 | 0 | { |
1236 | 0 | g_return_val_if_fail (g_task_is_valid (result, stream), NULL); |
1237 | | |
1238 | 0 | return g_data_input_stream_read_finish (stream, result, length, error); |
1239 | 0 | } |
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 | | g_data_input_stream_read_line_finish_utf8 (GDataInputStream *stream, |
1262 | | GAsyncResult *result, |
1263 | | gsize *length, |
1264 | | GError **error) |
1265 | 0 | { |
1266 | 0 | 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 | 0 | { |
1274 | 0 | g_set_error_literal (error, G_CONVERT_ERROR, |
1275 | 0 | G_CONVERT_ERROR_ILLEGAL_SEQUENCE, |
1276 | 0 | _("Invalid byte sequence in conversion input")); |
1277 | 0 | g_free (res); |
1278 | 0 | return NULL; |
1279 | 0 | } |
1280 | 0 | return res; |
1281 | 0 | } |
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 | | g_data_input_stream_read_until_finish (GDataInputStream *stream, |
1304 | | GAsyncResult *result, |
1305 | | gsize *length, |
1306 | | GError **error) |
1307 | 0 | { |
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 | 0 | } |
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 | | 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 | 0 | { |
1351 | 0 | GBufferedInputStream *bstream; |
1352 | 0 | gsize checked; |
1353 | 0 | gssize found_pos; |
1354 | 0 | gssize res; |
1355 | 0 | char *data_until; |
1356 | 0 | gsize stop_chars_len_unsigned; |
1357 | |
|
1358 | 0 | g_return_val_if_fail (G_IS_DATA_INPUT_STREAM (stream), NULL); |
1359 | | |
1360 | 0 | if (stop_chars_len < 0) |
1361 | 0 | stop_chars_len_unsigned = strlen (stop_chars); |
1362 | 0 | else |
1363 | 0 | stop_chars_len_unsigned = (gsize) stop_chars_len; |
1364 | |
|
1365 | 0 | bstream = G_BUFFERED_INPUT_STREAM (stream); |
1366 | |
|
1367 | 0 | checked = 0; |
1368 | |
|
1369 | 0 | while ((found_pos = scan_for_chars (stream, &checked, stop_chars, stop_chars_len_unsigned)) == -1) |
1370 | 0 | { |
1371 | 0 | if (g_buffered_input_stream_get_available (bstream) == |
1372 | 0 | 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 | 0 | res = g_buffered_input_stream_fill (bstream, -1, cancellable, error); |
1377 | 0 | if (res < 0) |
1378 | 0 | return NULL; |
1379 | 0 | if (res == 0) |
1380 | 0 | { |
1381 | | /* End of stream */ |
1382 | 0 | if (g_buffered_input_stream_get_available (bstream) == 0) |
1383 | 0 | { |
1384 | 0 | if (length) |
1385 | 0 | *length = 0; |
1386 | 0 | return NULL; |
1387 | 0 | } |
1388 | 0 | else |
1389 | 0 | { |
1390 | 0 | found_pos = checked; |
1391 | 0 | break; |
1392 | 0 | } |
1393 | 0 | } |
1394 | 0 | } |
1395 | | |
1396 | 0 | data_until = g_malloc (found_pos + 1); |
1397 | |
|
1398 | 0 | res = g_input_stream_read (G_INPUT_STREAM (stream), |
1399 | 0 | data_until, |
1400 | 0 | found_pos, |
1401 | 0 | NULL, NULL); |
1402 | 0 | if (length) |
1403 | 0 | *length = (gsize)found_pos; |
1404 | 0 | g_warn_if_fail (res == found_pos); |
1405 | 0 | data_until[found_pos] = 0; |
1406 | |
|
1407 | 0 | return data_until; |
1408 | 0 | } |
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 | | 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 | 0 | { |
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 | 0 | cancellable, callback, user_data); |
1453 | 0 | } |
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 | | g_data_input_stream_read_upto_finish (GDataInputStream *stream, |
1480 | | GAsyncResult *result, |
1481 | | gsize *length, |
1482 | | GError **error) |
1483 | 0 | { |
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 | 0 | } |