summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitry Stogov <dmitry@zend.com>2014-12-19 18:00:16 +0300
committerDmitry Stogov <dmitry@zend.com>2014-12-19 18:00:16 +0300
commit4514ba016ff158cd113deef1a215fcdcb6913b48 (patch)
treee6620ce3b55ae6bfcbfbc3386ef39e013b0487bd
parent92655be7cf10f7551ee1a1ae7ea0f1bdcfa2ca6b (diff)
downloadphp-git-4514ba016ff158cd113deef1a215fcdcb6913b48.tar.gz
Improved setlocale(). Eliminated locale comparison in ext/pcre if it's not necessary.
-rw-r--r--ext/pcre/php_pcre.c44
-rw-r--r--ext/pcre/php_pcre.h2
-rw-r--r--ext/standard/basic_functions.c4
-rw-r--r--ext/standard/basic_functions.h2
-rw-r--r--ext/standard/string.c67
5 files changed, 52 insertions, 67 deletions
diff --git a/ext/pcre/php_pcre.c b/ext/pcre/php_pcre.c
index ffdb411796..d3eb4d49fe 100644
--- a/ext/pcre/php_pcre.c
+++ b/ext/pcre/php_pcre.c
@@ -23,6 +23,7 @@
#include "php_globals.h"
#include "php_pcre.h"
#include "ext/standard/info.h"
+#include "ext/standard/basic_functions.h"
#include "zend_smart_str.h"
#if HAVE_PCRE || HAVE_BUNDLED_PCRE
@@ -96,7 +97,9 @@ static void php_free_pcre_cache(zval *data) /* {{{ */
}
#if HAVE_SETLOCALE
if ((void*)pce->tables) pefree((void*)pce->tables, 1);
- pefree(pce->locale, 1);
+ if (pce->locale) {
+ zend_string_release(pce->locale);
+ }
#endif
pefree(pce, 1);
}
@@ -238,41 +241,24 @@ PHPAPI pcre_cache_entry* pcre_get_compiled_regex_cache(zend_string *regex)
int do_study = 0;
int poptions = 0;
unsigned const char *tables = NULL;
-#if HAVE_SETLOCALE
- char *locale;
-#endif
pcre_cache_entry *pce;
pcre_cache_entry new_entry;
int rc;
-#if HAVE_SETLOCALE
-# if defined(PHP_WIN32) && defined(ZTS)
- _configthreadlocale(_ENABLE_PER_THREAD_LOCALE);
-# endif
- locale = setlocale(LC_CTYPE, NULL);
-#endif
-
/* Try to lookup the cached regex entry, and if successful, just pass
back the compiled pattern, otherwise go on and compile it. */
pce = zend_hash_find_ptr(&PCRE_G(pcre_cache), regex);
if (pce) {
- /*
- * We use a quick pcre_fullinfo() check to see whether cache is corrupted, and if it
- * is, we flush it and compile the pattern from scratch.
- */
-//??? int count = 0;
-//???
-//??? if (pcre_fullinfo(pce->re, NULL, PCRE_INFO_CAPTURECOUNT, &count) == PCRE_ERROR_BADMAGIC) {
-//??? zend_hash_clean(&PCRE_G(pcre_cache));
-//??? } else {
-#if HAVE_SETLOCALE
- if (!strcmp(pce->locale, locale)) {
-#endif
- return pce;
#if HAVE_SETLOCALE
- }
+ if (pce->locale == BG(locale_string) ||
+ (pce->locale && BG(locale_string) &&
+ pce->locale->len == BG(locale_string)->len &&
+ !memcmp(pce->locale->val, BG(locale_string)->val, pce->locale->len))) {
+ return pce;
+ }
+#else
+ return pce;
#endif
-//??? }
}
p = regex->val;
@@ -389,8 +375,10 @@ PHPAPI pcre_cache_entry* pcre_get_compiled_regex_cache(zend_string *regex)
}
#if HAVE_SETLOCALE
- if (strcmp(locale, "C"))
+ if (BG(locale_string) &&
+ (!BG(locale_string)->len != 1 || !BG(locale_string)->val[0] != 'C')) {
tables = pcre_maketables();
+ }
#endif
/* Compile pattern and display a warning if compilation failed. */
@@ -451,7 +439,7 @@ PHPAPI pcre_cache_entry* pcre_get_compiled_regex_cache(zend_string *regex)
new_entry.preg_options = poptions;
new_entry.compile_options = coptions;
#if HAVE_SETLOCALE
- new_entry.locale = pestrdup(locale, 1);
+ new_entry.locale = BG(locale_string) ? zend_string_dup(BG(locale_string), 1) : NULL;
new_entry.tables = tables;
#endif
diff --git a/ext/pcre/php_pcre.h b/ext/pcre/php_pcre.h
index 86f13e3447..ff1b2267e8 100644
--- a/ext/pcre/php_pcre.h
+++ b/ext/pcre/php_pcre.h
@@ -47,7 +47,7 @@ typedef struct {
int capture_count;
int name_count;
#if HAVE_SETLOCALE
- char *locale;
+ zend_string *locale;
unsigned const char *tables;
#endif
int compile_options;
diff --git a/ext/standard/basic_functions.c b/ext/standard/basic_functions.c
index 7cae46f29b..cef9c6d967 100644
--- a/ext/standard/basic_functions.c
+++ b/ext/standard/basic_functions.c
@@ -3760,9 +3760,7 @@ PHP_RSHUTDOWN_FUNCTION(basic) /* {{{ */
setlocale(LC_ALL, "C");
setlocale(LC_CTYPE, "");
zend_update_current_locale();
- }
- if (BG(locale_string)) {
- efree(BG(locale_string));
+ zend_string_release(BG(locale_string));
BG(locale_string) = NULL;
}
diff --git a/ext/standard/basic_functions.h b/ext/standard/basic_functions.h
index d6f926a90e..fe09dc5e25 100644
--- a/ext/standard/basic_functions.h
+++ b/ext/standard/basic_functions.h
@@ -168,7 +168,7 @@ typedef struct _php_basic_globals {
HashTable putenv_ht;
zval strtok_zval;
char *strtok_string;
- char *locale_string;
+ zend_string *locale_string;
char *strtok_last;
char strtok_table[256];
zend_ulong strtok_len;
diff --git a/ext/standard/string.c b/ext/standard/string.c
index 4ea0c9ff4b..419fef3d59 100644
--- a/ext/standard/string.c
+++ b/ext/standard/string.c
@@ -4184,8 +4184,9 @@ PHP_FUNCTION(setlocale)
{
zval *args = NULL;
zval *pcategory, *plocale;
+ zend_string *loc;
+ char *retval;
int num_args, cat, i = 0;
- char *loc, *retval;
HashPosition pos;
if (zend_parse_parameters(ZEND_NUM_ARGS(), "z+", &pcategory, &args, &num_args) == FAILURE) {
@@ -4197,38 +4198,32 @@ PHP_FUNCTION(setlocale)
cat = (int)Z_LVAL_P(pcategory);
} else {
/* FIXME: The following behaviour should be removed. */
- char *category;
- zval tmp;
+ zend_string *category = zval_get_string(pcategory);
php_error_docref(NULL, E_DEPRECATED, "Passing locale category name as string is deprecated. Use the LC_* -constants instead");
-
- ZVAL_DUP(&tmp, pcategory);
- convert_to_string_ex(&tmp);
- category = Z_STRVAL(tmp);
-
- if (!strcasecmp("LC_ALL", category)) {
+ if (!strcasecmp("LC_ALL", category->val)) {
cat = LC_ALL;
- } else if (!strcasecmp("LC_COLLATE", category)) {
+ } else if (!strcasecmp("LC_COLLATE", category->val)) {
cat = LC_COLLATE;
- } else if (!strcasecmp("LC_CTYPE", category)) {
+ } else if (!strcasecmp("LC_CTYPE", category->val)) {
cat = LC_CTYPE;
#ifdef LC_MESSAGES
- } else if (!strcasecmp("LC_MESSAGES", category)) {
+ } else if (!strcasecmp("LC_MESSAGES", category->val)) {
cat = LC_MESSAGES;
#endif
- } else if (!strcasecmp("LC_MONETARY", category)) {
+ } else if (!strcasecmp("LC_MONETARY", category->val)) {
cat = LC_MONETARY;
- } else if (!strcasecmp("LC_NUMERIC", category)) {
+ } else if (!strcasecmp("LC_NUMERIC", category->val)) {
cat = LC_NUMERIC;
- } else if (!strcasecmp("LC_TIME", category)) {
+ } else if (!strcasecmp("LC_TIME", category->val)) {
cat = LC_TIME;
} else {
- php_error_docref(NULL, E_WARNING, "Invalid locale category name %s, must be one of LC_ALL, LC_COLLATE, LC_CTYPE, LC_MONETARY, LC_NUMERIC, or LC_TIME", category);
+ php_error_docref(NULL, E_WARNING, "Invalid locale category name %s, must be one of LC_ALL, LC_COLLATE, LC_CTYPE, LC_MONETARY, LC_NUMERIC, or LC_TIME", category->val);
- zval_dtor(&tmp);
+ zend_string_release(category);
RETURN_FALSE;
}
- zval_dtor(&tmp);
+ zend_string_release(category);
}
if (Z_TYPE(args[0]) == IS_ARRAY) {
@@ -4236,7 +4231,6 @@ PHP_FUNCTION(setlocale)
}
while (1) {
- zval tmp;
if (Z_TYPE(args[0]) == IS_ARRAY) {
if (!zend_hash_num_elements(Z_ARRVAL(args[0]))) {
break;
@@ -4248,36 +4242,41 @@ PHP_FUNCTION(setlocale)
plocale = &args[i];
}
- ZVAL_DUP(&tmp, plocale);
- convert_to_string(&tmp);
+ loc = zval_get_string(plocale);
- if (!strcmp ("0", Z_STRVAL(tmp))) {
+ if (!strcmp("0", loc->val)) {
+ zend_string_release(loc);
loc = NULL;
} else {
- loc = Z_STRVAL(tmp);
- if (Z_STRLEN(tmp) >= 255) {
+ if (loc->len >= 255) {
php_error_docref(NULL, E_WARNING, "Specified locale name is too long");
- zval_dtor(&tmp);
+ zend_string_release(loc);
break;
}
}
- retval = php_my_setlocale(cat, loc);
+ retval = php_my_setlocale(cat, loc ? loc->val : NULL);
zend_update_current_locale();
if (retval) {
- /* Remember if locale was changed */
if (loc) {
-//??? zend_string_free(BG(locale_string));
+ /* Remember if locale was changed */
+ size_t len;
+
if (BG(locale_string)) {
- efree(BG(locale_string));
+ zend_string_release(BG(locale_string));
+ }
+ len = strlen(retval);
+ if (len == loc->len && !memcmp(loc->val, retval, len)) {
+ BG(locale_string) = zend_string_copy(loc);
+ } else {
+ BG(locale_string) = zend_string_init(retval, len, 0);
}
- BG(locale_string) = estrdup(retval);
- }
- zval_dtor(&tmp);
- RETURN_STRING(retval);
+ zend_string_release(loc);
+ }
+ RETURN_STR(zend_string_copy(BG(locale_string)));
}
- zval_dtor(&tmp);
+ zend_string_release(loc);
if (Z_TYPE(args[0]) == IS_ARRAY) {
if (zend_hash_move_forward_ex(Z_ARRVAL(args[0]), &pos) == FAILURE) break;