upstream nginx-0.7.31
[nginx.git] / nginx / src / core / ngx_regex.c
1
2 /*
3  * Copyright (C) Igor Sysoev
4  */
5
6
7 #include <ngx_config.h>
8 #include <ngx_core.h>
9
10
11 static void * ngx_libc_cdecl ngx_regex_malloc(size_t size);
12 static void ngx_libc_cdecl ngx_regex_free(void *p);
13
14
15 static ngx_pool_t  *ngx_pcre_pool;
16
17
18 void
19 ngx_regex_init(void)
20 {
21     pcre_malloc = ngx_regex_malloc;
22     pcre_free = ngx_regex_free;
23 }
24
25
26 ngx_regex_t *
27 ngx_regex_compile(ngx_str_t *pattern, ngx_int_t options, ngx_pool_t *pool,
28     ngx_str_t *err)
29 {
30     int              erroff;
31     const char      *errstr;
32     ngx_regex_t     *re;
33 #if (NGX_THREADS)
34     ngx_core_tls_t  *tls;
35
36 #if (NGX_SUPPRESS_WARN)
37     tls = NULL;
38 #endif
39
40     if (ngx_threaded) {
41         tls = ngx_thread_get_tls(ngx_core_tls_key);
42         tls->pool = pool;
43     } else {
44         ngx_pcre_pool = pool;
45     }
46
47 #else
48
49     ngx_pcre_pool = pool;
50
51 #endif
52
53     re = pcre_compile((const char *) pattern->data, (int) options,
54                       &errstr, &erroff, NULL);
55
56     if (re == NULL) {
57        if ((size_t) erroff == pattern->len) {
58            ngx_snprintf(err->data, err->len - 1,
59                         "pcre_compile() failed: %s in \"%s\"%Z",
60                         errstr, pattern->data);
61         } else {
62            ngx_snprintf(err->data, err->len - 1,
63                         "pcre_compile() failed: %s in \"%s\" at \"%s\"%Z",
64                         errstr, pattern->data, pattern->data + erroff);
65         }
66     }
67
68     /* ensure that there is no current pool */
69
70 #if (NGX_THREADS)
71     if (ngx_threaded) {
72         tls->pool = NULL;
73     } else {
74         ngx_pcre_pool = NULL;
75     }
76 #else
77     ngx_pcre_pool = NULL;
78 #endif
79
80     return re;
81 }
82
83
84 ngx_int_t
85 ngx_regex_capture_count(ngx_regex_t *re)
86 {
87     int  rc, n;
88
89     n = 0;
90
91     rc = pcre_fullinfo(re, NULL, PCRE_INFO_CAPTURECOUNT, &n);
92
93     if (rc < 0) {
94         return (ngx_int_t) rc;
95     }
96
97     return (ngx_int_t) n;
98 }
99
100
101 ngx_int_t
102 ngx_regex_exec(ngx_regex_t *re, ngx_str_t *s, int *captures, ngx_int_t size)
103 {
104     int  rc;
105
106     rc = pcre_exec(re, NULL, (const char *) s->data, s->len, 0, 0,
107                    captures, size);
108
109     if (rc == -1) {
110         return NGX_REGEX_NO_MATCHED;
111     }
112
113     return rc;
114 }
115
116
117 ngx_int_t
118 ngx_regex_exec_array(ngx_array_t *a, ngx_str_t *s, ngx_log_t *log)
119 {
120     ngx_int_t         n;
121     ngx_uint_t        i;
122     ngx_regex_elt_t  *re;
123
124     re = a->elts;
125
126     for (i = 0; i < a->nelts; i++) {
127
128         n = ngx_regex_exec(re[i].regex, s, NULL, 0);
129
130         if (n == NGX_REGEX_NO_MATCHED) {
131             continue;
132         }
133
134         if (n < 0) {
135             ngx_log_error(NGX_LOG_ALERT, log, 0,
136                           ngx_regex_exec_n " failed: %d on \"%V\" using \"%s\"",
137                           n, s, re[i].name);
138             return NGX_ERROR;
139         }
140
141         /* match */
142
143         return NGX_OK;
144     }
145
146     return NGX_DECLINED;
147 }
148
149
150 static void * ngx_libc_cdecl
151 ngx_regex_malloc(size_t size)
152 {
153     ngx_pool_t      *pool;
154 #if (NGX_THREADS)
155     ngx_core_tls_t  *tls;
156
157     if (ngx_threaded) {
158         tls = ngx_thread_get_tls(ngx_core_tls_key);
159         pool = tls->pool;
160     } else {
161         pool = ngx_pcre_pool;
162     }
163 #else
164     pool = ngx_pcre_pool;
165 #endif
166
167     if (pool) {
168         return ngx_palloc(pool, size);
169     }
170
171     return NULL;
172 }
173
174
175 static void ngx_libc_cdecl
176 ngx_regex_free(void *p)
177 {
178     return;
179 }