commit 96b1e52802a0e9c7c3206f683734e5a744b0cd7a
Author: Oswald Buddenhagen <[email protected]>
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
[email protected]
https://lists.sourceforge.net/lists/listinfo/isync-devel