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