deps: update nghttp3 to 1.10.1

This commit is contained in:
nodejs-github-bot 2025-06-08 00:40:38 +00:00 committed by github-actions[bot]
parent 3b111eb3f5
commit 5da29ecec4
26 changed files with 1144 additions and 753 deletions

View File

@ -2480,8 +2480,6 @@ typedef struct nghttp3_data_reader {
* This function returns 0 if it succeeds, or one of the following
* negative error codes:
*
* :macro:`NGHTTP3_ERR_INVALID_ARGUMENT`
* |stream_id| identifies unidirectional stream.
* :macro:`NGHTTP3_ERR_CONN_CLOSING`
* Connection is shutting down, and no new stream is allowed.
* :macro:`NGHTTP3_ERR_STREAM_IN_USE`

View File

@ -31,7 +31,7 @@
*
* Version number of the nghttp3 library release.
*/
#define NGHTTP3_VERSION "1.6.0"
#define NGHTTP3_VERSION "1.10.1"
/**
* @macro
@ -41,6 +41,6 @@
* number, 8 bits for minor and 8 bits for patch. Version 1.2.3
* becomes 0x010203.
*/
#define NGHTTP3_VERSION_NUM 0x010600
#define NGHTTP3_VERSION_NUM 0x010a01
#endif /* !defined(NGHTTP3_VERSION_H) */

View File

@ -50,6 +50,10 @@ size_t nghttp3_buf_cap(const nghttp3_buf *buf) {
return (size_t)(buf->end - buf->begin);
}
size_t nghttp3_buf_offset(const nghttp3_buf *buf) {
return (size_t)(buf->pos - buf->begin);
}
void nghttp3_buf_reset(nghttp3_buf *buf) { buf->pos = buf->last = buf->begin; }
int nghttp3_buf_reserve(nghttp3_buf *buf, size_t size, const nghttp3_mem *mem) {
@ -87,4 +91,12 @@ void nghttp3_typed_buf_init(nghttp3_typed_buf *tbuf, const nghttp3_buf *buf,
nghttp3_buf_type type) {
tbuf->buf = *buf;
tbuf->type = type;
tbuf->buf.begin = tbuf->buf.pos;
}
void nghttp3_typed_buf_shared_init(nghttp3_typed_buf *tbuf,
const nghttp3_buf *chunk) {
tbuf->buf = *chunk;
tbuf->type = NGHTTP3_BUF_TYPE_SHARED;
tbuf->buf.begin = tbuf->buf.pos = tbuf->buf.last;
}

View File

@ -42,6 +42,12 @@ void nghttp3_buf_wrap_init(nghttp3_buf *buf, uint8_t *src, size_t len);
*/
size_t nghttp3_buf_cap(const nghttp3_buf *buf);
/*
* nghttp3_buf_offset returns the distance from tbuf->begin to
* tbuf->pos. In other words, it returns buf->pos - buf->begin.
*/
size_t nghttp3_buf_offset(const nghttp3_buf *buf);
int nghttp3_buf_reserve(nghttp3_buf *buf, size_t size, const nghttp3_mem *mem);
/*
@ -69,6 +75,13 @@ typedef struct nghttp3_typed_buf {
void nghttp3_typed_buf_init(nghttp3_typed_buf *tbuf, const nghttp3_buf *buf,
nghttp3_buf_type type);
/*
* nghttp3_typed_buf_shared_init initializes |tbuf| of type
* NGHTTP3_BUF_TYPE_SHARED.
*/
void nghttp3_typed_buf_shared_init(nghttp3_typed_buf *tbuf,
const nghttp3_buf *chunk);
void nghttp3_typed_buf_free(nghttp3_typed_buf *tbuf);
#endif /* !defined(NGHTTP3_BUF_H) */

View File

@ -39,7 +39,7 @@
dynamic table capacity that QPACK encoder is willing to use. */
#define NGHTTP3_QPACK_ENCODER_MAX_DTABLE_CAPACITY 4096
nghttp3_objalloc_def(chunk, nghttp3_chunk, oplent);
nghttp3_objalloc_def(chunk, nghttp3_chunk, oplent)
/*
* conn_remote_stream_uni returns nonzero if |stream_id| is remote
@ -233,12 +233,16 @@ static int conn_new(nghttp3_conn **pconn, int server, int callbacks_version,
const nghttp3_callbacks *callbacks, int settings_version,
const nghttp3_settings *settings, const nghttp3_mem *mem,
void *user_data) {
int rv;
nghttp3_conn *conn;
size_t i;
(void)callbacks_version;
(void)settings_version;
assert(settings->max_field_section_size <= NGHTTP3_VARINT_MAX);
assert(settings->qpack_max_dtable_capacity <= NGHTTP3_VARINT_MAX);
assert(settings->qpack_encoder_max_dtable_capacity <= NGHTTP3_VARINT_MAX);
assert(settings->qpack_blocked_streams <= NGHTTP3_VARINT_MAX);
if (mem == NULL) {
mem = nghttp3_mem_default();
}
@ -254,18 +258,11 @@ static int conn_new(nghttp3_conn **pconn, int server, int callbacks_version,
nghttp3_map_init(&conn->streams, mem);
rv =
nghttp3_qpack_decoder_init(&conn->qdec, settings->qpack_max_dtable_capacity,
settings->qpack_blocked_streams, mem);
if (rv != 0) {
goto qdec_init_fail;
}
rv = nghttp3_qpack_encoder_init(
&conn->qenc, settings->qpack_encoder_max_dtable_capacity, mem);
if (rv != 0) {
goto qenc_init_fail;
}
nghttp3_qpack_encoder_init(&conn->qenc,
settings->qpack_encoder_max_dtable_capacity, mem);
nghttp3_pq_init(&conn->qpack_blocked_streams, ricnt_less, mem);
@ -291,16 +288,6 @@ static int conn_new(nghttp3_conn **pconn, int server, int callbacks_version,
*pconn = conn;
return 0;
qenc_init_fail:
nghttp3_qpack_decoder_free(&conn->qdec);
qdec_init_fail:
nghttp3_map_free(&conn->streams);
nghttp3_objalloc_free(&conn->stream_objalloc);
nghttp3_objalloc_free(&conn->out_chunk_objalloc);
nghttp3_mem_free(mem, conn);
return rv;
}
int nghttp3_conn_client_new_versioned(nghttp3_conn **pconn,
@ -399,6 +386,9 @@ nghttp3_ssize nghttp3_conn_read_stream(nghttp3_conn *conn, int64_t stream_id,
size_t bidi_nproc;
int rv;
assert(stream_id >= 0);
assert(stream_id <= (int64_t)NGHTTP3_MAX_VARINT);
stream = nghttp3_conn_find_stream(conn, stream_id);
if (stream == NULL) {
/* TODO Assert idtr */
@ -434,6 +424,10 @@ nghttp3_ssize nghttp3_conn_read_stream(nghttp3_conn *conn, int64_t stream_id,
return rv;
}
}
} else if (!nghttp3_client_stream_uni(stream_id)) {
/* server does not expect to receive new server initiated
bidirectional or unidirectional stream from client. */
return NGHTTP3_ERR_H3_STREAM_CREATION_ERROR;
} else {
/* unidirectional stream */
if (srclen == 0 && fin) {
@ -448,7 +442,7 @@ nghttp3_ssize nghttp3_conn_read_stream(nghttp3_conn *conn, int64_t stream_id,
stream->rx.hstate = NGHTTP3_HTTP_STATE_REQ_INITIAL;
stream->tx.hstate = NGHTTP3_HTTP_STATE_REQ_INITIAL;
} else if (nghttp3_stream_uni(stream_id)) {
} else if (nghttp3_server_stream_uni(stream_id)) {
if (srclen == 0 && fin) {
return 0;
}
@ -461,17 +455,16 @@ nghttp3_ssize nghttp3_conn_read_stream(nghttp3_conn *conn, int64_t stream_id,
stream->rx.hstate = NGHTTP3_HTTP_STATE_RESP_INITIAL;
stream->tx.hstate = NGHTTP3_HTTP_STATE_RESP_INITIAL;
} else {
/* client doesn't expect to receive new bidirectional stream
from server. */
/* client doesn't expect to receive new bidirectional stream or
client initiated unidirectional stream from server. */
return NGHTTP3_ERR_H3_STREAM_CREATION_ERROR;
}
} else if (conn->server) {
if (nghttp3_client_stream_bidi(stream_id)) {
if (stream->rx.hstate == NGHTTP3_HTTP_STATE_NONE) {
stream->rx.hstate = NGHTTP3_HTTP_STATE_REQ_INITIAL;
stream->tx.hstate = NGHTTP3_HTTP_STATE_REQ_INITIAL;
}
}
assert(nghttp3_client_stream_bidi(stream_id) ||
nghttp3_client_stream_uni(stream_id));
} else {
assert(nghttp3_client_stream_bidi(stream_id) ||
nghttp3_server_stream_uni(stream_id));
}
if (srclen == 0 && !fin) {
@ -608,6 +601,9 @@ nghttp3_ssize nghttp3_conn_read_uni(nghttp3_conn *conn, nghttp3_stream *stream,
break;
case NGHTTP3_STREAM_TYPE_UNKNOWN:
nconsumed = (nghttp3_ssize)srclen;
if (fin) {
break;
}
rv = conn_call_stop_sending(conn, stream, NGHTTP3_H3_STREAM_CREATION_ERROR);
if (rv != 0) {
@ -665,7 +661,7 @@ nghttp3_ssize nghttp3_conn_read_control(nghttp3_conn *conn,
nghttp3_varint_read_state_reset(rvint);
rstate->state = NGHTTP3_CTRL_STREAM_STATE_FRAME_LENGTH;
if (p == end) {
break;
return (nghttp3_ssize)nconsumed;
}
/* Fall through */
case NGHTTP3_CTRL_STREAM_STATE_FRAME_LENGTH:
@ -973,6 +969,10 @@ nghttp3_ssize nghttp3_conn_read_control(nghttp3_conn *conn,
rstate->state = NGHTTP3_CTRL_STREAM_STATE_PRIORITY_UPDATE;
if (p == end) {
return (nghttp3_ssize)nconsumed;
}
/* Fall through */
case NGHTTP3_CTRL_STREAM_STATE_PRIORITY_UPDATE:
/* We need to buffer Priority Field Value because it might be
@ -1792,6 +1792,8 @@ conn_on_priority_update_stream(nghttp3_conn *conn,
stream->node.pri = fr->pri;
stream->flags |= NGHTTP3_STREAM_FLAG_PRIORITY_UPDATE_RECVED;
stream->rx.hstate = NGHTTP3_HTTP_STATE_REQ_INITIAL;
stream->tx.hstate = NGHTTP3_HTTP_STATE_REQ_INITIAL;
return 0;
}
@ -1836,7 +1838,7 @@ int nghttp3_conn_create_stream(nghttp3_conn *conn, nghttp3_stream **pstream,
nghttp3_stream *stream;
int rv;
nghttp3_stream_callbacks callbacks = {
conn_stream_acked_data,
.acked_data = conn_stream_acked_data,
};
rv = nghttp3_stream_new(&stream, stream_id, &callbacks,
@ -1874,6 +1876,8 @@ int nghttp3_conn_bind_control_stream(nghttp3_conn *conn, int64_t stream_id) {
nghttp3_frame_entry frent;
int rv;
assert(stream_id >= 0);
assert(stream_id <= (int64_t)NGHTTP3_MAX_VARINT);
assert(!conn->server || nghttp3_server_stream_uni(stream_id));
assert(conn->server || nghttp3_client_stream_uni(stream_id));
@ -1906,6 +1910,10 @@ int nghttp3_conn_bind_qpack_streams(nghttp3_conn *conn, int64_t qenc_stream_id,
nghttp3_stream *stream;
int rv;
assert(qenc_stream_id >= 0);
assert(qenc_stream_id <= (int64_t)NGHTTP3_MAX_VARINT);
assert(qdec_stream_id >= 0);
assert(qdec_stream_id <= (int64_t)NGHTTP3_MAX_VARINT);
assert(!conn->server || nghttp3_server_stream_uni(qenc_stream_id));
assert(!conn->server || nghttp3_server_stream_uni(qdec_stream_id));
assert(conn->server || nghttp3_client_stream_uni(qenc_stream_id));
@ -2194,13 +2202,11 @@ int nghttp3_conn_submit_request(nghttp3_conn *conn, int64_t stream_id,
assert(!conn->server);
assert(conn->tx.qenc);
assert(stream_id >= 0);
assert(stream_id <= (int64_t)NGHTTP3_MAX_VARINT);
assert(nghttp3_client_stream_bidi(stream_id));
/* TODO Should we check that stream_id is client stream_id? */
/* TODO Check GOAWAY last stream ID */
if (nghttp3_stream_uni(stream_id)) {
return NGHTTP3_ERR_INVALID_ARGUMENT;
}
if (conn->flags & NGHTTP3_CONN_FLAG_GOAWAY_RECVED) {
return NGHTTP3_ERR_CONN_CLOSING;
@ -2454,6 +2460,9 @@ int nghttp3_conn_close_stream(nghttp3_conn *conn, int64_t stream_id,
int nghttp3_conn_shutdown_stream_read(nghttp3_conn *conn, int64_t stream_id) {
nghttp3_stream *stream;
assert(stream_id >= 0);
assert(stream_id <= (int64_t)NGHTTP3_MAX_VARINT);
if (!nghttp3_client_stream_bidi(stream_id)) {
return 0;
}
@ -2515,6 +2524,9 @@ uint64_t nghttp3_conn_get_frame_payload_left(nghttp3_conn *conn,
nghttp3_stream *stream;
int uni = 0;
assert(stream_id >= 0);
assert(stream_id <= (int64_t)NGHTTP3_MAX_VARINT);
if (!nghttp3_client_stream_bidi(stream_id)) {
uni = conn_remote_stream_uni(conn, stream_id);
if (!uni) {
@ -2542,6 +2554,8 @@ int nghttp3_conn_get_stream_priority_versioned(nghttp3_conn *conn,
(void)pri_version;
assert(conn->server);
assert(stream_id >= 0);
assert(stream_id <= (int64_t)NGHTTP3_MAX_VARINT);
if (!nghttp3_client_stream_bidi(stream_id)) {
return NGHTTP3_ERR_INVALID_ARGUMENT;
@ -2566,6 +2580,8 @@ int nghttp3_conn_set_client_stream_priority(nghttp3_conn *conn,
uint8_t *buf = NULL;
assert(!conn->server);
assert(stream_id >= 0);
assert(stream_id <= (int64_t)NGHTTP3_MAX_VARINT);
if (!nghttp3_client_stream_bidi(stream_id)) {
return NGHTTP3_ERR_INVALID_ARGUMENT;
@ -2603,6 +2619,8 @@ int nghttp3_conn_set_server_stream_priority_versioned(nghttp3_conn *conn,
assert(conn->server);
assert(pri->urgency < NGHTTP3_URGENCY_LEVELS);
assert(pri->inc == 0 || pri->inc == 1);
assert(stream_id >= 0);
assert(stream_id <= (int64_t)NGHTTP3_MAX_VARINT);
if (!nghttp3_client_stream_bidi(stream_id)) {
return NGHTTP3_ERR_INVALID_ARGUMENT;

View File

@ -76,7 +76,7 @@ typedef struct nghttp3_chunk {
nghttp3_opl_entry oplent;
} nghttp3_chunk;
nghttp3_objalloc_decl(chunk, nghttp3_chunk, oplent);
nghttp3_objalloc_decl(chunk, nghttp3_chunk, oplent)
struct nghttp3_conn {
nghttp3_objalloc out_chunk_objalloc;

View File

@ -66,8 +66,6 @@ const uint8_t *nghttp3_get_varint(int64_t *dest, const uint8_t *p) {
}
}
int64_t nghttp3_get_varint_fb(const uint8_t *p) { return *p & 0x3f; }
size_t nghttp3_get_varintlen(const uint8_t *p) {
return (size_t)(1u << (*p >> 6));
}

View File

@ -135,12 +135,6 @@ STIN uint16_t ntohs(uint16_t netshort) {
*/
const uint8_t *nghttp3_get_varint(int64_t *dest, const uint8_t *p);
/*
* nghttp3_get_varint_fb reads first byte of encoded variable-length
* integer from |p|.
*/
int64_t nghttp3_get_varint_fb(const uint8_t *p);
/*
* nghttp3_get_varintlen returns the required number of bytes to read
* variable-length integer starting at |p|.

View File

@ -29,14 +29,16 @@
#include <assert.h>
void nghttp3_gaptr_init(nghttp3_gaptr *gaptr, const nghttp3_mem *mem) {
nghttp3_ksl_init(&gaptr->gap, nghttp3_ksl_range_compar, sizeof(nghttp3_range),
mem);
nghttp3_ksl_init(&gaptr->gap, nghttp3_ksl_range_compar,
nghttp3_ksl_range_search, sizeof(nghttp3_range), mem);
gaptr->mem = mem;
}
static int gaptr_gap_init(nghttp3_gaptr *gaptr) {
nghttp3_range range = {0, UINT64_MAX};
nghttp3_range range = {
.end = UINT64_MAX,
};
return nghttp3_ksl_insert(&gaptr->gap, NULL, &range, NULL);
}
@ -52,7 +54,11 @@ void nghttp3_gaptr_free(nghttp3_gaptr *gaptr) {
int nghttp3_gaptr_push(nghttp3_gaptr *gaptr, uint64_t offset,
uint64_t datalen) {
int rv;
nghttp3_range k, m, l, r, q = {offset, offset + datalen};
nghttp3_range k, m, l, r;
nghttp3_range q = {
.begin = offset,
.end = offset + datalen,
};
nghttp3_ksl_it it;
if (nghttp3_ksl_len(&gaptr->gap) == 0) {
@ -62,8 +68,8 @@ int nghttp3_gaptr_push(nghttp3_gaptr *gaptr, uint64_t offset,
}
}
it = nghttp3_ksl_lower_bound_compar(&gaptr->gap, &q,
nghttp3_ksl_range_exclusive_compar);
it = nghttp3_ksl_lower_bound_search(&gaptr->gap, &q,
nghttp3_ksl_range_exclusive_search);
for (; !nghttp3_ksl_it_end(&it);) {
k = *(nghttp3_range *)nghttp3_ksl_it_key(&it);
@ -112,7 +118,10 @@ uint64_t nghttp3_gaptr_first_gap_offset(nghttp3_gaptr *gaptr) {
nghttp3_range nghttp3_gaptr_get_first_gap_after(nghttp3_gaptr *gaptr,
uint64_t offset) {
nghttp3_range q = {offset, offset + 1};
nghttp3_range q = {
.begin = offset,
.end = offset + 1,
};
nghttp3_ksl_it it;
if (nghttp3_ksl_len(&gaptr->gap) == 0) {
@ -120,8 +129,8 @@ nghttp3_range nghttp3_gaptr_get_first_gap_after(nghttp3_gaptr *gaptr,
return r;
}
it = nghttp3_ksl_lower_bound_compar(&gaptr->gap, &q,
nghttp3_ksl_range_exclusive_compar);
it = nghttp3_ksl_lower_bound_search(&gaptr->gap, &q,
nghttp3_ksl_range_exclusive_search);
assert(!nghttp3_ksl_it_end(&it));
@ -130,7 +139,10 @@ nghttp3_range nghttp3_gaptr_get_first_gap_after(nghttp3_gaptr *gaptr,
int nghttp3_gaptr_is_pushed(nghttp3_gaptr *gaptr, uint64_t offset,
uint64_t datalen) {
nghttp3_range q = {offset, offset + datalen};
nghttp3_range q = {
.begin = offset,
.end = offset + datalen,
};
nghttp3_ksl_it it;
nghttp3_range m;
@ -138,8 +150,11 @@ int nghttp3_gaptr_is_pushed(nghttp3_gaptr *gaptr, uint64_t offset,
return 0;
}
it = nghttp3_ksl_lower_bound_compar(&gaptr->gap, &q,
nghttp3_ksl_range_exclusive_compar);
it = nghttp3_ksl_lower_bound_search(&gaptr->gap, &q,
nghttp3_ksl_range_exclusive_search);
assert(!nghttp3_ksl_it_end(&it));
m = nghttp3_range_intersect(&q, (nghttp3_range *)nghttp3_ksl_it_key(&it));
return nghttp3_range_len(&m) == 0;

View File

@ -69,11 +69,11 @@ static int64_t parse_uint(const uint8_t *s, size_t len) {
}
for (i = 0; i < len; ++i) {
if ('0' <= s[i] && s[i] <= '9') {
if (n > INT64_MAX / 10) {
if (n > (int64_t)NGHTTP3_MAX_VARINT / 10) {
return -1;
}
n *= 10;
if (n > INT64_MAX - (s[i] - '0')) {
if (n > (int64_t)NGHTTP3_MAX_VARINT - (s[i] - '0')) {
return -1;
}
n += s[i] - '0';
@ -124,17 +124,17 @@ static int is_ws(uint8_t c) {
int nghttp3_http_parse_priority(nghttp3_pri *dest, const uint8_t *value,
size_t valuelen) {
nghttp3_pri pri = *dest;
sf_parser sfp;
sf_vec key;
sf_value val;
sfparse_parser sfp;
sfparse_vec key;
sfparse_value val;
int rv;
sf_parser_init(&sfp, value, valuelen);
sfparse_parser_init(&sfp, value, valuelen);
for (;;) {
rv = sf_parser_dict(&sfp, &key, &val);
rv = sfparse_parser_dict(&sfp, &key, &val);
if (rv != 0) {
if (rv == SF_ERR_EOF) {
if (rv == SFPARSE_ERR_EOF) {
break;
}
@ -147,7 +147,7 @@ int nghttp3_http_parse_priority(nghttp3_pri *dest, const uint8_t *value,
switch (key.base[0]) {
case 'i':
if (val.type != SF_TYPE_BOOLEAN) {
if (val.type != SFPARSE_TYPE_BOOLEAN) {
return NGHTTP3_ERR_INVALID_ARGUMENT;
}
@ -155,7 +155,8 @@ int nghttp3_http_parse_priority(nghttp3_pri *dest, const uint8_t *value,
break;
case 'u':
if (val.type != SF_TYPE_INTEGER || val.integer < NGHTTP3_URGENCY_HIGH ||
if (val.type != SFPARSE_TYPE_INTEGER ||
val.integer < NGHTTP3_URGENCY_HIGH ||
NGHTTP3_URGENCY_LOW < val.integer) {
return NGHTTP3_ERR_INVALID_ARGUMENT;
}
@ -197,7 +198,7 @@ static char VALID_AUTHORITY_CHARS[] = {
1 /* 4 */, 1 /* 5 */, 1 /* 6 */, 1 /* 7 */,
1 /* 8 */, 1 /* 9 */, 1 /* : */, 1 /* ; */,
0 /* < */, 1 /* = */, 0 /* > */, 0 /* ? */,
1 /* @ */, 1 /* A */, 1 /* B */, 1 /* C */,
0 /* @ */, 1 /* A */, 1 /* B */, 1 /* C */,
1 /* D */, 1 /* E */, 1 /* F */, 1 /* G */,
1 /* H */, 1 /* I */, 1 /* J */, 1 /* K */,
1 /* L */, 1 /* M */, 1 /* N */, 1 /* O */,
@ -548,6 +549,9 @@ static int http_request_on_header(nghttp3_http_state *http,
break;
case NGHTTP3_QPACK_TOKEN_PRIORITY:
if (!nghttp3_check_header_value(nv->value->base, nv->value->len)) {
http->flags &= ~NGHTTP3_HTTP_FLAG_PRIORITY;
http->flags |= NGHTTP3_HTTP_FLAG_BAD_PRIORITY;
return NGHTTP3_ERR_REMOVE_HTTP_HEADER;
}
@ -991,7 +995,11 @@ int nghttp3_check_header_value(const uint8_t *value, size_t len) {
case 0:
return 1;
case 1:
return !is_ws(*value);
if (is_ws(*value)) {
return 0;
}
break;
default:
if (is_ws(*value) || is_ws(*(value + len - 1))) {
return 0;

View File

@ -34,9 +34,9 @@
#include "nghttp3_mem.h"
#include "nghttp3_range.h"
static nghttp3_ksl_blk null_blk = {{{NULL, NULL, 0, 0, {0}}}};
static nghttp3_ksl_blk null_blk;
nghttp3_objalloc_def(ksl_blk, nghttp3_ksl_blk, oplent);
nghttp3_objalloc_def(ksl_blk, nghttp3_ksl_blk, oplent)
static size_t ksl_nodelen(size_t keylen) {
assert(keylen >= sizeof(uint64_t));
@ -59,7 +59,8 @@ static void ksl_node_set_key(nghttp3_ksl *ksl, nghttp3_ksl_node *node,
}
void nghttp3_ksl_init(nghttp3_ksl *ksl, nghttp3_ksl_compar compar,
size_t keylen, const nghttp3_mem *mem) {
nghttp3_ksl_search search, size_t keylen,
const nghttp3_mem *mem) {
size_t nodelen = ksl_nodelen(keylen);
nghttp3_objalloc_init(&ksl->blkalloc,
@ -68,6 +69,7 @@ void nghttp3_ksl_init(nghttp3_ksl *ksl, nghttp3_ksl_compar compar,
ksl->head = NULL;
ksl->front = ksl->back = NULL;
ksl->compar = compar;
ksl->search = search;
ksl->n = 0;
ksl->keylen = keylen;
ksl->nodelen = nodelen;
@ -274,20 +276,6 @@ static void ksl_insert_node(nghttp3_ksl *ksl, nghttp3_ksl_blk *blk, size_t i,
++blk->n;
}
static size_t ksl_search(const nghttp3_ksl *ksl, nghttp3_ksl_blk *blk,
const nghttp3_ksl_key *key,
nghttp3_ksl_compar compar) {
size_t i;
nghttp3_ksl_node *node;
for (i = 0, node = (nghttp3_ksl_node *)(void *)blk->nodes;
i < blk->n && compar((nghttp3_ksl_key *)node->key, key);
++i, node = (nghttp3_ksl_node *)(void *)((uint8_t *)node + ksl->nodelen))
;
return i;
}
int nghttp3_ksl_insert(nghttp3_ksl *ksl, nghttp3_ksl_it *it,
const nghttp3_ksl_key *key, void *data) {
nghttp3_ksl_blk *blk;
@ -312,7 +300,7 @@ int nghttp3_ksl_insert(nghttp3_ksl *ksl, nghttp3_ksl_it *it,
blk = ksl->head;
for (;;) {
i = ksl_search(ksl, blk, key, ksl->compar);
i = ksl->search(ksl, blk, key);
if (blk->leaf) {
if (i < blk->n &&
@ -571,7 +559,7 @@ int nghttp3_ksl_remove(nghttp3_ksl *ksl, nghttp3_ksl_it *it,
}
for (;;) {
i = ksl_search(ksl, blk, key, ksl->compar);
i = ksl->search(ksl, blk, key);
if (i == blk->n) {
if (it) {
@ -642,12 +630,12 @@ int nghttp3_ksl_remove(nghttp3_ksl *ksl, nghttp3_ksl_it *it,
nghttp3_ksl_it nghttp3_ksl_lower_bound(const nghttp3_ksl *ksl,
const nghttp3_ksl_key *key) {
return nghttp3_ksl_lower_bound_compar(ksl, key, ksl->compar);
return nghttp3_ksl_lower_bound_search(ksl, key, ksl->search);
}
nghttp3_ksl_it nghttp3_ksl_lower_bound_compar(const nghttp3_ksl *ksl,
nghttp3_ksl_it nghttp3_ksl_lower_bound_search(const nghttp3_ksl *ksl,
const nghttp3_ksl_key *key,
nghttp3_ksl_compar compar) {
nghttp3_ksl_search search) {
nghttp3_ksl_blk *blk = ksl->head;
nghttp3_ksl_it it;
size_t i;
@ -658,7 +646,7 @@ nghttp3_ksl_it nghttp3_ksl_lower_bound_compar(const nghttp3_ksl *ksl,
}
for (;;) {
i = ksl_search(ksl, blk, key, compar);
i = search(ksl, blk, key);
if (blk->leaf) {
if (i == blk->n && blk->next) {
@ -702,7 +690,7 @@ void nghttp3_ksl_update_key(nghttp3_ksl *ksl, const nghttp3_ksl_key *old_key,
assert(ksl->head);
for (;;) {
i = ksl_search(ksl, blk, old_key, ksl->compar);
i = ksl->search(ksl, blk, old_key);
assert(i < blk->n);
node = nghttp3_ksl_nth_node(ksl, blk, i);
@ -825,9 +813,50 @@ int nghttp3_ksl_range_compar(const nghttp3_ksl_key *lhs,
return a->begin < b->begin;
}
nghttp3_ksl_search_def(range, nghttp3_ksl_range_compar)
size_t nghttp3_ksl_range_search(const nghttp3_ksl *ksl, nghttp3_ksl_blk *blk,
const nghttp3_ksl_key *key) {
return ksl_range_search(ksl, blk, key);
}
int nghttp3_ksl_range_exclusive_compar(const nghttp3_ksl_key *lhs,
const nghttp3_ksl_key *rhs) {
const nghttp3_range *a = lhs, *b = rhs;
return a->begin < b->begin && !(nghttp3_max_uint64(a->begin, b->begin) <
nghttp3_min_uint64(a->end, b->end));
}
nghttp3_ksl_search_def(range_exclusive, nghttp3_ksl_range_exclusive_compar)
size_t nghttp3_ksl_range_exclusive_search(const nghttp3_ksl *ksl,
nghttp3_ksl_blk *blk,
const nghttp3_ksl_key *key) {
return ksl_range_exclusive_search(ksl, blk, key);
}
int nghttp3_ksl_uint64_less(const nghttp3_ksl_key *lhs,
const nghttp3_ksl_key *rhs) {
return *(uint64_t *)lhs < *(uint64_t *)rhs;
}
nghttp3_ksl_search_def(uint64_less, nghttp3_ksl_uint64_less)
size_t nghttp3_ksl_uint64_less_search(const nghttp3_ksl *ksl,
nghttp3_ksl_blk *blk,
const nghttp3_ksl_key *key) {
return ksl_uint64_less_search(ksl, blk, key);
}
int nghttp3_ksl_int64_greater(const nghttp3_ksl_key *lhs,
const nghttp3_ksl_key *rhs) {
return *(int64_t *)lhs > *(int64_t *)rhs;
}
nghttp3_ksl_search_def(int64_greater, nghttp3_ksl_int64_greater)
size_t nghttp3_ksl_int64_greater_search(const nghttp3_ksl *ksl,
nghttp3_ksl_blk *blk,
const nghttp3_ksl_key *key) {
return ksl_int64_greater_search(ksl, blk, key);
}

View File

@ -104,7 +104,7 @@ struct nghttp3_ksl_blk {
};
};
nghttp3_objalloc_decl(ksl_blk, nghttp3_ksl_blk, oplent);
nghttp3_objalloc_decl(ksl_blk, nghttp3_ksl_blk, oplent)
/*
* nghttp3_ksl_compar is a function type which returns nonzero if key
@ -115,6 +115,35 @@ typedef int (*nghttp3_ksl_compar)(const nghttp3_ksl_key *lhs,
typedef struct nghttp3_ksl nghttp3_ksl;
/*
* nghttp3_ksl_search is a function to search for the first element in
* |blk|->nodes which is not ordered before |key|. It returns the
* index of such element. It returns |blk|->n if there is no such
* element.
*/
typedef size_t (*nghttp3_ksl_search)(const nghttp3_ksl *ksl,
nghttp3_ksl_blk *blk,
const nghttp3_ksl_key *key);
/*
* nghttp3_ksl_search_def is a macro to implement nghttp3_ksl_search
* with COMPAR which is supposed to be nghttp3_ksl_compar.
*/
#define nghttp3_ksl_search_def(NAME, COMPAR) \
static size_t ksl_##NAME##_search(const nghttp3_ksl *ksl, \
nghttp3_ksl_blk *blk, \
const nghttp3_ksl_key *key) { \
size_t i; \
nghttp3_ksl_node *node; \
\
for (i = 0, node = (nghttp3_ksl_node *)(void *)blk->nodes; \
i < blk->n && COMPAR((nghttp3_ksl_key *)node->key, key); ++i, \
node = (nghttp3_ksl_node *)(void *)((uint8_t *)node + ksl->nodelen)) \
; \
\
return i; \
}
typedef struct nghttp3_ksl_it nghttp3_ksl_it;
/*
@ -138,6 +167,7 @@ struct nghttp3_ksl {
/* back points to the last leaf block. */
nghttp3_ksl_blk *back;
nghttp3_ksl_compar compar;
nghttp3_ksl_search search;
/* n is the number of elements stored. */
size_t n;
/* keylen is the size of key */
@ -149,11 +179,13 @@ struct nghttp3_ksl {
/*
* nghttp3_ksl_init initializes |ksl|. |compar| specifies compare
* function. |keylen| is the length of key and must be at least
* function. |search| is a search function which must use |compar|.
* |keylen| is the length of key and must be at least
* sizeof(uint64_t).
*/
void nghttp3_ksl_init(nghttp3_ksl *ksl, nghttp3_ksl_compar compar,
size_t keylen, const nghttp3_mem *mem);
nghttp3_ksl_search search, size_t keylen,
const nghttp3_mem *mem);
/*
* nghttp3_ksl_free frees resources allocated for |ksl|. If |ksl| is
@ -218,12 +250,12 @@ nghttp3_ksl_it nghttp3_ksl_lower_bound(const nghttp3_ksl *ksl,
const nghttp3_ksl_key *key);
/*
* nghttp3_ksl_lower_bound_compar works like nghttp3_ksl_lower_bound,
* but it takes custom function |compar| to do lower bound search.
* nghttp3_ksl_lower_bound_search works like nghttp3_ksl_lower_bound,
* but it takes custom function |search| to do lower bound search.
*/
nghttp3_ksl_it nghttp3_ksl_lower_bound_compar(const nghttp3_ksl *ksl,
nghttp3_ksl_it nghttp3_ksl_lower_bound_search(const nghttp3_ksl *ksl,
const nghttp3_ksl_key *key,
nghttp3_ksl_compar compar);
nghttp3_ksl_search search);
/*
* nghttp3_ksl_update_key replaces the key of nodes which has
@ -330,22 +362,69 @@ int nghttp3_ksl_it_begin(const nghttp3_ksl_it *it);
/*
* nghttp3_ksl_range_compar is an implementation of
* nghttp3_ksl_compar. lhs->ptr and rhs->ptr must point to
* nghttp3_range object and the function returns nonzero if (const
* nghttp3_range *)(lhs->ptr)->begin < (const nghttp3_range
* *)(rhs->ptr)->begin.
* nghttp3_ksl_compar. |lhs| and |rhs| must point to nghttp3_range
* object, and the function returns nonzero if ((const nghttp3_range
* *)lhs)->begin < ((const nghttp3_range *)rhs)->begin.
*/
int nghttp3_ksl_range_compar(const nghttp3_ksl_key *lhs,
const nghttp3_ksl_key *rhs);
/*
* nghttp3_ksl_range_search is an implementation of nghttp3_ksl_search
* that uses nghttp3_ksl_range_compar.
*/
size_t nghttp3_ksl_range_search(const nghttp3_ksl *ksl, nghttp3_ksl_blk *blk,
const nghttp3_ksl_key *key);
/*
* nghttp3_ksl_range_exclusive_compar is an implementation of
* nghttp3_ksl_compar. lhs->ptr and rhs->ptr must point to
* nghttp3_range object and the function returns nonzero if (const
* nghttp3_range *)(lhs->ptr)->begin < (const nghttp3_range
* *)(rhs->ptr)->begin and the 2 ranges do not intersect.
* nghttp3_ksl_compar. |lhs| and |rhs| must point to nghttp3_range
* object, and the function returns nonzero if ((const nghttp3_range
* *)lhs)->begin < ((const nghttp3_range *)rhs)->begin, and the 2
* ranges do not intersect.
*/
int nghttp3_ksl_range_exclusive_compar(const nghttp3_ksl_key *lhs,
const nghttp3_ksl_key *rhs);
/*
* nghttp3_ksl_range_exclusive_search is an implementation of
* nghttp3_ksl_search that uses nghttp3_ksl_range_exclusive_compar.
*/
size_t nghttp3_ksl_range_exclusive_search(const nghttp3_ksl *ksl,
nghttp3_ksl_blk *blk,
const nghttp3_ksl_key *key);
/*
* nghttp3_ksl_uint64_less is an implementation of nghttp3_ksl_compar.
* |lhs| and |rhs| must point to uint64_t objects, and the function
* returns nonzero if *(uint64_t *)|lhs| < *(uint64_t *)|rhs|.
*/
int nghttp3_ksl_uint64_less(const nghttp3_ksl_key *lhs,
const nghttp3_ksl_key *rhs);
/*
* nghttp3_ksl_uint64_less_search is an implementation of
* nghttp3_ksl_search that uses nghttp3_ksl_uint64_less.
*/
size_t nghttp3_ksl_uint64_less_search(const nghttp3_ksl *ksl,
nghttp3_ksl_blk *blk,
const nghttp3_ksl_key *key);
/*
* nghttp3_ksl_int64_greater is an implementation of
* nghttp3_ksl_compar. |lhs| and |rhs| must point to int64_t objects,
* and the function returns nonzero if *(int64_t *)|lhs| > *(int64_t
* *)|rhs|.
*/
int nghttp3_ksl_int64_greater(const nghttp3_ksl_key *lhs,
const nghttp3_ksl_key *rhs);
/*
* nghttp3_ksl_int64_greater_search is an implementation of
* nghttp3_ksl_search that uses nghttp3_ksl_int64_greater.
*/
size_t nghttp3_ksl_int64_greater_search(const nghttp3_ksl *ksl,
nghttp3_ksl_blk *blk,
const nghttp3_ksl_key *key);
#endif /* !defined(NGHTTP3_KSL_H) */

View File

@ -48,27 +48,27 @@
#define nghttp3_max_def(SUFFIX, T) \
static inline T nghttp3_max_##SUFFIX(T a, T b) { return a < b ? b : a; }
nghttp3_max_def(int8, int8_t);
nghttp3_max_def(int16, int16_t);
nghttp3_max_def(int32, int32_t);
nghttp3_max_def(int64, int64_t);
nghttp3_max_def(uint8, uint8_t);
nghttp3_max_def(uint16, uint16_t);
nghttp3_max_def(uint32, uint32_t);
nghttp3_max_def(uint64, uint64_t);
nghttp3_max_def(size, size_t);
nghttp3_max_def(int8, int8_t)
nghttp3_max_def(int16, int16_t)
nghttp3_max_def(int32, int32_t)
nghttp3_max_def(int64, int64_t)
nghttp3_max_def(uint8, uint8_t)
nghttp3_max_def(uint16, uint16_t)
nghttp3_max_def(uint32, uint32_t)
nghttp3_max_def(uint64, uint64_t)
nghttp3_max_def(size, size_t)
#define nghttp3_min_def(SUFFIX, T) \
static inline T nghttp3_min_##SUFFIX(T a, T b) { return a < b ? a : b; }
nghttp3_min_def(int8, int8_t);
nghttp3_min_def(int16, int16_t);
nghttp3_min_def(int32, int32_t);
nghttp3_min_def(int64, int64_t);
nghttp3_min_def(uint8, uint8_t);
nghttp3_min_def(uint16, uint16_t);
nghttp3_min_def(uint32, uint32_t);
nghttp3_min_def(uint64, uint64_t);
nghttp3_min_def(size, size_t);
nghttp3_min_def(int8, int8_t)
nghttp3_min_def(int16, int16_t)
nghttp3_min_def(int32, int32_t)
nghttp3_min_def(int64, int64_t)
nghttp3_min_def(uint8, uint8_t)
nghttp3_min_def(uint16, uint16_t)
nghttp3_min_def(uint32, uint32_t)
nghttp3_min_def(uint64, uint64_t)
nghttp3_min_def(size, size_t)
#endif /* !defined(NGHTTP3_MACRO_H) */

View File

@ -120,7 +120,11 @@ void nghttp3_map_print_distance(const nghttp3_map *map) {
static int insert(nghttp3_map_bucket *table, size_t hashbits,
nghttp3_map_key_type key, void *data) {
size_t idx = hash(key, hashbits);
nghttp3_map_bucket b = {0, key, data}, *bkt;
nghttp3_map_bucket b = {
.key = key,
.data = data,
};
nghttp3_map_bucket *bkt;
size_t mask = (1u << hashbits) - 1;
for (;;) {

View File

@ -164,20 +164,4 @@ int nghttp3_pq_empty(const nghttp3_pq *pq) { return pq->length == 0; }
size_t nghttp3_pq_size(const nghttp3_pq *pq) { return pq->length; }
int nghttp3_pq_each(const nghttp3_pq *pq, nghttp3_pq_item_cb fun, void *arg) {
size_t i;
if (pq->length == 0) {
return 0;
}
for (i = 0; i < pq->length; ++i) {
if ((*fun)(pq->q[i], arg)) {
return 1;
}
}
return 0;
}
void nghttp3_pq_clear(nghttp3_pq *pq) { pq->length = 0; }

View File

@ -112,17 +112,6 @@ int nghttp3_pq_empty(const nghttp3_pq *pq);
*/
size_t nghttp3_pq_size(const nghttp3_pq *pq);
typedef int (*nghttp3_pq_item_cb)(nghttp3_pq_entry *item, void *arg);
/*
* nghttp3_pq_each applies |fun| to each item in |pq|. The |arg| is
* passed as arg parameter to callback function. This function must
* not change the ordering key. If the return value from callback is
* nonzero, this function returns 1 immediately without iterating
* remaining items. Otherwise this function returns 0.
*/
int nghttp3_pq_each(const nghttp3_pq *pq, nghttp3_pq_item_cb fun, void *arg);
/*
* nghttp3_pq_remove removes |item| from |pq|. |pq| must contain
* |item| otherwise the behavior is undefined.

View File

@ -41,7 +41,12 @@
#define NGHTTP3_QPACK_MAX_QPACK_STREAMS 2000
/* Make scalar initialization form of nghttp3_qpack_static_entry */
#define MAKE_STATIC_ENT(I, T, H) {I, T, H}
#define MAKE_STATIC_ENT(I, T, H) \
{ \
.absidx = I, \
.token = T, \
.hash = H, \
}
/* Generated by mkstatichdtbl.py */
static nghttp3_qpack_static_entry token_stable[] = {
@ -166,9 +171,19 @@ static nghttp3_qpack_static_entry token_stable[] = {
/* Make scalar initialization form of nghttp3_qpack_static_entry */
#define MAKE_STATIC_HD(N, V, T) \
{ \
{NULL, (uint8_t *)(N), sizeof((N)) - 1, -1}, \
{NULL, (uint8_t *)(V), sizeof((V)) - 1, -1}, \
T, \
.name = \
{ \
.base = (uint8_t *)(N), \
.len = sizeof((N)) - 1, \
.ref = -1, \
}, \
.value = \
{ \
.base = (uint8_t *)(V), \
.len = sizeof((V)) - 1, \
.ref = -1, \
}, \
.token = T, \
}
static nghttp3_qpack_static_header stable[] = {
@ -828,29 +843,12 @@ static void encoder_qpack_map_find(nghttp3_qpack_encoder *encoder,
* ctx->max_dtable_capacity and it is initialized to 0.
* |hard_max_dtable_capacity| is the upper bound of
* ctx->max_dtable_capacity.
*
* This function returns 0 if it succeeds, or one of the following
* negative error codes:
*
* NGHTTP3_ERR_NOMEM
* Out of memory.
*/
static int qpack_context_init(nghttp3_qpack_context *ctx,
static void qpack_context_init(nghttp3_qpack_context *ctx,
size_t hard_max_dtable_capacity,
size_t max_blocked_streams,
const nghttp3_mem *mem) {
int rv;
size_t len = 4096 / NGHTTP3_QPACK_ENTRY_OVERHEAD;
size_t len2;
for (len2 = 1; len2 < len; len2 <<= 1)
;
rv = nghttp3_ringbuf_init(&ctx->dtable, len2, sizeof(nghttp3_qpack_entry *),
mem);
if (rv != 0) {
return rv;
}
nghttp3_ringbuf_init(&ctx->dtable, 0, sizeof(nghttp3_qpack_entry *), mem);
ctx->mem = mem;
ctx->dtable_size = 0;
@ -860,8 +858,6 @@ static int qpack_context_init(nghttp3_qpack_context *ctx,
ctx->max_blocked_streams = max_blocked_streams;
ctx->next_absidx = 0;
ctx->bad = 0;
return 0;
}
static void qpack_context_free(nghttp3_qpack_context *ctx) {
@ -898,19 +894,17 @@ static int max_cnt_greater(const nghttp3_ksl_key *lhs,
return a->max_cnt > b->max_cnt || (a->max_cnt == b->max_cnt && a->id < b->id);
}
int nghttp3_qpack_encoder_init(nghttp3_qpack_encoder *encoder,
nghttp3_ksl_search_def(max_cnt_greater, max_cnt_greater)
void nghttp3_qpack_encoder_init(nghttp3_qpack_encoder *encoder,
size_t hard_max_dtable_capacity,
const nghttp3_mem *mem) {
int rv;
rv = qpack_context_init(&encoder->ctx, hard_max_dtable_capacity, 0, mem);
if (rv != 0) {
return rv;
}
qpack_context_init(&encoder->ctx, hard_max_dtable_capacity, 0, mem);
nghttp3_map_init(&encoder->streams, mem);
nghttp3_ksl_init(&encoder->blocked_streams, max_cnt_greater,
ksl_max_cnt_greater_search,
sizeof(nghttp3_blocked_streams_key), mem);
qpack_map_init(&encoder->dtable_map);
@ -925,8 +919,6 @@ int nghttp3_qpack_encoder_init(nghttp3_qpack_encoder *encoder,
encoder->flags = NGHTTP3_QPACK_ENCODER_FLAG_NONE;
nghttp3_qpack_read_state_reset(&encoder->rstate);
return 0;
}
static int map_stream_free(void *data, void *ptr) {
@ -1149,6 +1141,9 @@ int nghttp3_qpack_encoder_encode(nghttp3_qpack_encoder *encoder,
int blocked_stream;
nghttp3_qpack_stream *stream;
assert(stream_id >= 0);
assert(stream_id <= (int64_t)NGHTTP3_MAX_VARINT);
if (encoder->ctx.bad) {
return NGHTTP3_ERR_QPACK_FATAL;
}
@ -1444,7 +1439,14 @@ int nghttp3_qpack_encoder_encode_nv(nghttp3_qpack_encoder *encoder,
uint32_t hash = 0;
int32_t token;
nghttp3_qpack_indexing_mode indexing_mode;
nghttp3_qpack_lookup_result sres = {-1, 0, -1}, dres = {-1, 0, -1};
nghttp3_qpack_lookup_result sres = {
.index = -1,
.pb_index = -1,
};
nghttp3_qpack_lookup_result dres = {
.index = -1,
.pb_index = -1,
};
nghttp3_qpack_entry *new_ent = NULL;
int static_entry;
int just_index = 0;
@ -1608,8 +1610,10 @@ int nghttp3_qpack_encoder_encode_nv(nghttp3_qpack_encoder *encoder,
nghttp3_qpack_lookup_result
nghttp3_qpack_lookup_stable(const nghttp3_nv *nv, int32_t token,
nghttp3_qpack_indexing_mode indexing_mode) {
nghttp3_qpack_lookup_result res = {(nghttp3_ssize)token_stable[token].absidx,
0, -1};
nghttp3_qpack_lookup_result res = {
.index = (nghttp3_ssize)token_stable[token].absidx,
.pb_index = -1,
};
nghttp3_qpack_static_entry *ent;
nghttp3_qpack_static_header *hdr;
size_t i;
@ -1639,7 +1643,10 @@ nghttp3_qpack_lookup_result nghttp3_qpack_encoder_lookup_dtable(
nghttp3_qpack_encoder *encoder, const nghttp3_nv *nv, int32_t token,
uint32_t hash, nghttp3_qpack_indexing_mode indexing_mode, uint64_t krcnt,
int allow_blocking) {
nghttp3_qpack_lookup_result res = {-1, 0, -1};
nghttp3_qpack_lookup_result res = {
.index = -1,
.pb_index = -1,
};
int exact_match = 0;
nghttp3_qpack_entry *match, *pb_match;
@ -1694,7 +1701,6 @@ static int ref_max_cnt_greater(const nghttp3_pq_entry *lhsx,
int nghttp3_qpack_stream_new(nghttp3_qpack_stream **pstream, int64_t stream_id,
const nghttp3_mem *mem) {
int rv;
nghttp3_qpack_stream *stream;
stream = nghttp3_mem_malloc(mem, sizeof(nghttp3_qpack_stream));
@ -1702,12 +1708,8 @@ int nghttp3_qpack_stream_new(nghttp3_qpack_stream **pstream, int64_t stream_id,
return NGHTTP3_ERR_NOMEM;
}
rv = nghttp3_ringbuf_init(&stream->refs, 4,
nghttp3_ringbuf_init(&stream->refs, 0,
sizeof(nghttp3_qpack_header_block_ref *), mem);
if (rv != 0) {
nghttp3_mem_free(mem, stream);
return rv;
}
nghttp3_pq_init(&stream->max_cnts, ref_max_cnt_greater, mem);
@ -1759,17 +1761,23 @@ int nghttp3_qpack_stream_add_ref(nghttp3_qpack_stream *stream,
int rv;
if (nghttp3_ringbuf_full(&stream->refs)) {
rv = nghttp3_ringbuf_reserve(&stream->refs,
nghttp3_ringbuf_len(&stream->refs) * 2);
rv = nghttp3_ringbuf_reserve(
&stream->refs,
nghttp3_max_size(4, nghttp3_ringbuf_len(&stream->refs) * 2));
if (rv != 0) {
return rv;
}
}
rv = nghttp3_pq_push(&stream->max_cnts, &ref->max_cnts_pe);
if (rv != 0) {
return rv;
}
dest = nghttp3_ringbuf_push_back(&stream->refs);
*dest = ref;
return nghttp3_pq_push(&stream->max_cnts, &ref->max_cnts_pe);
return 0;
}
void nghttp3_qpack_stream_pop_ref(nghttp3_qpack_stream *stream) {
@ -1834,7 +1842,7 @@ static int qpack_encoder_write_indexed_name(nghttp3_qpack_encoder *encoder,
int h = 0;
hlen = nghttp3_qpack_huffman_encode_count(nv->value, nv->valuelen);
if (hlen * 4 < nv->valuelen * 3) {
if (hlen < nv->valuelen) {
h = 1;
len += nghttp3_qpack_put_varint_len(hlen, 7) + hlen;
} else {
@ -1925,7 +1933,7 @@ static int qpack_encoder_write_literal(nghttp3_qpack_encoder *encoder,
int nh = 0, vh = 0;
nhlen = nghttp3_qpack_huffman_encode_count(nv->name, nv->namelen);
if (nhlen * 4 < nv->namelen * 3) {
if (nhlen < nv->namelen) {
nh = 1;
len = nghttp3_qpack_put_varint_len(nhlen, prefix) + nhlen;
} else {
@ -1933,7 +1941,7 @@ static int qpack_encoder_write_literal(nghttp3_qpack_encoder *encoder,
}
vhlen = nghttp3_qpack_huffman_encode_count(nv->value, nv->valuelen);
if (vhlen * 4 < nv->valuelen * 3) {
if (vhlen < nv->valuelen) {
vh = 1;
len += nghttp3_qpack_put_varint_len(vhlen, 7) + vhlen;
} else {
@ -2083,8 +2091,9 @@ int nghttp3_qpack_context_dtable_add(nghttp3_qpack_context *ctx,
hash);
if (nghttp3_ringbuf_full(&ctx->dtable)) {
rv = nghttp3_ringbuf_reserve(&ctx->dtable,
nghttp3_ringbuf_len(&ctx->dtable) * 2);
rv = nghttp3_ringbuf_reserve(
&ctx->dtable,
nghttp3_max_size(128, nghttp3_ringbuf_len(&ctx->dtable) * 2));
if (rv != 0) {
goto fail;
}
@ -2259,10 +2268,11 @@ void nghttp3_qpack_entry_free(nghttp3_qpack_entry *ent) {
int nghttp3_qpack_encoder_block_stream(nghttp3_qpack_encoder *encoder,
nghttp3_qpack_stream *stream) {
nghttp3_blocked_streams_key bsk = {
nghttp3_struct_of(nghttp3_pq_top(&stream->max_cnts),
.max_cnt = nghttp3_struct_of(nghttp3_pq_top(&stream->max_cnts),
nghttp3_qpack_header_block_ref, max_cnts_pe)
->max_cnt,
(uint64_t)stream->stream_id};
.id = (uint64_t)stream->stream_id,
};
return nghttp3_ksl_insert(&encoder->blocked_streams, NULL, &bsk, stream);
}
@ -2270,10 +2280,11 @@ int nghttp3_qpack_encoder_block_stream(nghttp3_qpack_encoder *encoder,
void nghttp3_qpack_encoder_unblock_stream(nghttp3_qpack_encoder *encoder,
nghttp3_qpack_stream *stream) {
nghttp3_blocked_streams_key bsk = {
nghttp3_struct_of(nghttp3_pq_top(&stream->max_cnts),
.max_cnt = nghttp3_struct_of(nghttp3_pq_top(&stream->max_cnts),
nghttp3_qpack_header_block_ref, max_cnts_pe)
->max_cnt,
(uint64_t)stream->stream_id};
.id = (uint64_t)stream->stream_id,
};
nghttp3_ksl_it it;
/* This is purely debugging purpose only */
@ -2287,7 +2298,9 @@ void nghttp3_qpack_encoder_unblock_stream(nghttp3_qpack_encoder *encoder,
void nghttp3_qpack_encoder_unblock(nghttp3_qpack_encoder *encoder,
uint64_t max_cnt) {
nghttp3_blocked_streams_key bsk = {max_cnt, 0};
nghttp3_blocked_streams_key bsk = {
.max_cnt = max_cnt,
};
nghttp3_ksl_it it;
it = nghttp3_ksl_lower_bound(&encoder->blocked_streams, &bsk);
@ -2667,17 +2680,12 @@ void nghttp3_qpack_read_state_reset(nghttp3_qpack_read_state *rstate) {
rstate->huffman_encoded = 0;
}
int nghttp3_qpack_decoder_init(nghttp3_qpack_decoder *decoder,
void nghttp3_qpack_decoder_init(nghttp3_qpack_decoder *decoder,
size_t hard_max_dtable_capacity,
size_t max_blocked_streams,
const nghttp3_mem *mem) {
int rv;
rv = qpack_context_init(&decoder->ctx, hard_max_dtable_capacity,
qpack_context_init(&decoder->ctx, hard_max_dtable_capacity,
max_blocked_streams, mem);
if (rv != 0) {
return rv;
}
decoder->state = NGHTTP3_QPACK_ES_STATE_OPCODE;
decoder->opcode = 0;
@ -2687,8 +2695,6 @@ int nghttp3_qpack_decoder_init(nghttp3_qpack_decoder *decoder,
nghttp3_qpack_read_state_reset(&decoder->rstate);
nghttp3_buf_init(&decoder->dbuf);
return 0;
}
void nghttp3_qpack_decoder_free(nghttp3_qpack_decoder *decoder) {
@ -3171,6 +3177,7 @@ int nghttp3_qpack_decoder_dtable_static_add(nghttp3_qpack_decoder *decoder) {
rv = nghttp3_qpack_context_dtable_add(&decoder->ctx, &qnv, NULL, 0);
nghttp3_rcbuf_decref(qnv.value);
decoder->rstate.value = NULL;
return rv;
}
@ -3197,6 +3204,7 @@ int nghttp3_qpack_decoder_dtable_dynamic_add(nghttp3_qpack_decoder *decoder) {
rv = nghttp3_qpack_context_dtable_add(&decoder->ctx, &qnv, NULL, 0);
nghttp3_rcbuf_decref(qnv.value);
decoder->rstate.value = NULL;
nghttp3_rcbuf_decref(qnv.name);
return rv;
@ -3250,7 +3258,9 @@ int nghttp3_qpack_decoder_dtable_literal_add(nghttp3_qpack_decoder *decoder) {
rv = nghttp3_qpack_context_dtable_add(&decoder->ctx, &qnv, NULL, 0);
nghttp3_rcbuf_decref(qnv.value);
decoder->rstate.value = NULL;
nghttp3_rcbuf_decref(qnv.name);
decoder->rstate.name = NULL;
return rv;
}
@ -3818,6 +3828,9 @@ int nghttp3_qpack_decoder_cancel_stream(nghttp3_qpack_decoder *decoder,
uint8_t *p;
int rv;
assert(stream_id >= 0);
assert(stream_id <= (int64_t)NGHTTP3_MAX_VARINT);
if (qpack_decoder_dbuf_overflow(decoder)) {
return NGHTTP3_ERR_QPACK_FATAL;
}
@ -4062,7 +4075,6 @@ void nghttp3_qpack_decoder_emit_literal(nghttp3_qpack_decoder *decoder,
int nghttp3_qpack_encoder_new(nghttp3_qpack_encoder **pencoder,
size_t hard_max_dtable_capacity,
const nghttp3_mem *mem) {
int rv;
nghttp3_qpack_encoder *p;
p = nghttp3_mem_malloc(mem, sizeof(nghttp3_qpack_encoder));
@ -4070,10 +4082,7 @@ int nghttp3_qpack_encoder_new(nghttp3_qpack_encoder **pencoder,
return NGHTTP3_ERR_NOMEM;
}
rv = nghttp3_qpack_encoder_init(p, hard_max_dtable_capacity, mem);
if (rv != 0) {
return rv;
}
nghttp3_qpack_encoder_init(p, hard_max_dtable_capacity, mem);
*pencoder = p;
@ -4098,6 +4107,9 @@ int nghttp3_qpack_stream_context_new(nghttp3_qpack_stream_context **psctx,
const nghttp3_mem *mem) {
nghttp3_qpack_stream_context *p;
assert(stream_id >= 0);
assert(stream_id <= (int64_t)NGHTTP3_MAX_VARINT);
p = nghttp3_mem_malloc(mem, sizeof(nghttp3_qpack_stream_context));
if (p == NULL) {
return NGHTTP3_ERR_NOMEM;
@ -4127,7 +4139,6 @@ int nghttp3_qpack_decoder_new(nghttp3_qpack_decoder **pdecoder,
size_t hard_max_dtable_capacity,
size_t max_blocked_streams,
const nghttp3_mem *mem) {
int rv;
nghttp3_qpack_decoder *p;
p = nghttp3_mem_malloc(mem, sizeof(nghttp3_qpack_decoder));
@ -4135,11 +4146,8 @@ int nghttp3_qpack_decoder_new(nghttp3_qpack_decoder **pdecoder,
return NGHTTP3_ERR_NOMEM;
}
rv = nghttp3_qpack_decoder_init(p, hard_max_dtable_capacity,
max_blocked_streams, mem);
if (rv != 0) {
return rv;
}
nghttp3_qpack_decoder_init(p, hard_max_dtable_capacity, max_blocked_streams,
mem);
*pdecoder = p;

View File

@ -270,14 +270,8 @@ struct nghttp3_qpack_encoder {
* nghttp3_qpack_encoder_init initializes |encoder|.
* |hard_max_dtable_capacity| is the upper bound of the dynamic table
* capacity. |mem| is a memory allocator.
*
* This function returns 0 if it succeeds, or one of the following
* negative error codes:
*
* NGHTTP3_ERR_NOMEM
* Out of memory.
*/
int nghttp3_qpack_encoder_init(nghttp3_qpack_encoder *encoder,
void nghttp3_qpack_encoder_init(nghttp3_qpack_encoder *encoder,
size_t hard_max_dtable_capacity,
const nghttp3_mem *mem);
@ -800,14 +794,8 @@ struct nghttp3_qpack_decoder {
* |hard_max_dtable_capacity| is the upper bound of the dynamic table
* capacity. |max_blocked_streams| is the maximum number of stream
* which can be blocked. |mem| is a memory allocator.
*
* This function returns 0 if it succeeds, or one of the following
* negative error codes:
*
* NGHTTP3_ERR_NOMEM
* Out of memory.
*/
int nghttp3_qpack_decoder_init(nghttp3_qpack_decoder *decoder,
void nghttp3_qpack_decoder_init(nghttp3_qpack_decoder *decoder,
size_t hard_max_dtable_capacity,
size_t max_blocked_streams,
const nghttp3_mem *mem);

View File

@ -88,7 +88,9 @@ nghttp3_qpack_huffman_decode(nghttp3_qpack_huffman_decode_context *ctx,
int fin) {
uint8_t *p = dest;
const uint8_t *end = src + srclen;
nghttp3_qpack_huffman_decode_node node = {ctx->fstate, 0};
nghttp3_qpack_huffman_decode_node node = {
.fstate = ctx->fstate,
};
const nghttp3_qpack_huffman_decode_node *t = &node;
uint8_t c;

View File

@ -33,7 +33,7 @@ void nghttp3_range_init(nghttp3_range *r, uint64_t begin, uint64_t end) {
nghttp3_range nghttp3_range_intersect(const nghttp3_range *a,
const nghttp3_range *b) {
nghttp3_range r = {0, 0};
nghttp3_range r = {0};
uint64_t begin = nghttp3_max_uint64(a->begin, b->begin);
uint64_t end = nghttp3_min_uint64(a->end, b->end);

View File

@ -33,9 +33,11 @@
#include "nghttp3_macro.h"
#ifndef NDEBUG
static int ispow2(size_t n) {
#if defined(_MSC_VER) && !defined(__clang__) && \
(defined(_M_ARM) || (defined(_M_ARM64) && _MSC_VER < 1941))
# if defined(DISABLE_POPCNT) || \
(defined(_MSC_VER) && !defined(__clang__) && \
(defined(_M_ARM) || (defined(_M_ARM64) && _MSC_VER < 1941)))
return n && !(n & (n - 1));
# elif defined(WIN32)
return 1 == __popcnt((unsigned int)n);
@ -45,6 +47,7 @@ static int ispow2(size_t n) {
# endif /* !((defined(_MSC_VER) && !defined(__clang__) && (defined(_M_ARM) || \
(defined(_M_ARM64) && _MSC_VER < 1941))) || defined(WIN32)) */
}
#endif /* !defined(NDEBUG) */
int nghttp3_ringbuf_init(nghttp3_ringbuf *rb, size_t nmemb, size_t size,
const nghttp3_mem *mem) {

View File

@ -44,7 +44,7 @@
/* NGHTTP3_MIN_RBLEN is the minimum length of nghttp3_ringbuf */
#define NGHTTP3_MIN_RBLEN 4
nghttp3_objalloc_def(stream, nghttp3_stream, oplent);
nghttp3_objalloc_def(stream, nghttp3_stream, oplent)
int nghttp3_stream_new(nghttp3_stream **pstream, int64_t stream_id,
const nghttp3_stream_callbacks *callbacks,
@ -181,42 +181,45 @@ void nghttp3_stream_read_state_reset(nghttp3_stream_read_state *rstate) {
nghttp3_ssize nghttp3_read_varint(nghttp3_varint_read_state *rvint,
const uint8_t *begin, const uint8_t *end,
int fin) {
const uint8_t *orig_begin = begin;
size_t len;
size_t len, vlen;
uint8_t *p;
assert(begin != end);
if (rvint->left == 0) {
assert(rvint->acc == 0);
len = nghttp3_get_varintlen(begin);
if (len <= (size_t)(end - begin)) {
vlen = nghttp3_get_varintlen(begin);
len = nghttp3_min_size(vlen, (size_t)(end - begin));
if (vlen <= len) {
nghttp3_get_varint(&rvint->acc, begin);
return (nghttp3_ssize)len;
return (nghttp3_ssize)vlen;
}
if (fin) {
return NGHTTP3_ERR_INVALID_ARGUMENT;
}
rvint->acc = nghttp3_get_varint_fb(begin++);
rvint->left = len - 1;
p = (uint8_t *)&rvint->acc + (sizeof(rvint->acc) - vlen);
memcpy(p, begin, len);
*p &= 0x3f;
rvint->left = vlen - len;
return (nghttp3_ssize)len;
}
len = nghttp3_min_size(rvint->left, (size_t)(end - begin));
end = begin + len;
for (; begin != end;) {
rvint->acc = (rvint->acc << 8) + *begin++;
}
p = (uint8_t *)&rvint->acc + (sizeof(rvint->acc) - rvint->left);
memcpy(p, begin, len);
rvint->left -= len;
if (fin && rvint->left) {
if (rvint->left == 0) {
rvint->acc = (int64_t)nghttp3_ntohl64((uint64_t)rvint->acc);
} else if (fin) {
return NGHTTP3_ERR_INVALID_ARGUMENT;
}
return (nghttp3_ssize)(begin - orig_begin);
return (nghttp3_ssize)len;
}
int nghttp3_stream_frq_add(nghttp3_stream *stream,
@ -301,12 +304,6 @@ int nghttp3_stream_fill_outq(nghttp3_stream *stream) {
return 0;
}
static void typed_buf_shared_init(nghttp3_typed_buf *tbuf,
const nghttp3_buf *chunk) {
nghttp3_typed_buf_init(tbuf, chunk, NGHTTP3_BUF_TYPE_SHARED);
tbuf->buf.pos = tbuf->buf.last;
}
int nghttp3_stream_write_stream_type(nghttp3_stream *stream) {
size_t len = nghttp3_put_varintlen((int64_t)stream->type);
nghttp3_buf *chunk;
@ -319,7 +316,7 @@ int nghttp3_stream_write_stream_type(nghttp3_stream *stream) {
}
chunk = nghttp3_stream_get_chunk(stream);
typed_buf_shared_init(&tbuf, chunk);
nghttp3_typed_buf_shared_init(&tbuf, chunk);
chunk->last = nghttp3_put_varint(chunk->last, (int64_t)stream->type);
tbuf.buf.last = chunk->last;
@ -336,12 +333,19 @@ int nghttp3_stream_write_settings(nghttp3_stream *stream,
struct {
nghttp3_frame_settings settings;
nghttp3_settings_entry iv[15];
} fr;
} fr = {
.settings =
{
.hd =
{
.type = NGHTTP3_FRAME_SETTINGS,
},
.niv = 3,
},
};
nghttp3_settings_entry *iv;
nghttp3_settings *local_settings = frent->aux.settings.local_settings;
fr.settings.hd.type = NGHTTP3_FRAME_SETTINGS;
fr.settings.niv = 3;
iv = &fr.settings.iv[0];
iv[0].id = NGHTTP3_SETTINGS_ID_MAX_FIELD_SECTION_SIZE;
@ -373,7 +377,7 @@ int nghttp3_stream_write_settings(nghttp3_stream *stream,
}
chunk = nghttp3_stream_get_chunk(stream);
typed_buf_shared_init(&tbuf, chunk);
nghttp3_typed_buf_shared_init(&tbuf, chunk);
chunk->last = nghttp3_frame_write_settings(chunk->last, &fr.settings);
@ -398,7 +402,7 @@ int nghttp3_stream_write_goaway(nghttp3_stream *stream,
}
chunk = nghttp3_stream_get_chunk(stream);
typed_buf_shared_init(&tbuf, chunk);
nghttp3_typed_buf_shared_init(&tbuf, chunk);
chunk->last = nghttp3_frame_write_goaway(chunk->last, fr);
@ -423,7 +427,7 @@ int nghttp3_stream_write_priority_update(nghttp3_stream *stream,
}
chunk = nghttp3_stream_get_chunk(stream);
typed_buf_shared_init(&tbuf, chunk);
nghttp3_typed_buf_shared_init(&tbuf, chunk);
chunk->last = nghttp3_frame_write_priority_update(chunk->last, fr);
@ -464,7 +468,7 @@ int nghttp3_stream_write_header_block(nghttp3_stream *stream,
rv = nghttp3_qpack_encoder_encode(qenc, &pbuf, rbuf, ebuf, stream->node.id,
nva, nvlen);
if (rv != 0) {
goto fail;
return rv;
}
pbuflen = nghttp3_buf_len(&pbuf);
@ -482,11 +486,11 @@ int nghttp3_stream_write_header_block(nghttp3_stream *stream,
rv = nghttp3_stream_ensure_chunk(stream, len);
if (rv != 0) {
goto fail;
return rv;
}
chunk = nghttp3_stream_get_chunk(stream);
typed_buf_shared_init(&tbuf, chunk);
nghttp3_typed_buf_shared_init(&tbuf, chunk);
chunk->last = nghttp3_frame_write_hd(chunk->last, &hd);
@ -498,13 +502,13 @@ int nghttp3_stream_write_header_block(nghttp3_stream *stream,
rv = nghttp3_stream_outq_add(stream, &tbuf);
if (rv != 0) {
goto fail;
return rv;
}
nghttp3_typed_buf_init(&tbuf, rbuf, NGHTTP3_BUF_TYPE_PRIVATE);
rv = nghttp3_stream_outq_add(stream, &tbuf);
if (rv != 0) {
goto fail;
return rv;
}
nghttp3_buf_init(rbuf);
} else if (rbuflen) {
@ -513,7 +517,7 @@ int nghttp3_stream_write_header_block(nghttp3_stream *stream,
rv = nghttp3_stream_outq_add(stream, &tbuf);
if (rv != 0) {
goto fail;
return rv;
}
nghttp3_buf_reset(rbuf);
}
@ -532,18 +536,18 @@ int nghttp3_stream_write_header_block(nghttp3_stream *stream,
rv = nghttp3_stream_ensure_chunk(qenc_stream, ebuflen);
if (rv != 0) {
goto fail;
return rv;
}
chunk = nghttp3_stream_get_chunk(qenc_stream);
typed_buf_shared_init(&tbuf, chunk);
nghttp3_typed_buf_shared_init(&tbuf, chunk);
chunk->last = nghttp3_cpymem(chunk->last, ebuf->pos, ebuflen);
tbuf.buf.last = chunk->last;
rv = nghttp3_stream_outq_add(qenc_stream, &tbuf);
if (rv != 0) {
goto fail;
return rv;
}
nghttp3_buf_reset(ebuf);
}
@ -553,10 +557,6 @@ int nghttp3_stream_write_header_block(nghttp3_stream *stream,
assert(0 == nghttp3_buf_len(ebuf));
return 0;
fail:
return rv;
}
int nghttp3_stream_write_data(nghttp3_stream *stream, int *peof,
@ -635,7 +635,7 @@ int nghttp3_stream_write_data(nghttp3_stream *stream, int *peof,
}
chunk = nghttp3_stream_get_chunk(stream);
typed_buf_shared_init(&tbuf, chunk);
nghttp3_typed_buf_shared_init(&tbuf, chunk);
chunk->last = nghttp3_frame_write_hd(chunk->last, &hd);
@ -690,7 +690,7 @@ int nghttp3_stream_write_qpack_decoder_stream(nghttp3_stream *stream) {
}
chunk = nghttp3_stream_get_chunk(stream);
typed_buf_shared_init(&tbuf, chunk);
nghttp3_typed_buf_shared_init(&tbuf, chunk);
nghttp3_qpack_decoder_write_decoder(qdec, chunk);
@ -717,17 +717,16 @@ int nghttp3_stream_outq_add(nghttp3_stream *stream,
if (len) {
dest = nghttp3_ringbuf_get(outq, len - 1);
if (dest->type == tbuf->type && dest->type == NGHTTP3_BUF_TYPE_SHARED &&
dest->buf.begin == tbuf->buf.begin && dest->buf.last == tbuf->buf.pos) {
dest->buf.end == tbuf->buf.end && dest->buf.last == tbuf->buf.pos) {
/* If we have already written last entry, adjust outq_idx and
offset so that this entry is eligible to send. */
if (len == stream->outq_idx) {
--stream->outq_idx;
stream->outq_offset = nghttp3_buf_len(&dest->buf);
}
dest->buf.last = tbuf->buf.last;
/* TODO Is this required? */
dest->buf.end = tbuf->buf.end;
assert(dest->buf.end == tbuf->buf.end);
return 0;
}
@ -817,34 +816,24 @@ size_t nghttp3_stream_writev(nghttp3_stream *stream, int *pfin,
nghttp3_ringbuf *outq = &stream->outq;
size_t len = nghttp3_ringbuf_len(outq);
size_t i = stream->outq_idx;
uint64_t offset = stream->outq_offset;
size_t buflen;
nghttp3_vec *vbegin = vec, *vend = vec + veccnt;
nghttp3_typed_buf *tbuf;
assert(veccnt > 0);
if (i < len) {
for (; i < len && vec != vend; ++i) {
tbuf = nghttp3_ringbuf_get(outq, i);
buflen = nghttp3_buf_len(&tbuf->buf);
if (offset < buflen) {
vec->base = tbuf->buf.pos + offset;
vec->len = (size_t)(buflen - offset);
++vec;
} else {
/* This is the only case that satisfies offset >= buflen */
assert(0 == offset);
assert(0 == buflen);
if (buflen == 0) {
continue;
}
++i;
for (; i < len && vec != vend; ++i, ++vec) {
tbuf = nghttp3_ringbuf_get(outq, i);
vec->base = tbuf->buf.pos;
vec->len = nghttp3_buf_len(&tbuf->buf);
}
vec->len = buflen;
++vec;
}
/* TODO Rework this if we have finished implementing HTTP
@ -859,26 +848,27 @@ void nghttp3_stream_add_outq_offset(nghttp3_stream *stream, size_t n) {
nghttp3_ringbuf *outq = &stream->outq;
size_t i;
size_t len = nghttp3_ringbuf_len(outq);
uint64_t offset = stream->outq_offset + n;
size_t buflen;
nghttp3_typed_buf *tbuf;
stream->unsent_bytes -= n;
for (i = stream->outq_idx; i < len; ++i) {
tbuf = nghttp3_ringbuf_get(outq, i);
buflen = nghttp3_buf_len(&tbuf->buf);
if (offset >= buflen) {
offset -= buflen;
continue;
}
if (n < buflen) {
tbuf->buf.pos += n;
break;
}
assert(i < len || offset == 0);
tbuf->buf.pos = tbuf->buf.last;
n -= buflen;
}
assert(i < len || n == 0);
stream->unsent_bytes -= n;
stream->outq_idx = i;
stream->outq_offset = offset;
}
int nghttp3_stream_outq_write_done(nghttp3_stream *stream) {
@ -904,7 +894,6 @@ static void stream_pop_outq_entry(nghttp3_stream *stream,
chunk = nghttp3_ringbuf_get(chunks, 0);
assert(chunk->begin == tbuf->buf.begin);
assert(chunk->end == tbuf->buf.end);
if (chunk->last == tbuf->buf.last) {
@ -927,14 +916,13 @@ static void stream_pop_outq_entry(nghttp3_stream *stream,
int nghttp3_stream_update_ack_offset(nghttp3_stream *stream, uint64_t offset) {
nghttp3_ringbuf *outq = &stream->outq;
size_t buflen;
size_t npopped = 0;
uint64_t nack;
nghttp3_typed_buf *tbuf;
int rv;
for (; nghttp3_ringbuf_len(outq);) {
tbuf = nghttp3_ringbuf_get(outq, 0);
buflen = nghttp3_buf_len(&tbuf->buf);
buflen = (size_t)(tbuf->buf.last - tbuf->buf.begin);
/* For NGHTTP3_BUF_TYPE_ALIEN, we never add 0 length buffer. */
if (tbuf->type == NGHTTP3_BUF_TYPE_ALIEN && stream->ack_offset < offset &&
@ -949,17 +937,13 @@ int nghttp3_stream_update_ack_offset(nghttp3_stream *stream, uint64_t offset) {
}
}
if (offset >= stream->ack_base + buflen) {
if (stream->outq_idx > 0 && offset >= stream->ack_base + buflen) {
stream_pop_outq_entry(stream, tbuf);
stream->ack_base += buflen;
stream->ack_offset = stream->ack_base;
++npopped;
if (stream->outq_idx + 1 == npopped) {
stream->outq_offset = 0;
break;
}
--stream->outq_idx;
continue;
}
@ -967,13 +951,6 @@ int nghttp3_stream_update_ack_offset(nghttp3_stream *stream, uint64_t offset) {
break;
}
assert(stream->outq_idx + 1 >= npopped);
if (stream->outq_idx >= npopped) {
stream->outq_idx -= npopped;
} else {
stream->outq_idx = 0;
}
stream->ack_offset = offset;
return 0;
@ -1045,19 +1022,17 @@ int nghttp3_stream_transit_rx_http_state(nghttp3_stream *stream,
switch (stream->rx.hstate) {
case NGHTTP3_HTTP_STATE_NONE:
return NGHTTP3_ERR_H3_INTERNAL_ERROR;
nghttp3_unreachable();
case NGHTTP3_HTTP_STATE_REQ_INITIAL:
switch (event) {
case NGHTTP3_HTTP_EVENT_HEADERS_BEGIN:
stream->rx.hstate = NGHTTP3_HTTP_STATE_REQ_HEADERS_BEGIN;
return 0;
default:
if (event != NGHTTP3_HTTP_EVENT_HEADERS_BEGIN) {
return NGHTTP3_ERR_H3_FRAME_UNEXPECTED;
}
stream->rx.hstate = NGHTTP3_HTTP_STATE_REQ_HEADERS_BEGIN;
return 0;
case NGHTTP3_HTTP_STATE_REQ_HEADERS_BEGIN:
if (event != NGHTTP3_HTTP_EVENT_HEADERS_END) {
return NGHTTP3_ERR_MALFORMED_HTTP_MESSAGING;
}
assert(NGHTTP3_HTTP_EVENT_HEADERS_END == event);
stream->rx.hstate = NGHTTP3_HTTP_STATE_REQ_HEADERS_END;
return 0;
case NGHTTP3_HTTP_STATE_REQ_HEADERS_END:
@ -1080,12 +1055,10 @@ int nghttp3_stream_transit_rx_http_state(nghttp3_stream *stream,
stream->rx.hstate = NGHTTP3_HTTP_STATE_REQ_END;
return 0;
default:
return NGHTTP3_ERR_H3_FRAME_UNEXPECTED;
nghttp3_unreachable();
}
case NGHTTP3_HTTP_STATE_REQ_DATA_BEGIN:
if (event != NGHTTP3_HTTP_EVENT_DATA_END) {
return NGHTTP3_ERR_MALFORMED_HTTP_MESSAGING;
}
assert(NGHTTP3_HTTP_EVENT_DATA_END == event);
stream->rx.hstate = NGHTTP3_HTTP_STATE_REQ_DATA_END;
return 0;
case NGHTTP3_HTTP_STATE_REQ_DATA_END:
@ -1108,12 +1081,10 @@ int nghttp3_stream_transit_rx_http_state(nghttp3_stream *stream,
stream->rx.hstate = NGHTTP3_HTTP_STATE_REQ_END;
return 0;
default:
return NGHTTP3_ERR_H3_FRAME_UNEXPECTED;
nghttp3_unreachable();
}
case NGHTTP3_HTTP_STATE_REQ_TRAILERS_BEGIN:
if (event != NGHTTP3_HTTP_EVENT_HEADERS_END) {
return NGHTTP3_ERR_MALFORMED_HTTP_MESSAGING;
}
assert(NGHTTP3_HTTP_EVENT_HEADERS_END == event);
stream->rx.hstate = NGHTTP3_HTTP_STATE_REQ_TRAILERS_END;
return 0;
case NGHTTP3_HTTP_STATE_REQ_TRAILERS_END:
@ -1129,7 +1100,7 @@ int nghttp3_stream_transit_rx_http_state(nghttp3_stream *stream,
stream->rx.hstate = NGHTTP3_HTTP_STATE_REQ_END;
return 0;
case NGHTTP3_HTTP_STATE_REQ_END:
return NGHTTP3_ERR_MALFORMED_HTTP_MESSAGING;
return NGHTTP3_ERR_H3_FRAME_UNEXPECTED;
case NGHTTP3_HTTP_STATE_RESP_INITIAL:
if (event != NGHTTP3_HTTP_EVENT_HEADERS_BEGIN) {
return NGHTTP3_ERR_H3_FRAME_UNEXPECTED;
@ -1137,9 +1108,7 @@ int nghttp3_stream_transit_rx_http_state(nghttp3_stream *stream,
stream->rx.hstate = NGHTTP3_HTTP_STATE_RESP_HEADERS_BEGIN;
return 0;
case NGHTTP3_HTTP_STATE_RESP_HEADERS_BEGIN:
if (event != NGHTTP3_HTTP_EVENT_HEADERS_END) {
return NGHTTP3_ERR_MALFORMED_HTTP_MESSAGING;
}
assert(NGHTTP3_HTTP_EVENT_HEADERS_END == event);
stream->rx.hstate = NGHTTP3_HTTP_STATE_RESP_HEADERS_END;
return 0;
case NGHTTP3_HTTP_STATE_RESP_HEADERS_END:
@ -1169,12 +1138,10 @@ int nghttp3_stream_transit_rx_http_state(nghttp3_stream *stream,
stream->rx.hstate = NGHTTP3_HTTP_STATE_RESP_END;
return 0;
default:
return NGHTTP3_ERR_H3_FRAME_UNEXPECTED;
nghttp3_unreachable();
}
case NGHTTP3_HTTP_STATE_RESP_DATA_BEGIN:
if (event != NGHTTP3_HTTP_EVENT_DATA_END) {
return NGHTTP3_ERR_MALFORMED_HTTP_MESSAGING;
}
assert(NGHTTP3_HTTP_EVENT_DATA_END == event);
stream->rx.hstate = NGHTTP3_HTTP_STATE_RESP_DATA_END;
return 0;
case NGHTTP3_HTTP_STATE_RESP_DATA_END:
@ -1197,17 +1164,15 @@ int nghttp3_stream_transit_rx_http_state(nghttp3_stream *stream,
stream->rx.hstate = NGHTTP3_HTTP_STATE_RESP_END;
return 0;
default:
return NGHTTP3_ERR_H3_FRAME_UNEXPECTED;
nghttp3_unreachable();
}
case NGHTTP3_HTTP_STATE_RESP_TRAILERS_BEGIN:
if (event != NGHTTP3_HTTP_EVENT_HEADERS_END) {
return NGHTTP3_ERR_MALFORMED_HTTP_MESSAGING;
}
assert(NGHTTP3_HTTP_EVENT_HEADERS_END == event);
stream->rx.hstate = NGHTTP3_HTTP_STATE_RESP_TRAILERS_END;
return 0;
case NGHTTP3_HTTP_STATE_RESP_TRAILERS_END:
if (event != NGHTTP3_HTTP_EVENT_MSG_END) {
return NGHTTP3_ERR_MALFORMED_HTTP_MESSAGING;
return NGHTTP3_ERR_H3_FRAME_UNEXPECTED;
}
rv = nghttp3_http_on_remote_end_stream(stream);
if (rv != 0) {
@ -1216,7 +1181,7 @@ int nghttp3_stream_transit_rx_http_state(nghttp3_stream *stream,
stream->rx.hstate = NGHTTP3_HTTP_STATE_RESP_END;
return 0;
case NGHTTP3_HTTP_STATE_RESP_END:
return NGHTTP3_ERR_MALFORMED_HTTP_MESSAGING;
return NGHTTP3_ERR_H3_FRAME_UNEXPECTED;
default:
nghttp3_unreachable();
}

View File

@ -223,9 +223,6 @@ struct nghttp3_stream {
uint64_t unsent_bytes;
/* outq_idx is an index into outq where next write is made. */
size_t outq_idx;
/* outq_offset is write offset relative to the element at outq_idx
in outq. */
uint64_t outq_offset;
/* ack_base is the number of bytes acknowledged by a remote
endpoint where the first element in outq is positioned at. */
uint64_t ack_base;
@ -255,7 +252,7 @@ struct nghttp3_stream {
};
};
nghttp3_objalloc_decl(stream, nghttp3_stream, oplent);
nghttp3_objalloc_decl(stream, nghttp3_stream, oplent)
typedef struct nghttp3_frame_entry {
nghttp3_frame fr;

View File

@ -28,8 +28,11 @@
#include <nghttp3/nghttp3.h>
static nghttp3_info version = {NGHTTP3_VERSION_AGE, NGHTTP3_VERSION_NUM,
NGHTTP3_VERSION};
static nghttp3_info version = {
.age = NGHTTP3_VERSION_AGE,
.version_num = NGHTTP3_VERSION_NUM,
.version_str = NGHTTP3_VERSION,
};
const nghttp3_info *nghttp3_version(int least_version) {
if (least_version > NGHTTP3_VERSION_NUM) {

File diff suppressed because it is too large Load Diff

View File

@ -31,90 +31,90 @@
libcurl) */
#if (defined(_WIN32) || defined(__WIN32__)) && !defined(WIN32)
# define WIN32
#endif
#endif /* (defined(_WIN32) || defined(__WIN32__)) && !defined(WIN32) */
#ifdef __cplusplus
extern "C" {
#endif
#endif /* defined(__cplusplus) */
#if defined(_MSC_VER) && (_MSC_VER < 1800)
/* MSVC < 2013 does not have inttypes.h because it is not C99
compliant. See compiler macros and version number in
https://sourceforge.net/p/predef/wiki/Compilers/ */
# include <stdint.h>
#else /* !defined(_MSC_VER) || (_MSC_VER >= 1800) */
#else /* !(defined(_MSC_VER) && (_MSC_VER < 1800)) */
# include <inttypes.h>
#endif /* !defined(_MSC_VER) || (_MSC_VER >= 1800) */
#endif /* !(defined(_MSC_VER) && (_MSC_VER < 1800)) */
#include <sys/types.h>
#include <stddef.h>
/**
* @enum
*
* :type:`sf_type` defines value type.
* :type:`sfparse_type` defines value type.
*/
typedef enum sf_type {
typedef enum sfparse_type {
/**
* :enum:`SF_TYPE_BOOLEAN` indicates boolean type.
* :enum:`SFPARSE_TYPE_BOOLEAN` indicates boolean type.
*/
SF_TYPE_BOOLEAN,
SFPARSE_TYPE_BOOLEAN,
/**
* :enum:`SF_TYPE_INTEGER` indicates integer type.
* :enum:`SFPARSE_TYPE_INTEGER` indicates integer type.
*/
SF_TYPE_INTEGER,
SFPARSE_TYPE_INTEGER,
/**
* :enum:`SF_TYPE_DECIMAL` indicates decimal type.
* :enum:`SFPARSE_TYPE_DECIMAL` indicates decimal type.
*/
SF_TYPE_DECIMAL,
SFPARSE_TYPE_DECIMAL,
/**
* :enum:`SF_TYPE_STRING` indicates string type.
* :enum:`SFPARSE_TYPE_STRING` indicates string type.
*/
SF_TYPE_STRING,
SFPARSE_TYPE_STRING,
/**
* :enum:`SF_TYPE_TOKEN` indicates token type.
* :enum:`SFPARSE_TYPE_TOKEN` indicates token type.
*/
SF_TYPE_TOKEN,
SFPARSE_TYPE_TOKEN,
/**
* :enum:`SF_TYPE_BYTESEQ` indicates byte sequence type.
* :enum:`SFPARSE_TYPE_BYTESEQ` indicates byte sequence type.
*/
SF_TYPE_BYTESEQ,
SFPARSE_TYPE_BYTESEQ,
/**
* :enum:`SF_TYPE_INNER_LIST` indicates inner list type.
* :enum:`SFPARSE_TYPE_INNER_LIST` indicates inner list type.
*/
SF_TYPE_INNER_LIST,
SFPARSE_TYPE_INNER_LIST,
/**
* :enum:`SF_TYPE_DATE` indicates date type.
* :enum:`SFPARSE_TYPE_DATE` indicates date type.
*/
SF_TYPE_DATE,
SFPARSE_TYPE_DATE,
/**
* :enum:`SF_TYPE_DISPSTRING` indicates display string type.
* :enum:`SFPARSE_TYPE_DISPSTRING` indicates display string type.
*/
SF_TYPE_DISPSTRING
} sf_type;
SFPARSE_TYPE_DISPSTRING
} sfparse_type;
/**
* @macro
*
* :macro:`SF_ERR_PARSE_ERROR` indicates fatal parse error has
* :macro:`SFPARSE_ERR_PARSE` indicates fatal parse error has
* occurred, and it is not possible to continue the processing.
*/
#define SF_ERR_PARSE_ERROR -1
#define SFPARSE_ERR_PARSE -1
/**
* @macro
*
* :macro:`SF_ERR_EOF` indicates that there is nothing left to read.
* The context of this error varies depending on the function that
* returns this error code.
* :macro:`SFPARSE_ERR_EOF` indicates that there is nothing left to
* read. The context of this error varies depending on the function
* that returns this error code.
*/
#define SF_ERR_EOF -2
#define SFPARSE_ERR_EOF -2
/**
* @struct
*
* :type:`sf_vec` stores sequence of bytes.
* :type:`sfparse_vec` stores sequence of bytes.
*/
typedef struct sf_vec {
typedef struct sfparse_vec {
/**
* :member:`base` points to the beginning of the sequence of bytes.
*/
@ -123,29 +123,29 @@ typedef struct sf_vec {
* :member:`len` is the number of bytes contained in this sequence.
*/
size_t len;
} sf_vec;
} sfparse_vec;
/**
* @macro
*
* :macro:`SF_VALUE_FLAG_NONE` indicates no flag set.
* :macro:`SFPARSE_VALUE_FLAG_NONE` indicates no flag set.
*/
#define SF_VALUE_FLAG_NONE 0x0u
#define SFPARSE_VALUE_FLAG_NONE 0x0u
/**
* @macro
*
* :macro:`SF_VALUE_FLAG_ESCAPED_STRING` indicates that a string
* :macro:`SFPARSE_VALUE_FLAG_ESCAPED_STRING` indicates that a string
* contains escaped character(s).
*/
#define SF_VALUE_FLAG_ESCAPED_STRING 0x1u
#define SFPARSE_VALUE_FLAG_ESCAPED_STRING 0x1u
/**
* @struct
*
* :type:`sf_decimal` contains decimal value.
* :type:`sfparse_decimal` contains decimal value.
*/
typedef struct sf_decimal {
typedef struct sfparse_decimal {
/**
* :member:`numer` contains numerator of the decimal value.
*/
@ -154,275 +154,289 @@ typedef struct sf_decimal {
* :member:`denom` contains denominator of the decimal value.
*/
int64_t denom;
} sf_decimal;
} sfparse_decimal;
/**
* @struct
*
* :type:`sf_value` stores a Structured Field item. For Inner List,
* only type is set to :enum:`sf_type.SF_TYPE_INNER_LIST`. In order
* to read the items contained in an inner list, call
* `sf_parser_inner_list`.
* :type:`sfparse_value` stores a Structured Field item. For Inner
* List, only type is set to
* :enum:`sfparse_type.SFPARSE_TYPE_INNER_LIST`. In order to read the
* items contained in an inner list, call `sfparse_parser_inner_list`.
*/
typedef struct sf_value {
typedef struct sfparse_value {
/**
* :member:`type` is the type of the value contained in this
* particular object.
*/
sf_type type;
sfparse_type type;
/**
* :member:`flags` is bitwise OR of one or more of
* :macro:`SF_VALUE_FLAG_* <SF_VALUE_FLAG_NONE>`.
* :macro:`SFPARSE_VALUE_FLAG_* <SFPARSE_VALUE_FLAG_NONE>`.
*/
uint32_t flags;
/**
* @anonunion_start
*
* @sf_value_value
* @sfparse_value_value
*/
union {
/**
* :member:`boolean` contains boolean value if :member:`type` ==
* :enum:`sf_type.SF_TYPE_BOOLEAN`. 1 indicates true, and 0
* indicates false.
* :enum:`sfparse_type.SFPARSE_TYPE_BOOLEAN`. 1 indicates true,
* and 0 indicates false.
*/
int boolean;
/**
* :member:`integer` contains integer value if :member:`type` is
* either :enum:`sf_type.SF_TYPE_INTEGER` or
* :enum:`sf_type.SF_TYPE_DATE`.
* either :enum:`sfparse_type.SFPARSE_TYPE_INTEGER` or
* :enum:`sfparse_type.SFPARSE_TYPE_DATE`.
*/
int64_t integer;
/**
* :member:`decimal` contains decimal value if :member:`type` ==
* :enum:`sf_type.SF_TYPE_DECIMAL`.
* :enum:`sfparse_type.SFPARSE_TYPE_DECIMAL`.
*/
sf_decimal decimal;
sfparse_decimal decimal;
/**
* :member:`vec` contains sequence of bytes if :member:`type` is
* either :enum:`sf_type.SF_TYPE_STRING`,
* :enum:`sf_type.SF_TYPE_TOKEN`, :enum:`sf_type.SF_TYPE_BYTESEQ`,
* or :enum:`sf_type.SF_TYPE_DISPSTRING`.
* either :enum:`sfparse_type.SFPARSE_TYPE_STRING`,
* :enum:`sfparse_type.SFPARSE_TYPE_TOKEN`,
* :enum:`sfparse_type.SFPARSE_TYPE_BYTESEQ`, or
* :enum:`sfparse_type.SFPARSE_TYPE_DISPSTRING`.
*
* For :enum:`sf_type.SF_TYPE_STRING`, this field contains one or
* more escaped characters if :member:`flags` has
* :macro:`SF_VALUE_FLAG_ESCAPED_STRING` set. To unescape the
* string, use `sf_unescape`.
* For :enum:`sfparse_type.SFPARSE_TYPE_STRING`, this field
* contains one or more escaped characters if :member:`flags` has
* :macro:`SFPARSE_VALUE_FLAG_ESCAPED_STRING` set. To unescape
* the string, use `sfparse_unescape`.
*
* For :enum:`sf_type.SF_TYPE_BYTESEQ`, this field contains base64
* encoded string. To decode this byte string, use
* `sf_base64decode`.
* For :enum:`sfparse_type.SFPARSE_TYPE_BYTESEQ`, this field
* contains base64 encoded string. To decode this byte string,
* use `sfparse_base64decode`.
*
* For :enum:`sf_type.SF_TYPE_DISPSTRING`, this field may contain
* percent-encoded UTF-8 byte sequences. To decode it, use
* `sf_pctdecode`.
* For :enum:`sfparse_type.SFPARSE_TYPE_DISPSTRING`, this field
* may contain percent-encoded UTF-8 byte sequences. To decode
* it, use `sfparse_pctdecode`.
*
* If :member:`vec.len <sf_vec.len>` == 0, :member:`vec.base
* <sf_vec.base>` is guaranteed to be NULL.
* If :member:`vec.len <sfparse_vec.len>` == 0, :member:`vec.base
* <sfparse_vec.base>` is guaranteed to be NULL.
*/
sf_vec vec;
sfparse_vec vec;
/**
* @anonunion_end
*/
};
} sf_value;
} sfparse_value;
/**
* @struct
*
* :type:`sf_parser` is the Structured Field Values parser. Use
* `sf_parser_init` to initialize it.
* :type:`sfparse_parser` is the Structured Field Values parser. Use
* `sfparse_parser_init` to initialize it.
*/
typedef struct sf_parser {
typedef struct sfparse_parser {
/* all fields are private */
const uint8_t *pos;
const uint8_t *end;
uint32_t state;
} sf_parser;
} sfparse_parser;
/**
* @function
*
* `sf_parser_init` initializes |sfp| with the given buffer pointed by
* |data| of length |datalen|.
* `sfparse_parser_init` initializes |sfp| with the given data encoded
* in Structured Field Values pointed by |data| of length |datalen|.
*/
void sf_parser_init(sf_parser *sfp, const uint8_t *data, size_t datalen);
void sfparse_parser_init(sfparse_parser *sfp, const uint8_t *data,
size_t datalen);
/**
* @function
*
* `sf_parser_param` reads a parameter. If this function returns 0,
* it stores parameter key and value in |dest_key| and |dest_value|
* `sfparse_parser_param` reads a parameter. If this function returns
* 0, it stores parameter key and value in |dest_key| and |dest_value|
* respectively, if they are not NULL.
*
* This function does no effort to find duplicated keys. Same key may
* be reported more than once.
*
* Caller should keep calling this function until it returns negative
* error code. If it returns :macro:`SF_ERR_EOF`, all parameters have
* read, and caller can continue to read rest of the values. If it
* returns :macro:`SF_ERR_PARSE_ERROR`, it encountered fatal error
* error code. If it returns :macro:`SFPARSE_ERR_EOF`, all parameters
* have read, and caller can continue to read rest of the values. If
* it returns :macro:`SFPARSE_ERR_PARSE`, it encountered fatal error
* while parsing field value.
*/
int sf_parser_param(sf_parser *sfp, sf_vec *dest_key, sf_value *dest_value);
int sfparse_parser_param(sfparse_parser *sfp, sfparse_vec *dest_key,
sfparse_value *dest_value);
/**
* @function
*
* `sf_parser_dict` reads the next dictionary key and value pair. If
* this function returns 0, it stores the key and value in |dest_key|
* and |dest_value| respectively, if they are not NULL.
* `sfparse_parser_dict` reads the next dictionary key and value pair.
* If this function returns 0, it stores the key and value in
* |dest_key| and |dest_value| respectively, if they are not NULL.
*
* Caller can optionally read parameters attached to the pair by
* calling `sf_parser_param`.
* calling `sfparse_parser_param`.
*
* This function does no effort to find duplicated keys. Same key may
* be reported more than once.
*
* Caller should keep calling this function until it returns negative
* error code. If it returns :macro:`SF_ERR_EOF`, all key and value
* pairs have been read, and there is nothing left to read.
* error code. If it returns :macro:`SFPARSE_ERR_EOF`, all key and
* value pairs have been read, and there is nothing left to read.
*
* This function returns 0 if it succeeds, or one of the following
* negative error codes:
*
* :macro:`SF_ERR_EOF`
* :macro:`SFPARSE_ERR_EOF`
* All values in the dictionary have read.
* :macro:`SF_ERR_PARSE_ERROR`
* :macro:`SFPARSE_ERR_PARSE`
* It encountered fatal error while parsing field value.
*/
int sf_parser_dict(sf_parser *sfp, sf_vec *dest_key, sf_value *dest_value);
int sfparse_parser_dict(sfparse_parser *sfp, sfparse_vec *dest_key,
sfparse_value *dest_value);
/**
* @function
*
* `sf_parser_list` reads the next list item. If this function
* `sfparse_parser_list` reads the next list item. If this function
* returns 0, it stores the item in |dest| if it is not NULL.
*
* Caller can optionally read parameters attached to the item by
* calling `sf_parser_param`.
* calling `sfparse_parser_param`.
*
* Caller should keep calling this function until it returns negative
* error code. If it returns :macro:`SF_ERR_EOF`, all values in the
* list have been read, and there is nothing left to read.
* error code. If it returns :macro:`SFPARSE_ERR_EOF`, all values in
* the list have been read, and there is nothing left to read.
*
* This function returns 0 if it succeeds, or one of the following
* negative error codes:
*
* :macro:`SF_ERR_EOF`
* :macro:`SFPARSE_ERR_EOF`
* All values in the list have read.
* :macro:`SF_ERR_PARSE_ERROR`
* :macro:`SFPARSE_ERR_PARSE`
* It encountered fatal error while parsing field value.
*/
int sf_parser_list(sf_parser *sfp, sf_value *dest);
int sfparse_parser_list(sfparse_parser *sfp, sfparse_value *dest);
/**
* @function
*
* `sf_parser_item` reads a single item. If this function returns 0,
* it stores the item in |dest| if it is not NULL.
* `sfparse_parser_item` reads a single item. If this function
* returns 0, it stores the item in |dest| if it is not NULL.
*
* This function is only used for the field value that consists of a
* single item.
*
* Caller can optionally read parameters attached to the item by
* calling `sf_parser_param`.
* calling `sfparse_parser_param`.
*
* Caller should call this function again to make sure that there is
* nothing left to read. If this 2nd function call returns
* :macro:`SF_ERR_EOF`, all data have been processed successfully.
* :macro:`SFPARSE_ERR_EOF`, all data have been processed
* successfully.
*
* This function returns 0 if it succeeds, or one of the following
* negative error codes:
*
* :macro:`SF_ERR_EOF`
* :macro:`SFPARSE_ERR_EOF`
* There is nothing left to read.
* :macro:`SF_ERR_PARSE_ERROR`
* :macro:`SFPARSE_ERR_PARSE`
* It encountered fatal error while parsing field value.
*/
int sf_parser_item(sf_parser *sfp, sf_value *dest);
int sfparse_parser_item(sfparse_parser *sfp, sfparse_value *dest);
/**
* @function
*
* `sf_parser_inner_list` reads the next inner list item. If this
* function returns 0, it stores the item in |dest| if it is not NULL.
* `sfparse_parser_inner_list` reads the next inner list item. If
* this function returns 0, it stores the item in |dest| if it is not
* NULL.
*
* Caller can optionally read parameters attached to the item by
* calling `sf_parser_param`.
* calling `sfparse_parser_param`.
*
* Caller should keep calling this function until it returns negative
* error code. If it returns :macro:`SF_ERR_EOF`, all values in this
* inner list have been read, and caller can optionally read
* error code. If it returns :macro:`SFPARSE_ERR_EOF`, all values in
* this inner list have been read, and caller can optionally read
* parameters attached to this inner list by calling
* `sf_parser_param`. Then caller can continue to read rest of the
* values.
* `sfparse_parser_param`. Then caller can continue to read rest of
* the values.
*
* This function returns 0 if it succeeds, or one of the following
* negative error codes:
*
* :macro:`SF_ERR_EOF`
* :macro:`SFPARSE_ERR_EOF`
* All values in the inner list have read.
* :macro:`SF_ERR_PARSE_ERROR`
* :macro:`SFPARSE_ERR_PARSE`
* It encountered fatal error while parsing field value.
*/
int sf_parser_inner_list(sf_parser *sfp, sf_value *dest);
int sfparse_parser_inner_list(sfparse_parser *sfp, sfparse_value *dest);
/**
* @function
*
* `sf_unescape` copies |src| to |dest| by removing escapes (``\``).
* |src| should be the pointer to :member:`sf_value.vec` of type
* :enum:`sf_type.SF_TYPE_STRING` produced by either `sf_parser_dict`,
* `sf_parser_list`, `sf_parser_inner_list`, `sf_parser_item`, or
* `sf_parser_param`, otherwise the behavior is undefined.
* `sfparse_unescape` copies |src| to |dest| by removing escapes
* (``\``). |src| should be the pointer to
* :member:`sfparse_value.vec` of type
* :enum:`sfparse_type.SFPARSE_TYPE_STRING` produced by either
* `sfparse_parser_dict`, `sfparse_parser_list`,
* `sfparse_parser_inner_list`, `sfparse_parser_item`, or
* `sfparse_parser_param`, otherwise the behavior is undefined.
*
* :member:`dest->base <sf_vec.base>` must point to the buffer that
* has sufficient space to store the unescaped string.
* :member:`dest->base <sfparse_vec.base>` must point to the buffer
* that has sufficient space to store the unescaped string. The
* memory areas pointed by :member:`dest->base <sfparse_vec.base>` and
* :member:`src->base <sfparse_vec.base>` must not overlap.
*
* This function sets the length of unescaped string to
* :member:`dest->len <sf_vec.len>`.
* :member:`dest->len <sfparse_vec.len>`.
*/
void sf_unescape(sf_vec *dest, const sf_vec *src);
void sfparse_unescape(sfparse_vec *dest, const sfparse_vec *src);
/**
* @function
*
* `sf_base64decode` decodes Base64 encoded string |src| and writes
* `sfparse_base64decode` decodes Base64 encoded string |src| and
* writes the result into |dest|. |src| should be the pointer to
* :member:`sfparse_value.vec` of type
* :enum:`sfparse_type.SFPARSE_TYPE_BYTESEQ` produced by either
* `sfparse_parser_dict`, `sfparse_parser_list`,
* `sfparse_parser_inner_list`, `sfparse_parser_item`, or
* `sfparse_parser_param`, otherwise the behavior is undefined.
*
* :member:`dest->base <sfparse_vec.base>` must point to the buffer
* that has sufficient space to store the decoded byte string.
*
* This function sets the length of decoded byte string to
* :member:`dest->len <sfparse_vec.len>`.
*/
void sfparse_base64decode(sfparse_vec *dest, const sfparse_vec *src);
/**
* @function
*
* `sfparse_pctdecode` decodes percent-encoded string |src| and writes
* the result into |dest|. |src| should be the pointer to
* :member:`sf_value.vec` of type :enum:`sf_type.SF_TYPE_BYTESEQ`
* produced by either `sf_parser_dict`, `sf_parser_list`,
* `sf_parser_inner_list`, `sf_parser_item`, or `sf_parser_param`,
* otherwise the behavior is undefined.
* :member:`sfparse_value.vec` of type
* :enum:`sfparse_type.SFPARSE_TYPE_DISPSTRING` produced by either
* `sfparse_parser_dict`, `sfparse_parser_list`,
* `sfparse_parser_inner_list`, `sfparse_parser_item`, or
* `sfparse_parser_param`, otherwise the behavior is undefined.
*
* :member:`dest->base <sf_vec.base>` must point to the buffer that
* has sufficient space to store the decoded byte string.
* :member:`dest->base <sfparse_vec.base>` must point to the buffer
* that has sufficient space to store the decoded byte string. The
* memory areas pointed by :member:`dest->base <sfparse_vec.base>` and
* :member:`src->base <sfparse_vec.base>` must not overlap.
*
* This function sets the length of decoded byte string to
* :member:`dest->len <sf_vec.len>`.
* :member:`dest->len <sfparse_vec.len>`.
*/
void sf_base64decode(sf_vec *dest, const sf_vec *src);
/**
* @function
*
* `sf_pctdecode` decodes percent-encoded string |src| and writes the
* result into |dest|. |src| should be the pointer to
* :member:`sf_value.vec` of type :enum:`sf_type.SF_TYPE_DISPSTRING`
* produced by either `sf_parser_dict`, `sf_parser_list`,
* `sf_parser_inner_list`, `sf_parser_item`, or `sf_parser_param`,
* otherwise the behavior is undefined.
*
* :member:`dest->base <sf_vec.base>` must point to the buffer that
* has sufficient space to store the decoded byte string.
*
* This function sets the length of decoded byte string to
* :member:`dest->len <sf_vec.len>`.
*/
void sf_pctdecode(sf_vec *dest, const sf_vec *src);
void sfparse_pctdecode(sfparse_vec *dest, const sfparse_vec *src);
#ifdef __cplusplus
}
#endif
#endif /* defined(__cplusplus) */
#endif /* SFPARSE_H */
#endif /* !defined(SFPARSE_H) */