make a blocking version of the header parser. When the fs stream uses
authorbertrand <Bertrand.Guiheneuf@aful.org>
Mon, 14 Feb 2000 22:03:58 +0000 (22:03 +0000)
committerBertrand Guiheneuf <bertrand@src.gnome.org>
Mon, 14 Feb 2000 22:03:58 +0000 (22:03 +0000)
2000-02-14  bertrand  <Bertrand.Guiheneuf@aful.org>

* camel/gmime-utils.c (get_header_array_from_stream):
make a blocking version of the header parser.
When the fs stream uses gnome-vfs, this should
be changed.
(gmime_read_line_from_stream): ditto.

2000-02-11  bertrand  <Bertrand.Guiheneuf@aful.org>

* camel/camel-stream-fs.c:
everywhere, when using the cur_pos field, do it
on the CamelSeekableStream object.
(_seek): small fix.

* camel/camel-seekable-stream.c (camel_seekable_stream_seek):
s/camel_stream_seek/camel_seekable_stream_seek/g

* camel/camel-seekable-stream.h:
(struct ): added a field to store the
current position.

* camel/camel-seekable-stream.c (camel_seekable_stream_get_current_position):
New function. Allows to get the current position
of a seekable stream.

In fact much more changes, but I am lazy.
This is the begining of some major changes
in camel.

12 files changed:
camel/Makefile.am
camel/camel-mime-part.c
camel/camel-mime-part.h
camel/camel-seekable-stream.c
camel/camel-seekable-stream.h
camel/camel-seekable-substream.c [new file with mode: 0644]
camel/camel-seekable-substream.h [new file with mode: 0644]
camel/camel-stream-fs.c
camel/camel-stream-fs.h
camel/camel-stream.c
camel/camel-stream.h
camel/gmime-utils.c

index 2db0ecf..cff67fc 100644 (file)
@@ -53,6 +53,7 @@ libcamel_la_SOURCES =                                 \
        camel-provider.c                        \
        camel-recipient.c                       \
        camel-seekable-stream.c                 \
+       camel-seekable-substream.c              \
        camel-service.c                         \
        camel-session.c                         \
        camel-store.c                           \
@@ -94,6 +95,7 @@ libcamelinclude_HEADERS =                     \
        camel-provider.h                        \
        camel-recipient.h                       \
        camel-seekable-stream.h                 \
+       camel-seekable-substream.h              \
        camel-service.h                         \
        camel-session.h                         \
        camel-store.h                           \
index 84140f5..974c770 100644 (file)
@@ -60,8 +60,10 @@ static CamelMediumClass *parent_class=NULL;
 static void _finalize (GtkObject *object);
 
 /* from CamelDataWrapper */
-static void _write_to_stream (CamelDataWrapper *data_wrapper, CamelStream *stream);
+static void _write_to_stream       (CamelDataWrapper *data_wrapper, CamelStream *stream);
 static void _construct_from_stream (CamelDataWrapper *data_wrapper, CamelStream *stream);
+static void _set_input_stream      (CamelDataWrapper *data_wrapper, CamelStream *stream);
+
 
 /* from CamelMedia */ 
 static void _add_header (CamelMedium *medium, gchar *header_name, gchar *header_value);
@@ -791,6 +793,19 @@ _construct_from_stream (CamelDataWrapper *data_wrapper, CamelStream *stream)
 }
 
 
