giomodule test: force shared library build
[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_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 {
88   GObjectClass *object_class;
89
90   object_class = G_OBJECT_CLASS (klass);
91   object_class->get_property = g_data_output_stream_get_property;
92   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   g_object_class_install_property (object_class,
101                                    PROP_BYTE_ORDER,
102                                    g_param_spec_enum ("byte-order",
103                                                       P_("Byte order"),
104                                                       P_("The byte order"),
105                                                       G_TYPE_DATA_STREAM_BYTE_ORDER,
106                                                       G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN,
107                                                       G_PARAM_READWRITE|G_PARAM_STATIC_NAME|G_PARAM_STATIC_BLURB));
108
109 }
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 {
117   GDataOutputStream *dstream;
118
119   dstream = G_DATA_OUTPUT_STREAM (object);
120
121   switch (prop_id) 
122     {
123     case PROP_BYTE_ORDER:
124       g_data_output_stream_set_byte_order (dstream, g_value_get_enum (value));
125       break;
126
127     default:
128       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
129       break;
130     }
131 }
132
133 static void
134 g_data_output_stream_get_property (GObject    *object,
135                                    guint       prop_id,
136                                    GValue     *value,
137                                    GParamSpec *pspec)
138 {
139   GDataOutputStreamPrivate *priv;
140   GDataOutputStream        *dstream;
141
142   dstream = G_DATA_OUTPUT_STREAM (object);
143   priv = dstream->priv;
144
145   switch (prop_id)
146     {
147     case PROP_BYTE_ORDER:
148       g_value_set_enum (value, priv->byte_order);
149       break;
150
151     default:
152       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
153       break;
154     }
155 }
156
157 static void
158 g_data_output_stream_init (GDataOutputStream *stream)
159 {
160   stream->priv = g_data_output_stream_get_instance_private (stream);
161   stream->priv->byte_order = G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN;
162 }
163
164 static void
165 g_data_output_stream_seekable_iface_init (GSeekableIface *iface)
166 {
167   iface->tell         = g_data_output_stream_tell;
168   iface->can_seek     = g_data_output_stream_can_seek;
169   iface->seek         = g_data_output_stream_seek;
170   iface->can_truncate = g_data_output_stream_can_truncate;
171   iface->truncate_fn  = g_data_output_stream_truncate;
172 }
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 {
185   GDataOutputStream *stream;
186
187   g_return_val_if_fail (G_IS_OUTPUT_STREAM (base_stream), NULL);
188
189   stream = g_object_new (G_TYPE_DATA_OUTPUT_STREAM,
190                          "base-stream", base_stream,
191                          NULL);
192
193   return stream;
194 }
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 {
207   GDataOutputStreamPrivate *priv;
208   g_return_if_fail (G_IS_DATA_OUTPUT_STREAM (stream));
209   priv = stream->priv;
210   if (priv->byte_order != order)
211     {
212       priv->byte_order = order;
213       g_object_notify (G_OBJECT (stream), "byte-order");
214     }
215 }
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 {
228   g_return_val_if_fail (G_IS_DATA_OUTPUT_STREAM (stream), G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN);
229
230   return stream->priv->byte_order;
231 }
232
233 /**
234  * g_data_output_stream_put_byte:
235  * @stream: a #GDataOutputStream.
236  * @data: a #guchar.
237  * @cancellable: (allow-none): 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 {
250   gsize bytes_written;
251   
252   g_return_val_if_fail (G_IS_DATA_OUTPUT_STREAM (stream), FALSE);
253
254   return g_output_stream_write_all (G_OUTPUT_STREAM (stream),
255                                     &data, 1,
256                                     &bytes_written,
257                                     cancellable, error);
258 }
259
260 /**
261  * g_data_output_stream_put_int16:
262  * @stream: a #GDataOutputStream.
263  * @data: a #gint16.
264  * @cancellable: (allow-none): 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 {
277   gsize bytes_written;
278   
279   g_return_val_if_fail (G_IS_DATA_OUTPUT_STREAM (stream), FALSE);
280
281   switch (stream->priv->byte_order)
282     {
283     case G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN:
284       data = GINT16_TO_BE (data);
285       break;
286     case G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN:
287       data = GINT16_TO_LE (data);
288       break;
289     case G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN:
290     default:
291       break;
292     }
293   
294   return g_output_stream_write_all (G_OUTPUT_STREAM (stream),
295                                     &data, 2,
296                                     &bytes_written,
297                                     cancellable, error);
298 }
299
300 /**
301  * g_data_output_stream_put_uint16:
302  * @stream: a #GDataOutputStream.
303  * @data: a #guint16.
304  * @cancellable: (allow-none): 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 {
317   gsize bytes_written;
318   
319   g_return_val_if_fail (G_IS_DATA_OUTPUT_STREAM (stream), FALSE);
320
321   switch (stream->priv->byte_order)
322     {
323     case G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN:
324       data = GUINT16_TO_BE (data);
325       break;
326     case G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN:
327       data = GUINT16_TO_LE (data);
328       break;
329     case G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN:
330     default:
331       break;
332     }
333   
334   return g_output_stream_write_all (G_OUTPUT_STREAM (stream),
335                                     &data, 2,
336                                     &bytes_written,
337                                     cancellable, error);
338 }
339
340 /**
341  * g_data_output_stream_put_int32:
342  * @stream: a #GDataOutputStream.
343  * @data: a #gint32.
344  * @cancellable: (allow-none): 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 {
357   gsize bytes_written;
358   
359   g_return_val_if_fail (G_IS_DATA_OUTPUT_STREAM (stream), FALSE);
360
361   switch (stream->priv->byte_order)
362     {
363     case G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN:
364       data = GINT32_TO_BE (data);
365       break;
366     case G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN:
367       data = GINT32_TO_LE (data);
368       break;
369     case G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN:
370     default:
371       break;
372     }
373   
374   return g_output_stream_write_all (G_OUTPUT_STREAM (stream),
375                                     &data, 4,
376                                     &bytes_written,
377                                     cancellable, error);
378 }
379
380 /**
381  * g_data_output_stream_put_uint32:
382  * @stream: a #GDataOutputStream.
383  * @data: a #guint32.
384  * @cancellable: (allow-none): 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 {
397   gsize bytes_written;
398   
399   g_return_val_if_fail (G_IS_DATA_OUTPUT_STREAM (stream), FALSE);
400
401   switch (stream->priv->byte_order)
402     {
403     case G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN:
404       data = GUINT32_TO_BE (data);
405       break;
406     case G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN:
407       data = GUINT32_TO_LE (data);
408       break;
409     case G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN:
410     default:
411       break;
412     }
413   
414   return g_output_stream_write_all (G_OUTPUT_STREAM (stream),
415                                     &data, 4,
416                                     &bytes_written,
417                                     cancellable, error);
418 }
419
420 /**
421  * g_data_output_stream_put_int64:
422  * @stream: a #GDataOutputStream.
423  * @data: a #gint64.
424  * @cancellable: (allow-none): 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 {
437   gsize bytes_written;
438   
439   g_return_val_if_fail (G_IS_DATA_OUTPUT_STREAM (stream), FALSE);
440
441   switch (stream->priv->byte_order)
442     {
443     case G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN:
444       data = GINT64_TO_BE (data);
445       break;
446     case G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN:
447       data = GINT64_TO_LE (data);
448       break;
449     case G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN:
450     default:
451       break;
452     }
453   
454   return g_output_stream_write_all (G_OUTPUT_STREAM (stream),
455                                     &data, 8,
456                                     &bytes_written,
457                                     cancellable, error);
458 }
459
460 /**
461  * g_data_output_stream_put_uint64:
462  * @stream: a #GDataOutputStream.
463  * @data: a #guint64.
464  * @cancellable: (allow-none): 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 {
477   gsize bytes_written;
478   
479   g_return_val_if_fail (G_IS_DATA_OUTPUT_STREAM (stream), FALSE);
480
481   switch (stream->priv->byte_order)
482     {
483     case G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN:
484       data = GUINT64_TO_BE (data);
485       break;
486     case G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN:
487       data = GUINT64_TO_LE (data);
488       break;
489     case G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN:
490     default:
491       break;
492     }
493   
494   return g_output_stream_write_all (G_OUTPUT_STREAM (stream),
495                                     &data, 8,
496                                     &bytes_written,
497                                     cancellable, error);
498 }
499
500 /**
501  * g_data_output_stream_put_string:
502  * @stream: a #GDataOutputStream.
503  * @str: a string.
504  * @cancellable: (allow-none): 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 {
517   gsize bytes_written;
518   
519   g_return_val_if_fail (G_IS_DATA_OUTPUT_STREAM (stream), FALSE);
520   g_return_val_if_fail (str != NULL, FALSE);
521
522   return g_output_stream_write_all (G_OUTPUT_STREAM (stream),
523                                     str, strlen (str),
524                                     &bytes_written,
525                                     cancellable, error);
526 }
527
528 static goffset
529 g_data_output_stream_tell (GSeekable *seekable)
530 {
531   GOutputStream *base_stream;
532   GSeekable *base_stream_seekable;
533
534   base_stream = G_FILTER_OUTPUT_STREAM (seekable)->base_stream;
535   if (!G_IS_SEEKABLE (base_stream))
536     return 0;
537   base_stream_seekable = G_SEEKABLE (base_stream);
538   return g_seekable_tell (base_stream_seekable);
539 }
540
541 static gboolean
542 g_data_output_stream_can_seek (GSeekable *seekable)
543 {
544   GOutputStream *base_stream;
545   
546   base_stream = G_FILTER_OUTPUT_STREAM (seekable)->base_stream;
547   return G_IS_SEEKABLE (base_stream) && g_seekable_can_seek (G_SEEKABLE (base_stream));
548 }
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 {
557   GOutputStream *base_stream;
558   GSeekable *base_stream_seekable;
559
560   base_stream = G_FILTER_OUTPUT_STREAM (seekable)->base_stream;
561   if (!G_IS_SEEKABLE (base_stream))
562     {
563       g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
564                            _("Seek not supported on base stream"));
565       return FALSE;
566     }
567
568   base_stream_seekable = G_SEEKABLE (base_stream);
569   return g_seekable_seek (base_stream_seekable, offset, type, cancellable, error);
570 }
571
572 static gboolean
573 g_data_output_stream_can_truncate (GSeekable *seekable)
574 {
575   GOutputStream *base_stream;
576   
577   base_stream = G_FILTER_OUTPUT_STREAM (seekable)->base_stream;
578   return G_IS_SEEKABLE (base_stream) && g_seekable_can_truncate (G_SEEKABLE (base_stream));
579 }
580
581 static gboolean
582 g_data_output_stream_truncate (GSeekable     *seekable,
583                                    goffset        offset,
584                                    GCancellable  *cancellable,
585                                    GError       **error)
586 {
587   GOutputStream *base_stream;
588   GSeekable *base_stream_seekable;
589
590   base_stream = G_FILTER_OUTPUT_STREAM (seekable)->base_stream;
591   if (!G_IS_SEEKABLE (base_stream))
592     {
593       g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
594                            _("Truncate not supported on base stream"));
595       return FALSE;
596     }
597
598   base_stream_seekable = G_SEEKABLE (base_stream);
599   return g_seekable_truncate (base_stream_seekable, offset, cancellable, error);
600 }