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