1 /* GIO - GLib Input, Output and Streaming Library
3 * Copyright (C) 2006-2007 Red Hat, Inc.
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.
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.
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.
20 * Author: Christian Kellner <gicmo@gnome.org>
24 #include "gmemoryoutputstream.h"
25 #include "goutputstream.h"
26 #include "gseekable.h"
27 #include "gsimpleasyncresult.h"
31 struct _GMemoryOutputStreamPrivate {
47 static void g_memory_output_stream_finalize (GObject *object);
49 static void g_memory_output_stream_set_property (GObject *object,
54 static void g_memory_output_stream_get_property (GObject *object,
59 static gssize g_memory_output_stream_write (GOutputStream *stream,
62 GCancellable *cancellable,
65 static gboolean g_memory_output_stream_close (GOutputStream *stream,
66 GCancellable *cancellable,
69 static void g_memory_output_stream_write_async (GOutputStream *stream,
73 GCancellable *cancellable,
74 GAsyncReadyCallback callback,
76 static gssize g_memory_output_stream_write_finish (GOutputStream *stream,
79 static void g_memory_output_stream_close_async (GOutputStream *stream,
81 GCancellable *cancellable,
82 GAsyncReadyCallback callback,
84 static gboolean g_memory_output_stream_close_finish (GOutputStream *stream,
88 static void g_memory_output_stream_seekable_iface_init (GSeekableIface *iface);
89 static goffset g_memory_output_stream_tell (GSeekable *seekable);
90 static gboolean g_memory_output_stream_can_seek (GSeekable *seekable);
91 static gboolean g_memory_output_stream_seek (GSeekable *seekable,
94 GCancellable *cancellable,
96 static gboolean g_memory_output_stream_can_truncate (GSeekable *seekable);
97 static gboolean g_memory_output_stream_truncate (GSeekable *seekable,
99 GCancellable *cancellable,
102 G_DEFINE_TYPE_WITH_CODE (GMemoryOutputStream, g_memory_output_stream, G_TYPE_OUTPUT_STREAM,
103 G_IMPLEMENT_INTERFACE (G_TYPE_SEEKABLE,
104 g_memory_output_stream_seekable_iface_init))
108 g_memory_output_stream_class_init (GMemoryOutputStreamClass *klass)
110 GOutputStreamClass *ostream_class;
111 GObjectClass *gobject_class;
113 g_type_class_add_private (klass, sizeof (GMemoryOutputStreamPrivate));
115 gobject_class = G_OBJECT_CLASS (klass);
116 gobject_class->finalize = g_memory_output_stream_finalize;
117 gobject_class->get_property = g_memory_output_stream_get_property;
118 gobject_class->set_property = g_memory_output_stream_set_property;
120 ostream_class = G_OUTPUT_STREAM_CLASS (klass);
122 ostream_class->write = g_memory_output_stream_write;
123 ostream_class->close = g_memory_output_stream_close;
124 ostream_class->write_async = g_memory_output_stream_write_async;
125 ostream_class->write_finish = g_memory_output_stream_write_finish;
126 ostream_class->close_async = g_memory_output_stream_close_async;
127 ostream_class->close_finish = g_memory_output_stream_close_finish;
129 g_object_class_install_property (gobject_class,
131 g_param_spec_pointer ("data",
132 P_("Data byte array"),
133 P_("The byte array used as internal storage."),
134 G_PARAM_READWRITE | G_PARAM_CONSTRUCT |
135 G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB));
137 g_object_class_install_property (gobject_class,
139 g_param_spec_boolean ("free-array",
140 P_("Free array data"),
141 P_("Wether or not the interal array should be free on close."),
144 G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB));
145 g_object_class_install_property (gobject_class,
147 g_param_spec_uint ("size-limit",
149 P_("Maximum amount of bytes that can be written to the stream."),
154 G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB));
160 g_memory_output_stream_finalize (GObject *object)
162 GMemoryOutputStream *stream;
164 stream = G_MEMORY_OUTPUT_STREAM (object);
166 if (stream->priv->free_data)
167 g_byte_array_free (stream->priv->data, TRUE);
169 if (G_OBJECT_CLASS (g_memory_output_stream_parent_class)->finalize)
170 (*G_OBJECT_CLASS (g_memory_output_stream_parent_class)->finalize) (object);
174 g_memory_output_stream_seekable_iface_init (GSeekableIface *iface)
176 iface->tell = g_memory_output_stream_tell;
177 iface->can_seek = g_memory_output_stream_can_seek;
178 iface->seek = g_memory_output_stream_seek;
179 iface->can_truncate = g_memory_output_stream_can_truncate;
180 iface->truncate = g_memory_output_stream_truncate;
185 g_memory_output_stream_init (GMemoryOutputStream *stream)
187 GMemoryOutputStreamPrivate *priv;
189 stream->priv = G_TYPE_INSTANCE_GET_PRIVATE (stream,
190 G_TYPE_MEMORY_OUTPUT_STREAM,
191 GMemoryOutputStreamPrivate);
198 * g_memory_output_stream_new:
199 * @data: a #GByteArray.
201 * Creates a new #GMemoryOutputStream. If @data is non-%NULL it will use
202 * that for its internal storage otherwise it will create a new #GByteArray.
203 * In both cases the internal #GByteArray can later be accessed through the
206 * Note: The new stream will not take ownership of the supplied
207 * @data so you have to free it yourself after use or explicitly
208 * ask for it be freed on close by setting the "free-array"
211 * Return value: A newly created #GMemoryOutputStream object.
214 g_memory_output_stream_new (GByteArray *data)
216 GOutputStream *stream;
219 stream = g_object_new (G_TYPE_MEMORY_OUTPUT_STREAM, NULL);
221 stream = g_object_new (G_TYPE_MEMORY_OUTPUT_STREAM,
230 * g_memory_output_stream_set_free_data:
236 g_memory_output_stream_set_free_data (GMemoryOutputStream *ostream,
239 GMemoryOutputStreamPrivate *priv;
241 g_return_if_fail (G_IS_MEMORY_OUTPUT_STREAM (ostream));
243 priv = ostream->priv;
245 priv->free_data = free_data;
249 * g_memory_output_stream_set_max_size:
255 g_memory_output_stream_set_max_size (GMemoryOutputStream *ostream,
258 GMemoryOutputStreamPrivate *priv;
260 g_return_if_fail (G_IS_MEMORY_OUTPUT_STREAM (ostream));
262 priv = ostream->priv;
264 priv->max_size = max_size;
266 if (priv->max_size > 0 &&
267 priv->max_size < priv->data->len) {
269 g_byte_array_set_size (priv->data, priv->max_size);
271 if (priv->pos > priv->max_size) {
272 priv->pos = priv->max_size;
276 g_object_notify (G_OBJECT (ostream), "size-limit");
280 g_memory_output_stream_set_property (GObject *object,
285 GMemoryOutputStream *ostream;
286 GMemoryOutputStreamPrivate *priv;
290 ostream = G_MEMORY_OUTPUT_STREAM (object);
291 priv = ostream->priv;
297 if (priv->data && priv->free_data) {
298 g_byte_array_free (priv->data, TRUE);
301 data = g_value_get_pointer (value);
304 data = g_byte_array_new ();
305 priv->free_data = TRUE;
307 priv->free_data = FALSE;
312 g_object_notify (G_OBJECT (ostream), "data");
315 case PROP_FREE_ARRAY:
316 priv->free_data = g_value_get_boolean (value);
319 case PROP_SIZE_LIMIT:
320 max_size = g_value_get_uint (value);
321 g_memory_output_stream_set_max_size (ostream, max_size);
325 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
331 g_memory_output_stream_get_property (GObject *object,
336 GMemoryOutputStream *ostream;
337 GMemoryOutputStreamPrivate *priv;
339 ostream = G_MEMORY_OUTPUT_STREAM (object);
340 priv = ostream->priv;
345 g_value_set_pointer (value, priv->data);
348 case PROP_FREE_ARRAY:
349 g_value_set_boolean (value, priv->free_data);
352 case PROP_SIZE_LIMIT:
353 g_value_set_uint (value, priv->max_size);
357 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
363 * g_memory_output_stream_get_data:
366 * Returns: #GByteArray of the stream's data.
369 g_memory_output_stream_get_data (GMemoryOutputStream *ostream)
371 g_return_val_if_fail (G_IS_MEMORY_OUTPUT_STREAM (ostream), NULL);
373 return ostream->priv->data;
378 array_check_boundary (GMemoryOutputStream *stream,
382 GMemoryOutputStreamPrivate *priv;
386 if (! priv->max_size) {
390 if (priv->max_size < size || size > G_MAXUINT) {
395 "Reached maximum data array limit");
404 array_resize (GMemoryOutputStream *stream,
408 GMemoryOutputStreamPrivate *priv;
413 if (! array_check_boundary (stream, size, error))
417 if (priv->data->len == size)
418 return priv->data->len - priv->pos;
421 old_len = priv->data->len;
422 g_byte_array_set_size (priv->data, size);
424 if (size > old_len && priv->pos > old_len)
425 memset (priv->data->data + priv->pos, 0, size - old_len);
428 return priv->data->len - priv->pos;
432 g_memory_output_stream_write (GOutputStream *stream,
435 GCancellable *cancellable,
438 GMemoryOutputStream *ostream;
439 GMemoryOutputStreamPrivate *priv;
444 ostream = G_MEMORY_OUTPUT_STREAM (stream);
445 priv = ostream->priv;
447 /* count < 0 is ensured by GOutputStream */
449 n = MIN (count, priv->data->len - priv->pos);
453 new_size = priv->pos + count;
455 if (priv->max_size > 0)
457 new_size = MIN (new_size, priv->max_size);
460 n = array_resize (ostream, new_size, error);
467 "Reached maximum data array limit");
476 dest = priv->data->data + priv->pos;
477 memcpy (dest, buffer, n);
484 g_memory_output_stream_close (GOutputStream *stream,
485 GCancellable *cancellable,
488 GMemoryOutputStream *ostream;
489 GMemoryOutputStreamPrivate *priv;
491 ostream = G_MEMORY_OUTPUT_STREAM (stream);
492 priv = ostream->priv;
498 g_memory_output_stream_write_async (GOutputStream *stream,
502 GCancellable *cancellable,
503 GAsyncReadyCallback callback,
506 GSimpleAsyncResult *simple;
509 nwritten = g_memory_output_stream_write (stream,
516 simple = g_simple_async_result_new (G_OBJECT (stream),
519 g_memory_output_stream_write_async);
521 g_simple_async_result_set_op_res_gssize (simple, nwritten);
522 g_simple_async_result_complete_in_idle (simple);
523 g_object_unref (simple);
528 g_memory_output_stream_write_finish (GOutputStream *stream,
529 GAsyncResult *result,
532 GSimpleAsyncResult *simple;
535 simple = G_SIMPLE_ASYNC_RESULT (result);
537 g_assert (g_simple_async_result_get_source_tag (simple) ==
538 g_memory_output_stream_write_async);
540 nwritten = g_simple_async_result_get_op_res_gssize (simple);
545 g_memory_output_stream_close_async (GOutputStream *stream,
547 GCancellable *cancellable,
548 GAsyncReadyCallback callback,
551 GSimpleAsyncResult *simple;
553 simple = g_simple_async_result_new (G_OBJECT (stream),
556 g_memory_output_stream_close_async);
559 /* will always return TRUE */
560 g_memory_output_stream_close (stream, cancellable, NULL);
562 g_simple_async_result_complete_in_idle (simple);
563 g_object_unref (simple);
568 g_memory_output_stream_close_finish (GOutputStream *stream,
569 GAsyncResult *result,
572 GSimpleAsyncResult *simple;
574 simple = G_SIMPLE_ASYNC_RESULT (result);
576 g_assert (g_simple_async_result_get_source_tag (simple) ==
577 g_memory_output_stream_close_async);
584 g_memory_output_stream_tell (GSeekable *seekable)
586 GMemoryOutputStream *stream;
587 GMemoryOutputStreamPrivate *priv;
589 stream = G_MEMORY_OUTPUT_STREAM (seekable);
596 g_memory_output_stream_can_seek (GSeekable *seekable)
602 g_memory_output_stream_seek (GSeekable *seekable,
605 GCancellable *cancellable,
608 GMemoryOutputStream *stream;
609 GMemoryOutputStreamPrivate *priv;
612 stream = G_MEMORY_OUTPUT_STREAM (seekable);
618 absolute = priv->pos + offset;
626 absolute = priv->data->len + offset;
632 G_IO_ERROR_INVALID_ARGUMENT,
633 "Invalid GSeekType supplied");
641 G_IO_ERROR_INVALID_ARGUMENT,
642 "Invalid seek request");
646 if (! array_check_boundary (stream, absolute, error))
649 priv->pos = absolute;
655 g_memory_output_stream_can_truncate (GSeekable *seekable)
661 g_memory_output_stream_truncate (GSeekable *seekable,
663 GCancellable *cancellable,
666 GMemoryOutputStream *ostream;
667 GMemoryOutputStreamPrivate *priv;
669 ostream = G_MEMORY_OUTPUT_STREAM (seekable);
670 priv = ostream->priv;
672 if (array_resize (ostream, offset, error) < 0)
678 /* vim: ts=2 sw=2 et */