commit 96b1e52802a0e9c7c3206f683734e5a744b0cd7a
Author: Oswald Buddenhagen <o...@users.sf.net>
Date:   Fri Nov 26 11:39:55 2021 +0100

    make socket_read()'s interface more like socket_read_line()'s
    
    return a pointer into the internal buffer rather than copying into a
    user-supplied one. this permits zero-copy in future use cases.

 src/drv_imap.c |  9 ++++++---
 src/socket.c   | 36 +++++++++++++++++++++++-------------
 src/socket.h   |  5 +++--
 3 files changed, 32 insertions(+), 18 deletions(-)

diff --git a/src/drv_imap.c b/src/drv_imap.c
index 80cfbd75..b887400c 100644
--- a/src/drv_imap.c
+++ b/src/drv_imap.c
@@ -824,7 +824,8 @@ parse_imap_list( imap_store_t *ctx, char **sp, 
parse_list_state_t *sts )
 {
        list_t *cur, **curp;
        char *s = *sp, *d, *p;
-       int n, bytes;
+       int bytes;
+       uint n;
        char c;
 
        assert( sts );
@@ -882,12 +883,14 @@ parse_imap_list( imap_store_t *ctx, char **sp, 
parse_list_state_t *sts )
                        s[cur->len] = 0;
 
                  getbytes:
-                       n = socket_read( &ctx->conn, s, (uint)bytes );
-                       if (n < 0) {
+                       if (!(p = socket_read( &ctx->conn, 1, (uint)bytes, &n 
)))
+                               goto postpone;
+                       if (p == (void *)~0) {
                          badeof:
                                sts->err = "unexpected EOF";
                                goto bail;
                        }
+                       memcpy( s, p, n );
                        bytes -= n;
                        if (bytes > 0)
                                goto postpone;
diff --git a/src/socket.c b/src/socket.c
index 83ba143d..802f69d0 100644
--- a/src/socket.c
+++ b/src/socket.c
@@ -799,20 +799,30 @@ socket_expect_eof( conn_t *sock )
 #endif
 }
 
-int
-socket_read( conn_t *conn, char *buf, uint len )
+char *
+socket_read( conn_t *conn, uint min_len, uint max_len, uint *out_len )
 {
-       uint n = conn->bytes;
-       if (!n && conn->state == SCK_EOF)
-               return -1;
-       if (n > len)
-               n = len;
-       memcpy( buf, conn->buf + conn->offset, n );
-       if (!(conn->bytes -= n))
-               conn->offset = 0;
-       else
-               conn->offset += n;
-       return (int)n;
+       assert( min_len > 0 );
+       assert( min_len <= sizeof(conn->buf) );
+       assert( min_len <= max_len );
+
+       uint off = conn->offset;
+       uint cnt = conn->bytes;
+       if (cnt < min_len) {
+               if (conn->state == SCK_EOF)
+                       return (void *)~0;
+               if (off + min_len > sizeof(conn->buf)) {
+                       memmove( conn->buf, conn->buf + off, cnt );
+                       conn->offset = 0;
+               }
+               return NULL;
+       }
+       uint n = (cnt < max_len) ? cnt : max_len;
+       cnt -= n;
+       conn->offset = cnt ? off + n : 0;
+       conn->bytes = cnt;
+       *out_len = n;
+       return conn->buf + off;
 }
 
 char *
diff --git a/src/socket.h b/src/socket.h
index 7a9e3d96..9f11933a 100644
--- a/src/socket.h
+++ b/src/socket.h
@@ -128,8 +128,9 @@ void socket_start_deflate( conn_t *conn );
 void socket_close( conn_t *sock );
 void socket_expect_activity( conn_t *sock, int expect );
 void socket_expect_eof( conn_t *sock );
-int socket_read( conn_t *sock, char *buf, uint len ); /* never waits */
-char *socket_read_line( conn_t *sock ); /* don't free return value; never 
waits */
+// Don't free return values. These functions never wait.
+char *socket_read( conn_t *conn, uint min_len, uint max_len, uint *out_len );
+char *socket_read_line( conn_t *conn );
 typedef enum { KeepOwn = 0, GiveOwn } ownership_t;
 typedef struct {
        char *buf;


_______________________________________________
isync-devel mailing list
isync-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/isync-devel

Reply via email to