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