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.
This commit is contained in:
Oswald Buddenhagen 2021-11-26 11:39:55 +01:00
parent 6f15980cd9
commit 96b1e52802
3 changed files with 32 additions and 18 deletions

View File

@ -824,7 +824,8 @@ parse_imap_list( imap_store_t *ctx, char **sp, parse_list_state_t *sts )
{ {
list_t *cur, **curp; list_t *cur, **curp;
char *s = *sp, *d, *p; char *s = *sp, *d, *p;
int n, bytes; int bytes;
uint n;
char c; char c;
assert( sts ); assert( sts );
@ -882,12 +883,14 @@ parse_imap_list( imap_store_t *ctx, char **sp, parse_list_state_t *sts )
s[cur->len] = 0; s[cur->len] = 0;
getbytes: getbytes:
n = socket_read( &ctx->conn, s, (uint)bytes ); if (!(p = socket_read( &ctx->conn, 1, (uint)bytes, &n )))
if (n < 0) { goto postpone;
if (p == (void *)~0) {
badeof: badeof:
sts->err = "unexpected EOF"; sts->err = "unexpected EOF";
goto bail; goto bail;
} }
memcpy( s, p, n );
bytes -= n; bytes -= n;
if (bytes > 0) if (bytes > 0)
goto postpone; goto postpone;

View File

@ -799,20 +799,30 @@ socket_expect_eof( conn_t *sock )
#endif #endif
} }
int char *
socket_read( conn_t *conn, char *buf, uint len ) socket_read( conn_t *conn, uint min_len, uint max_len, uint *out_len )
{ {
uint n = conn->bytes; assert( min_len > 0 );
if (!n && conn->state == SCK_EOF) assert( min_len <= sizeof(conn->buf) );
return -1; assert( min_len <= max_len );
if (n > len)
n = len; uint off = conn->offset;
memcpy( buf, conn->buf + conn->offset, n ); uint cnt = conn->bytes;
if (!(conn->bytes -= n)) 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; conn->offset = 0;
else }
conn->offset += n; return NULL;
return (int)n; }
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 * char *

View File

@ -128,8 +128,9 @@ void socket_start_deflate( conn_t *conn );
void socket_close( conn_t *sock ); void socket_close( conn_t *sock );
void socket_expect_activity( conn_t *sock, int expect ); void socket_expect_activity( conn_t *sock, int expect );
void socket_expect_eof( conn_t *sock ); void socket_expect_eof( conn_t *sock );
int socket_read( conn_t *sock, char *buf, uint len ); /* never waits */ // Don't free return values. These functions never wait.
char *socket_read_line( conn_t *sock ); /* don't free return value; never waits */ 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 enum { KeepOwn = 0, GiveOwn } ownership_t;
typedef struct { typedef struct {
char *buf; char *buf;