aboutsummaryrefslogtreecommitdiffstats
path: root/camel/camel-simple-data-wrapper-stream.c
diff options
context:
space:
mode:
authorEttore Perazzoli <ettore@src.gnome.org>1999-11-17 22:39:25 +0800
committerEttore Perazzoli <ettore@src.gnome.org>1999-11-17 22:39:25 +0800
commitca7044930f42a698fd88f914c2512a20e2eeaae9 (patch)
tree522962a77005d741097713e87de1d50353b17768 /camel/camel-simple-data-wrapper-stream.c
parent16de3313b700cb56ab9e829d1e9b7e7d2c81241b (diff)
downloadgsoc2013-evolution-ca7044930f42a698fd88f914c2512a20e2eeaae9.tar.gz
gsoc2013-evolution-ca7044930f42a698fd88f914c2512a20e2eeaae9.tar.zst
gsoc2013-evolution-ca7044930f42a698fd88f914c2512a20e2eeaae9.zip
Added streaming capability to CamelDataWrapper. This makes it possible, for
example, to build multipart messages out of files that are on disk without loading them in memory. svn path=/trunk/; revision=1394
Diffstat (limited to 'camel/camel-simple-data-wrapper-stream.c')
-rw-r--r--camel/camel-simple-data-wrapper-stream.c276
1 files changed, 276 insertions, 0 deletions
diff --git a/camel/camel-simple-data-wrapper-stream.c b/camel/camel-simple-data-wrapper-stream.c
new file mode 100644
index 0000000000..8c45c7530d
--- /dev/null
+++ b/camel/camel-simple-data-wrapper-stream.c
@@ -0,0 +1,276 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/* camel-simple-data-wrapper-stream.c
+ *
+ * Copyright 1999 International GNOME Support (http://www.gnome-support.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Ettore Perazzoli
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "camel-simple-data-wrapper-stream.h"
+
+
+static CamelStreamClass *parent_class = NULL;
+
+
+/* CamelStream methods. */
+
+static gint
+read (CamelStream *stream,
+ gchar *buffer,
+ gint n)
+{
+ CamelSimpleDataWrapperStream *wrapper_stream;
+ CamelSimpleDataWrapper *wrapper;
+ GByteArray *array;
+ gint len;
+
+ wrapper_stream = CAMEL_SIMPLE_DATA_WRAPPER_STREAM (stream);
+ wrapper = wrapper_stream->wrapper;
+ g_return_val_if_fail (wrapper != NULL, -1);
+ array = wrapper->byte_array;
+
+ len = MIN (n, array->len - wrapper_stream->current_position);
+ if (len > 0) {
+ memcpy (buffer, array->data, len);
+ wrapper_stream->current_position += len;
+ return len;
+ } else {
+ return 0;
+ }
+}
+
+static gint
+write (CamelStream *stream,
+ const gchar *buffer,
+ gint n)
+{
+ CamelSimpleDataWrapperStream *wrapper_stream;
+ CamelSimpleDataWrapper *wrapper;
+ GByteArray *array;
+ gint len;
+ const gchar *buffer_next;
+ gint left;
+
+ wrapper_stream = CAMEL_SIMPLE_DATA_WRAPPER_STREAM (stream);
+ wrapper = wrapper_stream->wrapper;
+ g_return_val_if_fail (wrapper != NULL, -1);
+ array = wrapper->byte_array;
+
+ len = MIN (n, array->len - wrapper_stream->current_position);
+ if (len > 0) {
+ memcpy (array->data, buffer, len);
+ buffer_next = buffer + len;
+ left = n - len;
+ } else {
+ /* If we are past the end of the array, fill with zeros. */
+ if (wrapper_stream->current_position > array->len) {
+ gint saved_length;
+
+ saved_length = array->len;
+ g_byte_array_set_size
+ (array, wrapper_stream->current_position);
+ memset (array->data + saved_length,
+ 0,
+ (wrapper_stream->current_position
+ - saved_length));
+ }
+
+ buffer_next = buffer;
+ left = n;
+ }
+
+ if (n > 0)
+ g_byte_array_append (array, buffer_next, left);
+
+ wrapper_stream->current_position += n;
+ return n;
+}
+
+static void
+flush (CamelStream *stream)
+{
+ /* No op, as we don't do any buffering. */
+}
+
+static gint
+available (CamelStream *stream)
+{
+ CamelSimpleDataWrapperStream *wrapper_stream;
+ CamelSimpleDataWrapper *wrapper;
+ GByteArray *array;
+ gint available;
+
+ wrapper_stream = CAMEL_SIMPLE_DATA_WRAPPER_STREAM (stream);
+ wrapper = wrapper_stream->wrapper;
+ g_return_val_if_fail (wrapper != NULL, -1);
+ array = wrapper->byte_array;
+
+ available = array->len - wrapper_stream->current_position;
+ return MAX (available, 0);
+}
+
+static gboolean
+eos (CamelStream *stream)
+{
+ if (available (stream) > 0)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+static void
+close (CamelStream *stream)
+{
+ /* Nothing to do, we have no associated file descriptor. */
+}
+
+static gint
+seek (CamelStream *stream,
+ gint offset,
+ CamelStreamSeekPolicy policy)
+{
+ CamelSimpleDataWrapperStream *wrapper_stream;
+ gint new_position;
+
+ wrapper_stream = CAMEL_SIMPLE_DATA_WRAPPER_STREAM (stream);
+
+ switch (policy) {
+ case CAMEL_STREAM_SET:
+ new_position = offset;
+ break;
+ case CAMEL_STREAM_CUR:
+ new_position = wrapper_stream->current_position + offset;
+ break;
+ case CAMEL_STREAM_END:
+ new_position = wrapper_stream->wrapper->byte_array->len;
+ break;
+ default:
+ g_warning ("Unknown CamelStreamSeekPolicy %d.", policy);
+ return -1;
+ }
+
+ wrapper_stream->current_position = new_position;
+ return new_position;
+}
+
+
+/* This handles destruction of the associated CamelDataWrapper. */
+/* Hm, this should never happen though, because we gtk_object_ref() the
+ wrapper. */
+static void
+wrapper_destroy_cb (GtkObject *object,
+ gpointer data)
+{
+ CamelSimpleDataWrapperStream *stream;
+
+ g_warning ("CamelSimpleDataWrapperStream: associated CamelSimpleDataWrapper was destroyed.");
+ stream = CAMEL_SIMPLE_DATA_WRAPPER_STREAM (object);
+ stream->wrapper = NULL;
+}
+
+
+/* GtkObject methods. */
+
+static void
+destroy (GtkObject *object)
+{
+ CamelSimpleDataWrapperStream *stream;
+
+ stream = CAMEL_SIMPLE_DATA_WRAPPER_STREAM (object);
+
+ gtk_object_unref (GTK_OBJECT (stream->wrapper));
+
+ if (GTK_OBJECT_CLASS (parent_class)->destroy != NULL)
+ (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
+}
+
+
+static void
+class_init (CamelSimpleDataWrapperStreamClass *klass)
+{
+ GtkObjectClass *object_class;
+
+ object_class = (GtkObjectClass*) klass;
+
+ parent_class = gtk_type_class (camel_stream_get_type ());
+}
+
+static void
+init (CamelSimpleDataWrapperStream *simple_data_wrapper_stream)
+{
+ simple_data_wrapper_stream->current_position = 0;
+}
+
+
+GtkType
+camel_simple_data_wrapper_stream_get_type (void)
+{
+ static GtkType type = 0;
+
+ if (type == 0) {
+ static const GtkTypeInfo info = {
+ "CamelSimpleDataWrapperStream",
+ sizeof (CamelSimpleDataWrapperStream),
+ sizeof (CamelSimpleDataWrapperStreamClass),
+ (GtkClassInitFunc) class_init,
+ (GtkObjectInitFunc) init,
+ /* reserved_1 */ NULL,
+ /* reserved_2 */ NULL,
+ (GtkClassInitFunc) NULL,
+ };
+
+ type = gtk_type_unique (camel_stream_get_type (), &info);
+ }
+
+ return type;
+}
+
+void
+camel_simple_data_wrapper_stream_construct (CamelSimpleDataWrapperStream *stream,
+ CamelSimpleDataWrapper *wrapper)
+{
+ g_return_if_fail (stream != NULL);
+ g_return_if_fail (IS_CAMEL_SIMPLE_DATA_WRAPPER_STREAM (stream));
+ g_return_if_fail (wrapper != NULL);
+ g_return_if_fail (IS_CAMEL_SIMPLE_DATA_WRAPPER (wrapper));
+
+ gtk_object_ref (GTK_OBJECT (wrapper));
+ stream->wrapper = wrapper;
+ gtk_signal_connect (GTK_OBJECT (wrapper), "destroy",
+ wrapper_destroy_cb, stream);
+}
+
+CamelStream *
+camel_simple_data_wrapper_stream_new (CamelSimpleDataWrapper *wrapper)
+{
+ CamelStream *stream;
+
+ g_return_val_if_fail (wrapper != NULL, NULL);
+ g_return_val_if_fail (IS_CAMEL_SIMPLE_DATA_WRAPPER (wrapper), NULL);
+
+ stream = gtk_type_new (camel_simple_data_wrapper_stream_get_type ());
+
+ camel_simple_data_wrapper_stream_construct
+ (CAMEL_SIMPLE_DATA_WRAPPER_STREAM (stream), wrapper);
+
+ return stream;
+}