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;
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;

View File

@ -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))
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;
else
conn->offset += n;
return (int)n;
}
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 *

View File

@ -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;