commit-mailutils
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[SCM] GNU Mailutils branch, stream-cleanup, updated. rel-2_1-85-g17e7050


From: Sergey Poznyakoff
Subject: [SCM] GNU Mailutils branch, stream-cleanup, updated. rel-2_1-85-g17e7050
Date: Sat, 01 May 2010 16:59:14 +0000

This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "GNU Mailutils".

http://git.savannah.gnu.org/cgit/mailutils.git/commit/?id=17e7050b820314f268996c7f06ae9344a5f4f5c2

The branch, stream-cleanup has been updated
       via  17e7050b820314f268996c7f06ae9344a5f4f5c2 (commit)
       via  d223d743be22bc5dae7aa42b12e529f6c5f03858 (commit)
       via  55187d77a5aece6b16c1a6091f9704bd159fda73 (commit)
       via  e745b7a0a24f3f29f1737d9bb52a0c2683384ffb (commit)
       via  1ec505ce98996b4633faf3961692becf0a711bd9 (commit)
      from  fd5cc1028e705b1c5fc350361e3a10a0b23f6b23 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit 17e7050b820314f268996c7f06ae9344a5f4f5c2
Author: Sergey Poznyakoff <address@hidden>
Date:   Sat May 1 19:58:33 2010 +0300

    Optimize readline/readdelim/getdelim calls.
    
    This speeds up common reading operations by factor of 4-6.
    
    * include/mailutils/stream.h (mu_stream_readdelim): New proto.
    * include/mailutils/sys/stream.h (_mu_stream) <readdelim>: New method.
    * mailbox/stream.c (_stream_scandelim, _stream_readdelim): New functions.
    (mu_stream_readdelim): New function.
    (mu_stream_readline): Rewrite using mu_stream_readdelim.
    (mu_stream_getdelim): Optimize.
    
    * mailbox/amd.c (amd_body_stream_readdelim): New function.
    (_amd_attach_message): Set the readdelim method.
    * mailbox/header.c: Add a placeholder for readdelim method.
    * mailbox/message.c (_message_stream_readdelim): New function.
    (_message_stream_create): Set the readdelim method.
    * mailbox/streamref.c (_streamref_readdelim): New function.
    (mu_streamref_create_abridged): Set the readdelim method.

commit d223d743be22bc5dae7aa42b12e529f6c5f03858
Author: Sergey Poznyakoff <address@hidden>
Date:   Sat May 1 17:44:07 2010 +0300

    Fix amd
    
    * mailbox/amd.c (_amd_attach_message): Store body.
    (amd_scan_message): Scan the message only if it has been modified
    after the last scan.
    Fix loop condition.
    Store mhm->mtime on success.
    (amd_message_stream_open): Enforce full buffering.
    (amd_body_stream_read): Fix.
    (amd_body_stream_seek): Don't call mu_stream_seek on mhm->stream.

commit 55187d77a5aece6b16c1a6091f9704bd159fda73
Author: Sergey Poznyakoff <address@hidden>
Date:   Sat May 1 17:43:48 2010 +0300

    Bugfixes
    
    * mailbox/message.c (_check_stream_state): Bugfix.
    (_message_stream_seek): Bugfix.
    (_message_stream_read): Always try to fill out the buffer.
    (_message_stream_create): Set MU_STREAM_SEEK flag bit.

commit e745b7a0a24f3f29f1737d9bb52a0c2683384ffb
Author: Sergey Poznyakoff <address@hidden>
Date:   Sat May 1 17:42:52 2010 +0300

    Bugfix in filter_iconv.
    
    * mailbox/filter_iconv.c (mu_filter_iconv_create): Return
    the created stream in *s.

