mirror of
https://github.com/php/php-src.git
synced 2025-08-16 22:18:50 +02:00
-Added regex cache
-Made module thread-safe
This commit is contained in:
parent
c57c0e9cd5
commit
e3a70c1f04
2 changed files with 115 additions and 17 deletions
104
ext/pcre/pcre.c
104
ext/pcre/pcre.c
|
@ -48,24 +48,53 @@ function_entry pcre_functions[] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
php3_module_entry pcre_module_entry = {
|
php3_module_entry pcre_module_entry = {
|
||||||
"PCRE", pcre_functions, NULL, NULL, php_rinit_pcre, NULL,
|
"PCRE", pcre_functions, php_minit_pcre, php_mshutdown_pcre,
|
||||||
|
php_rinit_pcre, NULL,
|
||||||
php_info_pcre, STANDARD_MODULE_PROPERTIES
|
php_info_pcre, STANDARD_MODULE_PROPERTIES
|
||||||
};
|
};
|
||||||
|
|
||||||
/* }}} */
|
/* }}} */
|
||||||
|
|
||||||
|
#ifdef ZTS
|
||||||
|
int pcre_globals_id;
|
||||||
|
#else
|
||||||
|
php_pcre_globals pcre_globals;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
static void *php_pcre_malloc(size_t size)
|
static void *php_pcre_malloc(size_t size)
|
||||||
{
|
{
|
||||||
return emalloc(size);
|
return pemalloc(size, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void php_pcre_free(void *ptr)
|
static void php_pcre_free(void *ptr)
|
||||||
{
|
{
|
||||||
efree(ptr);
|
pefree(ptr, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void _php_free_pcre_cache(void *data)
|
||||||
|
{
|
||||||
|
pcre_cache_entry *pce = (pcre_cache_entry *) data;
|
||||||
|
pefree(pce->re, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef ZTS
|
||||||
|
static void _php_pcre_init_globals(php_pcre_globals *pcre_globals)
|
||||||
|
{
|
||||||
|
zend_hash_init(&PCRE_G(pcre_cache), 0, NULL, _php_free_pcre_cache, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void _php_pcre_shutdown_globals(php_pcre_globals *pcre_globals)
|
||||||
|
{
|
||||||
|
zend_hash_destroy(&PCRE_G(pcre_cache));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/* {{{ void php_info_pcre(ZEND_MODULE_INFO_FUNC_ARGS) */
|
/* {{{ void php_info_pcre(ZEND_MODULE_INFO_FUNC_ARGS) */
|
||||||
void php_info_pcre(ZEND_MODULE_INFO_FUNC_ARGS)
|
void php_info_pcre(ZEND_MODULE_INFO_FUNC_ARGS)
|
||||||
{
|
{
|
||||||
|
@ -78,6 +107,33 @@ void php_info_pcre(ZEND_MODULE_INFO_FUNC_ARGS)
|
||||||
/* }}} */
|
/* }}} */
|
||||||
|
|
||||||
|
|
||||||
|
/* {{{ int php_minit_pcre(INIT_FUNC_ARGS) */
|
||||||
|
int php_minit_pcre(INIT_FUNC_ARGS)
|
||||||
|
{
|
||||||
|
#ifdef ZTS
|
||||||
|
pcre_globals_id = tsrm_allocate_id(
|
||||||
|
sizeof(php_pcre_globals),
|
||||||
|
_php_pcre_init_globals,
|
||||||
|
_php_pcre_shutdown_globals);
|
||||||
|
#else
|
||||||
|
zend_hash_init(&PCRE_G(pcre_cache), 0, NULL, _php_free_pcre_cache, 1);
|
||||||
|
#endif
|
||||||
|
return SUCCESS;
|
||||||
|
}
|
||||||
|
/* }}} */
|
||||||
|
|
||||||
|
|
||||||
|
/* {{{ int php_mshutdown_pcre(void) */
|
||||||
|
int php_mshutdown_pcre(SHUTDOWN_FUNC_ARGS)
|
||||||
|
{
|
||||||
|
#ifndef ZTS
|
||||||
|
zend_hash_destroy(&PCRE_G(pcre_cache));
|
||||||
|
#endif
|
||||||
|
return SUCCESS;
|
||||||
|
}
|
||||||
|
/* }}} */
|
||||||
|
|
||||||
|
|
||||||
/* {{{ int php_rinit_pcre(INIT_FUNC_ARGS) */
|
/* {{{ int php_rinit_pcre(INIT_FUNC_ARGS) */
|
||||||
int php_rinit_pcre(INIT_FUNC_ARGS)
|
int php_rinit_pcre(INIT_FUNC_ARGS)
|
||||||
{
|
{
|
||||||
|
@ -97,10 +153,22 @@ static pcre* _pcre_get_compiled_regex(char *regex, pcre_extra *extra) {
|
||||||
const char *error;
|
const char *error;
|
||||||
int erroffset;
|
int erroffset;
|
||||||
char delimiter;
|
char delimiter;
|
||||||
unsigned char *p, *pp;
|
char *p, *pp;
|
||||||
char *pattern;
|
char *pattern;
|
||||||
|
int regex_len;
|
||||||
int do_study = 0;
|
int do_study = 0;
|
||||||
|
pcre_cache_entry *pce;
|
||||||
|
pcre_cache_entry new_entry;
|
||||||
|
PCRE_LS_FETCH();
|
||||||
|
|
||||||
|
/* Try to lookup the cached regex entry, and if successful, just pass
|
||||||
|
back the compiled pattern, otherwise go on and compile it. */
|
||||||
|
regex_len = strlen(regex);
|
||||||
|
if (zend_hash_find(&PCRE_G(pcre_cache), regex, regex_len+1, (void **)&pce) == SUCCESS) {
|
||||||
|
extra = pce->extra;
|
||||||
|
return pce->re;
|
||||||
|
}
|
||||||
|
|
||||||
p = regex;
|
p = regex;
|
||||||
|
|
||||||
/* Parse through the leading whitespace, and display a warning if we
|
/* Parse through the leading whitespace, and display a warning if we
|
||||||
|
@ -188,7 +256,13 @@ static pcre* _pcre_get_compiled_regex(char *regex, pcre_extra *extra) {
|
||||||
}
|
}
|
||||||
|
|
||||||
efree(pattern);
|
efree(pattern);
|
||||||
|
|
||||||
|
/* Store the compiled pattern and extra info in the cache. */
|
||||||
|
new_entry.re = re;
|
||||||
|
new_entry.extra = extra;
|
||||||
|
zend_hash_update(&PCRE_G(pcre_cache), regex, regex_len+1, (void *)&new_entry,
|
||||||
|
sizeof(pcre_cache_entry), NULL);
|
||||||
|
|
||||||
return re;
|
return re;
|
||||||
}
|
}
|
||||||
/* }}} */
|
/* }}} */
|
||||||
|
@ -204,7 +278,6 @@ PHP_FUNCTION(pcre_match)
|
||||||
pcre *re = NULL;
|
pcre *re = NULL;
|
||||||
pcre_extra *extra = NULL;
|
pcre_extra *extra = NULL;
|
||||||
int exoptions = 0;
|
int exoptions = 0;
|
||||||
const char *error;
|
|
||||||
int count;
|
int count;
|
||||||
int *offsets;
|
int *offsets;
|
||||||
int size_offsets;
|
int size_offsets;
|
||||||
|
@ -289,7 +362,7 @@ PHP_FUNCTION(pcre_match)
|
||||||
zend_hash_index_update(subpats->value.ht, i, &entry, sizeof(zval *), NULL);
|
zend_hash_index_update(subpats->value.ht, i, &entry, sizeof(zval *), NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
efree(stringlist);
|
php_pcre_free(stringlist);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* If nothing matched */
|
/* If nothing matched */
|
||||||
|
@ -305,7 +378,6 @@ PHP_FUNCTION(pcre_match)
|
||||||
}
|
}
|
||||||
|
|
||||||
efree(offsets);
|
efree(offsets);
|
||||||
efree(re);
|
|
||||||
|
|
||||||
RETVAL_LONG(matched);
|
RETVAL_LONG(matched);
|
||||||
}
|
}
|
||||||
|
@ -337,12 +409,9 @@ PHP_FUNCTION(pcre_replace)
|
||||||
pcre *re = NULL;
|
pcre *re = NULL;
|
||||||
pcre_extra *extra = NULL;
|
pcre_extra *extra = NULL;
|
||||||
int exoptions = 0;
|
int exoptions = 0;
|
||||||
const char *error;
|
|
||||||
int count = 0;
|
int count = 0;
|
||||||
int *offsets;
|
int *offsets;
|
||||||
int size_offsets;
|
int size_offsets;
|
||||||
int matched;
|
|
||||||
const char ***stringlist;
|
|
||||||
int new_len;
|
int new_len;
|
||||||
int alloc_len;
|
int alloc_len;
|
||||||
int subject_len;
|
int subject_len;
|
||||||
|
@ -354,6 +423,7 @@ PHP_FUNCTION(pcre_replace)
|
||||||
*walkbuf,
|
*walkbuf,
|
||||||
*walk;
|
*walk;
|
||||||
|
|
||||||
|
/* Get function parameters and do error-checking. */
|
||||||
if (ARG_COUNT(ht) != 3 || getParameters(ht, 3, ®ex, &replace, &subject) == FAILURE) {
|
if (ARG_COUNT(ht) != 3 || getParameters(ht, 3, ®ex, &replace, &subject) == FAILURE) {
|
||||||
WRONG_PARAM_COUNT;
|
WRONG_PARAM_COUNT;
|
||||||
}
|
}
|
||||||
|
@ -389,7 +459,8 @@ PHP_FUNCTION(pcre_replace)
|
||||||
/* Execute the regular expression. */
|
/* Execute the regular expression. */
|
||||||
count = pcre_exec(re, extra, &subject->value.str.val[subject_offset],
|
count = pcre_exec(re, extra, &subject->value.str.val[subject_offset],
|
||||||
subject->value.str.len-subject_offset,
|
subject->value.str.len-subject_offset,
|
||||||
(subject_offset ? PCRE_NOTBOL : 0), offsets, size_offsets);
|
(subject_offset ? exoptions|PCRE_NOTBOL : exoptions),
|
||||||
|
offsets, size_offsets);
|
||||||
|
|
||||||
/* Check for too many substrings condition. */
|
/* Check for too many substrings condition. */
|
||||||
if (count == 0) {
|
if (count == 0) {
|
||||||
|
@ -404,7 +475,7 @@ PHP_FUNCTION(pcre_replace)
|
||||||
if ('\\' == *walk &&
|
if ('\\' == *walk &&
|
||||||
_pcre_get_backref(walk+1, &backref) &&
|
_pcre_get_backref(walk+1, &backref) &&
|
||||||
backref < count) {
|
backref < count) {
|
||||||
new_len += offsets[2*backref+1] - offsets[2*backref];
|
new_len += offsets[(backref<<1)+1] - offsets[backref<<1];
|
||||||
walk += (backref > 9) ? 3 : 2;
|
walk += (backref > 9) ? 3 : 2;
|
||||||
} else {
|
} else {
|
||||||
new_len++;
|
new_len++;
|
||||||
|
@ -429,9 +500,9 @@ PHP_FUNCTION(pcre_replace)
|
||||||
if ('\\' == *walk &&
|
if ('\\' == *walk &&
|
||||||
_pcre_get_backref(walk+1, &backref) &&
|
_pcre_get_backref(walk+1, &backref) &&
|
||||||
backref < count) {
|
backref < count) {
|
||||||
result_len = offsets[2*backref+1] - offsets[2*backref];
|
result_len = offsets[(backref<<1)+1] - offsets[backref<<1];
|
||||||
memcpy (walkbuf,
|
memcpy (walkbuf,
|
||||||
&subject->value.str.val[subject_offset + offsets[2*backref]],
|
&subject->value.str.val[subject_offset + offsets[backref<<1]],
|
||||||
result_len);
|
result_len);
|
||||||
walkbuf += result_len;
|
walkbuf += result_len;
|
||||||
walk += (backref > 9) ? 3 : 2;
|
walk += (backref > 9) ? 3 : 2;
|
||||||
|
@ -457,7 +528,7 @@ PHP_FUNCTION(pcre_replace)
|
||||||
} else {
|
} else {
|
||||||
subject_offset += offsets[1];
|
subject_offset += offsets[1];
|
||||||
}
|
}
|
||||||
} else { /* REG_NOMATCH */
|
} else {
|
||||||
new_len = strlen(result) + strlen(&subject->value.str.val[subject_offset]);
|
new_len = strlen(result) + strlen(&subject->value.str.val[subject_offset]);
|
||||||
if (new_len + 1 > alloc_len) {
|
if (new_len + 1 > alloc_len) {
|
||||||
alloc_len = new_len + 1; /* now we know exactly how long it is */
|
alloc_len = new_len + 1; /* now we know exactly how long it is */
|
||||||
|
@ -472,7 +543,6 @@ PHP_FUNCTION(pcre_replace)
|
||||||
}
|
}
|
||||||
|
|
||||||
efree(offsets);
|
efree(offsets);
|
||||||
efree(re);
|
|
||||||
|
|
||||||
RETVAL_STRING(result, 1);
|
RETVAL_STRING(result, 1);
|
||||||
efree(result);
|
efree(result);
|
||||||
|
|
|
@ -37,6 +37,8 @@
|
||||||
#include "pcre.h"
|
#include "pcre.h"
|
||||||
|
|
||||||
extern void php_info_pcre(ZEND_MODULE_INFO_FUNC_ARGS);
|
extern void php_info_pcre(ZEND_MODULE_INFO_FUNC_ARGS);
|
||||||
|
extern int php_minit_pcre(INIT_FUNC_ARGS);
|
||||||
|
extern int php_mshutdown_pcre(SHUTDOWN_FUNC_ARGS);
|
||||||
extern int php_rinit_pcre(INIT_FUNC_ARGS);
|
extern int php_rinit_pcre(INIT_FUNC_ARGS);
|
||||||
|
|
||||||
PHP_FUNCTION(pcre_match);
|
PHP_FUNCTION(pcre_match);
|
||||||
|
@ -45,6 +47,32 @@ PHP_FUNCTION(pcre_replace);
|
||||||
extern zend_module_entry pcre_module_entry;
|
extern zend_module_entry pcre_module_entry;
|
||||||
#define pcre_module_ptr &pcre_module_entry
|
#define pcre_module_ptr &pcre_module_entry
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
pcre *re;
|
||||||
|
pcre_extra *extra;
|
||||||
|
} pcre_cache_entry;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
HashTable pcre_cache;
|
||||||
|
} php_pcre_globals;
|
||||||
|
|
||||||
|
#ifdef ZTS
|
||||||
|
# define PCRE_LS_D php_pcre_globals *pcre_globals
|
||||||
|
# define PCRE_LS_DC , PCRE_LS_D
|
||||||
|
# define PCRE_LS_C pcre_globals
|
||||||
|
# define PCRE_LS_CC , PCRE_LS_C
|
||||||
|
# define PCRE_G(v) (pcre_globals->v)
|
||||||
|
# define PCRE_LS_FETCH() php_pcre_globals *pcre_globals = ts_resource(pcre_globals_id);
|
||||||
|
#else
|
||||||
|
# define PCRE_LS_D
|
||||||
|
# define PCRE_LS_DC
|
||||||
|
# define PCRE_LS_C
|
||||||
|
# define PCRE_LS_CC
|
||||||
|
# define PCRE_G(v) (pcre_globals.v)
|
||||||
|
# define PCRE_LS_FETCH()
|
||||||
|
extern ZEND_API php_pcre_globals pcre_globals;
|
||||||
|
#endif
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
#define pcre_module_ptr NULL
|
#define pcre_module_ptr NULL
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue