2000-02-09 NotZed <notzed@zedzone.helixcode.com> * camel/camel-simple-data-wrapper-stream.c (read): Increment the copy source address to match the data read offset. (seek): Actually implement the seek. svn path=/trunk/; revision=1722
299 lines
7.2 KiB
C
299 lines
7.2 KiB
C
/* -*- 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 <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, 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;
|
||
}
|