aboutsummaryrefslogtreecommitdiffstats
path: root/camel/camel-seekable-substream.c
diff options
context:
space:
mode:
authorDan Winship <danw@src.gnome.org>2000-04-20 06:50:32 +0800
committerDan Winship <danw@src.gnome.org>2000-04-20 06:50:32 +0800
commit52d16fdd6399ddb106d42a94d8b517cd5b6621d2 (patch)
tree116bc18d5d6b7c81d8d78fa6326a5504fa86771e /camel/camel-seekable-substream.c
parent435ef42f7108cecefd0ed36bb4929d5bc4f1fb68 (diff)
downloadgsoc2013-evolution-52d16fdd6399ddb106d42a94d8b517cd5b6621d2.tar.gz
gsoc2013-evolution-52d16fdd6399ddb106d42a94d8b517cd5b6621d2.tar.zst
gsoc2013-evolution-52d16fdd6399ddb106d42a94d8b517cd5b6621d2.zip
clean up a lot. (eos): When testing for end-of-stream, reset the parent
* camel-seekable-substream.c: clean up a lot. (eos): When testing for end-of-stream, reset the parent position before testing if it is at end-of-stream, since either (a) it may have been seek'ed to eos by someone else, or (b) we may have been seek'ed away from eos and it hasn't been synced yet. svn path=/trunk/; revision=2519
Diffstat (limited to 'camel/camel-seekable-substream.c')
-rw-r--r--camel/camel-seekable-substream.c479
1 files changed, 188 insertions, 291 deletions
diff --git a/camel/camel-seekable-substream.c b/camel/camel-seekable-substream.c
index 3c9534e326..59f53c3090 100644
--- a/camel/camel-seekable-substream.c
+++ b/camel/camel-seekable-substream.c
@@ -1,16 +1,15 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/* camel-stream-fs.c : file system based stream */
-/* inspired by gnome-stream-fs.c in bonobo by Miguel de Icaza */
-/*
+/*
*
- * Author :
+ * Author :
* Bertrand Guiheneuf <bertrand@helixcode.com>
*
* Copyright 1999, 2000 Helix Code, Inc. (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
+ * 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.
*
@@ -27,120 +26,91 @@
#include <config.h>
#include "camel-seekable-substream.h"
-static CamelSeekableStreamClass *parent_class=NULL;
-
+static CamelSeekableStreamClass *parent_class = NULL;
/* Returns the class for a CamelSeekableSubStream */
#define CSS_CLASS(so) CAMEL_SEEKABLE_SUBSTREAM_CLASS (GTK_OBJECT(so)->klass)
-
-
-
-static gint _read (CamelStream *stream,
- gchar *buffer, gint n);
-static gint _write (CamelStream *stream,
- const gchar *buffer,
- gint n);
-static void _flush (CamelStream *stream);
-static gint _available (CamelStream *stream);
-static gboolean _eos (CamelStream *stream);
-static void _close (CamelStream *stream);
-static gint _seek (CamelSeekableStream *stream,
- gint offset,
- CamelStreamSeekPolicy policy);
-
-static void _finalize (GtkObject *object);
-static void _destroy (GtkObject *object);
-
-static void _init_with_seekable_stream_and_bounds (CamelSeekableSubstream *seekable_substream,
+static gint stream_read (CamelStream *stream,
+ gchar *buffer, gint n);
+static gint stream_write (CamelStream *stream,
+ const gchar *buffer,
+ gint n);
+static void stream_flush (CamelStream *stream);
+static gint available (CamelStream *stream);
+static gboolean eos (CamelStream *stream);
+static gint stream_seek (CamelSeekableStream *stream,
+ gint offset,
+ CamelStreamSeekPolicy policy);
+
+static void finalize (GtkObject *object);
+
+static void init_with_seekable_stream_and_bounds (CamelSeekableSubstream *seekable_substream,
CamelSeekableStream *parent_stream,
- guint32 inf_bound,
+ guint32 inf_bound,
gint64 sup_bound);
-
static void
camel_seekable_substream_class_init (CamelSeekableSubstreamClass *camel_seekable_substream_class)
{
- CamelSeekableStreamClass *camel_seekable_stream_class = CAMEL_SEEKABLE_STREAM_CLASS (camel_seekable_substream_class);
- CamelStreamClass *camel_stream_class = CAMEL_STREAM_CLASS (camel_seekable_substream_class);
- GtkObjectClass *gtk_object_class = GTK_OBJECT_CLASS (camel_seekable_substream_class);
+ CamelSeekableStreamClass *camel_seekable_stream_class =
+ CAMEL_SEEKABLE_STREAM_CLASS (camel_seekable_substream_class);
+ CamelStreamClass *camel_stream_class =
+ CAMEL_STREAM_CLASS (camel_seekable_substream_class);
+ GtkObjectClass *gtk_object_class =
+ GTK_OBJECT_CLASS (camel_seekable_substream_class);
parent_class = gtk_type_class (camel_seekable_stream_get_type ());
-
+
/* virtual method definition */
- camel_seekable_substream_class->init_with_seekable_stream_and_bounds = _init_with_seekable_stream_and_bounds;
-
- /* virtual method overload */
- camel_stream_class->read = _read;
- camel_stream_class->write = _write;
- camel_stream_class->flush = _flush;
- camel_stream_class->available = _available;
- camel_stream_class->eos = _eos;
- camel_stream_class->close = _close;
+ camel_seekable_substream_class->init_with_seekable_stream_and_bounds =
+ init_with_seekable_stream_and_bounds;
- camel_seekable_stream_class->seek = _seek;
+ /* virtual method overload */
+ camel_stream_class->read = stream_read;
+ camel_stream_class->write = stream_write;
+ camel_stream_class->flush = stream_flush;
+ camel_stream_class->available = available;
+ camel_stream_class->eos = eos;
- gtk_object_class->finalize = _finalize;
- gtk_object_class->destroy = _destroy;
+ camel_seekable_stream_class->seek = stream_seek;
+ gtk_object_class->finalize = finalize;
}
-static void
-camel_seekable_substream_init (gpointer object, gpointer klass)
-{
- /* does nothing */
-}
-
-
-
GtkType
camel_seekable_substream_get_type (void)
{
static GtkType camel_seekable_substream_type = 0;
-
- if (!camel_seekable_substream_type) {
- GtkTypeInfo camel_seekable_substream_info =
+
+ if (!camel_seekable_substream_type) {
+ GtkTypeInfo camel_seekable_substream_info =
{
"CamelSeekableSubstream",
sizeof (CamelSeekableSubstream),
sizeof (CamelSeekableSubstreamClass),
(GtkClassInitFunc) camel_seekable_substream_class_init,
- (GtkObjectInitFunc) camel_seekable_substream_init,
+ (GtkObjectInitFunc) NULL,
/* reserved_1 */ NULL,
/* reserved_2 */ NULL,
(GtkClassInitFunc) NULL,
};
-
+
camel_seekable_substream_type = gtk_type_unique (camel_seekable_stream_get_type (), &camel_seekable_substream_info);
}
-
- return camel_seekable_substream_type;
-}
-
-
-
-
-
-static void
-_destroy (GtkObject *object)
-{
- /* does nothing for the moment */
- GTK_OBJECT_CLASS (parent_class)->destroy (object);
+ return camel_seekable_substream_type;
}
-static void
-_finalize (GtkObject *object)
+static void
+finalize (GtkObject *object)
{
- CamelSeekableStream *seekable_stream;
- CamelSeekableSubstream *seekable_substream;
-
- seekable_stream = CAMEL_SEEKABLE_STREAM (object);
- seekable_substream = CAMEL_SEEKABLE_SUBSTREAM (object);
+ CamelSeekableSubstream *seekable_substream =
+ CAMEL_SEEKABLE_SUBSTREAM (object);
if (seekable_substream->parent_stream)
gtk_object_unref (GTK_OBJECT (seekable_substream->parent_stream));
@@ -149,334 +119,261 @@ _finalize (GtkObject *object)
}
-
-static void
-_set_bounds (CamelSeekableSubstream *seekable_substream, guint32 inf_bound, gint64 sup_bound)
+static void
+set_bounds (CamelSeekableSubstream *seekable_substream,
+ guint32 inf_bound, gint64 sup_bound)
{
- g_assert (seekable_substream);
- g_assert (seekable_substream->parent_stream);
-
/* store the bounds */
seekable_substream->inf_bound = inf_bound;
seekable_substream->sup_bound = sup_bound;
-
- seekable_substream->cur_pos = 0;
seekable_substream->eos = FALSE;
}
+
static void
-_reemit_parent_signal (CamelStream *parent_stream, gpointer user_data)
+reemit_parent_signal (CamelStream *parent_stream, gpointer user_data)
{
- CamelSeekableSubstream *seekable_substream = CAMEL_SEEKABLE_SUBSTREAM (user_data);
+ CamelSeekableSubstream *seekable_substream =
+ CAMEL_SEEKABLE_SUBSTREAM (user_data);
- gtk_signal_emit_by_name (GTK_OBJECT (seekable_substream), "data_available");
-
+ gtk_signal_emit_by_name (GTK_OBJECT (seekable_substream),
+ "data_available");
}
-static void
-_init_with_seekable_stream_and_bounds (CamelSeekableSubstream *seekable_substream,
- CamelSeekableStream *parent_stream,
- guint32 inf_bound,
- gint64 sup_bound)
+static void
+init_with_seekable_stream_and_bounds (CamelSeekableSubstream *seekable_substream,
+ CamelSeekableStream *parent_stream,
+ guint32 inf_bound, gint64 sup_bound)
{
- /* sanity checks */
- g_assert (seekable_substream);
- g_assert (!seekable_substream->parent_stream);
- g_assert (parent_stream);
-
- /* store the parent stream */
+ /* Store the parent stream. */
seekable_substream->parent_stream = parent_stream;
gtk_object_ref (GTK_OBJECT (parent_stream));
+ gtk_object_sink (GTK_OBJECT (parent_stream));
- /* set the bound of the substream */
- _set_bounds (seekable_substream, inf_bound, sup_bound);
+ /* Set the bound of the substream. */
+ set_bounds (seekable_substream, inf_bound, sup_bound);
- /*
- * connect to the parent stream "data_available"
- * stream so that we can reemit the signal on the
- * seekable substream in case some data would
- * be available for us
+ /* Connect to the parent stream "data_available" signal so
+ * that we can reemit the signal on the seekable substream in
+ * case some data would be available for us
*/
- gtk_signal_connect (GTK_OBJECT (parent_stream),
- "data_available",
- _reemit_parent_signal,
- seekable_substream);
-
- gtk_signal_emit_by_name (GTK_OBJECT (seekable_substream), "data_available");
+ gtk_signal_connect (GTK_OBJECT (parent_stream), "data_available",
+ reemit_parent_signal, seekable_substream);
+ gtk_signal_emit_by_name (GTK_OBJECT (seekable_substream),
+ "data_available");
}
-
-
+/**
+ * camel_seekable_substream_new_with_seekable_stream_and_bounds:
+ * @parent_stream: a seekable parent stream
+ * @inf_bound: a lower bound
+ * @sup_bound: an upper bound
+ *
+ * Creates a new CamelSeekableSubstream that references the portion
+ * of @parent_stream from @inf_bound to @sup_bound. (If @sup_bound is -1,
+ * it references to the end of stream, even if the stream grows.)
+ *
+ * While the substream is open, the caller cannot assume anything about
+ * the current position of @parent_stream. After the substream has been
+ * closed, @parent_stream will stabilize again.
+ *
+ * Return value: the substream
+ **/
CamelStream *
-camel_seekable_substream_new_with_seekable_stream_and_bounds (CamelSeekableStream *parent_stream,
- guint32 inf_bound,
- gint64 sup_bound)
+camel_seekable_substream_new_with_seekable_stream_and_bounds (CamelSeekableStream *parent_stream,
+ guint32 inf_bound,
+ gint64 sup_bound)
{
CamelSeekableSubstream *seekable_substream;
- /* create the seekable substream */
- seekable_substream = gtk_type_new (camel_seekable_substream_get_type ());
+ g_return_val_if_fail (CAMEL_IS_SEEKABLE_STREAM (parent_stream), NULL);
+
+ /* Create the seekable substream. */
+ seekable_substream =
+ gtk_type_new (camel_seekable_substream_get_type ());
- /* initialize it */
- CSS_CLASS (seekable_substream)->init_with_seekable_stream_and_bounds (seekable_substream,
- parent_stream,
- inf_bound,
- sup_bound);
+ /* Initialize it. */
+ init_with_seekable_stream_and_bounds (seekable_substream,
+ parent_stream,
+ inf_bound, sup_bound);
return CAMEL_STREAM (seekable_substream);
}
-
-
-
-/**
- * _read: read bytes from a stream
- * @stream: stream
- * @buffer: buffer where bytes are stored
- * @n: max number of bytes to read
- *
- *
- *
- * Return value: number of bytes actually read.
- **/
-static gint
-_read (CamelStream *stream, gchar *buffer, gint n)
+static gboolean
+parent_reset (CamelSeekableSubstream *seekable_substream)
{
- CamelSeekableStream *seekable_stream = CAMEL_SEEKABLE_STREAM (stream);
- CamelSeekableSubstream *seekable_substream = CAMEL_SEEKABLE_SUBSTREAM (stream);
- gint v;
- gint nb_to_read;
+ CamelSeekableStream *parent, *seekable_stream =
+ CAMEL_SEEKABLE_STREAM (seekable_substream);
guint32 parent_stream_current_position;
guint32 position_in_parent;
-
- g_assert (stream);
- g_assert (seekable_substream->parent_stream);
- g_assert (n);
+ parent = seekable_substream->parent_stream;
+ g_return_val_if_fail (parent != NULL, FALSE);
+ parent_stream_current_position =
+ camel_seekable_stream_get_current_position (parent);
- /*
- we are doing something quite infefficient :
-
- each time we want to read a block, we store
- the parent stream position so that we can
- change it, and restore it before returning
+ /* Compute our position in the parent stream. */
+ position_in_parent =
+ seekable_stream->cur_pos + seekable_substream->inf_bound;
- This may change. I don't know yet.
- It may be useless to reseek every time
- and is incompatible with buffering.
- */
+ /* Go to our position in the parent stream. */
+ if (parent_stream_current_position != position_in_parent) {
+ camel_seekable_stream_seek (parent, position_in_parent,
+ CAMEL_STREAM_SET);
+ }
+ /* Check if we were able to set the position in the parent. */
+ parent_stream_current_position =
+ camel_seekable_stream_get_current_position (parent);
- parent_stream_current_position =
- camel_seekable_stream_get_current_position (seekable_substream->parent_stream);
+ return parent_stream_current_position == position_in_parent;
+}
- /* compute the position in the parent stream */
- position_in_parent =
- seekable_stream->cur_pos + seekable_substream->inf_bound;
-
- /* compute how much byte should be read */
- if (seekable_substream->sup_bound != -1)
- nb_to_read =
- MIN (seekable_substream->sup_bound - position_in_parent, n);
- else
- nb_to_read = n;
- //printf ("Nb to read = %d\n", n);
- if (!nb_to_read) {
-
+static gint
+stream_read (CamelStream *stream, gchar *buffer, gint n)
+{
+ CamelSeekableStream *seekable_stream =
+ CAMEL_SEEKABLE_STREAM (stream);
+ CamelSeekableSubstream *seekable_substream =
+ CAMEL_SEEKABLE_SUBSTREAM (stream);
+ gint v, nb_to_read, position_in_parent;
+
+ /* Go to our position in the parent stream. */
+ if (!parent_reset (seekable_substream)) {
seekable_substream->eos = TRUE;
return 0;
}
- /*printf ("In SeekableSubstream(%p)::read, the position has to be changed\n", stream);
- printf ("--- parent_stream_current_position=%d, position_in_parent=%d\n",
- parent_stream_current_position, position_in_parent);
- printf ("--- seekable_substream->inf_bound=%d\n", seekable_substream->inf_bound);
- printf ("--- seekable_substream->sup_bound=%d\n", seekable_substream->sup_bound);
- printf ("--- seekable_substream->parent_stream=%p\n", seekable_substream->parent_stream);
- */
- /* go to our position in the parent stream */
- if (parent_stream_current_position != position_in_parent) {
-
-
- camel_seekable_stream_seek (seekable_substream->parent_stream,
- position_in_parent,
- CAMEL_STREAM_SET);
- }
-
- /* check if we were able to set the position in the parent */
- parent_stream_current_position =
- camel_seekable_stream_get_current_position (seekable_substream->parent_stream);
+ /* Compute how much byte should be read. */
+ position_in_parent =
+ seekable_stream->cur_pos + seekable_substream->inf_bound;
+ if (seekable_substream->sup_bound != -1) {
+ nb_to_read = MIN (seekable_substream->sup_bound -
+ position_in_parent, n);
+ } else
+ nb_to_read = n;
- if (parent_stream_current_position != position_in_parent) {
- seekable_substream->eos = TRUE;
+ if (!nb_to_read) {
+ if (n)
+ seekable_substream->eos = TRUE;
return 0;
}
-
- /* Read the data */
- if (nb_to_read >0 )
- v = camel_stream_read ( CAMEL_STREAM (seekable_substream->parent_stream),
- buffer,
- nb_to_read);
- else
+ /* Read the data. */
+ if (nb_to_read > 0) {
+ v = camel_stream_read (CAMEL_STREAM (seekable_substream->parent_stream),
+ buffer, nb_to_read);
+ } else
v = 0;
- /* if the return value is negative, an error occured,
- we must do something FIXME : handle exception */
- if (v>0)
+ /* If the return value is negative, an error occured,
+ * we must do something FIXME : handle exception
+ */
+ if (v > 0)
seekable_stream->cur_pos += v;
-
- /* printf ("Nb Bytes Read : %d\n",v); */
- /* return the number of bytes read */
return v;
}
-/**
- * _write: write bytes to a stream
- * @stream: the stream
- * @buffer: byte buffer
- * @n: number of bytes to write
- *
- *
- *
- * Return value: the number of bytes actually written
- * in the stream.
- **/
static gint
-_write (CamelStream *stream, const gchar *buffer, gint n)
+stream_write (CamelStream *stream, const gchar *buffer, gint n)
{
/* NOT VALID ON SEEKABLE SUBSTREAM */
- g_warning ("CamelSeekableSubstream:: seekable substream don't have a write method\n");
+ g_warning ("CamelSeekableSubstream:: seekable substream doesn't "
+ "have a write method\n");
return -1;
}
-
-/**
- * _flush: flush pending changes
- * @stream: the stream
- *
- *
- **/
static void
-_flush (CamelStream *stream)
+stream_flush (CamelStream *stream)
{
/* NOT VALID ON SEEKABLE SUBSTREAM */
- g_warning ("CamelSeekableSubstream:: seekable substream don't have a flush method\n");
+ g_warning ("CamelSeekableSubstream:: seekable substream doesn't "
+ "have a flush method\n");
}
-
-/**
- * _available: return the number of bytes available for reading
- * @stream: the stream
- *
- * Return the number of bytes available without blocking.
- *
- * Return value: the number of bytes available
- **/
-static gint
-_available (CamelStream *stream)
+static gint
+available (CamelStream *stream)
{
- g_warning ("not implemented\n");
+ g_warning ("CamelSeekableSubstream::available not implemented\n");
return -1;
}
-/**
- * _eos: test if there are bytes left to read
- * @stream: the stream
- *
- *
- *
- * Return value: true if all stream has been read
- **/
static gboolean
-_eos (CamelStream *stream)
+eos (CamelStream *stream)
{
- CamelSeekableSubstream *seekable_substream = CAMEL_SEEKABLE_SUBSTREAM (stream);
- CamelSeekableStream *seekable_stream = CAMEL_SEEKABLE_STREAM (stream);
+ CamelSeekableSubstream *seekable_substream =
+ CAMEL_SEEKABLE_SUBSTREAM (stream);
+ CamelSeekableStream *seekable_stream =
+ CAMEL_SEEKABLE_STREAM (stream);
guint32 substream_len;
gboolean eos;
-
+
g_assert (stream);
if (seekable_substream->eos)
eos = TRUE;
else {
+ parent_reset (seekable_substream);
- /* first check that the parent stream is ok */
eos = camel_stream_eos (CAMEL_STREAM (seekable_substream->parent_stream));
if ((!eos) && (seekable_substream->sup_bound != -1)) {
- substream_len = seekable_substream->sup_bound - seekable_substream->inf_bound;
+ substream_len = seekable_substream->sup_bound - seekable_substream->inf_bound;
eos = ( seekable_stream->cur_pos >= substream_len);
- }
+ }
}
-
return eos;
}
-/**
- * _close: close a stream
- * @stream: the stream
- *
- *
- **/
-static void
-_close (CamelStream *stream)
-{
- CamelSeekableSubstream *seekable_substream = CAMEL_SEEKABLE_SUBSTREAM (stream);
-
- g_assert (stream);
- seekable_substream->open = FALSE;
-}
-
-
static gint
-_seek (CamelSeekableStream *stream, gint offset, CamelStreamSeekPolicy policy)
+stream_seek (CamelSeekableStream *stream, gint offset,
+ CamelStreamSeekPolicy policy)
{
- CamelSeekableSubstream *seekable_substream = CAMEL_SEEKABLE_SUBSTREAM (stream);
- CamelSeekableStream *seekable_stream = CAMEL_SEEKABLE_STREAM (stream);
- gint64 real_offset = 0;
+ CamelSeekableSubstream *seekable_substream =
+ CAMEL_SEEKABLE_SUBSTREAM (stream);
+ CamelSeekableStream *seekable_stream =
+ CAMEL_SEEKABLE_STREAM (stream);
+ gint64 real_offset = 0;
guint32 substream_len;
guint32 parent_pos;
gboolean seek_done = FALSE;
- substream_len = seekable_substream->sup_bound - seekable_substream->inf_bound;
-
- seekable_substream->eos = FALSE;
+ substream_len = seekable_substream->sup_bound -
+ seekable_substream->inf_bound;
- switch (policy) {
+ seekable_substream->eos = FALSE;
+ switch (policy) {
case CAMEL_STREAM_SET:
real_offset = offset;
-
break;
case CAMEL_STREAM_CUR:
real_offset = seekable_stream->cur_pos + offset;
-
break;
case CAMEL_STREAM_END:
if (seekable_substream->sup_bound != -1)
real_offset = substream_len - offset;
else {
- parent_pos = camel_seekable_stream_seek (seekable_substream->parent_stream,
- offset,
+ parent_pos = camel_seekable_stream_seek (seekable_substream->parent_stream,
+ offset,
CAMEL_STREAM_END);
- seekable_stream->cur_pos = parent_pos - seekable_substream->inf_bound;
+ seekable_stream->cur_pos = parent_pos -
+ seekable_substream->inf_bound;
seek_done = TRUE;
}
-
break;
default:
@@ -485,11 +382,11 @@ _seek (CamelSeekableStream *stream, gint offset, CamelStreamSeekPolicy policy)
if (!seek_done) {
if (real_offset > 0) {
- seekable_stream->cur_pos = MIN (real_offset, substream_len);
- } else
+ seekable_stream->cur_pos = MIN (real_offset,
+ substream_len);
+ } else
seekable_stream->cur_pos = 0;
}
-
return seekable_stream->cur_pos;
}