commit 1ec505ce98996b4633faf3961692becf0a711bd9
Author: Sergey Poznyakoff <address@hidden>
Date:   Sat May 1 17:42:13 2010 +0300

    Keep track of the current offset in the _mu_stream structure.
    
    * include/mailutils/sys/stream.h (_mu_stream)<offset>: New member.
    * mailbox/stream.c (_stream_fill_buffer): Propagate return value
    from mu_stream_read_unbuffered.
    (_stream_flush_buffer): Use stream->offset. Honor the `all' argument.
    (mu_stream_seek): Rewrite using the `offset' member.
    (mu_stream_read_unbuffered)
    (mu_stream_write_unbuffered): Update offset.
    (mu_stream_readline): Return EINVAL if size is 0.

-----------------------------------------------------------------------

Summary of changes:
 include/mailutils/stream.h     |    2 +
 include/mailutils/sys/stream.h |    2 +
 mailbox/amd.c                  |  114 +++++++++++++++++++++++------
 mailbox/filter_iconv.c         |    1 +
 mailbox/header.c               |   53 +++++++++++++
 mailbox/message.c              |   67 +++++++++++++----
 mailbox/stream.c               |  158 ++++++++++++++++++++++++++++------------
 mailbox/streamref.c            |   11 +++
 8 files changed, 324 insertions(+), 84 deletions(-)

