[core] store addtl data in pcre_keyvalue_buffer
reduce pointer chasing in keyvalue.c mark keyvalue.h config routines as cold
This commit is contained in:
parent
f7d1434366
commit
63a6e52ce4
|
@ -1,7 +1,7 @@
|
|||
#include "first.h"
|
||||
|
||||
#include "keyvalue.h"
|
||||
#include "base.h"
|
||||
#include "base.h" /* struct cond_cache_t */
|
||||
#include "burl.h"
|
||||
#include "log.h"
|
||||
|
||||
|
@ -17,7 +17,7 @@ typedef struct pcre_keyvalue {
|
|||
pcre *key;
|
||||
pcre_extra *key_extra;
|
||||
#endif
|
||||
buffer *value;
|
||||
buffer value;
|
||||
} pcre_keyvalue;
|
||||
|
||||
pcre_keyvalue_buffer *pcre_keyvalue_buffer_init(void) {
|
||||
|
@ -29,75 +29,61 @@ pcre_keyvalue_buffer *pcre_keyvalue_buffer_init(void) {
|
|||
return kvb;
|
||||
}
|
||||
|
||||
int pcre_keyvalue_buffer_append(server *srv, pcre_keyvalue_buffer *kvb, buffer *key, buffer *value) {
|
||||
int pcre_keyvalue_buffer_append(log_error_st *errh, pcre_keyvalue_buffer *kvb, const buffer *key, const buffer *value) {
|
||||
#ifdef HAVE_PCRE_H
|
||||
size_t i;
|
||||
const char *errptr;
|
||||
int erroff;
|
||||
pcre_keyvalue *kv;
|
||||
|
||||
if (!key) return -1;
|
||||
|
||||
if (kvb->used == kvb->size) {
|
||||
kvb->size += 4;
|
||||
|
||||
kvb->kv = realloc(kvb->kv, kvb->size * sizeof(*kvb->kv));
|
||||
if (0 == (kvb->used & 3)) { /*(allocate in groups of 4)*/
|
||||
kvb->kv = realloc(kvb->kv, (kvb->used + 4) * sizeof(*kvb->kv));
|
||||
force_assert(NULL != kvb->kv);
|
||||
|
||||
for(i = kvb->used; i < kvb->size; i++) {
|
||||
kvb->kv[i] = calloc(1, sizeof(**kvb->kv));
|
||||
force_assert(NULL != kvb->kv[i]);
|
||||
}
|
||||
}
|
||||
|
||||
kv = kvb->kv[kvb->used];
|
||||
kv = kvb->kv + kvb->used++;
|
||||
kv->key_extra = NULL;
|
||||
|
||||
/* copy persistent config data, and elide free() in free_data below */
|
||||
memcpy(&kv->value, value, sizeof(buffer));
|
||||
/*buffer_copy_buffer(&kv->value, value);*/
|
||||
|
||||
if (NULL == (kv->key = pcre_compile(key->ptr,
|
||||
0, &errptr, &erroff, NULL))) {
|
||||
|
||||
log_error_write(srv, __FILE__, __LINE__, "SS",
|
||||
"rexexp compilation error at ", errptr);
|
||||
return -1;
|
||||
log_error(errh, __FILE__, __LINE__,
|
||||
"rexexp compilation error at %s", errptr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (NULL == (kv->key_extra = pcre_study(kv->key, 0, &errptr)) &&
|
||||
errptr != NULL) {
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
kv->value = buffer_init_buffer(value);
|
||||
|
||||
kvb->used++;
|
||||
|
||||
#else
|
||||
static int logged_message = 0;
|
||||
if (logged_message) return 0;
|
||||
if (logged_message) return 1;
|
||||
logged_message = 1;
|
||||
log_error_write(srv, __FILE__, __LINE__, "s",
|
||||
"pcre support is missing, please install libpcre and the headers");
|
||||
log_error(errh, __FILE__, __LINE__,
|
||||
"pcre support is missing, please install libpcre and the headers");
|
||||
UNUSED(kvb);
|
||||
UNUSED(key);
|
||||
UNUSED(value);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void pcre_keyvalue_buffer_free(pcre_keyvalue_buffer *kvb) {
|
||||
#ifdef HAVE_PCRE_H
|
||||
size_t i;
|
||||
pcre_keyvalue *kv;
|
||||
|
||||
for (i = 0; i < kvb->size; i++) {
|
||||
kv = kvb->kv[i];
|
||||
for (uint32_t i = 0; i < kvb->used; ++i) {
|
||||
pcre_keyvalue * const kv = kvb->kv+i;
|
||||
if (kv->key) pcre_free(kv->key);
|
||||
if (kv->key_extra) pcre_free(kv->key_extra);
|
||||
if (kv->value) buffer_free(kv->value);
|
||||
free(kv);
|
||||
/*free (kv->value.ptr);*//*(see pcre_keyvalue_buffer_append)*/
|
||||
}
|
||||
|
||||
if (kvb->kv) free(kvb->kv);
|
||||
#endif
|
||||
|
||||
free(kvb);
|
||||
}
|
||||
|
||||
|
@ -288,9 +274,9 @@ static void pcre_keyvalue_buffer_subst(buffer *b, const buffer *patternb, const
|
|||
buffer_append_string_len(b, pattern + start, pattern_len - start);
|
||||
}
|
||||
|
||||
handler_t pcre_keyvalue_buffer_process(pcre_keyvalue_buffer *kvb, pcre_keyvalue_ctx *ctx, buffer *input, buffer *result) {
|
||||
handler_t pcre_keyvalue_buffer_process(const pcre_keyvalue_buffer *kvb, pcre_keyvalue_ctx *ctx, const buffer *input, buffer *result) {
|
||||
for (int i = 0, used = (int)kvb->used; i < used; ++i) {
|
||||
pcre_keyvalue * const kv = kvb->kv[i];
|
||||
const pcre_keyvalue * const kv = kvb->kv+i;
|
||||
#define N 20
|
||||
int ovec[N * 3];
|
||||
#undef N
|
||||
|
@ -301,7 +287,7 @@ handler_t pcre_keyvalue_buffer_process(pcre_keyvalue_buffer *kvb, pcre_keyvalue_
|
|||
return HANDLER_ERROR;
|
||||
}
|
||||
}
|
||||
else if (buffer_string_is_empty(kv->value)) {
|
||||
else if (buffer_string_is_empty(&kv->value)) {
|
||||
/* short-circuit if blank replacement pattern
|
||||
* (do not attempt to match against remaining kvb rules) */
|
||||
ctx->m = i;
|
||||
|
@ -311,7 +297,7 @@ handler_t pcre_keyvalue_buffer_process(pcre_keyvalue_buffer *kvb, pcre_keyvalue_
|
|||
const char **list;
|
||||
ctx->m = i;
|
||||
pcre_get_substring_list(input->ptr, ovec, n, &list);
|
||||
pcre_keyvalue_buffer_subst(result, kv->value, list, n, ctx);
|
||||
pcre_keyvalue_buffer_subst(result, &kv->value, list, n, ctx);
|
||||
pcre_free(list);
|
||||
return HANDLER_FINISHED;
|
||||
}
|
||||
|
@ -320,7 +306,7 @@ handler_t pcre_keyvalue_buffer_process(pcre_keyvalue_buffer *kvb, pcre_keyvalue_
|
|||
return HANDLER_GO_ON;
|
||||
}
|
||||
#else
|
||||
handler_t pcre_keyvalue_buffer_process(pcre_keyvalue_buffer *kvb, pcre_keyvalue_ctx *ctx, buffer *input, buffer *result) {
|
||||
handler_t pcre_keyvalue_buffer_process(const pcre_keyvalue_buffer *kvb, pcre_keyvalue_ctx *ctx, const buffer *input, buffer *result) {
|
||||
UNUSED(kvb);
|
||||
UNUSED(ctx);
|
||||
UNUSED(input);
|
||||
|
|
|
@ -16,16 +16,27 @@ typedef struct pcre_keyvalue_ctx {
|
|||
} pcre_keyvalue_ctx;
|
||||
|
||||
typedef struct {
|
||||
struct pcre_keyvalue **kv;
|
||||
size_t used;
|
||||
size_t size;
|
||||
struct pcre_keyvalue *kv;
|
||||
uint32_t used;
|
||||
uint16_t x0;
|
||||
uint16_t x1;
|
||||
} pcre_keyvalue_buffer;
|
||||
|
||||
__attribute_cold__
|
||||
pcre_keyvalue_buffer *pcre_keyvalue_buffer_init(void);
|
||||
int pcre_keyvalue_buffer_append(struct server *srv, pcre_keyvalue_buffer *kvb, buffer *key, buffer *value);
|
||||
|
||||
__attribute_cold__
|
||||
int pcre_keyvalue_buffer_append(log_error_st *errh, pcre_keyvalue_buffer *kvb, const buffer *key, const buffer *value);
|
||||
|
||||
__attribute_cold__
|
||||
void pcre_keyvalue_buffer_free(pcre_keyvalue_buffer *kvb);
|
||||
handler_t pcre_keyvalue_buffer_process(pcre_keyvalue_buffer *kvb, pcre_keyvalue_ctx *ctx, buffer *input, buffer *result);
|
||||
|
||||
handler_t pcre_keyvalue_buffer_process(const pcre_keyvalue_buffer *kvb, pcre_keyvalue_ctx *ctx, const buffer *input, buffer *result);
|
||||
|
||||
__attribute_cold__
|
||||
void pcre_keyvalue_burl_normalize_key(buffer *k, buffer *t);
|
||||
|
||||
__attribute_cold__
|
||||
void pcre_keyvalue_burl_normalize_value(buffer *v, buffer *t);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -8,32 +8,36 @@
|
|||
|
||||
#include "keyvalue.c"
|
||||
|
||||
#include "base.h" /* struct server, struct cond_cache_t */
|
||||
|
||||
#ifdef HAVE_PCRE_H
|
||||
static pcre_keyvalue_buffer * test_keyvalue_test_kvb_init (void) {
|
||||
pcre_keyvalue_buffer *kvb = pcre_keyvalue_buffer_init();
|
||||
buffer *k = buffer_init();
|
||||
buffer *v = buffer_init();
|
||||
server srv;
|
||||
|
||||
static server srv;
|
||||
memset(&srv, 0, sizeof(srv));
|
||||
srv.errh = log_error_st_init(&srv.cur_ts, &srv.last_generated_debug_ts);
|
||||
|
||||
buffer_copy_string_len(k, CONST_STR_LEN("^/foo($|\\?.+)"));
|
||||
buffer_copy_string_len(v, CONST_STR_LEN("/foo/$1"));
|
||||
assert(0 == pcre_keyvalue_buffer_append(&srv, kvb, k, v));
|
||||
buffer_copy_string_len(k, CONST_STR_LEN("^/bar(?:$|\\?(.+))"));
|
||||
buffer_copy_string_len(v, CONST_STR_LEN("/?bar&$1"));
|
||||
assert(0 == pcre_keyvalue_buffer_append(&srv, kvb, k, v));
|
||||
buffer_copy_string_len(k, CONST_STR_LEN("^/redirect(?:\\?(.*))?$"));
|
||||
buffer_copy_string_len(v, CONST_STR_LEN("/?seg=%1&$1"));
|
||||
assert(0 == pcre_keyvalue_buffer_append(&srv, kvb, k, v));
|
||||
buffer_copy_string_len(k, CONST_STR_LEN("^(/[^?]*)(?:\\?(.*))?$"));
|
||||
buffer_copy_string_len(v, CONST_STR_LEN("/?file=$1&$2"));
|
||||
assert(0 == pcre_keyvalue_buffer_append(&srv, kvb, k, v));
|
||||
log_error_st * const errh =
|
||||
log_error_st_init(&srv.cur_ts, &srv.last_generated_debug_ts);
|
||||
|
||||
buffer_free(k);
|
||||
buffer_free(v);
|
||||
log_error_st_free(srv.errh);
|
||||
/* strings must be persistent for pcre_keyvalue_buffer_append() */
|
||||
static const buffer kvstr[] = {
|
||||
{ "^/foo($|\\?.+)", sizeof("^/foo($|\\?.+)"), 0 },
|
||||
{ "/foo/$1", sizeof("/foo/$1"), 0 },
|
||||
{ "^/bar(?:$|\\?(.+))", sizeof("^/bar(?:$|\\?(.+))"), 0 },
|
||||
{ "/?bar&$1", sizeof("/?bar&$1"), 0 },
|
||||
{ "^/redirect(?:\\?(.*))?$", sizeof("^/redirect(?:\\?(.*))?$"), 0 },
|
||||
{ "/?seg=%1&$1", sizeof("/?seg=%1&$1"), 0 },
|
||||
{ "^(/[^?]*)(?:\\?(.*))?$", sizeof("^(/[^?]*)(?:\\?(.*))?$"), 0 },
|
||||
{ "/?file=$1&$2", sizeof("/?file=$1&$2"), 0 }
|
||||
};
|
||||
|
||||
assert(pcre_keyvalue_buffer_append(errh, kvb, kvstr+0, kvstr+1));
|
||||
assert(pcre_keyvalue_buffer_append(errh, kvb, kvstr+2, kvstr+3));
|
||||
assert(pcre_keyvalue_buffer_append(errh, kvb, kvstr+4, kvstr+5));
|
||||
assert(pcre_keyvalue_buffer_append(errh, kvb, kvstr+6, kvstr+7));
|
||||
|
||||
log_error_st_free(errh);
|
||||
|
||||
return kvb;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue