};
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) */
/* }}} */
+/* {{{ 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)
{
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
}
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;
}
/* }}} */
pcre *re = NULL;
pcre_extra *extra = NULL;
int exoptions = 0;
- const char *error;
int count;
int *offsets;
int size_offsets;
zend_hash_index_update(subpats->value.ht, i, &entry, sizeof(zval *), NULL);
}
- efree(stringlist);
+ php_pcre_free(stringlist);
}
}
/* If nothing matched */
}
efree(offsets);
- efree(re);
RETVAL_LONG(matched);
}
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;
*walkbuf,
*walk;
+ /* Get function parameters and do error-checking. */
if (ARG_COUNT(ht) != 3 || getParameters(ht, 3, ®ex, &replace, &subject) == FAILURE) {
WRONG_PARAM_COUNT;
}
/* 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) {
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++;
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;
} 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 */
}
efree(offsets);
- efree(re);
RETVAL_STRING(result, 1);
efree(result);
#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);
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