/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ /* camel-simple-data-wrapper-stream.c * * Copyright 1999, 2000 HelixCode (http://www.helixcode.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" #include "camel-simple-data-wrapper.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, wrapper_stream->current_position + 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 (CamelSeekableStream *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 - offset; break; default: g_warning ("Unknown CamelStreamSeekPolicy %d.", policy); return -1; } if (new_position<0) new_position = 0; else if (new_position>=wrapper_stream->wrapper->byte_array->len) new_position = wrapper_stream->wrapper->byte_array->len-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; CamelStreamClass *stream_class; CamelSeekableStreamClass *seek_class; object_class = (GtkObjectClass*) klass; stream_class = (CamelStreamClass *)klass; seek_class = (CamelSeekableStreamClass *)klass; stream_class->read = read; stream_class->write = write; stream_class->flush = flush; stream_class->available = available; stream_class->eos = eos; stream_class->close = close; seek_class->seek = seek; object_class->destroy = destroy; 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 (CAMEL_IS_SIMPLE_DATA_WRAPPER_STREAM (stream)); g_return_if_fail (wrapper != NULL); g_return_if_fail (CAMEL_IS_SIMPLE_DATA_WRAPPER (wrapper)); gtk_object_ref (GTK_OBJECT (wrapper)); stream->wrapper = wrapper; #if 0 gtk_signal_connect (GTK_OBJECT (wrapper), "destroy", wrapper_destroy_cb, stream); #endif } CamelStream * camel_simple_data_wrapper_stream_new (CamelSimpleDataWrapper *wrapper) { CamelStream *stream; g_return_val_if_fail (wrapper != NULL, NULL); g_return_val_if_fail (CAMEL_IS_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; }