diff --git a/include/mailutils/stream.h b/include/mailutils/stream.h
index 0197fcd..cdc55e7 100644
--- a/include/mailutils/stream.h
+++ b/include/mailutils/stream.h
@@ -74,6 +74,8 @@ int mu_stream_seek (mu_stream_t stream, mu_off_t offset, int 
whence,
 int mu_stream_set_buffer (mu_stream_t stream, enum mu_buffer_type type,
                          size_t size);
 int mu_stream_read (mu_stream_t stream, void *buf, size_t size, size_t *pread);
+int mu_stream_readdelim (mu_stream_t stream, char *buf, size_t size,
+                        int delim, size_t *pread);
 int mu_stream_readline (mu_stream_t stream, char *buf, size_t size, size_t 
*pread);
 int mu_stream_getdelim (mu_stream_t stream, char **pbuf, size_t *psize,
                        int delim, size_t *pread);
diff --git a/include/mailutils/sys/stream.h b/include/mailutils/sys/stream.h
index 2800341..e63d60d 100644
--- a/include/mailutils/sys/stream.h
+++ b/include/mailutils/sys/stream.h
@@ -35,11 +35,13 @@ struct _mu_stream
   char *cur;
 
   int flags;
+  mu_off_t offset;
   mu_off_t bytes_in, bytes_out;
   
   int last_err;
 
   int (*read) (struct _mu_stream *, char *, size_t, size_t *);
+  int (*readdelim) (struct _mu_stream *, char *, size_t, int, size_t *);
   int (*write) (struct _mu_stream *, const char *, size_t, size_t *);
   int (*flush) (struct _mu_stream *);
   int (*open) (struct _mu_stream *);
diff --git a/mailbox/amd.c b/mailbox/amd.c
index befe43e..d5ff6d5 100644
--- a/mailbox/amd.c
+++ b/mailbox/amd.c
@@ -117,6 +117,10 @@ static int amd_envelope_sender (mu_envelope_t envelope, 
char *buf, size_t len,
 static int amd_body_stream_read (mu_stream_t str, char *buffer,
                                 size_t buflen,
                                 size_t *pnread);
+static int amd_body_stream_readdelim (mu_stream_t is,
+                                     char *buffer, size_t buflen,
+                                     int delim,
+                                     size_t *pnread);
 static int amd_body_stream_size (mu_stream_t str, mu_off_t *psize);
 static int amd_body_stream_seek (mu_stream_t str, mu_off_t off, int whence,
                                 mu_off_t *presult);
@@ -487,6 +491,7 @@ _amd_attach_message (mu_mailbox_t mailbox, struct 
_amd_message *mhm,
        return ENOMEM;
       }
     str->stream.read = amd_body_stream_read;
+    str->stream.readdelim = amd_body_stream_readdelim;
     str->stream.size = amd_body_stream_size;
     str->stream.seek = amd_body_stream_seek;
     mu_body_set_stream (body, (mu_stream_t) str, msg);
@@ -494,6 +499,7 @@ _amd_attach_message (mu_mailbox_t mailbox, struct 
_amd_message *mhm,
     mu_body_set_size (body, amd_body_size, msg);
     mu_body_set_lines (body, amd_body_lines, msg);
     mu_message_set_body (msg, body, mhm);
+    str->body = body;
   }
 
   /* Set the envelope.  */
@@ -1341,30 +1347,26 @@ amd_scan_message (struct _amd_message *mhm)
   size_t hlines = 0;
   size_t blines = 0;
   size_t body_start = 0;
+  struct stat st;
+  char *msg_name;
 
   /* Check if the message was modified after the last scan */
-  if (mhm->mtime)
-    {
-      struct stat st;
-      char *msg_name;
-
-      status = mhm->amd->cur_msg_file_name (mhm, &msg_name);
-      if (status)
-       return status;
+  status = mhm->amd->cur_msg_file_name (mhm, &msg_name);
+  if (status)
+    return status;
 
-      if (stat (msg_name, &st) == 0 && st.st_mtime == mhm->mtime)
-       {
-         /* Nothing to do */
-         free (msg_name);
-         return 0;
-       }
+  if (stat (msg_name, &st) == 0 && st.st_mtime == mhm->mtime)
+    {
+      /* Nothing to do */
       free (msg_name);
+      return 0;
     }
+  free (msg_name);
 
   off = 0;
   status = mu_stream_seek (stream, 0, MU_SEEK_SET, NULL);
   if (status == 0)
-    while ((status = mu_stream_readline (stream, buf, sizeof (buf), &n) == 0)
+    while ((status = mu_stream_readline (stream, buf, sizeof (buf), &n)) == 0
           && n != 0)
       {
        if (in_header)
@@ -1401,6 +1403,7 @@ amd_scan_message (struct _amd_message *mhm)
 
   if (status == 0)
     {
+      mhm->mtime = st.st_mtime;
       if (!body_start)
        body_start = off;
       mhm->header_lines = hlines;
@@ -1552,6 +1555,9 @@ amd_message_stream_open (struct _amd_message *mhm)
   if (status != 0)
     return status;
 
+  /* FIXME: Select buffer size dynamically */
+  mu_stream_set_buffer (mhm->stream, mu_buffer_full, 16384);
+  
   status = mu_stream_open (mhm->stream);
 
   if (status != 0)
@@ -1614,9 +1620,15 @@ amd_body_stream_read (mu_stream_t is, char *buffer, 
size_t buflen,
   if (ln > 0)
     {
       nread = ((size_t)ln < buflen) ? (size_t)ln : buflen;
-      status = mu_stream_read (mhm->stream, buffer, nread, pnread);
+      status = mu_stream_seek (mhm->stream, mhm->body_start + amdstr->off,
+                              MU_SEEK_SET, NULL);
       if (status == 0)
-       amdstr->off += pnread ? *pnread : nread;
+       {
+         status = mu_stream_read (mhm->stream, buffer, nread, &nread);
+         amdstr->off += nread;
+         if (pnread)
+           *pnread = nread;
+       }
     }
 
   mu_monitor_unlock (mhm->amd->mailbox->monitor);
@@ -1628,14 +1640,75 @@ amd_body_stream_read (mu_stream_t is, char *buffer, 
size_t buflen,
 }
 
 static int
+amd_body_stream_readdelim (mu_stream_t is, char *buffer, size_t buflen,
+                          int delim,
+                          size_t *pnread)
+{
+  struct _amd_body_stream *amdstr = (struct _amd_body_stream *)is;
+  mu_body_t body = amdstr->body;
+  mu_message_t msg = mu_body_get_owner (body);
+  struct _amd_message *mhm = mu_message_get_owner (msg);
+  size_t nread = 0;
+  int status = 0;
+
+  amd_pool_open (mhm);
+
+  if (buffer == NULL || buflen == 0)
+    {
+      if (pnread)
+       *pnread = nread;
+      return 0;
+    }
+
+  mu_monitor_rdlock (mhm->amd->mailbox->monitor);
+#ifdef WITH_PTHREAD
+  /* read() is cancellation point since we're doing a potentially
+     long operation.  Lets make sure we clean the state.  */
+  pthread_cleanup_push (amd_cleanup, (void *)mhm->amd->mailbox);
+#endif
+
+  status = mu_stream_seek (mhm->stream, mhm->body_start + amdstr->off,
+                          MU_SEEK_SET, NULL);
+  if (status)
+    {
+      buflen--;
+      while (buflen)
+       {
+         size_t ln, rdsize;
+         
+         ln = mhm->body_end - (mhm->body_start + amdstr->off);
+         if (ln > 0)
+           {
+             rdsize = ((size_t)ln < buflen) ? (size_t)ln : buflen;
+             status = mu_stream_readdelim (mhm->stream, buffer, rdsize,
+                                           delim, &rdsize);
+             amdstr->off += nread;
+             nread += rdsize;
+             if (status)
+               break;
+             buflen -= rdsize;
+             buffer += rdsize;
+           }
+       }
+    }
+
+  mu_monitor_unlock (mhm->amd->mailbox->monitor);
+#ifdef WITH_PTHREAD
+  pthread_cleanup_pop (0);
+#endif
+
+  if (pnread)
+    *pnread = nread;
+  return status;
+}
+
+static int
 amd_body_stream_seek (mu_stream_t str, mu_off_t off, int whence,
                      mu_off_t *presult)
 {
-  int rc;
   size_t size;
   struct _amd_body_stream *amdstr = (struct _amd_body_stream *)str;
   mu_message_t msg = mu_body_get_owner (amdstr->body);
-  struct _amd_message *mhm = mu_message_get_owner (msg);
   
   amd_body_size (amdstr->body, &size);
   switch (whence)
@@ -1655,9 +1728,6 @@ amd_body_stream_seek (mu_stream_t str, mu_off_t off, int 
whence,
   if (off < 0 || off >= size)
     return ESPIPE;
 
-  rc = mu_stream_seek (mhm->stream, mhm->body_start + off, MU_SEEK_SET, NULL);
-  if (rc)
-    return rc;
   amdstr->off = off;
   if (presult)
     *presult = off;
diff --git a/mailbox/filter_iconv.c b/mailbox/filter_iconv.c
index 3831b96..802c35d 100644
--- a/mailbox/filter_iconv.c
+++ b/mailbox/filter_iconv.c
@@ -462,5 +462,6 @@ mu_filter_iconv_create (mu_stream_t *s, mu_stream_t 
transport,
   iptr->stream.ctl = _icvt_ioctl;
   iptr->stream.wait = _icvt_wait;
   iptr->stream.seek = _icvt_seek;
+  *s = iptr;
   return 0;
 }
diff --git a/mailbox/header.c b/mailbox/header.c
index 224915f..4ad57ec 100644
--- a/mailbox/header.c
+++ b/mailbox/header.c
@@ -999,6 +999,59 @@ header_read (mu_stream_t is, char *buffer, size_t buflen, 
size_t *pnread)
   return 0;
 }
 
+#if 0
+/* FIXME: Implement header_readdelim based on this: */
+static int
+_header_readline (mu_stream_t is, char *buffer, size_t buflen, size_t *pnread)
+{
+  struct _mu_header_stream *hstr = (struct _mu_header_stream *) is;
+  mu_header_t header = hstr->hdr;
+  struct mu_hdrent *ent;
+  size_t ent_off;
+  int status;
+  size_t strsize;
+  char *start, *end;
+
+  if (buflen == 0)
+    return EINVAL;
+
+  header = mu_stream_get_owner (is);
+  status = mu_header_fill (header);
+  if (status)
+    return status;
+  if (mu_hdrent_find_stream_pos (header, hstr->off, &ent, &ent_off))
+    {
+      if (pnread)
+       *pnread = 0;
+      return 0;
+    }
+
+  buflen--; /* Account for the terminating nul */
+
+  mu_hdrent_fixup (header, ent);
+  strsize = MU_STR_SIZE (ent->nlen, ent->vlen) - ent_off;
+  start = MU_HDRENT_NAME (header, ent) + ent_off;
+  end = strchr (start, '\n');
+  if (end)
+    {
+      size_t len = end - start + 1;
+      if (len < strsize)
+       strsize = len;
+    }
+
+  if (strsize < buflen)
+    buflen = strsize;
+
+  memcpy (buffer, start, buflen);
+  buffer[buflen] = 0;
+  hstr->off += buflen;
+  mu_hdrent_unroll_fixup (header, ent);
+  if (pnread)
+    *pnread = buflen;
+  return 0;
+}
+#endif
+
 static int
 header_write (mu_stream_t os, const char *buf, size_t buflen, size_t *pnwrite)
 {
diff --git a/mailbox/message.c b/mailbox/message.c
index d23677c..4f93fa3 100644
--- a/mailbox/message.c
+++ b/mailbox/message.c
@@ -104,7 +104,7 @@ _check_stream_state (struct _mu_message_stream *str)
          rc = mu_body_get_streamref (str->msg->body, &str->transport);
          if (rc == 0)
            {
-             str->state = _mss_header;
+             str->state = _mss_body;
              rc = mu_stream_seek (str->transport, 0, MU_SEEK_SET, NULL);
            }
        }
@@ -194,13 +194,12 @@ _message_stream_seek (struct _mu_stream *str, mu_off_t 
off, int whence,
        return rc;
       /* fall through */
     case _mss_header:
-      if (off > hsize)
-       {
-         mu_stream_destroy (&sp->transport);
-         rc = _check_stream_state (sp);
-         if (rc)
-           return rc;
-       }
+      if (off < hsize)
+       break;
+      mu_stream_destroy (&sp->transport);
+      rc = _check_stream_state (sp);
+      if (rc)
+       return rc;
       /* fall through */
     case _mss_body:
       off -= hsize;
@@ -224,17 +223,51 @@ _message_stream_read (struct _mu_stream *str, char *buf, 
size_t bufsize,
                      size_t *pnread)
 {
   struct _mu_message_stream *sp = (struct _mu_message_stream *)str;
-  int rc = _check_stream_state (sp);
-  if (rc)
-    return rc;
-  if (sp->state == _mss_eof)
+  size_t nread = 0;
+  int rc;
+  
+  while (bufsize)
     {
-      *pnread = 0;
-      return 0;
+      size_t n;
+      rc = _check_stream_state (sp);
+      if (rc)
+       break;
+      if (sp->state == _mss_eof)
+       break;
+      rc = mu_stream_read (sp->transport, buf, bufsize, &n);
+      nread += n;
+      buf += n;
+      bufsize -= n;
     }
-  return mu_stream_read (sp->transport, buf, bufsize, pnread);
+  *pnread = nread;
+  return rc;
 }
 
+static int
+_message_stream_readdelim (struct _mu_stream *str, char *buf, size_t bufsize,
+                          int delim, size_t *pnread)
+{
+  struct _mu_message_stream *sp = (struct _mu_message_stream *)str;
+  size_t nread = 0;
+  int rc;
+  
+  while (bufsize)
+    {
+      size_t n;
+      rc = _check_stream_state (sp);
+      if (rc)
+       break;
+      if (sp->state == _mss_eof)
+       break;
+      rc = mu_stream_readdelim (sp->transport, buf, bufsize, delim, &n);
+      nread += n;
+      buf += n;
+      bufsize -= n;
+    }
+  *pnread = nread;
+  return rc;
+}  
+
 #if 0
 static int
 _message_stream_write (struct _mu_stream *str,
@@ -252,11 +285,13 @@ _message_stream_create (mu_stream_t *pmsg, mu_message_t 
msg, int flags)
 {
   struct _mu_message_stream *sp;
 
-  sp = (struct _mu_message_stream *) _mu_stream_create (sizeof (*sp), flags);
+  sp = (struct _mu_message_stream *) _mu_stream_create (sizeof (*sp),
+                                                       flags | MU_STREAM_SEEK);
   if (!sp)
     return ENOMEM;
 
   sp->stream.read = _message_stream_read;
+  sp->stream.readdelim = _message_stream_readdelim;
   /* FIXME: Write is not defined */
   /*  sp->stream.write = _message_stream_write;*/
   sp->stream.done = _message_stream_done;
diff --git a/mailbox/stream.c b/mailbox/stream.c
index 0ea5c01..21e4fec 100644
--- a/mailbox/stream.c
+++ b/mailbox/stream.c
@@ -69,11 +69,10 @@ _stream_fill_buffer (struct _mu_stream *stream)
       return 0;
        
     case mu_buffer_full:
-      if (mu_stream_read_unbuffered (stream,
-                                    stream->buffer, stream->bufsize,
-                                    0,
-                                    &stream->level))
-       return 1;
+      rc = mu_stream_read_unbuffered (stream,
+                                     stream->buffer, stream->bufsize,
+                                     0,
+                                     &stream->level);
       break;
        
     case mu_buffer_line:
@@ -124,9 +123,7 @@ _stream_flush_buffer (struct _mu_stream *stream, int all)
   if (stream->flags & _MU_STR_DIRTY)
     {
       if ((stream->flags & MU_STREAM_SEEK)
-         && (rc = mu_stream_seek (stream,
-                                  - _stream_orig_level (stream),
-                                  MU_SEEK_CUR, NULL)))
+         && (rc = mu_stream_seek (stream, stream->offset, MU_SEEK_SET, NULL)))
        return rc;
 
       switch (stream->buftype)
@@ -138,6 +135,8 @@ _stream_flush_buffer (struct _mu_stream *stream, int all)
          if ((rc = mu_stream_write_unbuffered (stream, stream->cur,
                                                stream->level, 1, NULL)))
            return rc;
+         if (all)
+           _stream_advance_buffer (stream, stream->level);
          break;
            
        case mu_buffer_line:
@@ -167,6 +166,9 @@ _stream_flush_buffer (struct _mu_stream *stream, int all)
            }
        }
     }
+  else if (all)
+    _stream_advance_buffer (stream, stream->level);
+  
   if (stream->level)
     {
       if (stream->cur > stream->buffer)
@@ -280,11 +282,10 @@ mu_stream_eof (mu_stream_t stream)
 int
 mu_stream_seek (mu_stream_t stream, mu_off_t offset, int whence,
                mu_off_t *pres)
-{
+{    
   int rc;
-  mu_off_t res;
-  size_t bpos;
-    
+  mu_off_t size;
+  
   if (!stream->seek)
     return _stream_seterror (stream, ENOSYS, 0);
 
@@ -297,35 +298,39 @@ mu_stream_seek (mu_stream_t stream, mu_off_t offset, int 
whence,
       break;
 
     case MU_SEEK_CUR:
-      break;
-
-    case MU_SEEK_END: 
-      bpos = _stream_buffer_offset (stream);
-      if (bpos + offset >= 0 && bpos + offset < _stream_orig_level (stream))
+      if (offset == 0)
        {
-         if ((rc = stream->seek (stream, offset, whence, &res)))
-           return _stream_seterror (stream, rc, 1);
-         offset -= bpos;
-         _stream_advance_buffer (stream, offset);
-         _stream_cleareof (stream);
-         if (pres)
-           *pres = res - stream->level;
+         *pres = stream->offset + _stream_buffer_offset (stream);
          return 0;
        }
+      offset += stream->offset;
+      break;
+
+    case MU_SEEK_END:
+      rc = mu_stream_size (stream, &size);
+      if (rc)
+       return _stream_seterror (stream, rc, 1);
+      offset += size;
       break;
 
     default:
       return _stream_seterror (stream, EINVAL, 1);
     }
 
-  if ((rc = _stream_flush_buffer (stream, 1)))
-    return rc;
-  rc = stream->seek (stream, offset, whence, &res);
-  if (rc)
-    return _stream_seterror (stream, rc, 1);
-  _stream_cleareof (stream);
+  if (stream->buftype == mu_buffer_none
+      || offset < stream->offset
+      || offset > stream->offset + _stream_buffer_offset (stream))
+    {
+      if ((rc = _stream_flush_buffer (stream, 1)))
+       return rc;
+      rc = stream->seek (stream, offset, MU_SEEK_SET, &stream->offset);
+      if (rc)
+       return _stream_seterror (stream, rc, 1);
+      _stream_cleareof (stream);
+    }
+  
   if (pres)
-    *pres = res - stream->level;
+    *pres = stream->offset + _stream_buffer_offset (stream);
   return 0;
 }
 
@@ -419,6 +424,7 @@ mu_stream_read_unbuffered (mu_stream_t stream, void *buf, 
size_t size,
          }
        _stream_seterror (stream, rc, rc != 0);
       }
+    stream->offset += nread;
     if (pnread)
       *pnread = nread;
     
@@ -478,6 +484,7 @@ mu_stream_write_unbuffered (mu_stream_t stream,
        stream->bytes_out += nwritten;
     }
   stream->flags |= _MU_STR_WRT;
+  stream->offset += nwritten;
   if (pnwritten)
     *pnwritten = nwritten;
   _stream_seterror (stream, rc, rc != 0);
@@ -524,29 +531,59 @@ mu_stream_read (mu_stream_t stream, void *buf, size_t 
size, size_t *pread)
       
       if (pread)
        *pread = nbytes;
-      else if (size) 
-       return _stream_seterror (stream, EIO, 1);
     }
   return 0;
 }
 
 int
-mu_stream_readline (mu_stream_t stream, char *buf, size_t size, size_t *pread)
+_stream_scandelim (mu_stream_t stream, char *buf, size_t size, int delim,
+                  size_t *pnread)
+{
+  int rc = 0;
+  size_t nread = 0;
+  
+  size--;
+  while (size)
+    {
+      char *p;
+      size_t len;
+      
+      if (stream->level == 0)
+       {
+         if ((rc = _stream_fill_buffer (stream)) || stream->level == 0)
+           break;
+       }
+      
+      p = memchr (stream->cur, delim, stream->level);
+      len = p ? p - stream->cur + 1 : stream->level;
+      if (len > size)
+       len = size;
+      memcpy (buf, stream->cur, len);
+      _stream_advance_buffer (stream, len);
+      buf += len;
+      size -= len;
+      nread += len;
+    }
+  *buf = 0;
+  *pnread = nread;
+  return rc;
+}
+
+static int
+_stream_readdelim (mu_stream_t stream, char *buf, size_t size,
+                  int delim, size_t *pread)
 {
   int rc;
   char c;
   size_t n = 0, rdn;
     
-  if (size == 0)
-    return EIO;
-    
   size--;
   for (n = 0;
        n < size && (rc = mu_stream_read (stream, &c, 1, &rdn)) == 0 && rdn;)
     {
       *buf++ = c;
       n++;
-      if (c == '\n')
+      if (c == delim)
        break;
     }
   *buf = 0;
@@ -556,6 +593,30 @@ mu_stream_readline (mu_stream_t stream, char *buf, size_t 
size, size_t *pread)
 }
 
 int
+mu_stream_readdelim (mu_stream_t stream, char *buf, size_t size,
+                    int delim, size_t *pread)
+{
+  int rc;
+  
+  if (size == 0)
+    return EINVAL;
+    
+  if (stream->readdelim)
+    rc = stream->readdelim (stream, buf, size, delim, pread);
+  else if (stream->buftype != mu_buffer_none)
+    rc = _stream_scandelim (stream, buf, size, delim, pread);
+  else
+    rc = _stream_readdelim (stream, buf, size, delim, pread);
+  return rc;
+}
+
+int
+mu_stream_readline (mu_stream_t stream, char *buf, size_t size, size_t *pread)
+{
+  return mu_stream_readdelim (stream, buf, size, '\n', pread);
+}
+
+int
 mu_stream_getdelim (mu_stream_t stream, char **pbuf, size_t *psize,
                    int delim, size_t *pread)
 {
@@ -576,13 +637,8 @@ mu_stream_getdelim (mu_stream_t stream, char **pbuf, 
size_t *psize,
     
   for (;;)
     {
-      char c;
       size_t rdn;
 
-      rc = mu_stream_read (stream, &c, 1, &rdn);
-      if (rc || rdn == 0)
-       break;
-       
       /* Make enough space for len+1 (for final NUL) bytes.  */
       if (cur_len + 1 >= n)
        {
@@ -610,10 +666,20 @@ mu_stream_getdelim (mu_stream_t stream, char **pbuf, 
size_t *psize,
          n = needed;
        }
 
-      lineptr[cur_len] = c;
-      cur_len++;
+      if (stream->readdelim)
+       rc = stream->readdelim (stream, lineptr + cur_len, n - cur_len, delim,
+                               &rdn);
+      else if (stream->buftype != mu_buffer_none)
+       rc = _stream_scandelim (stream, lineptr + cur_len, n - cur_len, delim,
+                               &rdn);
+      else
+       rc = mu_stream_read (stream, lineptr + cur_len, 1, &rdn);
+
+      if (rc || rdn == 0)
+       break;
+      cur_len += rdn;
       
-      if (c == delim)
+      if (lineptr[cur_len - 1] == delim)
        break;
     }
   lineptr[cur_len] = '\0';
diff --git a/mailbox/streamref.c b/mailbox/streamref.c
index 7e9ff4f..0cad3fa 100644
--- a/mailbox/streamref.c
+++ b/mailbox/streamref.c
@@ -69,6 +69,16 @@ _streamref_read (struct _mu_stream *str, char *buf, size_t 
bufsize,
 }
 
 static int
+_streamref_readdelim (struct _mu_stream *str, char *buf, size_t bufsize,
+                     int delim, size_t *pnread)
+{
+  struct _mu_streamref *sp = (struct _mu_streamref *)str;
+  return streamref_return (sp, mu_stream_readdelim (sp->transport,
+                                                   buf, bufsize,
+                                                   delim, pnread));
+}
+
+static int
 _streamref_write (struct _mu_stream *str, const char *buf, size_t bufsize,
                  size_t *pnwrite)
 {
@@ -264,6 +274,7 @@ mu_streamref_create_abridged (mu_stream_t *pref, 
mu_stream_t str,
   mu_stream_ref (str);
 
   sp->stream.read = _streamref_read; 
+  sp->stream.readdelim = _streamref_readdelim; 
   sp->stream.write = _streamref_write;
   sp->stream.flush = _streamref_flush;
   sp->stream.open = _streamref_open; 


hooks/post-receive
-- 
GNU Mailutils




reply via email to

[Prev in Thread] Current Thread [Next in Thread]