[nginx] Sub filter: support of multiple strings to replace.

Dmitry Volyntsev xeioex at nginx.com
Mon Aug 17 14:44:21 UTC 2015


details:   http://hg.nginx.org/nginx/rev/b9447fc457b4
branches:  
changeset: 6228:b9447fc457b4
user:      Dmitry Volyntsev <xeioex at nginx.com>
date:      Mon Aug 17 17:42:02 2015 +0300
description:
Sub filter: support of multiple strings to replace.

diffstat:

 src/http/modules/ngx_http_sub_filter_module.c |  433 +++++++++++++++----------
 1 files changed, 257 insertions(+), 176 deletions(-)

diffs (truncated from 638 to 300 lines):

diff -r bd55d75a1410 -r b9447fc457b4 src/http/modules/ngx_http_sub_filter_module.c
--- a/src/http/modules/ngx_http_sub_filter_module.c	Sun Aug 16 10:51:34 2015 +0300
+++ b/src/http/modules/ngx_http_sub_filter_module.c	Mon Aug 17 17:42:02 2015 +0300
@@ -13,6 +13,20 @@
 typedef struct {
     ngx_str_t                  match;
     ngx_http_complex_value_t   value;
+} ngx_http_sub_match_t;
+
+
+typedef struct {
+    ngx_uint_t                 min_match_len;
+    ngx_uint_t                 max_match_len;
+
+    u_char                     index[257];
+    u_char                     shift[256];
+} ngx_http_sub_tables_t;
+
+
+typedef struct {
+    ngx_http_sub_tables_t     *tables;
 
     ngx_hash_t                 types;
 
@@ -20,17 +34,11 @@ typedef struct {
     ngx_flag_t                 last_modified;
 
     ngx_array_t               *types_keys;
+    ngx_array_t               *matches;
 } ngx_http_sub_loc_conf_t;
 
 
-typedef enum {
-    sub_start_state = 0,
-    sub_match_state,
-} ngx_http_sub_state_e;
-
-
 typedef struct {
-    ngx_str_t                  match;
     ngx_str_t                  saved;
     ngx_str_t                  looked;
 
@@ -48,12 +56,17 @@ typedef struct {
     ngx_chain_t               *busy;
     ngx_chain_t               *free;
 
-    ngx_str_t                  sub;
+    ngx_str_t                 *sub;
+    ngx_uint_t                 applied;
 
-    ngx_uint_t                 state;
+    ngx_int_t                  offset;
+    ngx_uint_t                 index;
 } ngx_http_sub_ctx_t;
 
 
+static ngx_uint_t ngx_http_sub_cmp_index;
+
+
 static ngx_int_t ngx_http_sub_output(ngx_http_request_t *r,
     ngx_http_sub_ctx_t *ctx);
 static ngx_int_t ngx_http_sub_parse(ngx_http_request_t *r,
@@ -64,6 +77,9 @@ static char * ngx_http_sub_filter(ngx_co
 static void *ngx_http_sub_create_conf(ngx_conf_t *cf);
 static char *ngx_http_sub_merge_conf(ngx_conf_t *cf,
     void *parent, void *child);
+static void ngx_http_sub_init_tables(ngx_http_sub_tables_t *tables,
+    ngx_http_sub_match_t *match, ngx_uint_t n);
+static ngx_int_t ngx_http_sub_cmp_matches(const void *one, const void *two);
 static ngx_int_t ngx_http_sub_filter_init(ngx_conf_t *cf);
 
 
@@ -144,7 +160,7 @@ ngx_http_sub_header_filter(ngx_http_requ
 
     slcf = ngx_http_get_module_loc_conf(r, ngx_http_sub_filter_module);
 
-    if (slcf->match.len == 0
+    if (slcf->matches == NULL
         || r->headers_out.content_length_n == 0
         || ngx_http_test_content_type(r, &slcf->types) == NULL)
     {
@@ -156,19 +172,19 @@ ngx_http_sub_header_filter(ngx_http_requ
         return NGX_ERROR;
     }
 
-    ctx->saved.data = ngx_pnalloc(r->pool, slcf->match.len);
+    ctx->saved.data = ngx_pnalloc(r->pool, slcf->tables->max_match_len - 1);
     if (ctx->saved.data == NULL) {
         return NGX_ERROR;
     }
 
-    ctx->looked.data = ngx_pnalloc(r->pool, slcf->match.len);
+    ctx->looked.data = ngx_pnalloc(r->pool, slcf->tables->max_match_len - 1);
     if (ctx->looked.data == NULL) {
         return NGX_ERROR;
     }
 
     ngx_http_set_ctx(r, ctx, ngx_http_sub_filter_module);
 
-    ctx->match = slcf->match;
+    ctx->offset = slcf->tables->min_match_len - 1;
     ctx->last_out = &ctx->out;
 
     r->filter_need_in_memory = 1;
@@ -194,8 +210,10 @@ ngx_http_sub_body_filter(ngx_http_reques
 {
     ngx_int_t                  rc;
     ngx_buf_t                 *b;
+    ngx_str_t                 *sub;
     ngx_chain_t               *cl;
     ngx_http_sub_ctx_t        *ctx;
+    ngx_http_sub_match_t      *match;
     ngx_http_sub_loc_conf_t   *slcf;
 
     ctx = ngx_http_get_module_ctx(r, ngx_http_sub_filter_module);
@@ -242,18 +260,10 @@ ngx_http_sub_body_filter(ngx_http_reques
             ctx->pos = ctx->buf->pos;
         }
 
-        if (ctx->state == sub_start_state) {
-            ctx->copy_start = ctx->pos;
-            ctx->copy_end = ctx->pos;
-        }
-
         b = NULL;
 
         while (ctx->pos < ctx->buf->last) {
 
-            ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
-                           "saved: \"%V\" state: %d", &ctx->saved, ctx->state);
-
             rc = ngx_http_sub_parse(r, ctx);
 
             ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
@@ -320,20 +330,6 @@ ngx_http_sub_body_filter(ngx_http_reques
                 ctx->last_out = &cl->next;
             }
 
-            if (ctx->state == sub_start_state) {
-                ctx->copy_start = ctx->pos;
-                ctx->copy_end = ctx->pos;
-
-            } else {
-                ctx->copy_start = NULL;
-                ctx->copy_end = NULL;
-            }
-
-            if (ctx->looked.len > (size_t) (ctx->pos - ctx->buf->pos)) {
-                ctx->saved.len = ctx->looked.len - (ctx->pos - ctx->buf->pos);
-                ngx_memcpy(ctx->saved.data, ctx->looked.data, ctx->saved.len);
-            }
-
             if (rc == NGX_AGAIN) {
                 continue;
             }
@@ -352,19 +348,30 @@ ngx_http_sub_body_filter(ngx_http_reques
 
             slcf = ngx_http_get_module_loc_conf(r, ngx_http_sub_filter_module);
 
-            if (ctx->sub.data == NULL) {
+            if (ctx->sub == NULL) {
+                ctx->sub = ngx_pcalloc(r->pool, sizeof(ngx_str_t)
+                                                * slcf->matches->nelts);
+                if (ctx->sub == NULL) {
+                    return NGX_ERROR;
+                }
+            }
 
-                if (ngx_http_complex_value(r, &slcf->value, &ctx->sub)
+            sub = &ctx->sub[ctx->index];
+
+            if (sub->data == NULL) {
+                match = slcf->matches->elts;
+
+                if (ngx_http_complex_value(r, &match[ctx->index].value, sub)
                     != NGX_OK)
                 {
                     return NGX_ERROR;
                 }
             }
 
-            if (ctx->sub.len) {
+            if (sub->len) {
                 b->memory = 1;
-                b->pos = ctx->sub.data;
-                b->last = ctx->sub.data + ctx->sub.len;
+                b->pos = sub->data;
+                b->last = sub->data + sub->len;
 
             } else {
                 b->sync = 1;
@@ -373,7 +380,8 @@ ngx_http_sub_body_filter(ngx_http_reques
             *ctx->last_out = cl;
             ctx->last_out = &cl->next;
 
-            ctx->once = slcf->once;
+            ctx->index = 0;
+            ctx->once = slcf->once && (++ctx->applied == slcf->matches->nelts);
 
             continue;
         }
@@ -428,9 +436,6 @@ ngx_http_sub_body_filter(ngx_http_reques
         }
 
         ctx->buf = NULL;
-
-        ctx->saved.len = ctx->looked.len;
-        ngx_memcpy(ctx->saved.data, ctx->looked.data, ctx->looked.len);
     }
 
     if (ctx->out == NULL && ctx->busy == NULL) {
@@ -513,158 +518,142 @@ ngx_http_sub_output(ngx_http_request_t *
 static ngx_int_t
 ngx_http_sub_parse(ngx_http_request_t *r, ngx_http_sub_ctx_t *ctx)
 {
-    u_char                *p, *last, *copy_end, ch, match;
-    size_t                 looked, i;
-    ngx_http_sub_state_e   state;
+    u_char                   *p, *last, *pat, *pat_end, c;
+    ngx_str_t                *m;
+    ngx_int_t                 offset, start, next, end, len, rc;
+    ngx_uint_t                shift, i, j;
+    ngx_http_sub_match_t     *match;
+    ngx_http_sub_tables_t    *tables;
+    ngx_http_sub_loc_conf_t  *slcf;
+
+    slcf = ngx_http_get_module_loc_conf(r, ngx_http_sub_filter_module);
+    tables = slcf->tables;
+
+    offset = ctx->offset;
+    end = ctx->buf->last - ctx->pos;
 
     if (ctx->once) {
-        ctx->copy_start = ctx->pos;
-        ctx->copy_end = ctx->buf->last;
-        ctx->pos = ctx->buf->last;
-        ctx->looked.len = 0;
-
-        ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "once");
-
-        return NGX_AGAIN;
+        /* sets start and next to end */
+        offset = end + (ngx_int_t) tables->min_match_len - 1;
+        goto again;
     }
 
-    state = ctx->state;
-    looked = ctx->looked.len;
-    last = ctx->buf->last;
-    copy_end = ctx->copy_end;
+    while (offset < end) {
 
-    for (p = ctx->pos; p < last; p++) {
+        c = offset < 0 ? ctx->looked.data[ctx->looked.len + offset]
+                       : ctx->pos[offset];
 
-        ch = *p;
-        ch = ngx_tolower(ch);
+        c = ngx_tolower(c);
 
-        if (state == sub_start_state) {
-
-            /* the tight loop */
-
-            match = ctx->match.data[0];
-
-            for ( ;; ) {
-                if (ch == match) {
-
-                    if (ctx->match.len == 1) {
-                        ctx->pos = p + 1;
-                        ctx->copy_end = p;
-
-                        return NGX_OK;
-                    }
-
-                    copy_end = p;
-                    ctx->looked.data[0] = *p;
-                    looked = 1;
-                    state = sub_match_state;
-
-                    goto match_started;
-                }
-
-                if (++p == last) {
-                    break;
-                }
-
-                ch = *p;
-                ch = ngx_tolower(ch);
-            }
-
-            ctx->state = state;
-            ctx->pos = p;
-            ctx->looked.len = looked;
-            ctx->copy_end = p;
-
-            if (ctx->copy_start == NULL) {
-                ctx->copy_start = ctx->buf->pos;



More information about the nginx-devel mailing list