summaryrefslogtreecommitdiffhomepage
path: root/src/nxt_pcre.c
diff options
context:
space:
mode:
authorAxel Duch <axel.duch@nginx.com>2020-11-17 15:03:30 +0000
committerAxel Duch <axel.duch@nginx.com>2020-11-17 15:03:30 +0000
commite3af18834d7cc32734cba7532d8864bb343b416b (patch)
tree578c68e31396926abff818cdaf6cb83116157511 /src/nxt_pcre.c
parent2a381a82a6e1bc2bd5d2f43a08fce50a1994f2e8 (diff)
downloadunit-e3af18834d7cc32734cba7532d8864bb343b416b.tar.gz
unit-e3af18834d7cc32734cba7532d8864bb343b416b.tar.bz2
Router: matching regular expressions support.
Diffstat (limited to 'src/nxt_pcre.c')
-rw-r--r--src/nxt_pcre.c135
1 files changed, 135 insertions, 0 deletions
diff --git a/src/nxt_pcre.c b/src/nxt_pcre.c
new file mode 100644
index 00000000..737fc7cf
--- /dev/null
+++ b/src/nxt_pcre.c
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) Axel Duch
+ * Copyright (C) NGINX, Inc.
+ */
+
+#include <nxt_main.h>
+#include <nxt_regex.h>
+#include <pcre.h>
+
+
+struct nxt_regex_s {
+ pcre *code;
+ pcre_extra *extra;
+ nxt_str_t pattern;
+};
+
+struct nxt_regex_match_s {
+ int ovecsize;
+ int ovec[];
+};
+
+
+static void *nxt_pcre_malloc(size_t size);
+static void nxt_pcre_free(void *p);
+
+static nxt_mp_t *nxt_pcre_mp;
+
+
+nxt_regex_t *
+nxt_regex_compile(nxt_mp_t *mp, nxt_str_t *source, nxt_regex_err_t *err)
+{
+ int erroffset;
+ char *pattern;
+ void *saved_malloc, *saved_free;
+ nxt_regex_t *re;
+
+ err->offset = source->length;
+
+ re = nxt_mp_get(mp, sizeof(nxt_regex_t) + source->length + 1);
+ if (nxt_slow_path(re == NULL)) {
+ err->msg = "memory allocation failed";
+ return NULL;
+ }
+
+ pattern = nxt_pointer_to(re, sizeof(nxt_regex_t));
+
+ nxt_memcpy(pattern, source->start, source->length);
+ pattern[source->length] = '\0';
+
+ re->pattern.length = source->length;
+ re->pattern.start = (u_char *) pattern;
+
+ saved_malloc = pcre_malloc;
+ saved_free = pcre_free;
+
+ pcre_malloc = nxt_pcre_malloc;
+ pcre_free = nxt_pcre_free;
+ nxt_pcre_mp = mp;
+
+ re->code = pcre_compile(pattern, 0, &err->msg, &erroffset, NULL);
+ if (nxt_fast_path(re->code != NULL)) {
+#if 0
+ re->extra = pcre_study(re->code, PCRE_STUDY_JIT_COMPILE, &err->msg);
+ if (nxt_slow_path(re->extra == NULL && err->msg != NULL)) {
+ nxt_log_warn(thr->log, "pcre_study(%V) failed: %s", source, err->msg);
+ }
+#else
+ re->extra = NULL;
+#endif
+
+ } else {
+ err->offset = erroffset;
+ re = NULL;
+ }
+
+ pcre_malloc = saved_malloc;
+ pcre_free = saved_free;
+
+ return re;
+}
+
+
+static void*
+nxt_pcre_malloc(size_t size)
+{
+ if (nxt_slow_path(nxt_pcre_mp == NULL)) {
+ nxt_thread_log_alert("pcre_malloc(%uz) called without memory pool",
+ size);
+ return NULL;
+ }
+
+ nxt_thread_log_debug("pcre_malloc(%uz), pool %p", size, nxt_pcre_mp);
+
+ return nxt_mp_get(nxt_pcre_mp, size);
+}
+
+
+static void
+nxt_pcre_free(void *p)
+{
+}
+
+
+nxt_regex_match_t *
+nxt_regex_match_create(nxt_mp_t *mp, size_t size)
+{
+ nxt_regex_match_t *match;
+
+ match = nxt_mp_get(mp, sizeof(nxt_regex_match_t) + sizeof(int) * size);
+ if (nxt_fast_path(match != NULL)) {
+ match->ovecsize = size;
+ }
+
+ return match;
+}
+
+
+nxt_int_t
+nxt_regex_match(nxt_regex_t *re, u_char *subject, size_t length,
+ nxt_regex_match_t *match)
+{
+ int ret;
+
+ ret = pcre_exec(re->code, re->extra, (const char *) subject, length, 0, 0,
+ match->ovec, match->ovecsize);
+ if (nxt_slow_path(ret < PCRE_ERROR_NOMATCH)) {
+ nxt_thread_log_error(NXT_LOG_ERR,
+ "pcre_exec() failed: %d on \"%*s\" using \"%V\"",
+ ret, length, subject, &re->pattern);
+
+ return NXT_ERROR;
+ }
+
+ return (ret != PCRE_ERROR_NOMATCH);
+}