[njs] PCRE code is available via nxt_regex interface.

Igor Sysoev igor at sysoev.ru
Wed Jun 1 12:50:36 UTC 2016


details:   http://hg.nginx.org/njs/rev/b8084a72d667
branches:  
changeset: 112:b8084a72d667
user:      Igor Sysoev <igor at sysoev.ru>
date:      Wed Jun 01 15:30:50 2016 +0300
description:
PCRE code is available via nxt_regex interface.

diffstat:

 nxt/Makefile    |   35 +++++--
 nxt/nxt_pcre.c  |  259 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 nxt/nxt_pcre.h  |   34 +++++++
 nxt/nxt_regex.h |   42 +++++++++
 4 files changed, 359 insertions(+), 11 deletions(-)

diffs (414 lines):

diff -r 1c96b24bcdd2 -r b8084a72d667 nxt/Makefile
--- a/nxt/Makefile	Fri Apr 29 17:02:52 2016 +0300
+++ b/nxt/Makefile	Wed Jun 01 15:30:50 2016 +0300
@@ -10,6 +10,7 @@ NXT_LIB =	nxt
 	$(NXT_BUILDDIR)/nxt_rbtree.o \
 	$(NXT_BUILDDIR)/nxt_lvlhsh.o \
 	$(NXT_BUILDDIR)/nxt_random.o \
+	$(NXT_BUILDDIR)/nxt_pcre.o \
 	$(NXT_BUILDDIR)/nxt_malloc.o \
 	$(NXT_BUILDDIR)/nxt_mem_cache_pool.o \
 
@@ -19,8 +20,9 @@ NXT_LIB =	nxt
 		$(NXT_BUILDDIR)/nxt_array.o \
 		$(NXT_BUILDDIR)/nxt_rbtree.o \
 		$(NXT_BUILDDIR)/nxt_lvlhsh.o \
+		$(NXT_BUILDDIR)/nxt_random.o \
+		$(NXT_BUILDDIR)/nxt_pcre.o \
 		$(NXT_BUILDDIR)/nxt_malloc.o \
-		$(NXT_BUILDDIR)/nxt_random.o \
 		$(NXT_BUILDDIR)/nxt_mem_cache_pool.o \
 
 $(NXT_BUILDDIR)/nxt_murmur_hash.o: \
@@ -95,6 +97,27 @@ NXT_LIB =	nxt
 		-I$(NXT_LIB) \
 		$(NXT_LIB)/nxt_lvlhsh.c
 
+$(NXT_BUILDDIR)/nxt_random.o: \
+	$(NXT_LIB)/nxt_types.h \
+	$(NXT_LIB)/nxt_clang.h \
+	$(NXT_LIB)/nxt_random.h \
+	$(NXT_LIB)/nxt_random.c \
+
+	$(NXT_CC) -c -o $(NXT_BUILDDIR)/nxt_random.o $(NXT_CFLAGS) \
+		-I$(NXT_LIB) \
+		$(NXT_LIB)/nxt_random.c
+
+$(NXT_BUILDDIR)/nxt_pcre.o: \
+	$(NXT_LIB)/nxt_types.h \
+	$(NXT_LIB)/nxt_clang.h \
+	$(NXT_LIB)/nxt_regex.h \
+	$(NXT_LIB)/nxt_pcre.h \
+	$(NXT_LIB)/nxt_pcre.c \
+
+	$(NXT_CC) -c -o $(NXT_BUILDDIR)/nxt_pcre.o $(NXT_CFLAGS) \
+		-I$(NXT_LIB) $(NXT_PCRE_CFLAGS) \
+		$(NXT_LIB)/nxt_pcre.c
+
 $(NXT_BUILDDIR)/nxt_malloc.o: \
 	$(NXT_LIB)/nxt_auto_config.h \
 	$(NXT_LIB)/nxt_types.h \
@@ -106,16 +129,6 @@ NXT_LIB =	nxt
 		-I$(NXT_LIB) \
 		$(NXT_LIB)/nxt_malloc.c
 
