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