+static void 
+_set_input_stream (CamelDataWrapper *data_wrapper, CamelStream *stream)
+{
+       CamelMimePart *mime_part = CAMEL_MIME_PART (data_wrapper);
+       
+       CAMEL_LOG_FULL_DEBUG ("CamelMimePart::construct_from_stream entering\n");
+       camel_mime_part_construct_headers_from_stream (mime_part, stream);
+
+       
+       
+}
+
+
 const gchar *
 camel_mime_part_encoding_to_string (CamelMimePartEncodingType encoding)
 {
index 573cf69..e8ad6c1 100644 (file)
@@ -115,34 +115,35 @@ GtkType camel_mime_part_get_type (void);
 
 
 /* public methods */
-void camel_mime_part_set_description (CamelMimePart *mime_part,        
-                                     const gchar *description);
-const gchar *camel_mime_part_get_description (CamelMimePart *mime_part);
-void camel_mime_part_set_disposition (CamelMimePart *mime_part, 
-                                     const gchar *disposition);
-const gchar *camel_mime_part_get_disposition (CamelMimePart *mime_part);
-void camel_mime_part_set_filename (CamelMimePart *mime_part, 
-                                  gchar *filename);
-const gchar *camel_mime_part_get_filename (CamelMimePart *mime_part);
-const gchar *camel_mime_part_get_content_id (CamelMimePart *mime_part);
-const gchar *camel_mime_part_get_content_MD5 (CamelMimePart *mime_part);
-void camel_mime_part_set_encoding (CamelMimePart *mime_part, 
-                                  CamelMimePartEncodingType type);
-CamelMimePartEncodingType camel_mime_part_get_encoding (CamelMimePart *mime_part);
-void camel_mime_part_set_content_languages (CamelMimePart *mime_part, 
-                                           GList *content_languages);
-const GList *camel_mime_part_get_content_languages (CamelMimePart *mime_part);
-void camel_mime_part_set_header_lines (CamelMimePart *mime_part, 
-                                      GList *header_lines);
-const GList *camel_mime_part_get_header_lines (CamelMimePart *mime_part);
-
-GMimeContentField *camel_mime_part_get_content_type (CamelMimePart *mime_part);
-
-const gchar *camel_mime_part_encoding_to_string (CamelMimePartEncodingType encoding);
+void     camel_mime_part_set_description               (CamelMimePart *mime_part,      
+                                                        const gchar *description);
+const     gchar *camel_mime_part_get_description       (CamelMimePart *mime_part);
+void     camel_mime_part_set_disposition               (CamelMimePart *mime_part, 
+                                                        const gchar *disposition);
+const     gchar *camel_mime_part_get_disposition       (CamelMimePart *mime_part);
+void     camel_mime_part_set_filename                  (CamelMimePart *mime_part, 
+                                                        gchar *filename);
+const    gchar *camel_mime_part_get_filename           (CamelMimePart *mime_part);
+const    gchar *camel_mime_part_get_content_id         (CamelMimePart *mime_part);
+const    gchar *camel_mime_part_get_content_MD5        (CamelMimePart *mime_part);
+void     camel_mime_part_set_encoding                  (CamelMimePart *mime_part, 
+                                                        CamelMimePartEncodingType type);
+CamelMimePartEncodingType camel_mime_part_get_encoding (CamelMimePart *mime_part);
+void     camel_mime_part_set_content_languages         (CamelMimePart *mime_part, 
+                                                        GList *content_languages);
+const    GList *camel_mime_part_get_content_languages  (CamelMimePart *mime_part);
+void     camel_mime_part_set_header_lines              (CamelMimePart *mime_part, 
+                                                        GList *header_lines);
+const    GList *camel_mime_part_get_header_lines       (CamelMimePart *mime_part);
+
+GMimeContentField *camel_mime_part_get_content_type    (CamelMimePart *mime_part);
+
+const     gchar *camel_mime_part_encoding_to_string    (CamelMimePartEncodingType encoding);
 CamelMimePartEncodingType camel_mime_part_encoding_from_string (const gchar *string);
 
 /* utility functions */
-void camel_mime_part_set_text (CamelMimePart *camel_mime_part, const gchar *text);
+void      camel_mime_part_set_text                     (CamelMimePart *camel_mime_part, 
+                                                        const gchar *text);
 
 
 #ifdef __cplusplus
index 00cca3e..55bbbd6 100644 (file)
@@ -78,17 +78,15 @@ camel_seekable_stream_get_type (void)
 
 
 static gint
-_seek (CamelSeekableStream *stream, gint offset, CamelStreamSeekPolicy policy)
+_seek (CamelSeekableStream *stream, 
+       gint offset, 
+       CamelStreamSeekPolicy policy)
 {
        return -1;
 }
 
 
 
-
-
-
-
 /**
  * camel_stream_seek:
  * @stream: a CamelStream object.
@@ -100,7 +98,9 @@ _seek (CamelSeekableStream *stream, gint offset, CamelStreamSeekPolicy policy)
  * Return value: new position, -1 if operation failed.
  **/
 gint
-camel_stream_seek (CamelSeekableStream *stream, gint offset, CamelStreamSeekPolicy policy)
+camel_seekable_stream_seek (CamelSeekableStream *stream, 
+                           gint offset, 
+                           CamelStreamSeekPolicy policy)
 {
        return CSS_CLASS (stream)->seek (stream, offset, policy);
 }
@@ -108,5 +108,25 @@ camel_stream_seek (CamelSeekableStream *stream, gint offset, CamelStreamSeekPoli
 
 
 
+/**
+ * camel_seekable_stream_get_current_position: get the position of a stream
+ * @stream: seekable stream object 
+ * 
+ * Get the current position of a seekable stream.
+ * 
+ * Return value: the position.
+ **/
+guint32  
+camel_seekable_stream_get_current_position  (CamelSeekableStream *stream)
+{
+       return stream->cur_pos;         
+}
+
+
+
+
+
+
+
 
 
index 7f00edc..e7ab941 100644 (file)
@@ -57,6 +57,8 @@ typedef struct
 {
        CamelStream parent_object;
        
+       guint32 cur_pos;     /* current postion in the stream */
+
 } CamelSeekableStream;
 
 
@@ -66,8 +68,8 @@ typedef struct {
        
        /* Virtual methods */   
        gint (*seek)       (CamelSeekableStream *stream, gint offset, CamelStreamSeekPolicy policy);
-
-
+       
+       
 } CamelSeekableStreamClass;
 
 
@@ -77,7 +79,10 @@ GtkType camel_seekable_stream_get_type (void);
 
 
 /* public methods */
-gint     camel_stream_seek      (CamelSeekableStream *stream, gint offset, CamelStreamSeekPolicy policy);
+gint     camel_seekable_stream_seek                      (CamelSeekableStream *stream, 
+                                                         gint offset, 
+                                                         CamelStreamSeekPolicy policy);
+guint32  camel_seekable_stream_get_current_position      (CamelSeekableStream *stream);
 
 
 #ifdef __cplusplus
diff --git a/camel/camel-seekable-substream.c b/camel/camel-seekable-substream.c
new file mode 100644 (file)
index 0000000..270bae1
--- /dev/null
@@ -0,0 +1,442 @@
+/* -*- 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 : 
+ *  Bertrand Guiheneuf <bertrand@helixcode.com>
+ *
+ * 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
+ */
+#include <config.h>
+#include "camel-seekable-substream.h"
+#include "camel-log.h"
+
+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, 
+                                                                 CamelSeekableStream *parent_stream,
+                                                                 guint32 inf_bound, 
+                                                                 guint32 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);
+
+       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_stream_class->seek = _seek;
+
+       gtk_object_class->finalize = _finalize;
+       gtk_object_class->destroy = _destroy;
+
+}
+
+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 =     
+               {
+                       "CamelSeekableSubstream",
+                       sizeof (CamelSeekableSubstream),
+                       sizeof (CamelSeekableSubstreamClass),
+                       (GtkClassInitFunc) camel_seekable_substream_class_init,
+                       (GtkObjectInitFunc) camel_seekable_substream_init,
+                               /* 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)
+{
+       
+       CAMEL_LOG_FULL_DEBUG ("Entering CamelSeekableSubstream::destroy\n");
+       
+       /* does nothing for the moment */
+       GTK_OBJECT_CLASS (parent_class)->destroy (object);
+       
+       CAMEL_LOG_FULL_DEBUG ("Leaving CamelSeekableSubstream::destroy\n");
+}
+
+
+static void           
+_finalize (GtkObject *object)
+{
+
+
+       CAMEL_LOG_FULL_DEBUG ("Entering CamelSeekableSubstream::finalize\n");
+       
+       /* does nothing for the moment */
+       GTK_OBJECT_CLASS (parent_class)->finalize (object);
+       CAMEL_LOG_FULL_DEBUG ("Leaving CamelSeekableSubstream::finalize\n");
+}
+
+
+
+static void 
+_set_bounds (CamelSeekableSubstream *seekable_substream, guint32 inf_bound, guint32 sup_bound)
+{
+       CAMEL_LOG_FULL_DEBUG ("CamelSeekableSubstream::_set_bounds entering\n");
+
+       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;
+
+       /* go to the first position */
+       camel_seekable_stream_seek (seekable_substream->parent_stream, inf_bound, SEEK_SET);
+
+       seekable_substream->cur_pos = inf_bound;
+       
+       CAMEL_LOG_FULL_DEBUG ("In CamelSeekableSubstream::_set_bounds, "
+                             "setting inf bound to %u, "
+                             "sup bound to %ld, current postion to %u from %u\n", 
+                             seekable_substream->inf_bound, seekable_substream->sup_bound,
+                             seekable_substream->cur_pos, inf_bound);
+       
+       CAMEL_LOG_FULL_DEBUG ("CamelSeekableSubstream::_set_bounds Leaving\n");
+}
+
+
+
+static void       
+_init_with_seekable_stream_and_bounds   (CamelSeekableSubstream *seekable_substream, 
+                                         CamelSeekableStream    *parent_stream,
+                                         guint32                 inf_bound, 
+                                         guint32                  sup_bound)
+{
+       /* sanity checks */
+       g_assert (seekable_substream);
+       g_assert (!seekable_substream->parent_stream);
+       g_assert (parent_stream);
+       
+       /* store the parent stream */
+       seekable_substream->parent_stream = parent_stream;
+       
+       /* set the bound of the substream */
+       _set_bounds (seekable_substream, inf_bound, sup_bound);
+}
+
+
+void
+camel_seekable_substream_init_with_seekable_stream_and_bounds (CamelSeekableSubstream *seekable_substream, 
+                                                              CamelSeekableStream    *parent_stream,
+                                                              guint32                 inf_bound, 
+                                                              guint32                  sup_bound)
+{
+       
+       CSS_CLASS (seekable_substream)->init_with_seekable_stream_and_bounds (seekable_substream,
+                                                                             parent_stream,
+                                                                             inf_bound,
+                                                                             sup_bound);
+       
+}
+
+
+
+
+
+/**
+ * _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)
+{
+       CamelSeekableStream *seekable_stream = CAMEL_SEEKABLE_STREAM (stream);
+       CamelSeekableSubstream *seekable_substream = CAMEL_SEEKABLE_SUBSTREAM (stream);
+       gint v;
+       gint nb_to_read;
+       guint32 parent_stream_current_position;
+       guint32 position_in_parent;
+       
+       g_assert (stream);
+       g_assert (seekable_substream->parent_stream);
+       g_assert (seekable_substream->open);
+
+
+
+       /* 
+          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 
+
+          This may change. I don't know yet. 
+          It may be useless to reseek every time
+          and is incompatible with buffering. 
+       */
+
+       parent_stream_current_position = 
+               camel_seekable_stream_get_current_position (seekable_substream->parent_stream);
+
+       /* compute the position in the parent stream */
+       position_in_parent =  
+               seekable_stream->cur_pos + seekable_substream->inf_bound;
+               
+       /* go to our position in the parent stream */
+       camel_seekable_stream_seek (seekable_substream->parent_stream, 
+                                   position_in_parent,
+                                   CAMEL_STREAM_SET);
+
+
+
+       /* compute how much byte should be read */
+       nb_to_read = 
+               MIN (seekable_substream->sup_bound - position_in_parent, n);
+
+       
+       /* 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)
+               CAMEL_LOG_FULL_DEBUG ("CamelSeekableSubstream::read v=%d\n", v);
+       else 
+               seekable_stream->cur_pos += v;
+
+
+       /* restore the parent position */
+       camel_seekable_stream_seek (seekable_substream->parent_stream, 
+                                   parent_stream_current_position,
+                                   CAMEL_STREAM_SET);
+
+       
+       /* 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)
+{
+       /* NOT VALID ON SEEKABLE SUBSTREAM */
+       g_warning ("CamelSeekableSubstream:: seekable substream don't have a write method\n");
+       CAMEL_LOG_WARNING ( "CamelSeekableSubstream:: seekable substream don't have a write method\n");
+       return -1;
+}
+
+
+
+/**
+ * _flush: flush pending changes 
+ * @stream: the stream
+ * 
+ * 
+ **/
+static void
+_flush (CamelStream *stream)
+{
+       /* NOT VALID ON SEEKABLE SUBSTREAM */
+       g_warning ("CamelSeekableSubstream:: seekable substream don't have a flush method\n");
+       CAMEL_LOG_WARNING ( "CamelSeekableSubstream:: seekable substream don'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)
+{
+       g_warning ("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)
+{
+       CamelSeekableSubstream *seekable_substream = CAMEL_SEEKABLE_SUBSTREAM (stream);
+       CamelSeekableStream *seekable_stream = CAMEL_SEEKABLE_STREAM (stream);
+       guint32 substream_len;
+
+
+       g_assert (stream);
+       g_assert (seekable_substream->open);
+       
+       substream_len = seekable_substream->sup_bound - seekable_substream->inf_bound;
+       
+       return ( seekable_stream->cur_pos > substream_len);
+}
+
+
+/**
+ * _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)
+{
+       CamelSeekableSubstream *seekable_substream = CAMEL_SEEKABLE_SUBSTREAM (stream);
+       CamelSeekableStream *seekable_stream = CAMEL_SEEKABLE_STREAM (stream);
+       gint64 real_offset; 
+       guint32 substream_len;
+
+
+       substream_len = seekable_substream->sup_bound - seekable_substream->inf_bound;
+
+       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:
+               real_offset = substream_len - offset;
+
+               break;
+
+       default:
+               return -1;
+       }
+               
+       if (real_offset > 0) {
+               seekable_stream->cur_pos = MIN (real_offset, substream_len);
+       } else 
+               seekable_stream->cur_pos = 0;
+       
+       
+
+       return seekable_stream->cur_pos;
+}
+
+
diff --git a/camel/camel-seekable-substream.h b/camel/camel-seekable-substream.h
new file mode 100644 (file)
index 0000000..f7ef19d
--- /dev/null
@@ -0,0 +1,94 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/* camel-seekable-substream.h : stream */
+
+/* 
+ *
+ * Author : 
+ *  Bertrand Guiheneuf <bertrand@helixcode.com>
+ *
+ * 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
+ */
+
+
+#ifndef CAMEL_SEEKABLE_SUBSTREAM_H
+#define CAMEL_SEEKABLE_SUBSTREAM_H 1
+
+
+#ifdef __cplusplus
+extern "C" {
+#pragma }
+#endif /* __cplusplus }*/
+
+#include <gtk/gtk.h>
+#include <stdio.h>
+#include "camel-seekable-stream.h"
+
+
+
+#define CAMEL_SEEKABLE_SUBSTREAM_TYPE       (camel_seekable_substream_get_type ())
+#define CAMEL_SEEKABLE_SUBSTREAM(obj)       (GTK_CHECK_CAST((obj), CAMEL_SEEKABLE_SUBSTREAM_TYPE, CamelSeekableSubstream))
+#define CAMEL_SEEKABLE_SUBSTREAM_CLASS(k)   (GTK_CHECK_CLASS_CAST ((k), CAMEL_SEEKABLE_SUBSTREAM_TYPE, CamelSeekableSubstreamClass))
+#define CAMEL_IS_SEEKABLE_SUBSTREAM(o)      (GTK_CHECK_TYPE((o), CAMEL_SEEKABLE_SUBSTREAM_TYPE))
+
+
+
+
+typedef struct 
+{
+       CamelSeekableStream parent_object;
+
+       /*  --**-- Private fields --**--  */
+       CamelSeekableStream *parent_stream;   /* the stream this substream uses */ 
+       guint32 cur_pos;                      /* current postion in the stream */
+       guint32 inf_bound;                    /* first valid position */
+       guint32 sup_bound;                    /* first invalid position */
+       gboolean open;
+       
+} CamelSeekableSubstream;
+
+
+
+typedef struct {
+       CamelSeekableStreamClass parent_class;
+       
+       /* Virtual methods */   
+       void (*init_with_seekable_stream_and_bounds) (CamelSeekableSubstream *seekable_substream, 
+                                                     CamelSeekableStream    *parent_stream,
+                                                     guint32 inf_bound, 
+                                                     guint32 sup_bound);
+
+} CamelSeekableSubstreamClass;
+
+
+
+/* Standard Gtk function */
+GtkType camel_seekable_substream_get_type (void);
+
+
+/* public methods */
+void
+camel_seekable_substream_init_with_seekable_stream_and_bounds (CamelSeekableSubstream *seekable_substream, 
+                                                              CamelSeekableStream    *parent_stream,
+                                                              guint32                 inf_bound, 
+                                                              guint32                  sup_bound);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* CAMEL_SEEKABLE_SUBSTREAM_H */
index 26dde90..e816f88 100644 (file)
@@ -168,13 +168,13 @@ _set_bounds (CamelStreamFs *stream_fs, guint32 inf_bound, guint32 sup_bound)
        /* go to the first position */
        lseek (stream_fs->fd, inf_bound, SEEK_SET);
 
-       stream_fs->cur_pos = inf_bound;
+       CAMEL_SEEKABLE_STREAM (stream_fs)->cur_pos = inf_bound;
        
        CAMEL_LOG_FULL_DEBUG ("In CamelStreamFs::_set_bounds, "
                              "setting inf bound to %u, "
                              "sup bound to %ld, current postion to %u from %u\n", 
                              stream_fs->inf_bound, stream_fs->sup_bound,
-                             stream_fs->cur_pos, inf_bound);
+                             CAMEL_SEEKABLE_STREAM (stream_fs)->cur_pos, inf_bound);
        
 }
 
@@ -187,7 +187,7 @@ _init_with_fd (CamelStreamFs *stream_fs, int fd)
        stream_fs->fd = fd;
        stream_fs->inf_bound = 0;
        stream_fs->sup_bound = -1;
-       stream_fs->cur_pos = 0;
+       CAMEL_SEEKABLE_STREAM (stream_fs)->cur_pos = 0;
 }
 
 
@@ -219,12 +219,12 @@ _init_with_name (CamelStreamFs *stream_fs, const gchar *name, CamelStreamFsMode
        
        if (mode & CAMEL_STREAM_FS_READ){
                if (mode & CAMEL_STREAM_FS_WRITE)
-                       flags = O_RDWR | O_CREAT;
+                       flags = O_RDWR | O_CREAT | O_NONBLOCK;
                else
-                       flags = O_RDONLY;
+                       flags = O_RDONLY | O_NONBLOCK;
        } else {
                if (mode & CAMEL_STREAM_FS_WRITE)
-                       flags = O_WRONLY | O_CREAT;
+                       flags = O_WRONLY | O_CREAT | O_NONBLOCK;
                else
                        return;
        }
@@ -245,7 +245,7 @@ _init_with_name (CamelStreamFs *stream_fs, const gchar *name, CamelStreamFsMode
        
        stream_fs->name = g_strdup (name);
        CSFS_CLASS (stream_fs)->init_with_fd (stream_fs, fd);
-               
+       
 }
 
 
@@ -260,7 +260,7 @@ _init_with_name_and_bounds (CamelStreamFs *stream_fs, const gchar *name, CamelSt
                              "setting inf bound to %u, "
                              "sup bound to %ld, current postion to %u\n", 
                              stream_fs->inf_bound, stream_fs->sup_bound,
-                             stream_fs->cur_pos);
+                             CAMEL_SEEKABLE_STREAM (stream)->cur_pos);
 }
 
 
@@ -345,7 +345,7 @@ _read (CamelStream *stream, gchar *buffer, gint n)
        gint nb_to_read;
        
        if (stream_fs->sup_bound != -1)
-               nb_to_read = MIN (stream_fs->sup_bound - stream_fs->cur_pos, n);
+               nb_to_read = MIN (stream_fs->sup_bound - CAMEL_SEEKABLE_STREAM (stream)->cur_pos, n);
        else 
                nb_to_read = n;
        
@@ -355,7 +355,7 @@ _read (CamelStream *stream, gchar *buffer, gint n)
        if (v<0)
                CAMEL_LOG_FULL_DEBUG ("CamelStreamFs::read v=%d\n", v);
        else 
-               stream_fs->cur_pos += v;
+               CAMEL_SEEKABLE_STREAM (stream)->cur_pos += v;
 
        return v;
 }
