From ca7044930f42a698fd88f914c2512a20e2eeaae9 Mon Sep 17 00:00:00 2001 From: Ettore Perazzoli Date: Wed, 17 Nov 1999 14:39:25 +0000 Subject: 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 --- camel/camel-simple-data-wrapper-stream.c | 276 +++++++++++++++++++++++++++++++ 1 file changed, 276 insertions(+) create mode 100644 camel/camel-simple-data-wrapper-stream.c (limited to 'camel/camel-simple-data-wrapper-stream.c') 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 +#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; +} -- cgit v1.2.3