[multiple] reduce redundant NULL buffer checks
This commit is a large set of code changes and results in removal of hundreds, perhaps thousands, of CPU instructions, a portion of which are on hot code paths. Most (buffer *) used by lighttpd are not NULL, especially since buffers were inlined into numerous larger structs such as request_st and chunk. In the small number of instances where that is not the case, a NULL check is often performed earlier in a function where that buffer is later used with a buffer_* func. In the handful of cases that remained, a NULL check was added, e.g. with r->http_host and r->conf.server_tag. - check for empty strings at config time and set value to NULL if blank string will be ignored at runtime; at runtime, simple pointer check for NULL can be used to check for a value that has been set and is not blank ("") - use buffer_is_blank() instead of buffer_string_is_empty(), and use buffer_is_unset() instead of buffer_is_empty(), where buffer is known not to be NULL so that NULL check can be skipped - use buffer_clen() instead of buffer_string_length() when buffer is known not to be NULL (to avoid NULL check at runtime) - use buffer_truncate() instead of buffer_string_set_length() to truncate string, and use buffer_extend() to extend Examples where buffer known not to be NULL: - cpv->v.b from config_plugin_values_init is not NULL if T_CONFIG_BOOL (though we might set it to NULL if buffer_is_blank(cpv->v.b)) - address of buffer is arg (&foo) (compiler optimizer detects this in most, but not all, cases) - buffer is checked for NULL earlier in func - buffer is accessed in same scope without a NULL check (e.g. b->ptr) internal behavior change: callers must not pass a NULL buffer to some funcs. - buffer_init_buffer() requires non-null args - buffer_copy_buffer() requires non-null args - buffer_append_string_buffer() requires non-null args - buffer_string_space() requires non-null arg
This commit is contained in:
parent
937d83b6cf
commit
af3df29ae8
64
src/array.c
64
src/array.c
|
@ -12,7 +12,7 @@ __attribute_cold__
|
|||
static data_unset *array_data_string_copy(const data_unset *s) {
|
||||
data_string *src = (data_string *)s;
|
||||
data_string *ds = array_data_string_init();
|
||||
if (!buffer_is_empty(&src->key)) buffer_copy_buffer(&ds->key, &src->key);
|
||||
if (!buffer_is_unset(&src->key)) buffer_copy_buffer(&ds->key, &src->key);
|
||||
buffer_copy_buffer(&ds->value, &src->value);
|
||||
return (data_unset *)ds;
|
||||
}
|
||||
|
@ -21,9 +21,9 @@ __attribute_cold__
|
|||
static void array_data_string_insert_dup(data_unset *dst, data_unset *src) {
|
||||
data_string *ds_dst = (data_string *)dst;
|
||||
data_string *ds_src = (data_string *)src;
|
||||
if (!buffer_is_empty(&ds_dst->value))
|
||||
if (!buffer_is_blank(&ds_dst->value))
|
||||
buffer_append_str2(&ds_dst->value, CONST_STR_LEN(", "),
|
||||
CONST_BUF_LEN(&ds_src->value));
|
||||
BUF_PTR_LEN(&ds_src->value));
|
||||
else
|
||||
buffer_copy_buffer(&ds_dst->value, &ds_src->value);
|
||||
}
|
||||
|
@ -54,7 +54,7 @@ __attribute_cold__
|
|||
static data_unset *array_data_integer_copy(const data_unset *s) {
|
||||
data_integer *src = (data_integer *)s;
|
||||
data_integer *di = array_data_integer_init();
|
||||
if (!buffer_is_empty(&src->key)) buffer_copy_buffer(&di->key, &src->key);
|
||||
if (!buffer_is_unset(&src->key)) buffer_copy_buffer(&di->key, &src->key);
|
||||
di->value = src->value;
|
||||
return (data_unset *)di;
|
||||
}
|
||||
|
@ -84,7 +84,7 @@ __attribute_cold__
|
|||
static data_unset *array_data_array_copy(const data_unset *s) {
|
||||
data_array *src = (data_array *)s;
|
||||
data_array *da = array_data_array_init();
|
||||
if (!buffer_is_empty(&src->key)) buffer_copy_buffer(&da->key, &src->key);
|
||||
if (!buffer_is_unset(&src->key)) buffer_copy_buffer(&da->key, &src->key);
|
||||
array_copy_array(&da->value, &src->value);
|
||||
return (data_unset *)da;
|
||||
}
|
||||
|
@ -221,7 +221,7 @@ static int array_keycmpb(const char * const k, const uint32_t klen, const buffer
|
|||
* if inserted into key-value array */
|
||||
/*force_assert(b && b->used);*/
|
||||
return array_keycmp(k, klen, b->ptr, b->used-1);
|
||||
/*return array_keycmp(k, klen, CONST_BUF_LEN(b));*/
|
||||
/*return array_keycmp(k, klen, BUF_PTR_LEN(b));*/
|
||||
}
|
||||
|
||||
/* returns pos into a->sorted[] which contains copy of data (ptr) in a->data[]
|
||||
|
@ -276,7 +276,7 @@ static int32_t array_get_index(const array * const a, const char * const k, cons
|
|||
* if inserted into key-value array */
|
||||
/*force_assert(b && b->used);*/
|
||||
int cmp = array_keycmp(k, klen, b->ptr, b->used-1);
|
||||
/*int cmp = array_keycmp(k, klen, CONST_BUF_LEN(b));*/
|
||||
/*int cmp = array_keycmp(k, klen, BUF_PTR_LEN(b));*/
|
||||
if (cmp < 0) /* key < [probe] */
|
||||
upper = probe; /* still: lower <= upper */
|
||||
else if (cmp > 0) /* key > [probe] */
|
||||
|
@ -436,13 +436,13 @@ static data_unset **array_find_or_insert(array * const a, data_unset * const ent
|
|||
force_assert(NULL != entry);
|
||||
|
||||
/* push value onto end of array if there is no key */
|
||||
if (buffer_is_empty(&entry->key)) {
|
||||
if (buffer_is_unset(&entry->key)) {
|
||||
array_insert_data_at_pos(a, entry, a->used);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* try to find the entry */
|
||||
const int32_t ipos = array_get_index(a, CONST_BUF_LEN(&entry->key));
|
||||
const int32_t ipos = array_get_index(a, BUF_PTR_LEN(&entry->key));
|
||||
if (ipos >= 0) return &a->sorted[ipos];
|
||||
|
||||
array_insert_data_at_pos(a, entry, (uint32_t)(-ipos - 1));
|
||||
|
@ -454,7 +454,7 @@ void array_replace(array * const a, data_unset * const entry) {
|
|||
if (NULL == array_find_or_insert(a, entry)) return;
|
||||
|
||||
/* find the entry (array_find_or_insert() returned non-NULL) */
|
||||
const int32_t ipos = array_get_index(a, CONST_BUF_LEN(&entry->key));
|
||||
const int32_t ipos = array_get_index(a, BUF_PTR_LEN(&entry->key));
|
||||
force_assert(ipos >= 0);
|
||||
data_unset *old = a->sorted[ipos];
|
||||
force_assert(old != entry);
|
||||
|
@ -483,7 +483,7 @@ void array_insert_unique(array * const a, data_unset * const entry) {
|
|||
int array_is_vlist(const array * const a) {
|
||||
for (uint32_t i = 0; i < a->used; ++i) {
|
||||
data_unset *du = a->data[i];
|
||||
if (!buffer_is_empty(&du->key) || du->type != TYPE_STRING) return 0;
|
||||
if (!buffer_is_unset(&du->key) || du->type != TYPE_STRING) return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
@ -491,7 +491,7 @@ int array_is_vlist(const array * const a) {
|
|||
int array_is_kvany(const array * const a) {
|
||||
for (uint32_t i = 0; i < a->used; ++i) {
|
||||
data_unset *du = a->data[i];
|
||||
if (buffer_is_empty(&du->key)) return 0;
|
||||
if (buffer_is_unset(&du->key)) return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
@ -499,7 +499,7 @@ int array_is_kvany(const array * const a) {
|
|||
int array_is_kvarray(const array * const a) {
|
||||
for (uint32_t i = 0; i < a->used; ++i) {
|
||||
data_unset *du = a->data[i];
|
||||
if (buffer_is_empty(&du->key) || du->type != TYPE_ARRAY) return 0;
|
||||
if (buffer_is_unset(&du->key) || du->type != TYPE_ARRAY) return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
@ -507,7 +507,7 @@ int array_is_kvarray(const array * const a) {
|
|||
int array_is_kvstring(const array * const a) {
|
||||
for (uint32_t i = 0; i < a->used; ++i) {
|
||||
data_unset *du = a->data[i];
|
||||
if (buffer_is_empty(&du->key) || du->type != TYPE_STRING) return 0;
|
||||
if (buffer_is_unset(&du->key) || du->type != TYPE_STRING) return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
@ -523,7 +523,7 @@ array_match_key_prefix_klen (const array * const a, const char * const s, const
|
|||
{
|
||||
for (uint32_t i = 0; i < a->used; ++i) {
|
||||
const buffer * const key = &a->data[i]->key;
|
||||
const uint32_t klen = buffer_string_length(key);
|
||||
const uint32_t klen = buffer_clen(key);
|
||||
if (klen <= slen && 0 == memcmp(s, key->ptr, klen))
|
||||
return a->data[i];
|
||||
}
|
||||
|
@ -535,7 +535,7 @@ array_match_key_prefix_nc_klen (const array * const a, const char * const s, con
|
|||
{
|
||||
for (uint32_t i = 0; i < a->used; ++i) {
|
||||
const buffer * const key = &a->data[i]->key;
|
||||
const uint32_t klen = buffer_string_length(key);
|
||||
const uint32_t klen = buffer_clen(key);
|
||||
if (klen <= slen && buffer_eq_icase_ssn(s, key->ptr, klen))
|
||||
return a->data[i];
|
||||
}
|
||||
|
@ -548,23 +548,23 @@ array_match_key_prefix (const array * const a, const buffer * const b)
|
|||
#ifdef __clang_analyzer__
|
||||
force_assert(b);
|
||||
#endif
|
||||
return array_match_key_prefix_klen(a, CONST_BUF_LEN(b));
|
||||
return array_match_key_prefix_klen(a, BUF_PTR_LEN(b));
|
||||
}
|
||||
|
||||
data_unset *
|
||||
array_match_key_prefix_nc (const array * const a, const buffer * const b)
|
||||
{
|
||||
return array_match_key_prefix_nc_klen(a, CONST_BUF_LEN(b));
|
||||
return array_match_key_prefix_nc_klen(a, BUF_PTR_LEN(b));
|
||||
}
|
||||
|
||||
const buffer *
|
||||
array_match_value_prefix (const array * const a, const buffer * const b)
|
||||
{
|
||||
const uint32_t blen = buffer_string_length(b);
|
||||
const uint32_t blen = buffer_clen(b);
|
||||
|
||||
for (uint32_t i = 0; i < a->used; ++i) {
|
||||
const buffer * const value = &((data_string *)a->data[i])->value;
|
||||
const uint32_t vlen = buffer_string_length(value);
|
||||
const uint32_t vlen = buffer_clen(value);
|
||||
if (vlen <= blen && 0 == memcmp(b->ptr, value->ptr, vlen))
|
||||
return value;
|
||||
}
|
||||
|
@ -574,11 +574,11 @@ array_match_value_prefix (const array * const a, const buffer * const b)
|
|||
const buffer *
|
||||
array_match_value_prefix_nc (const array * const a, const buffer * const b)
|
||||
{
|
||||
const uint32_t blen = buffer_string_length(b);
|
||||
const uint32_t blen = buffer_clen(b);
|
||||
|
||||
for (uint32_t i = 0; i < a->used; ++i) {
|
||||
const buffer * const value = &((data_string *)a->data[i])->value;
|
||||
const uint32_t vlen = buffer_string_length(value);
|
||||
const uint32_t vlen = buffer_clen(value);
|
||||
if (vlen <= blen && buffer_eq_icase_ssn(b->ptr, value->ptr, vlen))
|
||||
return value;
|
||||
}
|
||||
|
@ -588,12 +588,12 @@ array_match_value_prefix_nc (const array * const a, const buffer * const b)
|
|||
data_unset *
|
||||
array_match_key_suffix (const array * const a, const buffer * const b)
|
||||
{
|
||||
const uint32_t blen = buffer_string_length(b);
|
||||
const uint32_t blen = buffer_clen(b);
|
||||
const char * const end = b->ptr + blen;
|
||||
|
||||
for (uint32_t i = 0; i < a->used; ++i) {
|
||||
const buffer * const key = &a->data[i]->key;
|
||||
const uint32_t klen = buffer_string_length(key);
|
||||
const uint32_t klen = buffer_clen(key);
|
||||
if (klen <= blen && 0 == memcmp(end - klen, key->ptr, klen))
|
||||
return a->data[i];
|
||||
}
|
||||
|
@ -603,12 +603,12 @@ array_match_key_suffix (const array * const a, const buffer * const b)
|
|||
data_unset *
|
||||
array_match_key_suffix_nc (const array * const a, const buffer * const b)
|
||||
{
|
||||
const uint32_t blen = buffer_string_length(b);
|
||||
const uint32_t blen = buffer_clen(b);
|
||||
const char * const end = b->ptr + blen;
|
||||
|
||||
for (uint32_t i = 0; i < a->used; ++i) {
|
||||
const buffer * const key = &a->data[i]->key;
|
||||
const uint32_t klen = buffer_string_length(key);
|
||||
const uint32_t klen = buffer_clen(key);
|
||||
if (klen <= blen && buffer_eq_icase_ssn(end - klen, key->ptr, klen))
|
||||
return a->data[i];
|
||||
}
|
||||
|
@ -618,12 +618,12 @@ array_match_key_suffix_nc (const array * const a, const buffer * const b)
|
|||
const buffer *
|
||||
array_match_value_suffix (const array * const a, const buffer * const b)
|
||||
{
|
||||
const uint32_t blen = buffer_string_length(b);
|
||||
const uint32_t blen = buffer_clen(b);
|
||||
const char * const end = b->ptr + blen;
|
||||
|
||||
for (uint32_t i = 0; i < a->used; ++i) {
|
||||
const buffer * const value = &((data_string *)a->data[i])->value;
|
||||
const uint32_t vlen = buffer_string_length(value);
|
||||
const uint32_t vlen = buffer_clen(value);
|
||||
if (vlen <= blen && 0 == memcmp(end - vlen, value->ptr, vlen))
|
||||
return value;
|
||||
}
|
||||
|
@ -633,12 +633,12 @@ array_match_value_suffix (const array * const a, const buffer * const b)
|
|||
const buffer *
|
||||
array_match_value_suffix_nc (const array * const a, const buffer * const b)
|
||||
{
|
||||
const uint32_t blen = buffer_string_length(b);
|
||||
const uint32_t blen = buffer_clen(b);
|
||||
const char * const end = b->ptr + blen;
|
||||
|
||||
for (uint32_t i = 0; i < a->used; ++i) {
|
||||
const buffer * const value = &((data_string *)a->data[i])->value;
|
||||
const uint32_t vlen = buffer_string_length(value);
|
||||
const uint32_t vlen = buffer_clen(value);
|
||||
if (vlen <= blen && buffer_eq_icase_ssn(end - vlen, value->ptr, vlen))
|
||||
return value;
|
||||
}
|
||||
|
@ -648,12 +648,12 @@ array_match_value_suffix_nc (const array * const a, const buffer * const b)
|
|||
data_unset *
|
||||
array_match_path_or_ext (const array * const a, const buffer * const b)
|
||||
{
|
||||
const uint32_t blen = buffer_string_length(b);
|
||||
const uint32_t blen = buffer_clen(b);
|
||||
|
||||
for (uint32_t i = 0; i < a->used; ++i) {
|
||||
/* check extension in the form "^/path" or ".ext$" */
|
||||
const buffer * const key = &a->data[i]->key;
|
||||
const uint32_t klen = buffer_string_length(key);
|
||||
const uint32_t klen = buffer_clen(key);
|
||||
if (klen <= blen
|
||||
&& 0 == memcmp((*(key->ptr) == '/' ? b->ptr : b->ptr + blen - klen),
|
||||
key->ptr, klen))
|
||||
|
|
58
src/buffer.c
58
src/buffer.c
|
@ -14,27 +14,21 @@ static const char hex_chars_uc[] = "0123456789ABCDEF";
|
|||
*
|
||||
*/
|
||||
|
||||
__attribute_noinline__
|
||||
buffer* buffer_init(void) {
|
||||
buffer *b;
|
||||
|
||||
b = malloc(sizeof(*b));
|
||||
buffer * const b = calloc(1, sizeof(*b));
|
||||
force_assert(b);
|
||||
|
||||
b->ptr = NULL;
|
||||
b->size = 0;
|
||||
b->used = 0;
|
||||
|
||||
return b;
|
||||
}
|
||||
|
||||
buffer *buffer_init_buffer(const buffer *src) {
|
||||
buffer *b = buffer_init();
|
||||
buffer_copy_buffer(b, src);
|
||||
buffer * const b = buffer_init();
|
||||
buffer_copy_string_len(b, BUF_PTR_LEN(src));
|
||||
return b;
|
||||
}
|
||||
|
||||
buffer *buffer_init_string(const char *str) {
|
||||
buffer *b = buffer_init();
|
||||
buffer * const b = buffer_init();
|
||||
buffer_copy_string(b, str);
|
||||
return b;
|
||||
}
|
||||
|
@ -102,8 +96,11 @@ __attribute_noinline__
|
|||
__attribute_nonnull__
|
||||
__attribute_returns_nonnull__
|
||||
static char* buffer_string_prepare_append_resize(buffer * const restrict b, const size_t size) {
|
||||
if (b->used < 2) /* buffer_string_is_empty(b) */
|
||||
return buffer_string_prepare_copy(b, size);
|
||||
if (b->used < 2) { /* buffer_is_blank(b) */
|
||||
char * const s = buffer_string_prepare_copy(b, size);
|
||||
*s = '\0'; /*(for case (1 == b->used))*/
|
||||
return s;
|
||||
}
|
||||
|
||||
/* not empty, b->used already includes a terminating 0 */
|
||||
/*(note: if size larger than one lshift, use size instead of power-2)*/
|
||||
|
@ -133,24 +130,20 @@ buffer_extend (buffer * const b, const size_t x)
|
|||
* (combine buffer_string_prepare_append() and buffer_commit())
|
||||
* (future: might make buffer.h static inline func for HTTP/1.1 performance)
|
||||
* pre-sets '\0' byte and b->used (unlike buffer_string_prepare_append())*/
|
||||
#if 0
|
||||
char * const s = buffer_string_prepare_append(b, x);
|
||||
b->used += x + (0 == b->used);
|
||||
#else
|
||||
const uint32_t len = b->used ? b->used-1 : 0;
|
||||
char * const s = (b->size - len >= x + 1)
|
||||
? b->ptr + len
|
||||
: buffer_string_prepare_append_resize(b, x);
|
||||
b->used = len+x+1;
|
||||
#endif
|
||||
s[x] = '\0';
|
||||
return s;
|
||||
}
|
||||
|
||||
void buffer_string_set_length(buffer *b, uint32_t len) {
|
||||
/*(intended for string truncate; prefer buffer_extend() to extend string)*/
|
||||
/*(unlike others routines, this routine potentially extends string
|
||||
* extra len + (up to) BUFFER_PIECE_SIZE without power-2 reallocation,
|
||||
* but does not optimize realloc of empty string)*/
|
||||
b->used = len + 1; /*(not resizing for power-2)*/
|
||||
(len < b->size ? b->ptr : buffer_realloc(b, len))[len] = '\0';
|
||||
}
|
||||
|
||||
void buffer_commit(buffer *b, size_t size)
|
||||
{
|
||||
size_t sz = b->used;
|
||||
|
@ -463,11 +456,11 @@ void li_tohex_uc(char * const restrict buf, size_t buf_len, const char * const r
|
|||
void buffer_substr_replace (buffer * const restrict b, const size_t offset,
|
||||
const size_t len, const buffer * const restrict replace)
|
||||
{
|
||||
const size_t blen = buffer_string_length(b);
|
||||
const size_t rlen = buffer_string_length(replace);
|
||||
const size_t blen = buffer_clen(b);
|
||||
const size_t rlen = buffer_clen(replace);
|
||||
|
||||
if (rlen > len) {
|
||||
buffer_string_set_length(b, blen-len+rlen);
|
||||
buffer_extend(b, blen-len+rlen);
|
||||
memmove(b->ptr+offset+rlen, b->ptr+offset+len, blen-offset-len);
|
||||
}
|
||||
|
||||
|
@ -475,7 +468,7 @@ void buffer_substr_replace (buffer * const restrict b, const size_t offset,
|
|||
|
||||
if (rlen < len) {
|
||||
memmove(b->ptr+offset+rlen, b->ptr+offset+len, blen-offset-len);
|
||||
buffer_string_set_length(b, blen-len+rlen);
|
||||
buffer_truncate(b, blen-len+rlen);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -731,7 +724,7 @@ void buffer_append_string_c_escaped(buffer * const restrict b, const char * cons
|
|||
*/
|
||||
|
||||
void buffer_urldecode_path(buffer * const b) {
|
||||
const size_t len = buffer_string_length(b);
|
||||
const size_t len = buffer_clen(b);
|
||||
char *src = len ? memchr(b->ptr, '%', len) : NULL;
|
||||
if (NULL == src) return;
|
||||
|
||||
|
@ -802,8 +795,11 @@ int buffer_is_valid_UTF8(const buffer *b) {
|
|||
|
||||
void buffer_path_simplify(buffer *b)
|
||||
{
|
||||
if (__builtin_expect( (buffer_string_is_empty(b)), 0)) {
|
||||
buffer_copy_string_len(b, CONST_STR_LEN(""));
|
||||
char *out = b->ptr;
|
||||
char * const end = b->ptr + b->used - 1;
|
||||
|
||||
if (__builtin_expect( (buffer_is_blank(b)), 0)) {
|
||||
buffer_blank(b);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -814,8 +810,6 @@ void buffer_path_simplify(buffer *b)
|
|||
}
|
||||
#endif
|
||||
|
||||
char *out = b->ptr;
|
||||
char * const end = b->ptr + b->used - 1;
|
||||
*end = '/'; /*(end of path modified to avoid need to check '\0')*/
|
||||
|
||||
char *walk = out;
|
||||
|
@ -874,7 +868,7 @@ void buffer_path_simplify(buffer *b)
|
|||
}
|
||||
*out = *end = '\0'; /* overwrite extra '/' added to end of path */
|
||||
b->used = (out - b->ptr) + 1;
|
||||
/*buffer_string_set_length(b, out - b->ptr);*/
|
||||
/*buffer_truncate(b, out - b->ptr);*/
|
||||
}
|
||||
|
||||
void buffer_to_lower(buffer * const b) {
|
||||
|
|
172
src/buffer.h
172
src/buffer.h
|
@ -13,13 +13,11 @@ struct tm; /* declaration */
|
|||
/* generic string + binary data container; contains a terminating 0 in both
|
||||
* cases
|
||||
*
|
||||
* used == 0 indicates a special "empty" state (unset config values); ptr
|
||||
* might be NULL too then. otherwise an empty string has used == 1 (and ptr[0]
|
||||
* == 0);
|
||||
* used == 0 indicates a special "empty" state (unset config values);
|
||||
* ptr might be NULL, too.
|
||||
*
|
||||
* copy/append functions will ensure used >= 1 (i.e. never leave it in the
|
||||
* special empty state); only buffer_copy_buffer will copy the special empty
|
||||
* state.
|
||||
* copy/append functions will ensure used >= 1
|
||||
* (i.e. never leave it in the special empty state)
|
||||
*/
|
||||
typedef struct {
|
||||
char *ptr;
|
||||
|
@ -34,8 +32,9 @@ typedef struct {
|
|||
__attribute_returns_nonnull__
|
||||
buffer* buffer_init(void);
|
||||
|
||||
__attribute_nonnull__
|
||||
__attribute_returns_nonnull__
|
||||
buffer* buffer_init_buffer(const buffer *src); /* src can be NULL */
|
||||
buffer* buffer_init_buffer(const buffer *src);
|
||||
|
||||
__attribute_returns_nonnull__
|
||||
buffer* buffer_init_string(const char *str); /* str can be NULL */
|
||||
|
@ -81,14 +80,6 @@ char* buffer_extend(buffer * const restrict b, size_t x);
|
|||
__attribute_nonnull__
|
||||
void buffer_commit(buffer *b, size_t size);
|
||||
|
||||
/* sets string length:
|
||||
* - always stores a terminating zero to terminate the "new" string
|
||||
* - does not modify the string data apart from terminating zero
|
||||
* - reallocates the buffer iff needed
|
||||
*/
|
||||
__attribute_nonnull__
|
||||
void buffer_string_set_length(buffer *b, uint32_t len);
|
||||
|
||||
/* clear buffer
|
||||
* - invalidate buffer contents
|
||||
* - unsets used chars but does not modify existing ptr contents
|
||||
|
@ -116,13 +107,11 @@ void buffer_free_ptr(buffer *b);
|
|||
|
||||
void buffer_copy_string(buffer * restrict b, const char * restrict s);
|
||||
void buffer_copy_string_len(buffer * restrict b, const char * restrict s, size_t len);
|
||||
static inline void buffer_copy_buffer(buffer * restrict b, const buffer * restrict src);
|
||||
|
||||
void buffer_append_string(buffer * restrict b, const char * restrict s);
|
||||
void buffer_append_string_len(buffer * restrict b, const char * restrict s, size_t len);
|
||||
void buffer_append_str2(buffer * restrict b, const char *s1, size_t len1, const char *s2, size_t len2);
|
||||
void buffer_append_str3(buffer * restrict b, const char *s1, size_t len1, const char *s2, size_t len2, const char *s3, size_t len3);
|
||||
static inline void buffer_append_string_buffer(buffer * restrict b, const buffer * restrict src);
|
||||
|
||||
struct const_iovec {
|
||||
const void *iov_base;
|
||||
|
@ -155,16 +144,6 @@ void li_tohex_lc(char * restrict buf, size_t buf_len, const char * restrict s, s
|
|||
__attribute_nonnull__
|
||||
void li_tohex_uc(char * restrict buf, size_t buf_len, const char * restrict s, size_t s_len);
|
||||
|
||||
/* NULL buffer or empty buffer (used == 0);
|
||||
* unset "string" (buffer) config options are initialized to used == 0,
|
||||
* while setting an empty string leads to used == 1
|
||||
*/
|
||||
__attribute_pure__
|
||||
static inline int buffer_is_empty(const buffer *b);
|
||||
/* NULL buffer, empty buffer (used == 0) or empty string (used == 1) */
|
||||
__attribute_pure__
|
||||
static inline int buffer_string_is_empty(const buffer *b);
|
||||
|
||||
__attribute_nonnull__
|
||||
__attribute_pure__
|
||||
int buffer_eq_icase_ssn(const char * const a, const char * const b, const size_t len);
|
||||
|
@ -176,12 +155,10 @@ int buffer_eq_icase_ss(const char * const a, const size_t alen, const char * con
|
|||
__attribute_nonnull__
|
||||
__attribute_pure__
|
||||
int buffer_eq_icase_slen(const buffer * const b, const char * const s, const size_t slen);
|
||||
#define buffer_is_equal_caseless_string buffer_eq_icase_slen
|
||||
|
||||
__attribute_nonnull__
|
||||
__attribute_pure__
|
||||
int buffer_eq_slen(const buffer * const b, const char * const s, const size_t slen);
|
||||
#define buffer_is_equal_string buffer_eq_slen
|
||||
|
||||
__attribute_nonnull__
|
||||
__attribute_pure__
|
||||
|
@ -263,16 +240,6 @@ static inline int light_isalnum(int c) {
|
|||
#define light_bset(a,b) ((a) |= ((uint64_t)1uL << (b)))
|
||||
|
||||
|
||||
__attribute_pure__
|
||||
static inline uint32_t buffer_string_length(const buffer *b); /* buffer string length without terminating 0 */
|
||||
|
||||
__attribute_nonnull__
|
||||
__attribute_pure__
|
||||
static inline uint32_t buffer_string_space(const buffer *b); /* maximum length of string that can be stored without reallocating */
|
||||
|
||||
__attribute_nonnull__
|
||||
static inline void buffer_append_slash(buffer *b); /* append '/' no non-empty strings not ending in '/' */
|
||||
|
||||
void buffer_append_path_len(buffer * restrict b, const char * restrict a, size_t alen); /* join strings with '/', if '/' not present */
|
||||
void buffer_copy_path_len2(buffer * restrict b, const char * restrict s1, size_t len1, const char * restrict s2, size_t len2);
|
||||
|
||||
|
@ -284,17 +251,11 @@ __attribute_nonnull__
|
|||
__attribute_pure__
|
||||
static inline int buffer_has_pathsep_suffix (const buffer * const b);
|
||||
|
||||
#define BUFFER_APPEND_STRING_CONST(x, y) \
|
||||
buffer_append_string_len(x, y, sizeof(y) - 1)
|
||||
|
||||
#define BUFFER_COPY_STRING_CONST(x, y) \
|
||||
buffer_copy_string_len(x, y, sizeof(y) - 1)
|
||||
|
||||
#define BUFFER_INTLEN_PTR(x) (x)->used ? (int)((x)->used - 1) : 0, (x)->ptr
|
||||
#define BUFFER_INTLEN_PTR(x) (int)buffer_clen(x), (x)->ptr
|
||||
#define BUF_PTR_LEN(x) (x)->ptr, buffer_clen(x)
|
||||
|
||||
#define CONST_LEN_STR(x) (uint32_t)sizeof(x)-1, x
|
||||
#define CONST_STR_LEN(x) x, (uint32_t)sizeof(x) - 1
|
||||
#define CONST_BUF_LEN(x) ((x) ? (x)->ptr : NULL), buffer_string_length(x)
|
||||
|
||||
|
||||
#define LI_NORETURN __attribute_noreturn__
|
||||
|
@ -304,34 +265,71 @@ void log_failed_assert(const char *filename, unsigned int line, const char *msg)
|
|||
#define force_assert(x) do { if (!(x)) log_failed_assert(__FILE__, __LINE__, "assertion failed: " #x); } while(0)
|
||||
#define SEGFAULT() log_failed_assert(__FILE__, __LINE__, "aborted");
|
||||
|
||||
|
||||
/* inline implementations */
|
||||
|
||||
static inline int buffer_is_empty(const buffer *b) {
|
||||
return NULL == b || 0 == b->used;
|
||||
}
|
||||
static inline int buffer_string_is_empty(const buffer *b) {
|
||||
return NULL == b || b->used < 2;
|
||||
__attribute_nonnull__
|
||||
__attribute_pure__
|
||||
static inline int buffer_is_unset(const buffer *b);
|
||||
static inline int buffer_is_unset(const buffer *b) {
|
||||
return 0 == b->used;
|
||||
}
|
||||
|
||||
static inline uint32_t buffer_string_length(const buffer *b) {
|
||||
return NULL != b && 0 != b->used ? b->used - 1 : 0;
|
||||
__attribute_nonnull__
|
||||
__attribute_pure__
|
||||
static inline int buffer_is_blank(const buffer *b);
|
||||
static inline int buffer_is_blank(const buffer *b) {
|
||||
return b->used < 2; /* buffer_is_blank() || buffer_is_unset() */
|
||||
}
|
||||
|
||||
/* buffer "C" len (bytes) */
|
||||
__attribute_nonnull__
|
||||
__attribute_pure__
|
||||
static inline uint32_t buffer_clen (const buffer *b);
|
||||
static inline uint32_t buffer_clen (const buffer *b) {
|
||||
return b->used - (0 != b->used);
|
||||
}
|
||||
|
||||
/* buffer space remaining to append string without reallocating */
|
||||
__attribute_nonnull__
|
||||
__attribute_pure__
|
||||
static inline uint32_t buffer_string_space(const buffer *b);
|
||||
static inline uint32_t buffer_string_space(const buffer *b) {
|
||||
return b->size ? b->size - (b->used | (0 == b->used)) : 0;
|
||||
return b->size ? b->size - (b->used | (0 == b->used)) : 0;
|
||||
}
|
||||
|
||||
__attribute_nonnull__
|
||||
static inline void buffer_copy_buffer(buffer * restrict b, const buffer * restrict src);
|
||||
static inline void buffer_copy_buffer(buffer * restrict b, const buffer * restrict src) {
|
||||
buffer_copy_string_len(b, CONST_BUF_LEN(src));
|
||||
buffer_copy_string_len(b, BUF_PTR_LEN(src));
|
||||
}
|
||||
|
||||
static inline void buffer_append_string_buffer(buffer * restrict b, const buffer * restrict src) {
|
||||
buffer_append_string_len(b, CONST_BUF_LEN(src));
|
||||
__attribute_nonnull__
|
||||
static inline void buffer_append_buffer(buffer * restrict b, const buffer * restrict src);
|
||||
static inline void buffer_append_buffer(buffer * restrict b, const buffer * restrict src) {
|
||||
buffer_append_string_len(b, BUF_PTR_LEN(src));
|
||||
}
|
||||
|
||||
__attribute_nonnull__
|
||||
static inline void buffer_truncate(buffer *b, uint32_t len);
|
||||
static inline void buffer_truncate(buffer *b, uint32_t len) {
|
||||
b->ptr[len] = '\0'; /* b->ptr must exist; use buffer_blank() for trunc 0 */
|
||||
b->used = len + 1;
|
||||
}
|
||||
|
||||
__attribute_nonnull__
|
||||
static inline void buffer_blank(buffer *b);
|
||||
static inline void buffer_blank(buffer *b) {
|
||||
b->ptr ? buffer_truncate(b, 0) : (void)buffer_extend(b, 0);
|
||||
}
|
||||
|
||||
/* append '/' to non-empty strings not ending in '/' */
|
||||
__attribute_nonnull__
|
||||
static inline void buffer_append_slash(buffer *b);
|
||||
static inline void buffer_append_slash(buffer *b) {
|
||||
uint32_t len = buffer_string_length(b);
|
||||
if (len > 0 && '/' != b->ptr[len-1]) BUFFER_APPEND_STRING_CONST(b, "/");
|
||||
const uint32_t len = buffer_clen(b);
|
||||
if (len > 0 && '/' != b->ptr[len-1])
|
||||
buffer_append_string_len(b, CONST_STR_LEN("/"));
|
||||
}
|
||||
|
||||
static inline void buffer_clear(buffer *b) {
|
||||
|
@ -352,4 +350,58 @@ static inline int buffer_has_pathsep_suffix (const buffer * const b) {
|
|||
return (b->used > 1 && b->ptr[b->used-2] == '/');
|
||||
}
|
||||
|
||||
|
||||
/* backwards compat (deprecated; older interfaces) */
|
||||
|
||||
#define buffer_append_string_buffer buffer_append_buffer
|
||||
#define buffer_is_equal_caseless_string buffer_eq_icase_slen
|
||||
#define buffer_is_equal_string buffer_eq_slen
|
||||
|
||||
#define BUFFER_APPEND_STRING_CONST(x, y) \
|
||||
buffer_append_string_len(x, y, sizeof(y) - 1)
|
||||
|
||||
#define BUFFER_COPY_STRING_CONST(x, y) \
|
||||
buffer_copy_string_len(x, y, sizeof(y) - 1)
|
||||
|
||||
#define CONST_BUF_LEN(x) ((x) ? (x)->ptr : NULL), buffer_string_length(x)
|
||||
|
||||
/* NULL buffer or empty buffer (used == 0);
|
||||
* unset "string" (buffer) config options are initialized to used == 0,
|
||||
* while setting an empty string leads to used == 1
|
||||
*/
|
||||
__attribute_pure__
|
||||
static inline int buffer_is_empty(const buffer *b);
|
||||
static inline int buffer_is_empty(const buffer *b) {
|
||||
return NULL == b || buffer_is_unset(b);
|
||||
}
|
||||
/* NULL buffer, empty buffer (used == 0) or empty string (used == 1) */
|
||||
__attribute_pure__
|
||||
static inline int buffer_string_is_empty(const buffer *b);
|
||||
static inline int buffer_string_is_empty(const buffer *b) {
|
||||
return NULL == b || buffer_is_blank(b);
|
||||
}
|
||||
|
||||
/* buffer string length without terminating 0 */
|
||||
__attribute_pure__
|
||||
static inline uint32_t buffer_string_length(const buffer *b);
|
||||
static inline uint32_t buffer_string_length(const buffer *b) {
|
||||
return NULL != b ? buffer_clen(b) : 0;
|
||||
}
|
||||
|
||||
/* sets string length:
|
||||
* - deprecated; use buffer_truncate() or buffer_extend() instead
|
||||
* - always stores a terminating zero to terminate the "new" string
|
||||
* - does not modify the string data apart from terminating zero
|
||||
* - reallocates the buffer iff needed
|
||||
*/
|
||||
__attribute_nonnull__
|
||||
static inline void buffer_string_set_length(buffer *b, uint32_t len);
|
||||
static inline void buffer_string_set_length(buffer *b, uint32_t len) {
|
||||
if (len < b->size)
|
||||
buffer_truncate(b, len);
|
||||
else
|
||||
buffer_extend(b, len - buffer_clen(b));
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
|
36
src/burl.c
36
src/burl.c
|
@ -58,7 +58,7 @@ static int burl_is_unreserved (const int c)
|
|||
static int burl_normalize_basic_unreserved_fix (buffer *b, buffer *t, int i, int qs)
|
||||
{
|
||||
int j = i;
|
||||
const int used = (int)buffer_string_length(b);
|
||||
const int used = (int)buffer_clen(b);
|
||||
const unsigned char * const s = (unsigned char *)b->ptr;
|
||||
unsigned char * const p =
|
||||
(unsigned char *)buffer_string_prepare_copy(t,i+(used-i)*3+1);
|
||||
|
@ -98,7 +98,7 @@ static int burl_normalize_basic_unreserved_fix (buffer *b, buffer *t, int i, int
|
|||
static int burl_normalize_basic_unreserved (buffer *b, buffer *t)
|
||||
{
|
||||
const unsigned char * const s = (unsigned char *)b->ptr;
|
||||
const int used = (int)buffer_string_length(b);
|
||||
const int used = (int)buffer_clen(b);
|
||||
unsigned int n1, n2, x;
|
||||
int qs = -1;
|
||||
|
||||
|
@ -114,7 +114,7 @@ static int burl_normalize_basic_unreserved (buffer *b, buffer *t)
|
|||
i+=2;
|
||||
}
|
||||
else if (s[i] == '#') { /* ignore fragment */
|
||||
buffer_string_set_length(b, (size_t)i);
|
||||
buffer_truncate(b, (size_t)i);
|
||||
break;
|
||||
}
|
||||
else {
|
||||
|
@ -130,7 +130,7 @@ static int burl_normalize_basic_unreserved (buffer *b, buffer *t)
|
|||
static int burl_normalize_basic_required_fix (buffer *b, buffer *t, int i, int qs)
|
||||
{
|
||||
int j = i;
|
||||
const int used = (int)buffer_string_length(b);
|
||||
const int used = (int)buffer_clen(b);
|
||||
const unsigned char * const s = (unsigned char *)b->ptr;
|
||||
unsigned char * const p =
|
||||
(unsigned char *)buffer_string_prepare_copy(t,i+(used-i)*3+1);
|
||||
|
@ -173,7 +173,7 @@ static int burl_normalize_basic_required_fix (buffer *b, buffer *t, int i, int q
|
|||
static int burl_normalize_basic_required (buffer *b, buffer *t)
|
||||
{
|
||||
const unsigned char * const s = (unsigned char *)b->ptr;
|
||||
const int used = (int)buffer_string_length(b);
|
||||
const int used = (int)buffer_clen(b);
|
||||
unsigned int n1, n2, x;
|
||||
int qs = -1;
|
||||
|
||||
|
@ -192,7 +192,7 @@ static int burl_normalize_basic_required (buffer *b, buffer *t)
|
|||
i+=2;
|
||||
}
|
||||
else if (s[i] == '#') { /* ignore fragment */
|
||||
buffer_string_set_length(b, (size_t)i);
|
||||
buffer_truncate(b, (size_t)i);
|
||||
break;
|
||||
}
|
||||
else {
|
||||
|
@ -208,7 +208,7 @@ static int burl_normalize_basic_required (buffer *b, buffer *t)
|
|||
static int burl_contains_ctrls (const buffer *b)
|
||||
{
|
||||
const char * const s = b->ptr;
|
||||
const int used = (int)buffer_string_length(b);
|
||||
const int used = (int)buffer_clen(b);
|
||||
for (int i = 0; i < used; ++i) {
|
||||
if (s[i] == '%' && (s[i+1] < '2' || (s[i+1] == '7' && s[i+2] == 'F')))
|
||||
return 1;
|
||||
|
@ -220,7 +220,7 @@ static int burl_contains_ctrls (const buffer *b)
|
|||
static void burl_normalize_qs20_to_plus_fix (buffer *b, int i)
|
||||
{
|
||||
char * const s = b->ptr;
|
||||
const int used = (int)buffer_string_length(b);
|
||||
const int used = (int)buffer_clen(b);
|
||||
int j = i;
|
||||
for (; i < used; ++i, ++j) {
|
||||
s[j] = s[i];
|
||||
|
@ -229,14 +229,14 @@ static void burl_normalize_qs20_to_plus_fix (buffer *b, int i)
|
|||
i+=2;
|
||||
}
|
||||
}
|
||||
buffer_string_set_length(b, j);
|
||||
buffer_truncate(b, j);
|
||||
}
|
||||
|
||||
|
||||
static void burl_normalize_qs20_to_plus (buffer *b, int qs)
|
||||
{
|
||||
const char * const s = b->ptr;
|
||||
const int used = qs < 0 ? 0 : (int)buffer_string_length(b);
|
||||
const int used = qs < 0 ? 0 : (int)buffer_clen(b);
|
||||
int i;
|
||||
if (qs < 0) return;
|
||||
for (i = qs+1; i < used; ++i) {
|
||||
|
@ -249,7 +249,7 @@ static void burl_normalize_qs20_to_plus (buffer *b, int qs)
|
|||
static int burl_normalize_2F_to_slash_fix (buffer *b, int qs, int i)
|
||||
{
|
||||
char * const s = b->ptr;
|
||||
const int blen = (int)buffer_string_length(b);
|
||||
const int blen = (int)buffer_clen(b);
|
||||
const int used = qs < 0 ? blen : qs;
|
||||
int j = i;
|
||||
for (; i < used; ++i, ++j) {
|
||||
|
@ -265,7 +265,7 @@ static int burl_normalize_2F_to_slash_fix (buffer *b, int qs, int i)
|
|||
qs = j;
|
||||
j += qslen;
|
||||
}
|
||||
buffer_string_set_length(b, j);
|
||||
buffer_truncate(b, j);
|
||||
return qs;
|
||||
}
|
||||
|
||||
|
@ -274,7 +274,7 @@ static int burl_normalize_2F_to_slash (buffer *b, int qs, int flags)
|
|||
{
|
||||
/*("%2F" must already have been uppercased during normalization)*/
|
||||
const char * const s = b->ptr;
|
||||
const int used = qs < 0 ? (int)buffer_string_length(b) : qs;
|
||||
const int used = qs < 0 ? (int)buffer_clen(b) : qs;
|
||||
for (int i = 0; i < used; ++i) {
|
||||
if (s[i] == '%' && s[i+1] == '2' && s[i+2] == 'F') {
|
||||
return (flags & HTTP_PARSEOPT_URL_NORMALIZE_PATH_2F_DECODE)
|
||||
|
@ -289,7 +289,7 @@ static int burl_normalize_2F_to_slash (buffer *b, int qs, int flags)
|
|||
static int burl_normalize_path (buffer *b, buffer *t, int qs, int flags)
|
||||
{
|
||||
const unsigned char * const s = (unsigned char *)b->ptr;
|
||||
const int used = (int)buffer_string_length(b);
|
||||
const int used = (int)buffer_clen(b);
|
||||
int path_simplify = 0;
|
||||
for (int i = 0, len = qs < 0 ? used : qs; i < len; ++i) {
|
||||
if (s[i] == '.' && (s[i+1] != '.' || ++i)
|
||||
|
@ -308,14 +308,14 @@ static int burl_normalize_path (buffer *b, buffer *t, int qs, int flags)
|
|||
if (flags & HTTP_PARSEOPT_URL_NORMALIZE_PATH_DOTSEG_REJECT) return -2;
|
||||
if (qs >= 0) {
|
||||
buffer_copy_string_len(t, b->ptr+qs, used - qs);
|
||||
buffer_string_set_length(b, qs);
|
||||
buffer_truncate(b, qs);
|
||||
}
|
||||
|
||||
buffer_path_simplify(b);
|
||||
|
||||
if (qs >= 0) {
|
||||
qs = (int)buffer_string_length(b);
|
||||
buffer_append_string_len(b, CONST_BUF_LEN(t));
|
||||
qs = (int)buffer_clen(b);
|
||||
buffer_append_string_len(b, BUF_PTR_LEN(t));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -490,7 +490,7 @@ void burl_append (buffer * const b, const char * const str, const size_t len, co
|
|||
return;
|
||||
}
|
||||
|
||||
if (flags & (BURL_TOUPPER|BURL_TOLOWER)) off = buffer_string_length(b);
|
||||
if (flags & (BURL_TOUPPER|BURL_TOLOWER)) off = buffer_clen(b);
|
||||
|
||||
if (flags & BURL_ENCODE_NONE) {
|
||||
buffer_append_string_len(b, str, len);
|
||||
|
|
67
src/chunk.c
67
src/chunk.c
|
@ -46,20 +46,6 @@ void chunkqueue_set_tempdirs_default_reset (void)
|
|||
chunkqueue_default_tempfile_size = DEFAULT_TEMPFILE_SIZE;
|
||||
}
|
||||
|
||||
/* chunk buffer (c->mem) is never NULL; specialize routines from buffer.h */
|
||||
__attribute_pure__
|
||||
static inline size_t chunk_buffer_string_length(const buffer *b) {
|
||||
return 0 != b->used ? b->used - 1 : 0;
|
||||
}
|
||||
__attribute_pure__
|
||||
static inline int chunk_buffer_string_is_empty(const buffer *b) {
|
||||
return b->used < 2;
|
||||
}
|
||||
__attribute_pure__
|
||||
static inline size_t chunk_buffer_string_space(const buffer *b) {
|
||||
return b->size ? b->size - (b->used | (0 == b->used)) : 0;
|
||||
}
|
||||
|
||||
chunkqueue *chunkqueue_init(chunkqueue *cq) {
|
||||
/* (if caller passes non-NULL cq, it must be 0-init) */
|
||||
if (NULL == cq) {
|
||||
|
@ -101,7 +87,7 @@ static chunk *chunk_init(size_t sz) {
|
|||
static void chunk_reset_file_chunk(chunk *c) {
|
||||
if (c->file.is_temp) {
|
||||
c->file.is_temp = 0;
|
||||
if (!chunk_buffer_string_is_empty(c->mem))
|
||||
if (!buffer_is_blank(c->mem))
|
||||
unlink(c->mem->ptr);
|
||||
}
|
||||
if (c->file.refchg) {
|
||||
|
@ -213,7 +199,7 @@ void chunk_buffer_release(buffer *b) {
|
|||
}
|
||||
|
||||
size_t chunk_buffer_prepare_append(buffer * const b, size_t sz) {
|
||||
if (sz > chunk_buffer_string_space(b)) {
|
||||
if (sz > buffer_string_space(b)) {
|
||||
sz += b->used ? b->used : 1;
|
||||
buffer * const cb = chunk_buffer_acquire_sz(sz);
|
||||
/* swap buffer contents and copy original b->ptr into larger b->ptr */
|
||||
|
@ -225,7 +211,7 @@ size_t chunk_buffer_prepare_append(buffer * const b, size_t sz) {
|
|||
memcpy(b->ptr, tb.ptr, tb.used);
|
||||
chunk_buffer_release(cb);
|
||||
}
|
||||
return chunk_buffer_string_space(b);
|
||||
return buffer_string_space(b);
|
||||
}
|
||||
|
||||
__attribute_returns_nonnull__
|
||||
|
@ -294,7 +280,7 @@ __attribute_pure__
|
|||
static off_t chunk_remaining_length(const chunk *c) {
|
||||
/* MEM_CHUNK or FILE_CHUNK */
|
||||
return (c->type == MEM_CHUNK
|
||||
? (off_t)chunk_buffer_string_length(c->mem)
|
||||
? (off_t)buffer_clen(c->mem)
|
||||
: c->file.length)
|
||||
- c->offset;
|
||||
}
|
||||
|
@ -340,13 +326,13 @@ static chunk * chunkqueue_append_mem_chunk(chunkqueue *cq, size_t sz) {
|
|||
|
||||
__attribute_returns_nonnull__
|
||||
static chunk * chunkqueue_append_file_chunk(chunkqueue * const restrict cq, const buffer * const restrict fn, off_t offset, off_t len) {
|
||||
chunk *c = chunk_acquire(buffer_string_length(fn)+1);
|
||||
chunk *c = chunk_acquire((fn ? buffer_clen(fn) : 0)+1);
|
||||
chunkqueue_append_chunk(cq, c);
|
||||
c->type = FILE_CHUNK;
|
||||
c->offset = offset;
|
||||
c->file.length = offset + len;
|
||||
cq->bytes_in += len;
|
||||
buffer_copy_buffer(c->mem, fn);
|
||||
if (fn) buffer_copy_buffer(c->mem, fn);
|
||||
return c;
|
||||
}
|
||||
|
||||
|
@ -377,7 +363,7 @@ static int chunkqueue_append_mem_extend_chunk(chunkqueue * const restrict cq, co
|
|||
chunk *c = cq->last;
|
||||
if (0 == len) return 1;
|
||||
if (c != NULL && c->type == MEM_CHUNK
|
||||
&& chunk_buffer_string_space(c->mem) >= len) {
|
||||
&& buffer_string_space(c->mem) >= len) {
|
||||
buffer_append_string_len(c->mem, mem, len);
|
||||
cq->bytes_in += len;
|
||||
return 1;
|
||||
|
@ -388,7 +374,7 @@ static int chunkqueue_append_mem_extend_chunk(chunkqueue * const restrict cq, co
|
|||
|
||||
void chunkqueue_append_buffer(chunkqueue * const restrict cq, buffer * const restrict mem) {
|
||||
chunk *c;
|
||||
size_t len = buffer_string_length(mem);
|
||||
size_t len = mem ? buffer_clen(mem) : 0;
|
||||
if (len < 256 && chunkqueue_append_mem_extend_chunk(cq, mem->ptr, len)) return;
|
||||
|
||||
c = chunkqueue_append_mem_chunk(cq, chunk_buf_sz);
|
||||
|
@ -449,7 +435,7 @@ buffer * chunkqueue_prepend_buffer_open(chunkqueue *cq) {
|
|||
|
||||
|
||||
void chunkqueue_prepend_buffer_commit(chunkqueue *cq) {
|
||||
cq->bytes_in += chunk_buffer_string_length(cq->first->mem);
|
||||
cq->bytes_in += buffer_clen(cq->first->mem);
|
||||
}
|
||||
|
||||
|
||||
|
@ -465,7 +451,7 @@ buffer * chunkqueue_append_buffer_open(chunkqueue *cq) {
|
|||
|
||||
|
||||
void chunkqueue_append_buffer_commit(chunkqueue *cq) {
|
||||
cq->bytes_in += chunk_buffer_string_length(cq->last->mem);
|
||||
cq->bytes_in += buffer_clen(cq->last->mem);
|
||||
}
|
||||
|
||||
|
||||
|
@ -478,17 +464,17 @@ char * chunkqueue_get_memory(chunkqueue * const restrict cq, size_t * const rest
|
|||
chunk *c = cq->last;
|
||||
if (NULL != c && MEM_CHUNK == c->type) {
|
||||
/* return pointer into existing buffer if large enough */
|
||||
size_t avail = chunk_buffer_string_space(c->mem);
|
||||
size_t avail = buffer_string_space(c->mem);
|
||||
if (avail >= sz) {
|
||||
*len = avail;
|
||||
b = c->mem;
|
||||
return b->ptr + chunk_buffer_string_length(b);
|
||||
return b->ptr + buffer_clen(b);
|
||||
}
|
||||
}
|
||||
|
||||
/* allocate new chunk */
|
||||
b = chunkqueue_append_buffer_open_sz(cq, sz);
|
||||
*len = chunk_buffer_string_space(b);
|
||||
*len = buffer_string_space(b);
|
||||
return b->ptr;
|
||||
}
|
||||
|
||||
|
@ -499,11 +485,11 @@ void chunkqueue_use_memory(chunkqueue * const restrict cq, chunk *ckpt, size_t l
|
|||
buffer_commit(b, len);
|
||||
cq->bytes_in += len;
|
||||
if (cq->last == ckpt || NULL == ckpt || MEM_CHUNK != ckpt->type
|
||||
|| len > chunk_buffer_string_space(ckpt->mem)) return;
|
||||
|| len > buffer_string_space(ckpt->mem)) return;
|
||||
|
||||
buffer_append_string_buffer(ckpt->mem, b);
|
||||
}
|
||||
else if (!chunk_buffer_string_is_empty(b)) { /*(cq->last == ckpt)*/
|
||||
else if (!buffer_is_blank(b)) { /*(cq->last == ckpt)*/
|
||||
return; /* last chunk is not empty */
|
||||
}
|
||||
|
||||
|
@ -616,7 +602,7 @@ static chunk *chunkqueue_get_append_tempfile(chunkqueue * const restrict cq, log
|
|||
for (errno = EIO; cq->tempdir_idx < cq->tempdirs->used; ++cq->tempdir_idx) {
|
||||
data_string *ds = (data_string *)cq->tempdirs->data[cq->tempdir_idx];
|
||||
buffer_copy_path_len2(template,
|
||||
CONST_BUF_LEN(&ds->value),
|
||||
BUF_PTR_LEN(&ds->value),
|
||||
CONST_STR_LEN("lighttpd-upload-XXXXXX"));
|
||||
if (-1 != (fd = fdevent_mkstemp_append(template->ptr))) break;
|
||||
}
|
||||
|
@ -877,10 +863,10 @@ void chunkqueue_compact_mem_offset(chunkqueue * const cq) {
|
|||
if (c->type != MEM_CHUNK) return; /*(should not happen)*/
|
||||
|
||||
buffer * const restrict b = c->mem;
|
||||
size_t len = chunk_buffer_string_length(b) - c->offset;
|
||||
size_t len = buffer_clen(b) - c->offset;
|
||||
memmove(b->ptr, b->ptr+c->offset, len);
|
||||
c->offset = 0;
|
||||
buffer_string_set_length(b, len);
|
||||
buffer_truncate(b, len);
|
||||
}
|
||||
|
||||
void chunkqueue_compact_mem(chunkqueue *cq, size_t clen) {
|
||||
|
@ -888,10 +874,10 @@ void chunkqueue_compact_mem(chunkqueue *cq, size_t clen) {
|
|||
* which is currently always true when reading input from client */
|
||||
chunk *c = cq->first;
|
||||
buffer *b = c->mem;
|
||||
size_t len = chunk_buffer_string_length(b) - c->offset;
|
||||
size_t len = buffer_clen(b) - c->offset;
|
||||
if (len >= clen) return;
|
||||
if (b->size > clen) {
|
||||
if (chunk_buffer_string_space(b) < clen - len)
|
||||
if (buffer_string_space(b) < clen - len)
|
||||
chunkqueue_compact_mem_offset(cq);
|
||||
}
|
||||
else {
|
||||
|
@ -904,7 +890,7 @@ void chunkqueue_compact_mem(chunkqueue *cq, size_t clen) {
|
|||
}
|
||||
|
||||
for (chunk *fc = c; ((clen -= len) && (c = fc->next)); ) {
|
||||
len = chunk_buffer_string_length(c->mem) - c->offset;
|
||||
len = buffer_clen(c->mem) - c->offset;
|
||||
if (len > clen) {
|
||||
buffer_append_string_len(b, c->mem->ptr + c->offset, clen);
|
||||
c->offset += clen;
|
||||
|
@ -1076,7 +1062,7 @@ static ssize_t
|
|||
chunkqueue_write_chunk_mem (const int fd, const chunk * const restrict c)
|
||||
{
|
||||
const void * const buf = c->mem->ptr + c->offset;
|
||||
const size_t count = chunk_buffer_string_length(c->mem) - (size_t)c->offset;
|
||||
const size_t count = buffer_clen(c->mem) - (size_t)c->offset;
|
||||
ssize_t wr;
|
||||
do { wr = write(fd, buf, count); } while (-1 == wr && errno == EINTR);
|
||||
return wr;
|
||||
|
@ -1144,14 +1130,14 @@ chunkqueue_small_resp_optim (chunkqueue * const restrict cq)
|
|||
|
||||
buffer *b = c->mem;
|
||||
off_t len = filec->file.length - filec->offset;
|
||||
if ((size_t)len > chunk_buffer_string_space(b)) {
|
||||
if ((size_t)len > buffer_string_space(b)) {
|
||||
chunk * const nc = chunk_acquire((size_t)len+1);
|
||||
c->next = nc;
|
||||
nc->next = filec;
|
||||
b = nc->mem;
|
||||
}
|
||||
|
||||
char * const ptr = b->ptr + chunk_buffer_string_length(b);
|
||||
char * const ptr = b->ptr + buffer_clen(b);
|
||||
ssize_t rd;
|
||||
offset = 0; /*(reuse offset var for offset into mem buffer)*/
|
||||
do {
|
||||
|
@ -1180,8 +1166,7 @@ chunkqueue_peek_data (chunkqueue * const cq,
|
|||
switch (c->type) {
|
||||
case MEM_CHUNK:
|
||||
{
|
||||
uint32_t have =
|
||||
chunk_buffer_string_length(c->mem) - (uint32_t)c->offset;
|
||||
uint32_t have = buffer_clen(c->mem) - (uint32_t)c->offset;
|
||||
if (have > space)
|
||||
have = space;
|
||||
if (*dlen)
|
||||
|
@ -1277,7 +1262,7 @@ chunkqueue_read_squash (chunkqueue * const restrict cq, log_error_st * const res
|
|||
chunk_release(c);
|
||||
return NULL;
|
||||
}
|
||||
buffer_string_set_length(c->mem, dlen);
|
||||
buffer_truncate(c->mem, dlen);
|
||||
|
||||
chunkqueue_release_chunks(cq);
|
||||
chunkqueue_append_chunk(cq, c);
|
||||
|
|
|
@ -516,7 +516,7 @@ static cond_result_t config_check_cond_nocache(request_st * const r, const data_
|
|||
|
||||
l = &r->uri.authority;
|
||||
|
||||
if (buffer_string_is_empty(l)) {
|
||||
if (buffer_is_blank(l)) {
|
||||
l = (buffer *)&empty_string;
|
||||
break;
|
||||
}
|
||||
|
@ -592,7 +592,7 @@ static cond_result_t config_check_cond_nocache(request_st * const r, const data_
|
|||
|
||||
case COMP_HTTP_REQUEST_HEADER:
|
||||
*((const buffer **)&l) =
|
||||
http_header_request_get(r, dc->ext, CONST_BUF_LEN(&dc->comp_tag));
|
||||
http_header_request_get(r, dc->ext, BUF_PTR_LEN(&dc->comp_tag));
|
||||
if (NULL == l) l = (buffer *)&empty_string;
|
||||
break;
|
||||
case COMP_HTTP_REQUEST_METHOD:
|
||||
|
@ -720,7 +720,7 @@ static int data_config_pcre_exec(const data_config *dc, cond_cache_t *cache, con
|
|||
#define elementsof(x) (sizeof(x) / sizeof(x[0]))
|
||||
#endif
|
||||
cache->patterncount =
|
||||
pcre_exec(dc->regex, dc->regex_study, CONST_BUF_LEN(b), 0, 0,
|
||||
pcre_exec(dc->regex, dc->regex_study, BUF_PTR_LEN(b), 0, 0,
|
||||
cond_match->matches, elementsof(cond_match->matches));
|
||||
if (cache->patterncount > 0)
|
||||
cond_match->comp_value = b; /*holds pointer to b (!) for pattern subst*/
|
||||
|
|
104
src/configfile.c
104
src/configfile.c
|
@ -215,7 +215,6 @@ void config_patch_config(request_st * const r) {
|
|||
void config_reset_config(request_st * const r) {
|
||||
/* initialize request_config (r->conf) from top-level request_config */
|
||||
config_data_base * const p = r->con->config_data_base;
|
||||
r->server_name = p->defaults.server_name;
|
||||
memcpy(&r->conf, &p->defaults, sizeof(request_config));
|
||||
}
|
||||
|
||||
|
@ -304,7 +303,7 @@ static void config_check_module_duplicates (server *srv) {
|
|||
if (buffer_is_equal(m, n)) break; /* duplicate */
|
||||
}
|
||||
if (j == modules->used)
|
||||
array_insert_value(modules, CONST_BUF_LEN(m));
|
||||
array_insert_value(modules, BUF_PTR_LEN(m));
|
||||
}
|
||||
array_free(srv->srvconf.modules);
|
||||
srv->srvconf.modules = modules;
|
||||
|
@ -330,7 +329,7 @@ static void config_compat_module_prepend (server *srv, const char *module, uint3
|
|||
|
||||
for (uint32_t i = 0; i < srv->srvconf.modules->used; ++i) {
|
||||
data_string *ds = (data_string *)srv->srvconf.modules->data[i];
|
||||
array_insert_value(modules, CONST_BUF_LEN(&ds->value));
|
||||
array_insert_value(modules, BUF_PTR_LEN(&ds->value));
|
||||
}
|
||||
|
||||
array_free(srv->srvconf.modules);
|
||||
|
@ -341,7 +340,7 @@ static void config_warn_authn_module (server *srv, const char *module, uint32_t
|
|||
buffer * const tb = srv->tmp_buf;
|
||||
buffer_copy_string_len(tb, CONST_STR_LEN("mod_authn_"));
|
||||
buffer_append_string_len(tb, module, len);
|
||||
array_insert_value(srv->srvconf.modules, CONST_BUF_LEN(tb));
|
||||
array_insert_value(srv->srvconf.modules, BUF_PTR_LEN(tb));
|
||||
log_error(srv->errh, __FILE__, __LINE__,
|
||||
"Warning: please add \"mod_authn_%s\" to server.modules list "
|
||||
"in lighttpd.conf. A future release of lighttpd 1.4.x will "
|
||||
|
@ -503,7 +502,7 @@ static void config_deprecate_module_compress (server *srv) {
|
|||
buffer *m = &((data_string *)srv->srvconf.modules->data[i])->value;
|
||||
if (buffer_eq_slen(m, CONST_STR_LEN("mod_compress")))
|
||||
continue;
|
||||
array_insert_value(a, CONST_BUF_LEN(m));
|
||||
array_insert_value(a, BUF_PTR_LEN(m));
|
||||
}
|
||||
array_free(srv->srvconf.modules);
|
||||
srv->srvconf.modules = a;
|
||||
|
@ -755,19 +754,24 @@ static int config_insert_srvconf(server *srv) {
|
|||
srv->srvconf.port = cpv->v.shrt;
|
||||
break;
|
||||
case 4: /* server.bind */
|
||||
srv->srvconf.bindhost = cpv->v.b;
|
||||
if (!buffer_is_blank(cpv->v.b))
|
||||
srv->srvconf.bindhost = cpv->v.b;
|
||||
break;
|
||||
case 5: /* server.network-backend */
|
||||
srv->srvconf.network_backend = cpv->v.b;
|
||||
if (!buffer_is_blank(cpv->v.b))
|
||||
srv->srvconf.network_backend = cpv->v.b;
|
||||
break;
|
||||
case 6: /* server.chroot */
|
||||
srv->srvconf.changeroot = cpv->v.b;
|
||||
if (!buffer_is_blank(cpv->v.b))
|
||||
srv->srvconf.changeroot = cpv->v.b;
|
||||
break;
|
||||
case 7: /* server.username */
|
||||
srv->srvconf.username = cpv->v.b;
|
||||
if (!buffer_is_blank(cpv->v.b))
|
||||
srv->srvconf.username = cpv->v.b;
|
||||
break;
|
||||
case 8: /* server.groupname */
|
||||
srv->srvconf.groupname = cpv->v.b;
|
||||
if (!buffer_is_blank(cpv->v.b))
|
||||
srv->srvconf.groupname = cpv->v.b;
|
||||
break;
|
||||
case 9: /* server.errorlog */ /* moved to config_insert() */
|
||||
/*srv->srvconf.errorlog_file = cpv->v.b;*/
|
||||
|
@ -779,7 +783,8 @@ static int config_insert_srvconf(server *srv) {
|
|||
srv->srvconf.errorlog_use_syslog = (unsigned short)cpv->v.u;
|
||||
break;
|
||||