-Added regex cache

-Made module thread-safe
This commit is contained in:
Andrey Hristov 1999-05-21 19:27:44 +00:00
parent c57c0e9cd5
commit e3a70c1f04
2 changed files with 115 additions and 17 deletions

View file

@ -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, &regex, &replace, &subject) == FAILURE) { if (ARG_COUNT(ht) != 3 || getParameters(ht, 3, &regex, &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);

View file

@ -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