summaryrefslogtreecommitdiff
path: root/ngx_stream_lua-0.0.16/src/ngx_stream_lua_regex.c
diff options
context:
space:
mode:
Diffstat (limited to 'ngx_stream_lua-0.0.16/src/ngx_stream_lua_regex.c')
-rw-r--r--ngx_stream_lua-0.0.16/src/ngx_stream_lua_regex.c1007
1 files changed, 1007 insertions, 0 deletions
diff --git a/ngx_stream_lua-0.0.16/src/ngx_stream_lua_regex.c b/ngx_stream_lua-0.0.16/src/ngx_stream_lua_regex.c
new file mode 100644
index 0000000..080e5dd
--- /dev/null
+++ b/ngx_stream_lua-0.0.16/src/ngx_stream_lua_regex.c
@@ -0,0 +1,1007 @@
+
+/*
+ * !!! DO NOT EDIT DIRECTLY !!!
+ * This file was automatically generated from the following template:
+ *
+ * src/subsys/ngx_subsys_lua_regex.c.tt2
+ */
+
+
+/*
+ * Copyright (C) Yichun Zhang (agentzh)
+ */
+
+
+#ifndef DDEBUG
+#define DDEBUG 0
+#endif
+#include "ddebug.h"
+
+
+#if (NGX_PCRE)
+
+#include "ngx_stream_lua_pcrefix.h"
+#include "ngx_stream_lua_script.h"
+#include "ngx_stream_lua_util.h"
+
+
+#if (PCRE_MAJOR >= 6 || NGX_PCRE2)
+# define LUA_HAVE_PCRE_DFA 1
+#else
+# define LUA_HAVE_PCRE_DFA 0
+#endif
+
+
+#if (NGX_PCRE2)
+static pcre2_compile_context *ngx_regex_compile_context;
+static pcre2_match_context *ngx_regex_match_context;
+static pcre2_match_data *ngx_regex_match_data;
+static ngx_uint_t ngx_regex_match_data_size = 0;
+
+#define PCRE2_VERSION_SIZE 64
+static char ngx_pcre2_version[PCRE2_VERSION_SIZE];
+#endif
+
+
+#define NGX_LUA_RE_MODE_DFA (1<<1)
+#define NGX_LUA_RE_MODE_JIT (1<<2)
+#define NGX_LUA_RE_NO_UTF8_CHECK (1<<4)
+
+#define NGX_LUA_RE_DFA_MODE_WORKSPACE_COUNT (100)
+
+#define NGX_LUA_RE_MIN_JIT_STACK_SIZE 32 * 1024
+
+
+typedef struct {
+ ngx_pool_t *pool;
+ u_char *name_table;
+ int name_count;
+ int name_entry_size;
+
+ int ncaptures;
+ int *captures;
+
+#if (NGX_PCRE2)
+ pcre2_code *regex;
+ /*
+ * pcre2 doesn't use pcre_extra any more,
+ * just for keeping same memory layout in the lua ffi cdef
+ */
+ void *regex_sd;
+#else
+ pcre *regex;
+ pcre_extra *regex_sd;
+#endif
+
+ ngx_stream_lua_complex_value_t *replace;
+
+ /* only for (stap) debugging, and may be an invalid pointer */
+ const u_char *pattern;
+} ngx_stream_lua_regex_t;
+
+
+typedef struct {
+ ngx_str_t pattern;
+ ngx_pool_t *pool;
+ ngx_int_t options;
+
+#if (NGX_PCRE2)
+ pcre2_code *regex;
+#else
+ pcre *regex;
+#endif
+ int captures;
+ ngx_str_t err;
+} ngx_stream_lua_regex_compile_t;
+
+
+typedef struct {
+ ngx_stream_lua_request_t *request;
+
+#if (NGX_PCRE2)
+ pcre2_code *regex;
+#else
+ pcre *regex;
+ pcre_extra *regex_sd;
+#endif
+ int ncaptures;
+ int *captures;
+ int captures_len;
+ uint8_t flags;
+} ngx_stream_lua_regex_ctx_t;
+
+
+static ngx_int_t ngx_stream_lua_regex_compile(
+ ngx_stream_lua_regex_compile_t *rc);
+
+
+#define ngx_stream_lua_regex_exec(re, e, s, start, captures, size, \
+ opts) \
+ pcre_exec(re, e, (const char *) (s)->data, (s)->len, start, opts, \
+ captures, size)
+
+
+#define ngx_stream_lua_regex_dfa_exec(re, e, s, start, captures, size, \
+ ws, wscount, opts) \
+ pcre_dfa_exec(re, e, (const char *) (s)->data, (s)->len, start, opts, \
+ captures, size, ws, wscount)
+
+
+static void
+ngx_stream_lua_regex_free_study_data(ngx_pool_t *pool,
+ ngx_stream_lua_regex_t *re)
+{
+ ngx_pool_t *old_pool;
+
+#if (NGX_PCRE2)
+ if (re && re->regex) {
+ old_pool = ngx_stream_lua_pcre_malloc_init(pool);
+
+ pcre2_code_free(re->regex);
+
+ ngx_stream_lua_pcre_malloc_done(old_pool);
+
+ re->regex = NULL;
+ }
+#else
+ if (re && re->regex_sd) {
+ old_pool = ngx_stream_lua_pcre_malloc_init(pool);
+#if LUA_HAVE_PCRE_JIT
+ pcre_free_study(re->regex_sd);
+#else
+ pcre_free(re->regex_sd);
+#endif
+ ngx_stream_lua_pcre_malloc_done(old_pool);
+
+ re->regex_sd = NULL;
+ }
+#endif
+}
+
+
+#if (NGX_PCRE2)
+static ngx_int_t
+ngx_stream_lua_regex_compile(ngx_stream_lua_regex_compile_t *rc)
+{
+ int n, errcode;
+ char *p;
+ size_t erroff;
+ u_char errstr[128];
+ pcre2_code *re;
+ ngx_pool_t *old_pool;
+ pcre2_general_context *gctx;
+ pcre2_compile_context *cctx;
+
+ ngx_stream_lua_main_conf_t *lmcf;
+
+ if (ngx_regex_compile_context == NULL) {
+ /*
+ * Allocate a compile context if not yet allocated. This uses
+ * direct allocations from heap, so the result can be cached
+ * even at runtime.
+ */
+
+ old_pool = ngx_stream_lua_pcre_malloc_init(NULL);
+
+ gctx = pcre2_general_context_create(ngx_stream_lua_pcre_malloc,
+ ngx_stream_lua_pcre_free,
+ NULL);
+ if (gctx == NULL) {
+ ngx_stream_lua_pcre_malloc_done(old_pool);
+ goto nomem;
+ }
+
+ cctx = pcre2_compile_context_create(gctx);
+ if (cctx == NULL) {
+ pcre2_general_context_free(gctx);
+ ngx_stream_lua_pcre_malloc_done(old_pool);
+ goto nomem;
+ }
+
+ ngx_regex_compile_context = cctx;
+
+ ngx_regex_match_context = pcre2_match_context_create(gctx);
+ if (ngx_regex_match_context == NULL) {
+ pcre2_general_context_free(gctx);
+ ngx_stream_lua_pcre_malloc_done(old_pool);
+ goto nomem;
+ }
+
+ lmcf = ngx_stream_cycle_get_module_main_conf(ngx_cycle,
+ ngx_stream_lua_module);
+ if (lmcf && lmcf->regex_match_limit > 0) {
+ pcre2_set_match_limit(ngx_regex_match_context,
+ lmcf->regex_match_limit);
+ }
+
+ pcre2_general_context_free(gctx);
+ ngx_stream_lua_pcre_malloc_done(old_pool);
+ }
+
+ old_pool = ngx_stream_lua_pcre_malloc_init(rc->pool);
+
+ re = pcre2_compile(rc->pattern.data,
+ rc->pattern.len, rc->options,
+ &errcode, &erroff, ngx_regex_compile_context);
+
+ ngx_stream_lua_pcre_malloc_done(old_pool);
+
+ if (re == NULL) {
+ pcre2_get_error_message(errcode, errstr, 128);
+
+ if ((size_t) erroff == rc->pattern.len) {
+ rc->err.len = ngx_snprintf(rc->err.data, rc->err.len,
+ "pcre2_compile() failed: %s in \"%V\"",
+ errstr, &rc->pattern)
+ - rc->err.data;
+
+ } else {
+ rc->err.len = ngx_snprintf(rc->err.data, rc->err.len,
+ "pcre2_compile() failed: %s in "
+ "\"%V\" at \"%s\"", errstr, &rc->pattern,
+ rc->pattern.data + erroff)
+ - rc->err.data;
+ }
+
+ return NGX_ERROR;
+ }
+
+ rc->regex = re;
+
+ n = pcre2_pattern_info(re, PCRE2_INFO_CAPTURECOUNT, &rc->captures);
+ if (n < 0) {
+ p = "pcre2_pattern_info(\"%V\", PCRE_INFO_CAPTURECOUNT) failed: %d";
+ goto failed;
+ }
+
+#if (NGX_DEBUG)
+ ngx_log_debug3(NGX_LOG_DEBUG_STREAM, ngx_cycle->log, 0,
+ "pcre2_compile: pattern[%V], options 0x%08Xd, ncaptures %d",
+ &rc->pattern, rc->options, rc->captures);
+#endif
+
+ return NGX_OK;
+
+failed:
+
+ rc->err.len = ngx_snprintf(rc->err.data, rc->err.len, p, &rc->pattern, n)
+ - rc->err.data;
+ return NGX_ERROR;
+
+nomem:
+
+ rc->err.len = ngx_snprintf(rc->err.data, rc->err.len,
+ "regex \"%V\" compilation failed: no memory",
+ &rc->pattern)
+ - rc->err.data;
+ return NGX_ERROR;
+}
+
+#else
+
+static ngx_int_t
+ngx_stream_lua_regex_compile(ngx_stream_lua_regex_compile_t *rc)
+{
+ int n, erroff;
+ char *p;
+ const char *errstr;
+ pcre *re;
+ ngx_pool_t *old_pool;
+
+ old_pool = ngx_stream_lua_pcre_malloc_init(rc->pool);
+
+ re = pcre_compile((const char *) rc->pattern.data, (int) rc->options,
+ &errstr, &erroff, NULL);
+
+ ngx_stream_lua_pcre_malloc_done(old_pool);
+
+ if (re == NULL) {
+ if ((size_t) erroff == rc->pattern.len) {
+ rc->err.len = ngx_snprintf(rc->err.data, rc->err.len,
+ "pcre_compile() failed: %s in \"%V\"",
+ errstr, &rc->pattern)
+ - rc->err.data;
+
+ } else {
+ rc->err.len = ngx_snprintf(rc->err.data, rc->err.len,
+ "pcre_compile() failed: %s in \"%V\" "
+ "at \"%s\"", errstr, &rc->pattern,
+ rc->pattern.data + erroff)
+ - rc->err.data;
+ }
+
+ return NGX_ERROR;
+ }
+
+ rc->regex = re;
+
+#if 1
+ n = pcre_fullinfo(re, NULL, PCRE_INFO_CAPTURECOUNT, &rc->captures);
+ if (n < 0) {
+ p = "pcre_fullinfo(\"%V\", PCRE_INFO_CAPTURECOUNT) failed: %d";
+ goto failed;
+ }
+#endif
+
+ return NGX_OK;
+
+failed:
+
+ rc->err.len = ngx_snprintf(rc->err.data, rc->err.len, p, &rc->pattern, n)
+ - rc->err.data;
+ return NGX_OK;
+}
+#endif
+
+
+ngx_int_t
+ngx_stream_lua_ffi_set_jit_stack_size(int size, u_char *errstr,
+ size_t *errstr_size)
+{
+#if (LUA_HAVE_PCRE_JIT)
+
+ ngx_stream_lua_main_conf_t *lmcf;
+ ngx_pool_t *pool, *old_pool;
+
+ lmcf = ngx_stream_cycle_get_module_main_conf(ngx_cycle,
+ ngx_stream_lua_module);
+
+ if (size < NGX_LUA_RE_MIN_JIT_STACK_SIZE) {
+ size = NGX_LUA_RE_MIN_JIT_STACK_SIZE;
+ }
+
+ pool = lmcf->pool;
+
+ dd("server pool %p", lmcf->pool);
+
+ if (lmcf->jit_stack) {
+ old_pool = ngx_stream_lua_pcre_malloc_init(pool);
+
+#if (NGX_PCRE2)
+ pcre2_jit_stack_free(lmcf->jit_stack);
+#else
+ pcre_jit_stack_free(lmcf->jit_stack);
+#endif
+
+ ngx_stream_lua_pcre_malloc_done(old_pool);
+ }
+
+ old_pool = ngx_stream_lua_pcre_malloc_init(pool);
+
+#if (NGX_PCRE2)
+ lmcf->jit_stack = pcre2_jit_stack_create(NGX_LUA_RE_MIN_JIT_STACK_SIZE,
+ size, NULL);
+#else
+ lmcf->jit_stack = pcre_jit_stack_alloc(NGX_LUA_RE_MIN_JIT_STACK_SIZE,
+ size);
+#endif
+
+ ngx_stream_lua_pcre_malloc_done(old_pool);
+
+ if (lmcf->jit_stack == NULL) {
+ *errstr_size = ngx_snprintf(errstr, *errstr_size,
+ "pcre jit stack allocation failed")
+ - errstr;
+ return NGX_ERROR;
+ }
+
+ return NGX_OK;
+
+#else /* LUA_HAVE_PCRE_JIT */
+
+ *errstr_size = ngx_snprintf(errstr, *errstr_size,
+ "no pcre jit support found") - errstr;
+ return NGX_ERROR;
+
+#endif
+}
+
+
+#if (NGX_PCRE2)
+static void
+ngx_stream_lua_regex_jit_compile(ngx_stream_lua_regex_t *re, int flags,
+ ngx_pool_t *pool, ngx_stream_lua_main_conf_t *lmcf,
+ ngx_stream_lua_regex_compile_t *re_comp)
+{
+ ngx_int_t ret;
+ ngx_pool_t *old_pool;
+
+ if (flags & NGX_LUA_RE_MODE_JIT) {
+ old_pool = ngx_stream_lua_pcre_malloc_init(pool);
+ ret = pcre2_jit_compile(re_comp->regex, PCRE2_JIT_COMPLETE);
+
+ if (ret != 0) {
+ ngx_log_error(NGX_LOG_INFO, ngx_cycle->log, 0,
+ "pcre2_jit_compile() failed: %d in \"%V\", "
+ "ignored",
+ ret, &re_comp->pattern);
+
+#if (NGX_DEBUG)
+
+ } else {
+ ngx_log_debug0(NGX_LOG_DEBUG_STREAM, ngx_cycle->log, 0,
+ "pcre2 JIT compiled successfully");
+# endif /* !(NGX_DEBUG) */
+ }
+
+ ngx_stream_lua_pcre_malloc_done(old_pool);
+
+ }
+
+ if (lmcf && lmcf->jit_stack) {
+ pcre2_jit_stack_assign(ngx_regex_match_context, NULL,
+ lmcf->jit_stack);
+ }
+
+ return;
+}
+
+#else
+
+static void
+ngx_stream_lua_regex_jit_compile(ngx_stream_lua_regex_t *re, int flags,
+ ngx_pool_t *pool, ngx_stream_lua_main_conf_t *lmcf,
+ ngx_stream_lua_regex_compile_t *re_comp)
+{
+ const char *msg;
+ pcre_extra *sd = NULL;
+ ngx_pool_t *old_pool;
+
+
+#if (LUA_HAVE_PCRE_JIT)
+ if (flags & NGX_LUA_RE_MODE_JIT) {
+ old_pool = ngx_stream_lua_pcre_malloc_init(pool);
+ sd = pcre_study(re_comp->regex, PCRE_STUDY_JIT_COMPILE, &msg);
+ ngx_stream_lua_pcre_malloc_done(old_pool);
+
+# if (NGX_DEBUG)
+ if (msg != NULL) {
+ ngx_log_debug2(NGX_LOG_DEBUG_STREAM, ngx_cycle->log, 0,
+ "pcre study failed with PCRE_STUDY_JIT_COMPILE: "
+ "%s (%p)", msg, sd);
+ }
+
+ if (sd != NULL) {
+ int jitted;
+
+ old_pool = ngx_stream_lua_pcre_malloc_init(pool);
+
+ pcre_fullinfo(re_comp->regex, sd, PCRE_INFO_JIT, &jitted);
+
+ ngx_stream_lua_pcre_malloc_done(old_pool);
+
+ ngx_log_debug1(NGX_LOG_DEBUG_STREAM, ngx_cycle->log, 0,
+ "pcre JIT compiling result: %d", jitted);
+ }
+# endif /* !(NGX_DEBUG) */
+
+ } else {
+ old_pool = ngx_stream_lua_pcre_malloc_init(pool);
+ sd = pcre_study(re_comp->regex, 0, &msg);
+ ngx_stream_lua_pcre_malloc_done(old_pool);
+ }
+
+ if (sd && lmcf && lmcf->jit_stack) {
+ pcre_assign_jit_stack(sd, NULL, lmcf->jit_stack);
+ }
+
+ if (sd
+ && lmcf && lmcf->regex_match_limit > 0
+ && !(flags & NGX_LUA_RE_MODE_DFA))
+ {
+ sd->flags |= PCRE_EXTRA_MATCH_LIMIT;
+ sd->match_limit = lmcf->regex_match_limit;
+ }
+
+#endif /* LUA_HAVE_PCRE_JIT */
+
+ re->regex_sd = sd;
+}
+#endif
+
+
+#if (NGX_PCRE2)
+void
+ngx_stream_lua_regex_cleanup(void *data)
+{
+ ngx_pool_t *old_pool;
+ ngx_stream_lua_main_conf_t *lmcf;
+
+ lmcf = data;
+
+ if (ngx_regex_compile_context) {
+ old_pool = ngx_stream_lua_pcre_malloc_init(NULL);
+ pcre2_compile_context_free(ngx_regex_compile_context);
+ ngx_regex_compile_context = NULL;
+ ngx_stream_lua_pcre_malloc_done(old_pool);
+ }
+
+ if (lmcf && lmcf->jit_stack) {
+ old_pool = ngx_stream_lua_pcre_malloc_init(NULL);
+
+ pcre2_jit_stack_free(lmcf->jit_stack);
+ lmcf->jit_stack = NULL;
+
+ ngx_stream_lua_pcre_malloc_done(old_pool);
+ }
+
+ if (ngx_regex_match_data) {
+ old_pool = ngx_stream_lua_pcre_malloc_init(NULL);
+ pcre2_match_data_free(ngx_regex_match_data);
+ ngx_regex_match_data = NULL;
+ ngx_regex_match_data_size = 0;
+ ngx_stream_lua_pcre_malloc_done(old_pool);
+ }
+
+}
+#endif
+
+
+ngx_stream_lua_regex_t *
+ngx_stream_lua_ffi_compile_regex(const unsigned char *pat, size_t pat_len,
+ int flags, int pcre_opts, u_char *errstr,
+ size_t errstr_size)
+{
+ int *cap = NULL, ovecsize;
+ u_char *p;
+ ngx_int_t rc;
+ const char *msg;
+ ngx_pool_t *pool, *old_pool;
+ ngx_stream_lua_regex_t *re = NULL;
+ ngx_stream_lua_main_conf_t *lmcf;
+ ngx_stream_lua_regex_compile_t re_comp;
+
+ pool = ngx_create_pool(512, ngx_cycle->log);
+ if (pool == NULL) {
+ msg = "no memory";
+ goto error;
+ }
+
+ pool->log = (ngx_log_t *) &ngx_cycle->new_log;
+
+ re = ngx_palloc(pool, sizeof(ngx_stream_lua_regex_t));
+ if (re == NULL) {
+ ngx_destroy_pool(pool);
+ pool = NULL;
+ msg = "no memory";
+ goto error;
+ }
+
+ re->pool = pool;
+ re->regex = NULL;
+ re->regex_sd = NULL;
+
+ re_comp.options = pcre_opts;
+ re_comp.pattern.data = (u_char *) pat;
+ re_comp.pattern.len = pat_len;
+ re_comp.err.len = errstr_size - 1;
+ re_comp.err.data = errstr;
+ re_comp.pool = pool;
+
+ old_pool = ngx_stream_lua_pcre_malloc_init(pool);
+ rc = ngx_stream_lua_regex_compile(&re_comp);
+ ngx_stream_lua_pcre_malloc_done(old_pool);
+
+ if (rc != NGX_OK) {
+ re_comp.err.data[re_comp.err.len] = '\0';
+ msg = (char *) re_comp.err.data;
+ goto error;
+ }
+
+ lmcf = ngx_stream_cycle_get_module_main_conf(ngx_cycle,
+ ngx_stream_lua_module);
+
+ ngx_stream_lua_regex_jit_compile(re, flags, pool, lmcf, &re_comp);
+
+ if (flags & NGX_LUA_RE_MODE_DFA) {
+ ovecsize = 2;
+ re_comp.captures = 0;
+
+ } else {
+#if (NGX_PCRE2)
+ ovecsize = (re_comp.captures + 1) * 2;
+#else
+ ovecsize = (re_comp.captures + 1) * 3;
+#endif
+ }
+
+ dd("allocating cap with size: %d", (int) ovecsize);
+
+ cap = ngx_palloc(pool, ovecsize * sizeof(int));
+ if (cap == NULL) {
+ msg = "no memory";
+ goto error;
+ }
+
+#if (NGX_PCRE2)
+ if (pcre2_pattern_info(re_comp.regex, PCRE2_INFO_NAMECOUNT,
+ &re->name_count) < 0)
+ {
+ msg = "cannot acquire named subpattern count";
+ goto error;
+ }
+
+ if (re->name_count > 0) {
+ if (pcre2_pattern_info(re_comp.regex, PCRE2_INFO_NAMEENTRYSIZE,
+ &re->name_entry_size) != 0)
+ {
+ msg = "cannot acquire named subpattern entry size";
+ goto error;
+ }
+
+ if (pcre2_pattern_info(re_comp.regex, PCRE2_INFO_NAMETABLE,
+ &re->name_table) != 0)
+ {
+ msg = "cannot acquire named subpattern table";
+ goto error;
+ }
+ }
+
+#else
+ if (pcre_fullinfo(re_comp.regex, NULL, PCRE_INFO_NAMECOUNT,
+ &re->name_count) != 0)
+ {
+ msg = "cannot acquire named subpattern count";
+ goto error;
+ }
+
+ if (re->name_count > 0) {
+ if (pcre_fullinfo(re_comp.regex, NULL, PCRE_INFO_NAMEENTRYSIZE,
+ &re->name_entry_size) != 0)
+ {
+ msg = "cannot acquire named subpattern entry size";
+ goto error;
+ }
+
+ if (pcre_fullinfo(re_comp.regex, NULL, PCRE_INFO_NAMETABLE,
+ &re->name_table) != 0)
+ {
+ msg = "cannot acquire named subpattern table";
+ goto error;
+ }
+ }
+#endif
+
+ re->regex = re_comp.regex;
+ re->ncaptures = re_comp.captures;
+ re->captures = cap;
+ re->replace = NULL;
+
+ /* only for (stap) debugging, the pointer might be invalid when the
+ * string is collected later on.... */
+ re->pattern = pat;
+
+ return re;
+
+error:
+
+ p = ngx_snprintf(errstr, errstr_size - 1, "%s", msg);
+ *p = '\0';
+
+ ngx_stream_lua_regex_free_study_data(pool, re);
+
+ if (pool) {
+ ngx_destroy_pool(pool);
+ }
+
+ return NULL;
+}
+
+
+#if (NGX_PCRE2)
+int
+ngx_stream_lua_ffi_exec_regex(ngx_stream_lua_regex_t *re, int flags,
+ const u_char *s, size_t len, int pos)
+{
+ int rc, exec_opts = 0;
+ size_t *ov;
+ ngx_uint_t ovecpair, n, i;
+ ngx_pool_t *old_pool;
+
+ if (flags & NGX_LUA_RE_MODE_DFA) {
+ ovecpair = 1;
+ re->ncaptures = 0;
+
+ } else {
+ ovecpair = re->ncaptures + 1;
+ }
+
+ old_pool = ngx_stream_lua_pcre_malloc_init(NULL);
+
+ if (ngx_regex_match_data == NULL
+ || ovecpair > ngx_regex_match_data_size)
+ {
+ /*
+ * Allocate a match data if not yet allocated or smaller than
+ * needed.
+ */
+
+ if (ngx_regex_match_data) {
+ pcre2_match_data_free(ngx_regex_match_data);
+ }
+
+ ngx_regex_match_data_size = ovecpair;
+ ngx_regex_match_data = pcre2_match_data_create(ovecpair, NULL);
+
+ if (ngx_regex_match_data == NULL) {
+ rc = PCRE2_ERROR_NOMEMORY;
+ goto failed;
+ }
+ }
+
+ if (flags & NGX_LUA_RE_NO_UTF8_CHECK) {
+ exec_opts = PCRE2_NO_UTF_CHECK;
+
+ } else {
+ exec_opts = 0;
+ }
+
+ if (flags & NGX_LUA_RE_MODE_DFA) {
+ int ws[NGX_LUA_RE_DFA_MODE_WORKSPACE_COUNT];
+ rc = pcre2_dfa_match(re->regex, s, len, pos, exec_opts,
+ ngx_regex_match_data, ngx_regex_match_context,
+ ws, sizeof(ws) / sizeof(ws[0]));
+
+ } else {
+ rc = pcre2_match(re->regex, s, len, pos, exec_opts,
+ ngx_regex_match_data, ngx_regex_match_context);
+ }
+
+ if (rc < 0) {
+#if (NGX_DEBUG)
+ ngx_log_debug4(NGX_LOG_DEBUG_STREAM, ngx_cycle->log, 0,
+ "pcre2_match failed: flags 0x%05Xd, options 0x%08Xd, rc %d, "
+ "ovecpair %ui", flags, exec_opts, rc, ovecpair);
+#endif
+
+ goto failed;
+ }
+
+ n = pcre2_get_ovector_count(ngx_regex_match_data);
+ ov = pcre2_get_ovector_pointer(ngx_regex_match_data);
+
+#if (NGX_DEBUG)
+ ngx_log_debug5(NGX_LOG_DEBUG_STREAM, ngx_cycle->log, 0,
+ "pcre2_match: flags 0x%05Xd, options 0x%08Xd, rc %d, "
+ "n %ui, ovecpair %ui", flags, exec_opts, rc, n, ovecpair);
+#endif
+
+ if (n > ovecpair) {
+ n = ovecpair;
+ }
+
+ for (i = 0; i < n; i++) {
+ re->captures[i * 2] = ov[i * 2];
+ re->captures[i * 2 + 1] = ov[i * 2 + 1];
+ }
+
+failed:
+
+ ngx_stream_lua_pcre_malloc_done(old_pool);
+
+ return rc;
+}
+
+#else
+
+int
+ngx_stream_lua_ffi_exec_regex(ngx_stream_lua_regex_t *re, int flags,
+ const u_char *s, size_t len, int pos)
+{
+ int rc, ovecsize, exec_opts, *cap;
+ ngx_str_t subj;
+ pcre_extra *sd;
+
+ cap = re->captures;
+ sd = re->regex_sd;
+
+ if (flags & NGX_LUA_RE_MODE_DFA) {
+ ovecsize = 2;
+ re->ncaptures = 0;
+
+ } else {
+ /* How pcre_exec() returns captured substrings
+ * The first two-thirds of the vector is used to pass back captured
+ * substrings, each substring using a pair of integers. The remaining
+ * third of the vector is used as workspace by pcre_exec() while
+ * matching capturing subpatterns, and is not available for passing
+ * back information. The number passed in ovecsize should always be a
+ * multiple of three. If it is not, it is rounded down.
+ *
+ * When a match is successful, information about captured substrings is
+ * returned in pairs of integers, starting at the beginning of ovector,
+ * and continuing up to two-thirds of its length at the most. The first
+ * element of each pair is set to the byte offset of the first character
+ * in a substring, and the second is set to the byte offset of the first
+ * character after the end of a substring.
+ */
+ ovecsize = (re->ncaptures + 1) * 3;
+ }
+
+ if (flags & NGX_LUA_RE_NO_UTF8_CHECK) {
+ exec_opts = PCRE_NO_UTF8_CHECK;
+
+ } else {
+ exec_opts = 0;
+ }
+
+ subj.data = (u_char *) s;
+ subj.len = len;
+
+ if (flags & NGX_LUA_RE_MODE_DFA) {
+
+#if LUA_HAVE_PCRE_DFA
+
+ int ws[NGX_LUA_RE_DFA_MODE_WORKSPACE_COUNT];
+ rc = ngx_stream_lua_regex_dfa_exec(re->regex, sd, &subj,
+ (int) pos, cap, ovecsize, ws,
+ sizeof(ws) / sizeof(ws[0]), exec_opts);
+
+#else
+
+ return PCRE_ERROR_BADOPTION;
+
+#endif /* LUA_HAVE_PCRE_DFA */
+
+ } else {
+ rc = ngx_stream_lua_regex_exec(re->regex, sd, &subj, (int) pos, cap,
+ ovecsize, exec_opts);
+ }
+
+ return rc;
+}
+
+#endif
+
+
+void
+ngx_stream_lua_ffi_destroy_regex(ngx_stream_lua_regex_t *re)
+{
+ dd("destroy regex called");
+
+ if (re == NULL || re->pool == NULL) {
+ return;
+ }
+
+ ngx_stream_lua_regex_free_study_data(re->pool, re);
+
+ ngx_destroy_pool(re->pool);
+}
+
+
+int
+ngx_stream_lua_ffi_compile_replace_template(ngx_stream_lua_regex_t *re,
+ const u_char *replace_data, size_t replace_len)
+{
+ ngx_int_t rc;
+ ngx_str_t tpl;
+
+ ngx_stream_lua_complex_value_t *ctpl;
+ ngx_stream_lua_compile_complex_value_t ccv;
+
+ ctpl = ngx_palloc(re->pool, sizeof(ngx_stream_lua_complex_value_t));
+ if (ctpl == NULL) {
+ return NGX_ERROR;
+ }
+
+ if (replace_len != 0) {
+ /* copy the string buffer pointed to by tpl.data from Lua VM */
+ tpl.data = ngx_palloc(re->pool, replace_len + 1);
+ if (tpl.data == NULL) {
+ return NGX_ERROR;
+ }
+
+ ngx_memcpy(tpl.data, replace_data, replace_len);
+ tpl.data[replace_len] = '\0';
+
+ } else {
+ tpl.data = (u_char *) replace_data;
+ }
+
+ tpl.len = replace_len;
+
+ ngx_memzero(&ccv, sizeof(ngx_stream_lua_compile_complex_value_t));
+ ccv.pool = re->pool;
+ ccv.log = ngx_cycle->log;
+ ccv.value = &tpl;
+ ccv.complex_value = ctpl;
+
+ rc = ngx_stream_lua_compile_complex_value(&ccv);
+
+ re->replace = ctpl;
+
+ return rc;
+}
+
+
+ngx_stream_lua_script_engine_t *
+ngx_stream_lua_ffi_create_script_engine(void)
+{
+ return ngx_calloc(sizeof(ngx_stream_lua_script_engine_t), ngx_cycle->log);
+}
+
+
+void
+ngx_stream_lua_ffi_init_script_engine(ngx_stream_lua_script_engine_t *e,
+ const unsigned char *subj, ngx_stream_lua_regex_t *compiled, int count)
+{
+ e->log = ngx_cycle->log;
+ e->ncaptures = count * 2;
+ e->captures = compiled->captures;
+ e->captures_data = (u_char *) subj;
+}
+
+
+void
+ngx_stream_lua_ffi_destroy_script_engine(ngx_stream_lua_script_engine_t *e)
+{
+ ngx_free(e);
+}
+
+
+size_t
+ngx_stream_lua_ffi_script_eval_len(ngx_stream_lua_script_engine_t *e,
+ ngx_stream_lua_complex_value_t *val)
+{
+ size_t len;
+
+ ngx_stream_lua_script_len_code_pt lcode;
+
+ e->ip = val->lengths;
+ len = 0;
+
+ while (*(uintptr_t *) e->ip) {
+ lcode = *(ngx_stream_lua_script_len_code_pt *) e->ip;
+ len += lcode(e);
+ }
+
+ return len;
+}
+
+
+void
+ngx_stream_lua_ffi_script_eval_data(ngx_stream_lua_script_engine_t *e,
+ ngx_stream_lua_complex_value_t *val, u_char *dst)
+{
+ ngx_stream_lua_script_code_pt code;
+
+ e->ip = val->values;
+ e->pos = dst;
+
+ while (*(uintptr_t *) e->ip) {
+ code = *(ngx_stream_lua_script_code_pt *) e->ip;
+ code(e);
+ }
+}
+
+
+uint32_t
+ngx_stream_lua_ffi_max_regex_cache_size(void)
+{
+ ngx_stream_lua_main_conf_t *lmcf;
+ lmcf = ngx_stream_cycle_get_module_main_conf(ngx_cycle,
+ ngx_stream_lua_module);
+ if (lmcf == NULL) {
+ return 0;
+ }
+ return (uint32_t) lmcf->regex_cache_max_entries;
+}
+
+
+const char *
+ngx_stream_lua_ffi_pcre_version(void)
+{
+#if (NGX_PCRE2)
+ pcre2_config(PCRE2_CONFIG_VERSION, ngx_pcre2_version);
+
+ return ngx_pcre2_version;
+#else
+ return pcre_version();
+#endif
+}
+
+
+#endif /* NGX_PCRE */
+
+
+/* vi:set ft=c ts=4 sw=4 et fdm=marker: */