-$(NXT_BUILDDIR)/nxt_random.o: \
-	$(NXT_LIB)/nxt_types.h \
-	$(NXT_LIB)/nxt_clang.h \
-	$(NXT_LIB)/nxt_random.h \
-	$(NXT_LIB)/nxt_random.c \
-
-	$(NXT_CC) -c -o $(NXT_BUILDDIR)/nxt_random.o $(NXT_CFLAGS) \
-		-I$(NXT_LIB) \
-		$(NXT_LIB)/nxt_random.c
-
 $(NXT_BUILDDIR)/nxt_mem_cache_pool.o: \
 	$(NXT_LIB)/nxt_types.h \
 	$(NXT_LIB)/nxt_clang.h \
diff -r 1c96b24bcdd2 -r b8084a72d667 nxt/nxt_pcre.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nxt/nxt_pcre.c	Wed Jun 01 15:30:50 2016 +0300
@@ -0,0 +1,259 @@
+
+/*
+ * Copyright (C) Igor Sysoev
+ * Copyright (C) NGINX, Inc.
+ */
+
+#include <nxt_types.h>
+#include <nxt_clang.h>
+#include <nxt_stub.h>
+#include <nxt_regex.h>
+#include <nxt_pcre.h>
+#include <stdio.h>
+#include <string.h>
+
+
+static void *nxt_pcre_malloc(size_t size);
+static void nxt_pcre_free(void *p);
+static void *nxt_pcre_default_malloc(size_t size, void *memory_data);
+static void nxt_pcre_default_free(void *p, void *memory_data);
+
+
+static nxt_regex_context_t  *regex_context;
+
+
+nxt_regex_context_t *
+nxt_regex_context_create(nxt_pcre_malloc_t private_malloc,
+    nxt_pcre_free_t private_free, void *memory_data)
+{
+    nxt_regex_context_t  *ctx;
+
+    if (private_malloc == NULL) {
+        private_malloc = nxt_pcre_default_malloc;
+        private_free = nxt_pcre_default_free;
+    }
+
+    ctx = private_malloc(sizeof(nxt_regex_context_t), memory_data);
+
+    if (nxt_fast_path(ctx != NULL)) {
+        ctx->private_malloc = private_malloc;
+        ctx->private_free = private_free;
+        ctx->memory_data = memory_data;
+    }
+
+    return ctx;
+}
+
+
+nxt_int_t
+nxt_regex_compile(nxt_regex_t *regex, u_char *source, size_t len,
+    nxt_uint_t options, nxt_regex_context_t *ctx)
+{
+    int         ret, err, erroff;
+    char        *pattern, *error;
+    void        *(*saved_malloc)(size_t size);
+    void        (*saved_free)(void *p);
+    size_t      size;
+    const char  *errstr;
+
+    ret = NXT_ERROR;
+
+    saved_malloc = pcre_malloc;
+    pcre_malloc = nxt_pcre_malloc;
+    saved_free = pcre_free;
+    pcre_free = nxt_pcre_free;
+    regex_context = ctx;
+
+    if (len == 0) {
+        pattern = (char *) source;
+
+    } else {
+        pattern = ctx->private_malloc(len + 1, ctx->memory_data);
+        if (nxt_slow_path(pattern == NULL)) {
+            goto done;
+        }
+
+        memcpy(pattern, source, len);
+        pattern[len] = '\0';
+    }
+
+    regex->code = pcre_compile(pattern, options, &errstr, &erroff, NULL);
+
+    if (nxt_slow_path(regex->code == NULL)) {
+        error = pattern + erroff;
+
+        size = sizeof("pcre_compile(\"\") failed:  at \"\"")
+               + strlen(errstr) + strlen(error) * 2 + erroff;
+
+        ctx->error = ctx->private_malloc(size, ctx->memory_data);
+        if (nxt_slow_path(ctx->error == NULL)) {
+            goto done;
+        }
+
+        if (*error != '\0') {
+            (void) snprintf((char *) ctx->error, size,
+                            "pcre_compile(\"%s\") failed: %s at \"%s\"",
+                            pattern, errstr, error);
+        } else {
+            (void) snprintf((char *) ctx->error, size,
+                            "pcre_compile(\"%s\") failed: %s",
+                            pattern, errstr);
+        }
+
+        goto done;
+    }
+
+    regex->extra = pcre_study(regex->code, 0, &errstr);
+
+    if (nxt_slow_path(errstr != NULL)) {
+        size = sizeof("pcre_study(\"\") failed: ")
+               + strlen(pattern) + strlen(errstr);
+
+        ctx->error = ctx->private_malloc(size, ctx->memory_data);
+        if (nxt_slow_path(ctx->error == NULL)) {
+            goto done;
+        }
+
+        (void) snprintf((char *) ctx->error, size,
+                        "pcre_study(\"%s\") failed: %s", pattern, errstr);
+
+        goto done;
+    }
+
+    err = pcre_fullinfo(regex->code, NULL, PCRE_INFO_CAPTURECOUNT,
+                        &regex->ncaptures);
+
+    if (nxt_slow_path(err < 0)) {
+        size = sizeof("pcre_fullinfo(\"\", PCRE_INFO_CAPTURECOUNT) failed: ")
+               + strlen(pattern) + sizeof("-2147483647");
+
+        ctx->error = ctx->private_malloc(size, ctx->memory_data);
+        if (nxt_slow_path(ctx->error == NULL)) {
+            goto done;
+        }
+
+        (void) snprintf((char *) ctx->error, size,
+                    "pcre_fullinfo(\"%s\", PCRE_INFO_CAPTURECOUNT) failed: %d",
+                    pattern, err);
+
+        goto done;
+    }
+
+    /* Reserve additional elements for the first "$0" capture. */
+    regex->ncaptures++;
+
+    ret = NXT_OK;
+
+done:
+
+    pcre_malloc = saved_malloc;
+    pcre_free = saved_free;
+    regex_context = NULL;
+
+    return ret;
+}
+
+
+nxt_regex_match_data_t *
+nxt_regex_match_data(nxt_regex_t *regex, nxt_regex_context_t *ctx)
+{
+    size_t                  size;
+    nxt_uint_t              ncaptures;
+    nxt_regex_match_data_t  *match_data;
+
+    if (regex != NULL) {
+        ncaptures = regex->ncaptures - 1;
+
+    } else {
+        ncaptures = 0;
+    }
+
+    /* Each capture is stored in 3 "int" vector elements. */
+    ncaptures *= 3;
+    size = sizeof(nxt_regex_match_data_t) + ncaptures * sizeof(int);
+
+    match_data = ctx->private_malloc(size, ctx->memory_data);
+
+    if (nxt_fast_path(match_data != NULL)) {
+        match_data->ncaptures = ncaptures + 3;
+    }
+
+    return match_data;
+}
+
+
+void
+nxt_regex_match_data_free(nxt_regex_match_data_t *match_data,
+    nxt_regex_context_t *ctx)
+{
+    ctx->private_free(match_data, ctx->memory_data);
+}
+
+
+static void *
+nxt_pcre_malloc(size_t size)
+{
+    return regex_context->private_malloc(size, regex_context->memory_data);
+}
+
+
+static void
+nxt_pcre_free(void *p)
+{
+    regex_context->private_free(p, regex_context->memory_data);
+}
+
+
+static void *
+nxt_pcre_default_malloc(size_t size, void *memory_data)
+{
+    return malloc(size);
+}
+
+
+static void
+nxt_pcre_default_free(void *p, void *memory_data)
+{
+    free(p);
+}
+
+
+nxt_bool_t
+nxt_regex_is_valid(nxt_regex_t *regex)
+{
+    return (regex->code != NULL);
+}
+
+
+nxt_int_t
+nxt_regex_match(nxt_regex_t *regex, u_char *subject, size_t len,
+    nxt_regex_match_data_t *match_data, nxt_regex_context_t *ctx)
+{
+    int     ret;
+    size_t  size;
+
+    ret = pcre_exec(regex->code, regex->extra, (char *) subject, len, 0, 0,
+                    match_data->captures, match_data->ncaptures);
+
+    /* PCRE_ERROR_NOMATCH is -1. */
+
+    if (nxt_slow_path(ret < PCRE_ERROR_NOMATCH)) {
+        size = sizeof("pcre_exec() failed: ") + sizeof("-2147483647");
+
+        ctx->error = ctx->private_malloc(size, ctx->memory_data);
+
+        if (nxt_fast_path(ctx->error != NULL)) {
+            (void) snprintf((char *) ctx->error, size, "pcre_exec() failed: %d",
+                            ret);
+        }
+    }
+
+    return ret;
+}
+
+
+int *
+nxt_regex_captures(nxt_regex_match_data_t *match_data)
+{
+     return (match_data)->captures;
+}
diff -r 1c96b24bcdd2 -r b8084a72d667 nxt/nxt_pcre.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nxt/nxt_pcre.h	Wed Jun 01 15:30:50 2016 +0300
@@ -0,0 +1,34 @@
+
+/*
+ * Copyright (C) Igor Sysoev
+ * Copyright (C) NGINX, Inc.
+ */
+
+#ifndef _NXT_PCRE_H_INCLUDED_
+#define _NXT_PCRE_H_INCLUDED_
+
+
+#include <pcre.h>
+
+
+#define NGX_REGEX_NOMATCH  PCRE_ERROR_NOMATCH
+
+
+struct nxt_regex_s {
+    pcre        *code;
+    pcre_extra  *extra;
+    int         ncaptures;
+};
+
+
+struct nxt_regex_match_data_s {
+    int         ncaptures;
+    /*
+     * Each capture is stored in 3 "int" vector elements.
+     * The first vector is for the "$0" capture and it is always allocated.
+     */
+    int         captures[3];
+};
+
+
+#endif /* _NXT_PCRE_H_INCLUDED_ */
diff -r 1c96b24bcdd2 -r b8084a72d667 nxt/nxt_regex.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nxt/nxt_regex.h	Wed Jun 01 15:30:50 2016 +0300
@@ -0,0 +1,42 @@
+
+/*
+ * Copyright (C) Igor Sysoev
+ * Copyright (C) NGINX, Inc.
+ */
+
+#ifndef _NXT_REGEX_H_INCLUDED_
+#define _NXT_REGEX_H_INCLUDED_
+
+
+typedef void *(*nxt_pcre_malloc_t)(size_t size, void *memory_data);
+typedef void (*nxt_pcre_free_t)(void *p, void *memory_data);
+
+
+typedef struct nxt_regex_s             nxt_regex_t;
+typedef struct nxt_regex_match_data_s  nxt_regex_match_data_t;
+
+
+typedef struct {
+    nxt_pcre_malloc_t  private_malloc;
+    nxt_pcre_free_t    private_free;
+    void               *memory_data;
+    u_char             *error;
+} nxt_regex_context_t;
+
+
+NXT_EXPORT nxt_regex_context_t *
+    nxt_regex_context_create(nxt_pcre_malloc_t private_malloc,
+    nxt_pcre_free_t private_free, void *memory_data);
+NXT_EXPORT nxt_int_t nxt_regex_compile(nxt_regex_t *regex, u_char *source,
+    size_t len, nxt_uint_t options, nxt_regex_context_t *ctx);
+NXT_EXPORT nxt_bool_t nxt_regex_is_valid(nxt_regex_t *regex);
+NXT_EXPORT nxt_regex_match_data_t *nxt_regex_match_data(nxt_regex_t *regex,
+    nxt_regex_context_t *ctx);
+NXT_EXPORT void nxt_regex_match_data_free(nxt_regex_match_data_t *match_data,
+    nxt_regex_context_t *ctx);
+NXT_EXPORT nxt_int_t nxt_regex_match(nxt_regex_t *regex, u_char *subject,
+    size_t len, nxt_regex_match_data_t *match_data, nxt_regex_context_t *ctx);
+NXT_EXPORT int *nxt_regex_captures(nxt_regex_match_data_t *match_data);
+
+
+#endif /* _NXT_REGEX_H_INCLUDED_ */



More information about the nginx-devel mailing list