@@ -384,7 +384,7 @@ _write (CamelStream *stream, const gchar *buffer, gint n)
        CAMEL_LOG_FULL_DEBUG ( "CamelStreamFs:: entering write. n=%d\n", n);
 
        if (stream_fs->sup_bound != -1)
-               nb_to_write =  MIN (stream_fs->sup_bound - stream_fs->cur_pos, n);
+               nb_to_write =  MIN (stream_fs->sup_bound - CAMEL_SEEKABLE_STREAM (stream)->cur_pos, n);
        else 
                nb_to_write = n;
 
@@ -400,7 +400,7 @@ _write (CamelStream *stream, const gchar *buffer, gint n)
 #endif
 
        if (v>0)
-               stream_fs->cur_pos += v;
+               CAMEL_SEEKABLE_STREAM (stream)->cur_pos += v;
 
        return v;
 
@@ -484,10 +484,10 @@ _seek (CamelSeekableStream *stream, gint offset, CamelStreamSeekPolicy policy)
                break;
 
        case CAMEL_STREAM_CUR:
-               if ((stream_fs->sup_bound == -1) && ((stream_fs->cur_pos + offset) > stream_fs->sup_bound)) {
+               if ((stream_fs->sup_bound != -1) && ((CAMEL_SEEKABLE_STREAM (stream)->cur_pos + offset) > stream_fs->sup_bound)) {
                        real_offset = stream_fs->sup_bound;
                        whence = SEEK_SET;      
-               } else if ((stream_fs->cur_pos + offset) < stream_fs->inf_bound) {
+               } else if ((CAMEL_SEEKABLE_STREAM (stream)->cur_pos + offset) < stream_fs->inf_bound) {
                        real_offset = stream_fs->inf_bound;
                        whence = SEEK_SET;      
                } else 
@@ -515,7 +515,7 @@ _seek (CamelSeekableStream *stream, gint offset, CamelStreamSeekPolicy policy)
        
                
        return_position =  lseek (stream_fs->fd, real_offset, whence) - stream_fs->inf_bound;
-       stream_fs->cur_pos = return_position;
+       CAMEL_SEEKABLE_STREAM (stream)->cur_pos = return_position;
 
        return return_position;
 }
