]> granicus.if.org Git - apache/commitdiff
Expression parser: Optimize another concatenation
authorRainer Jung <rjung@apache.org>
Thu, 5 Feb 2015 20:33:59 +0000 (20:33 +0000)
committerRainer Jung <rjung@apache.org>
Thu, 5 Feb 2015 20:33:59 +0000 (20:33 +0000)
case by using iteration instead of recursion.

We have a relatively small recursion limit of
about 10 operations. This is a compilation
limit (a define). It can be hit if many expr
vars or function calls are concatenated.

The new optimization is very similar to the
existing one, which optimizes consecutive
concatenations in node2 of the tree. The new
one optimizes consecutive concatenations in
node 1.

git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1657685 13f79535-47bb-0310-9956-ffa450edef68

server/util_expr_eval.c

index 9eb2792da13942c3669b7cb60f3bbd96d46a34b4..b37319e9b9aa4c0cdd2cbd44e9b641abebab574d 100644 (file)
@@ -103,7 +103,8 @@ static const char *ap_expr_eval_word(ap_expr_eval_ctx_t *ctx,
                                   node->node_arg2);
         break;
     case op_Concat:
-        if (((ap_expr_t *)node->node_arg2)->node_op != op_Concat) {
+        if (((ap_expr_t *)node->node_arg2)->node_op != op_Concat &&
+            ((ap_expr_t *)node->node_arg1)->node_op != op_Concat) {
             const char *s1 = ap_expr_eval_word(ctx, node->node_arg1);
             const char *s2 = ap_expr_eval_word(ctx, node->node_arg2);
             if (!*s1)
@@ -113,6 +114,30 @@ static const char *ap_expr_eval_word(ap_expr_eval_ctx_t *ctx,
             else
                 result = apr_pstrcat(ctx->p, s1, s2, NULL);
         }
+        else if (((ap_expr_t *)node->node_arg1)->node_op == op_Concat) {
+            const ap_expr_t *nodep = node;
+            int n;
+            int i = 1;
+            struct iovec *vec;
+            do {
+                nodep = nodep->node_arg1;
+                i++;
+            } while (nodep->node_op == op_Concat);
+            vec = apr_palloc(ctx->p, i * sizeof(struct iovec));
+            n = i;
+            nodep = node;
+            i--;
+            do {
+                vec[i].iov_base = (void *)ap_expr_eval_word(ctx,
+                                                            nodep->node_arg2);
+                vec[i].iov_len = strlen(vec[i].iov_base);
+                i--;
+                nodep = nodep->node_arg1;
+            } while (nodep->node_op == op_Concat);
+            vec[i].iov_base = (void *)ap_expr_eval_word(ctx, nodep);
+            vec[i].iov_len = strlen(vec[i].iov_base);
+            result = apr_pstrcatv(ctx->p, vec, n, NULL);
+        }
         else {
             const ap_expr_t *nodep = node;
             int i = 1;