From e3a70c1f04e8fc8df5fb7ba64509bc08ae25f12c Mon Sep 17 00:00:00 2001 From: Andrey Hristov Date: Fri, 21 May 1999 19:27:44 +0000 Subject: [PATCH] -Added regex cache -Made module thread-safe --- ext/pcre/pcre.c | 106 ++++++++++++++++++++++++++++++++++++-------- ext/pcre/php_pcre.h | 28 ++++++++++++ 2 files changed, 116 insertions(+), 18 deletions(-) diff --git a/ext/pcre/pcre.c b/ext/pcre/pcre.c index b15cdbaf01..f04f86a18c 100644 --- a/ext/pcre/pcre.c +++ b/ext/pcre/pcre.c @@ -48,22 +48,51 @@ function_entry pcre_functions[] = { }; 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 }; /* }}} */ +#ifdef ZTS +int pcre_globals_id; +#else +php_pcre_globals pcre_globals; +#endif + static void *php_pcre_malloc(size_t size) { - return emalloc(size); + return pemalloc(size, 1); } + 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) */ @@ -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) { @@ -97,10 +153,22 @@ static pcre* _pcre_get_compiled_regex(char *regex, pcre_extra *extra) { const char *error; int erroffset; char delimiter; - unsigned char *p, *pp; + char *p, *pp; char *pattern; + int regex_len; 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; /* 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); - + + /* 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; } /* }}} */ @@ -204,7 +278,6 @@ PHP_FUNCTION(pcre_match) pcre *re = NULL; pcre_extra *extra = NULL; int exoptions = 0; - const char *error; int count; int *offsets; int size_offsets; @@ -289,7 +362,7 @@ PHP_FUNCTION(pcre_match) zend_hash_index_update(subpats->value.ht, i, &entry, sizeof(zval *), NULL); } - efree(stringlist); + php_pcre_free(stringlist); } } /* If nothing matched */ @@ -305,7 +378,6 @@ PHP_FUNCTION(pcre_match) } efree(offsets); - efree(re); RETVAL_LONG(matched); } @@ -337,12 +409,9 @@ PHP_FUNCTION(pcre_replace) pcre *re = NULL; pcre_extra *extra = NULL; int exoptions = 0; - const char *error; int count = 0; int *offsets; int size_offsets; - int matched; - const char ***stringlist; int new_len; int alloc_len; int subject_len; @@ -354,6 +423,7 @@ PHP_FUNCTION(pcre_replace) *walkbuf, *walk; + /* Get function parameters and do error-checking. */ if (ARG_COUNT(ht) != 3 || getParameters(ht, 3, ®ex, &replace, &subject) == FAILURE) { WRONG_PARAM_COUNT; } @@ -389,7 +459,8 @@ PHP_FUNCTION(pcre_replace) /* Execute the regular expression. */ count = pcre_exec(re, extra, &subject->value.str.val[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. */ if (count == 0) { @@ -404,7 +475,7 @@ PHP_FUNCTION(pcre_replace) if ('\\' == *walk && _pcre_get_backref(walk+1, &backref) && 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; } else { new_len++; @@ -429,9 +500,9 @@ PHP_FUNCTION(pcre_replace) if ('\\' == *walk && _pcre_get_backref(walk+1, &backref) && backref < count) { - result_len = offsets[2*backref+1] - offsets[2*backref]; + result_len = offsets[(backref<<1)+1] - offsets[backref<<1]; memcpy (walkbuf, - &subject->value.str.val[subject_offset + offsets[2*backref]], + &subject->value.str.val[subject_offset + offsets[backref<<1]], result_len); walkbuf += result_len; walk += (backref > 9) ? 3 : 2; @@ -457,7 +528,7 @@ PHP_FUNCTION(pcre_replace) } else { subject_offset += offsets[1]; } - } else { /* REG_NOMATCH */ + } else { new_len = strlen(result) + strlen(&subject->value.str.val[subject_offset]); if (new_len + 1 > alloc_len) { alloc_len = new_len + 1; /* now we know exactly how long it is */ @@ -472,7 +543,6 @@ PHP_FUNCTION(pcre_replace) } efree(offsets); - efree(re); RETVAL_STRING(result, 1); efree(result); diff --git a/ext/pcre/php_pcre.h b/ext/pcre/php_pcre.h index a5b5671111..551f35b5a4 100644 --- a/ext/pcre/php_pcre.h +++ b/ext/pcre/php_pcre.h @@ -37,6 +37,8 @@ #include "pcre.h" 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); PHP_FUNCTION(pcre_match); @@ -45,6 +47,32 @@ PHP_FUNCTION(pcre_replace); extern zend_module_entry 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 #define pcre_module_ptr NULL -- 2.40.0