index 4910abb..2e7dfd9 100644 (file)
@@ -57,7 +57,6 @@ typedef struct
 
        gchar *name;       /* name of the underlying file */
        gint fd;           /* file descriptor on the underlying file */
-       guint32 cur_pos;     /* current postion in the stream */
        guint32 inf_bound;   /* first valid position */
        gint32 sup_bound;    /* last valid position, -1 means, no sup bound */
        
index 0a18ed1..bad7f68 100644 (file)
@@ -160,7 +160,7 @@ camel_stream_flush (CamelStream *stream)
  * 
  * Return value: the number of bytes available.
  **/
-gint 
+gboolean
 camel_stream_available (CamelStream *stream)
 {
        return CS_CLASS (stream)->available (stream);
index d032797..0496e13 100644 (file)
@@ -57,35 +57,49 @@ typedef struct {
        
        void  (*data_available) (CamelStream *stream); /* default "data_available" signal handler */
 
-       gint  (*read)      (CamelStream *stream, gchar *buffer, gint n);
-       gint  (*write)     (CamelStream *stream, const gchar *buffer, gint n);
-       void  (*flush)     (CamelStream *stream);
-       gint  (*available) (CamelStream *stream);
-       gboolean  (*eos)   (CamelStream *stream);
-       void  (*close)     (CamelStream *stream);
+       gint      (*read)       (CamelStream *stream, gchar *buffer, gint n);
+       gint      (*write)      (CamelStream *stream, const gchar *buffer, gint n);
+       void      (*flush)      (CamelStream *stream);
+       gint      (*available)  (CamelStream *stream);
+       gboolean  (*eos)        (CamelStream *stream);
+       void      (*close)      (CamelStream *stream);
 } CamelStreamClass;
 
 
 
+
+
+
 /* Standard Gtk function */
 GtkType camel_stream_get_type (void);
 
 
+
+
 /* public methods */
-gint     camel_stream_read      (CamelStream *stream, gchar *buffer, gint n);
-gint     camel_stream_write     (CamelStream *stream, const gchar *buffer, gint n);
-void     camel_stream_flush     (CamelStream *stream);
-gint     camel_stream_available (CamelStream *stream);
-gboolean camel_stream_eos       (CamelStream *stream);
-void     camel_stream_close     (CamelStream *stream);
+gint       camel_stream_read      (CamelStream *stream, gchar *buffer, gint n);
+gint       camel_stream_write     (CamelStream *stream, const gchar *buffer, gint n);
+void       camel_stream_flush     (CamelStream *stream);
+gboolean   camel_stream_available (CamelStream *stream);
+gboolean   camel_stream_eos       (CamelStream *stream);
+void       camel_stream_close     (CamelStream *stream);
+
+
+
 
 /* utility macros and funcs */
 #define camel_stream_write_string(stream, string) camel_stream_write ((stream), (string), strlen (string))
 
-void camel_stream_write_strings (CamelStream *stream, ... );
+void       camel_stream_write_strings (CamelStream *stream, ... );
 
 #ifdef __cplusplus
 }
 #endif /* __cplusplus */
 
 #endif /* CAMEL_STREAM_H */
