/src/glib/gio/gdataoutputstream.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 | | * |
5 | | * SPDX-License-Identifier: LGPL-2.1-or-later |
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 <string.h> |
25 | | #include "gdataoutputstream.h" |
26 | | #include "gseekable.h" |
27 | | #include "gioenumtypes.h" |
28 | | #include "gioerror.h" |
29 | | #include "glibintl.h" |
30 | | |
31 | | |
32 | | /** |
33 | | * SECTION:gdataoutputstream |
34 | | * @short_description: Data Output Stream |
35 | | * @include: gio/gio.h |
36 | | * @see_also: #GOutputStream |
37 | | * |
38 | | * Data output stream implements #GOutputStream and includes functions for |
39 | | * writing data directly to an output stream. |
40 | | * |
41 | | **/ |
42 | | |
43 | | |
44 | | |
45 | | struct _GDataOutputStreamPrivate { |
46 | | GDataStreamByteOrder byte_order; |
47 | | }; |
48 | | |
49 | | enum { |
50 | | PROP_0, |
51 | | PROP_BYTE_ORDER |
52 | | }; |
53 | | |
54 | | static void g_data_output_stream_set_property (GObject *object, |
55 | | guint prop_id, |
56 | | const GValue *value, |
57 | | GParamSpec *pspec); |
58 | | static void g_data_output_stream_get_property (GObject *object, |
59 | | guint prop_id, |
60 | | GValue *value, |
61 | | GParamSpec *pspec); |
62 | | |
63 | | static void g_data_output_stream_seekable_iface_init (GSeekableIface *iface); |
64 | | static goffset g_data_output_stream_tell (GSeekable *seekable); |
65 | | static gboolean g_data_output_stream_can_seek (GSeekable *seekable); |
66 | | static gboolean g_data_output_stream_seek (GSeekable *seekable, |
67 | | goffset offset, |
68 | | GSeekType type, |
69 | | GCancellable *cancellable, |
70 | | GError **error); |
71 | | static gboolean g_data_output_stream_can_truncate (GSeekable *seekable); |
72 | | static gboolean g_data_output_stream_truncate (GSeekable *seekable, |
73 | | goffset offset, |
74 | | GCancellable *cancellable, |
75 | | GError **error); |
76 | | |
77 | | G_DEFINE_TYPE_WITH_CODE (GDataOutputStream, |
78 | | g_data_output_stream, |
79 | | G_TYPE_FILTER_OUTPUT_STREAM, |
80 | | G_ADD_PRIVATE (GDataOutputStream) |
81 | | G_IMPLEMENT_INTERFACE (G_TYPE_SEEKABLE, |
82 | | g_data_output_stream_seekable_iface_init)) |
83 | | |
84 | | |
85 | | static void |
86 | | g_data_output_stream_class_init (GDataOutputStreamClass *klass) |
87 | 0 | { |
88 | 0 | GObjectClass *object_class; |
89 | |
|
90 | 0 | object_class = G_OBJECT_CLASS (klass); |
91 | 0 | object_class->get_property = g_data_output_stream_get_property; |
92 | 0 | object_class->set_property = g_data_output_stream_set_property; |
93 | | |
94 | | /** |
95 | | * GDataOutputStream:byte-order: |
96 | | * |
97 | | * Determines the byte ordering that is used when writing |
98 | | * multi-byte entities (such as integers) to the stream. |
99 | | */ |
100 | 0 | g_object_class_install_property (object_class, |
101 | 0 | PROP_BYTE_ORDER, |
102 | 0 | g_param_spec_enum ("byte-order", |
103 | 0 | P_("Byte order"), |
104 | 0 | P_("The byte order"), |
105 | 0 | G_TYPE_DATA_STREAM_BYTE_ORDER, |
106 | 0 | G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN, |
107 | 0 | G_PARAM_READWRITE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_BLURB)); |
108 | |
|
109 | 0 | } |
110 | | |
111 | | static void |
112 | | g_data_output_stream_set_property (GObject *object, |
113 | | guint prop_id, |
114 | | const GValue *value, |
115 | | GParamSpec *pspec) |
116 | 0 | { |
117 | 0 | GDataOutputStream *dstream; |
118 | |
|
119 | 0 | dstream = G_DATA_OUTPUT_STREAM (object); |
120 | |
|
121 | 0 | switch (prop_id) |
122 | 0 | { |
123 | 0 | case PROP_BYTE_ORDER: |
124 | 0 | g_data_output_stream_set_byte_order (dstream, g_value_get_enum (value)); |
125 | 0 | break; |
126 | | |
127 | 0 | default: |
128 | 0 | G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); |
129 | 0 | break; |
130 | 0 | } |
131 | 0 | } |
132 | | |
133 | | static void |
134 | | g_data_output_stream_get_property (GObject *object, |
135 | | guint prop_id, |
136 | | GValue *value, |
137 | | GParamSpec *pspec) |
138 | 0 | { |
139 | 0 | GDataOutputStreamPrivate *priv; |
140 | 0 | GDataOutputStream *dstream; |
141 | |
|
142 | 0 | dstream = G_DATA_OUTPUT_STREAM (object); |
143 | 0 | priv = dstream->priv; |
144 | |
|
145 | 0 | switch (prop_id) |
146 | 0 | { |
147 | 0 | case PROP_BYTE_ORDER: |
148 | 0 | g_value_set_enum (value, priv->byte_order); |
149 | 0 | break; |
150 | | |
151 | 0 | default: |
152 | 0 | G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); |
153 | 0 | break; |
154 | 0 | } |
155 | 0 | } |
156 | | |
157 | | static void |
158 | | g_data_output_stream_init (GDataOutputStream *stream) |
159 | 0 | { |
160 | 0 | stream->priv = g_data_output_stream_get_instance_private (stream); |
161 | 0 | stream->priv->byte_order = G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN; |
162 | 0 | } |
163 | | |
164 | | static void |
165 | | g_data_output_stream_seekable_iface_init (GSeekableIface *iface) |
166 | 0 | { |
167 | 0 | iface->tell = g_data_output_stream_tell; |
168 | 0 | iface->can_seek = g_data_output_stream_can_seek; |
169 | 0 | iface->seek = g_data_output_stream_seek; |
170 | 0 | iface->can_truncate = g_data_output_stream_can_truncate; |
171 | 0 | iface->truncate_fn = g_data_output_stream_truncate; |
172 | 0 | } |
173 | | |
174 | | /** |
175 | | * g_data_output_stream_new: |
176 | | * @base_stream: a #GOutputStream. |
177 | | * |
178 | | * Creates a new data output stream for @base_stream. |
179 | | * |
180 | | * Returns: #GDataOutputStream. |
181 | | **/ |
182 | | GDataOutputStream * |
183 | | g_data_output_stream_new (GOutputStream *base_stream) |
184 | 0 | { |
185 | 0 | GDataOutputStream *stream; |
186 | |
|
187 | 0 | g_return_val_if_fail (G_IS_OUTPUT_STREAM (base_stream), NULL); |
188 | | |
189 | 0 | stream = g_object_new (G_TYPE_DATA_OUTPUT_STREAM, |
190 | 0 | "base-stream", base_stream, |
191 | 0 | NULL); |
192 | |
|
193 | 0 | return stream; |
194 | 0 | } |
195 | | |
196 | | /** |
197 | | * g_data_output_stream_set_byte_order: |
198 | | * @stream: a #GDataOutputStream. |
199 | | * @order: a %GDataStreamByteOrder. |
200 | | * |
201 | | * Sets the byte order of the data output stream to @order. |
202 | | **/ |
203 | | void |
204 | | g_data_output_stream_set_byte_order (GDataOutputStream *stream, |
205 | | GDataStreamByteOrder order) |
206 | 0 | { |
207 | 0 | GDataOutputStreamPrivate *priv; |
208 | 0 | g_return_if_fail (G_IS_DATA_OUTPUT_STREAM (stream)); |
209 | 0 | priv = stream->priv; |
210 | 0 | if (priv->byte_order != order) |
211 | 0 | { |
212 | 0 | priv->byte_order = order; |
213 | 0 | g_object_notify (G_OBJECT (stream), "byte-order"); |
214 | 0 | } |
215 | 0 | } |
216 | | |
217 | | /** |
218 | | * g_data_output_stream_get_byte_order: |
219 | | * @stream: a #GDataOutputStream. |
220 | | * |
221 | | * Gets the byte order for the stream. |
222 | | * |
223 | | * Returns: the #GDataStreamByteOrder for the @stream. |
224 | | **/ |
225 | | GDataStreamByteOrder |
226 | | g_data_output_stream_get_byte_order (GDataOutputStream *stream) |
227 | 0 | { |
228 | 0 | g_return_val_if_fail (G_IS_DATA_OUTPUT_STREAM (stream), G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN); |
229 | | |
230 | 0 | return stream->priv->byte_order; |
231 | 0 | } |
232 | | |
233 | | /** |
234 | | * g_data_output_stream_put_byte: |
235 | | * @stream: a #GDataOutputStream. |
236 | | * @data: a #guchar. |
237 | | * @cancellable: (nullable): optional #GCancellable object, %NULL to ignore. |
238 | | * @error: a #GError, %NULL to ignore. |
239 | | * |
240 | | * Puts a byte into the output stream. |
241 | | * |
242 | | * Returns: %TRUE if @data was successfully added to the @stream. |
243 | | **/ |
244 | | gboolean |
245 | | g_data_output_stream_put_byte (GDataOutputStream *stream, |
246 | | guchar data, |
247 | | GCancellable *cancellable, |
248 | | GError **error) |
249 | 0 | { |
250 | 0 | gsize bytes_written; |
251 | | |
252 | 0 | g_return_val_if_fail (G_IS_DATA_OUTPUT_STREAM (stream), FALSE); |
253 | | |
254 | 0 | return g_output_stream_write_all (G_OUTPUT_STREAM (stream), |
255 | 0 | &data, 1, |
256 | 0 | &bytes_written, |
257 | 0 | cancellable, error); |
258 | 0 | } |
259 | | |
260 | | /** |
261 | | * g_data_output_stream_put_int16: |
262 | | * @stream: a #GDataOutputStream. |
263 | | * @data: a #gint16. |
264 | | * @cancellable: (nullable): optional #GCancellable object, %NULL to ignore. |
265 | | * @error: a #GError, %NULL to ignore. |
266 | | * |
267 | | * Puts a signed 16-bit integer into the output stream. |
268 | | * |
269 | | * Returns: %TRUE if @data was successfully added to the @stream. |
270 | | **/ |
271 | | gboolean |
272 | | g_data_output_stream_put_int16 (GDataOutputStream *stream, |
273 | | gint16 data, |
274 | | GCancellable *cancellable, |
275 | | GError **error) |
276 | 0 | { |
277 | 0 | gsize bytes_written; |
278 | | |
279 | 0 | g_return_val_if_fail (G_IS_DATA_OUTPUT_STREAM (stream), FALSE); |
280 | | |
281 | 0 | switch (stream->priv->byte_order) |
282 | 0 | { |
283 | 0 | case G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN: |
284 | 0 | data = GINT16_TO_BE (data); |
285 | 0 | break; |
286 | 0 | case G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN: |
287 | 0 | data = GINT16_TO_LE (data); |
288 | 0 | break; |
289 | 0 | case G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN: |
290 | 0 | default: |
291 | 0 | break; |
292 | 0 | } |
293 | | |
294 | 0 | return g_output_stream_write_all (G_OUTPUT_STREAM (stream), |
295 | 0 | &data, 2, |
296 | 0 | &bytes_written, |
297 | 0 | cancellable, error); |
298 | 0 | } |
299 | | |
300 | | /** |
301 | | * g_data_output_stream_put_uint16: |
302 | | * @stream: a #GDataOutputStream. |
303 | | * @data: a #guint16. |
304 | | * @cancellable: (nullable): optional #GCancellable object, %NULL to ignore. |
305 | | * @error: a #GError, %NULL to ignore. |
306 | | * |
307 | | * Puts an unsigned 16-bit integer into the output stream. |
308 | | * |
309 | | * Returns: %TRUE if @data was successfully added to the @stream. |
310 | | **/ |
311 | | gboolean |
312 | | g_data_output_stream_put_uint16 (GDataOutputStream *stream, |
313 | | guint16 data, |
314 | | GCancellable *cancellable, |
315 | | GError **error) |
316 | 0 | { |
317 | 0 | gsize bytes_written; |
318 | | |
319 | 0 | g_return_val_if_fail (G_IS_DATA_OUTPUT_STREAM (stream), FALSE); |
320 | | |
321 | 0 | switch (stream->priv->byte_order) |
322 | 0 | { |
323 | 0 | case G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN: |
324 | 0 | data = GUINT16_TO_BE (data); |
325 | 0 | break; |
326 | 0 | case G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN: |
327 | 0 | data = GUINT16_TO_LE (data); |
328 | 0 | break; |
329 | 0 | case G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN: |
330 | 0 | default: |
331 | 0 | break; |
332 | 0 | } |
333 | | |
334 | 0 | return g_output_stream_write_all (G_OUTPUT_STREAM (stream), |
335 | 0 | &data, 2, |
336 | 0 | &bytes_written, |
337 | 0 | cancellable, error); |
338 | 0 | } |
339 | | |
340 | | /** |
341 | | * g_data_output_stream_put_int32: |
342 | | * @stream: a #GDataOutputStream. |
343 | | * @data: a #gint32. |
344 | | * @cancellable: (nullable): optional #GCancellable object, %NULL to ignore. |
345 | | * @error: a #GError, %NULL to ignore. |
346 | | * |
347 | | * Puts a signed 32-bit integer into the output stream. |
348 | | * |
349 | | * Returns: %TRUE if @data was successfully added to the @stream. |
350 | | **/ |
351 | | gboolean |
352 | | g_data_output_stream_put_int32 (GDataOutputStream *stream, |
353 | | gint32 data, |
354 | | GCancellable *cancellable, |
355 | | GError **error) |
356 | 0 | { |
357 | 0 | gsize bytes_written; |
358 | | |
359 | 0 | g_return_val_if_fail (G_IS_DATA_OUTPUT_STREAM (stream), FALSE); |
360 | | |
361 | 0 | switch (stream->priv->byte_order) |
362 | 0 | { |
363 | 0 | case G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN: |
364 | 0 | data = GINT32_TO_BE (data); |
365 | 0 | break; |
366 | 0 | case G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN: |
367 | 0 | data = GINT32_TO_LE (data); |
368 | 0 | break; |
369 | 0 | case G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN: |
370 | 0 | default: |
371 | 0 | break; |
372 | 0 | } |
373 | | |
374 | 0 | return g_output_stream_write_all (G_OUTPUT_STREAM (stream), |
375 | 0 | &data, 4, |
376 | 0 | &bytes_written, |
377 | 0 | cancellable, error); |
378 | 0 | } |
379 | | |
380 | | /** |
381 | | * g_data_output_stream_put_uint32: |
382 | | * @stream: a #GDataOutputStream. |
383 | | * @data: a #guint32. |
384 | | * @cancellable: (nullable): optional #GCancellable object, %NULL to ignore. |
385 | | * @error: a #GError, %NULL to ignore. |
386 | | * |
387 | | * Puts an unsigned 32-bit integer into the stream. |
388 | | * |
389 | | * Returns: %TRUE if @data was successfully added to the @stream. |
390 | | **/ |
391 | | gboolean |
392 | | g_data_output_stream_put_uint32 (GDataOutputStream *stream, |
393 | | guint32 data, |
394 | | GCancellable *cancellable, |
395 | | GError **error) |
396 | 0 | { |
397 | 0 | gsize bytes_written; |
398 | | |
399 | 0 | g_return_val_if_fail (G_IS_DATA_OUTPUT_STREAM (stream), FALSE); |
400 | | |
401 | 0 | switch (stream->priv->byte_order) |
402 | 0 | { |
403 | 0 | case G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN: |
404 | 0 | data = GUINT32_TO_BE (data); |
405 | 0 | break; |
406 | 0 | case G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN: |
407 | 0 | data = GUINT32_TO_LE (data); |
408 | 0 | break; |
409 | 0 | case G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN: |
410 | 0 | default: |
411 | 0 | break; |
412 | 0 | } |
413 | | |
414 | 0 | return g_output_stream_write_all (G_OUTPUT_STREAM (stream), |
415 | 0 | &data, 4, |
416 | 0 | &bytes_written, |
417 | 0 | cancellable, error); |
418 | 0 | } |
419 | | |
420 | | /** |
421 | | * g_data_output_stream_put_int64: |
422 | | * @stream: a #GDataOutputStream. |
423 | | * @data: a #gint64. |
424 | | * @cancellable: (nullable): optional #GCancellable object, %NULL to ignore. |
425 | | * @error: a #GError, %NULL to ignore. |
426 | | * |
427 | | * Puts a signed 64-bit integer into the stream. |
428 | | * |
429 | | * Returns: %TRUE if @data was successfully added to the @stream. |
430 | | **/ |
431 | | gboolean |
432 | | g_data_output_stream_put_int64 (GDataOutputStream *stream, |
433 | | gint64 data, |
434 | | GCancellable *cancellable, |
435 | | GError **error) |
436 | 0 | { |
437 | 0 | gsize bytes_written; |
438 | | |
439 | 0 | g_return_val_if_fail (G_IS_DATA_OUTPUT_STREAM (stream), FALSE); |
440 | | |
441 | 0 | switch (stream->priv->byte_order) |
442 | 0 | { |
443 | 0 | case G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN: |
444 | 0 | data = GINT64_TO_BE (data); |
445 | 0 | break; |
446 | 0 | case G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN: |
447 | 0 | data = GINT64_TO_LE (data); |
448 | 0 | break; |
449 | 0 | case G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN: |
450 | 0 | default: |
451 | 0 | break; |
452 | 0 | } |
453 | | |
454 | 0 | return g_output_stream_write_all (G_OUTPUT_STREAM (stream), |
455 | 0 | &data, 8, |
456 | 0 | &bytes_written, |
457 | 0 | cancellable, error); |
458 | 0 | } |
459 | | |
460 | | /** |
461 | | * g_data_output_stream_put_uint64: |
462 | | * @stream: a #GDataOutputStream. |
463 | | * @data: a #guint64. |
464 | | * @cancellable: (nullable): optional #GCancellable object, %NULL to ignore. |
465 | | * @error: a #GError, %NULL to ignore. |
466 | | * |
467 | | * Puts an unsigned 64-bit integer into the stream. |
468 | | * |
469 | | * Returns: %TRUE if @data was successfully added to the @stream. |
470 | | **/ |
471 | | gboolean |
472 | | g_data_output_stream_put_uint64 (GDataOutputStream *stream, |
473 | | guint64 data, |
474 | | GCancellable *cancellable, |
475 | | GError **error) |
476 | 0 | { |
477 | 0 | gsize bytes_written; |
478 | | |
479 | 0 | g_return_val_if_fail (G_IS_DATA_OUTPUT_STREAM (stream), FALSE); |
480 | | |
481 | 0 | switch (stream->priv->byte_order) |
482 | 0 | { |
483 | 0 | case G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN: |
484 | 0 | data = GUINT64_TO_BE (data); |
485 | 0 | break; |
486 | 0 | case G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN: |
487 | 0 | data = GUINT64_TO_LE (data); |
488 | 0 | break; |
489 | 0 | case G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN: |
490 | 0 | default: |
491 | 0 | break; |
492 | 0 | } |
493 | | |
494 | 0 | return g_output_stream_write_all (G_OUTPUT_STREAM (stream), |
495 | 0 | &data, 8, |
496 | 0 | &bytes_written, |
497 | 0 | cancellable, error); |
498 | 0 | } |
499 | | |
500 | | /** |
501 | | * g_data_output_stream_put_string: |
502 | | * @stream: a #GDataOutputStream. |
503 | | * @str: a string. |
504 | | * @cancellable: (nullable): optional #GCancellable object, %NULL to ignore. |
505 | | * @error: a #GError, %NULL to ignore. |
506 | | * |
507 | | * Puts a string into the output stream. |
508 | | * |
509 | | * Returns: %TRUE if @string was successfully added to the @stream. |
510 | | **/ |
511 | | gboolean |
512 | | g_data_output_stream_put_string (GDataOutputStream *stream, |
513 | | const char *str, |
514 | | GCancellable *cancellable, |
515 | | GError **error) |
516 | 0 | { |
517 | 0 | gsize bytes_written; |
518 | | |
519 | 0 | g_return_val_if_fail (G_IS_DATA_OUTPUT_STREAM (stream), FALSE); |
520 | 0 | g_return_val_if_fail (str != NULL, FALSE); |
521 | | |
522 | 0 | return g_output_stream_write_all (G_OUTPUT_STREAM (stream), |
523 | 0 | str, strlen (str), |
524 | 0 | &bytes_written, |
525 | 0 | cancellable, error); |
526 | 0 | } |
527 | | |
528 | | static goffset |
529 | | g_data_output_stream_tell (GSeekable *seekable) |
530 | 0 | { |
531 | 0 | GOutputStream *base_stream; |
532 | 0 | GSeekable *base_stream_seekable; |
533 | |
|
534 | 0 | base_stream = G_FILTER_OUTPUT_STREAM (seekable)->base_stream; |
535 | 0 | if (!G_IS_SEEKABLE (base_stream)) |
536 | 0 | return 0; |
537 | 0 | base_stream_seekable = G_SEEKABLE (base_stream); |
538 | 0 | return g_seekable_tell (base_stream_seekable); |
539 | 0 | } |
540 | | |
541 | | static gboolean |
542 | | g_data_output_stream_can_seek (GSeekable *seekable) |
543 | 0 | { |
544 | 0 | GOutputStream *base_stream; |
545 | | |
546 | 0 | base_stream = G_FILTER_OUTPUT_STREAM (seekable)->base_stream; |
547 | 0 | return G_IS_SEEKABLE (base_stream) && g_seekable_can_seek (G_SEEKABLE (base_stream)); |
548 | 0 | } |
549 | | |
550 | | static gboolean |
551 | | g_data_output_stream_seek (GSeekable *seekable, |
552 | | goffset offset, |
553 | | GSeekType type, |
554 | | GCancellable *cancellable, |
555 | | GError **error) |
556 | 0 | { |
557 | 0 | GOutputStream *base_stream; |
558 | 0 | GSeekable *base_stream_seekable; |
559 | |
|
560 | 0 | base_stream = G_FILTER_OUTPUT_STREAM (seekable)->base_stream; |
561 | 0 | if (!G_IS_SEEKABLE (base_stream)) |
562 | 0 | { |
563 | 0 | g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, |
564 | 0 | _("Seek not supported on base stream")); |
565 | 0 | return FALSE; |
566 | 0 | } |
567 | | |
568 | 0 | base_stream_seekable = G_SEEKABLE (base_stream); |
569 | 0 | return g_seekable_seek (base_stream_seekable, offset, type, cancellable, error); |
570 | 0 | } |
571 | | |
572 | | static gboolean |
573 | | g_data_output_stream_can_truncate (GSeekable *seekable) |
574 | 0 | { |
575 | 0 | GOutputStream *base_stream; |
576 | | |
577 | 0 | base_stream = G_FILTER_OUTPUT_STREAM (seekable)->base_stream; |
578 | 0 | return G_IS_SEEKABLE (base_stream) && g_seekable_can_truncate (G_SEEKABLE (base_stream)); |
579 | 0 | } |
580 | | |
581 | | static gboolean |
582 | | g_data_output_stream_truncate (GSeekable *seekable, |
583 | | goffset offset, |
584 | | GCancellable *cancellable, |
585 | | GError **error) |
586 | 0 | { |
587 | 0 | GOutputStream *base_stream; |
588 | 0 | GSeekable *base_stream_seekable; |
589 | |
|
590 | 0 | base_stream = G_FILTER_OUTPUT_STREAM (seekable)->base_stream; |
591 | 0 | if (!G_IS_SEEKABLE (base_stream)) |
592 | 0 | { |
593 | 0 | g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, |
594 | 0 | _("Truncate not supported on base stream")); |
595 | 0 | return FALSE; |
596 | 0 | } |
597 | | |
598 | 0 | base_stream_seekable = G_SEEKABLE (base_stream); |
599 | 0 | return g_seekable_truncate (base_stream_seekable, offset, cancellable, error); |
600 | 0 | } |