+
+
+
+
+
+
index 421808a..1b1f1aa 100644 (file)
@@ -160,7 +160,11 @@ _store_header_pair_from_string (GArray *header_array, gchar *header_line)
 
 
        
-               
+/* 
+   this is a blocking version of the 
+   header parsing. Need to change when 
+   fs streams are non blocking
+*/
 GArray *
 get_header_array_from_stream (CamelStream *stream)
 {
@@ -177,8 +181,6 @@ get_header_array_from_stream (CamelStream *stream)
        gboolean end_of_file = FALSE;
 
        GString *header_line=NULL;
-       gchar *str_header_line;
-
        GArray *header_array;
 
 
@@ -215,23 +217,29 @@ get_header_array_from_stream (CamelStream *stream)
                                default:
                                        if (!crlf) header_line = g_string_append_c (header_line, next_char);                                    
                                        else end_of_header_line = TRUE;
+
                                }
                        } else {
-                               end_of_file=TRUE;
-                               end_of_header_line = TRUE;
+                               
+                               if (nb_char_read <0) {
+                                       end_of_file=TRUE;
+                                       end_of_header_line = TRUE;
+                                       
+                               }
                        }
+                       
                        /* if we have read a whole header line, we have also read
                           the first character of the next line to be sure the 
                           crlf was not followed by a space or a tab char */
                        if (!end_of_header_line) nb_char_read = camel_stream_read (stream, &next_char, 1);
-
+                       
                } while ( !end_of_header_line );
                if ( strlen(header_line->str) ) {
                        /*  str_header_line = g_strdup (header_line->str); */
                        _store_header_pair_from_string (header_array, header_line->str);                        
                }
                g_string_free (header_line, FALSE);
-
+               
        } while ( (!end_of_headers) && (!end_of_file) );
        
        CAMEL_LOG_FULL_DEBUG ( "gmime-utils:: Leaving get_header_table_from_stream\n");
@@ -239,6 +247,7 @@ get_header_array_from_stream (CamelStream *stream)
 }
                
                
+
 gchar *
 gmime_read_line_from_stream (CamelStream *stream)
 {
@@ -252,7 +261,9 @@ gmime_read_line_from_stream (CamelStream *stream)
        new_line = g_string_new ("");
        do {
                nb_char_read = camel_stream_read (stream, &next_char, 1);
+
                if (nb_char_read>0) {
+                       
                        switch (next_char) {
                        case '\n':                              
                                end_of_line = TRUE;
@@ -260,13 +271,22 @@ gmime_read_line_from_stream (CamelStream *stream)
                                break;
                        default:
                                g_string_append_c (new_line, next_char);
+
                        }
-               } else end_of_stream = TRUE;
+               } else {
+
+                       if (nb_char_read <0) 
+                               end_of_stream = TRUE;
+
+               }
        } while (!end_of_line && !end_of_stream);
 
+
        if (!end_of_stream)
                result = g_strdup (new_line->str);
        else result=NULL;
+
        g_string_free (new_line, TRUE);
+
        return result;
 }