diff options
author | Dmitry Stogov <dmitry@zend.com> | 2014-12-19 18:00:16 +0300 |
---|---|---|
committer | Dmitry Stogov <dmitry@zend.com> | 2014-12-19 18:00:16 +0300 |
commit | 4514ba016ff158cd113deef1a215fcdcb6913b48 (patch) | |
tree | e6620ce3b55ae6bfcbfbc3386ef39e013b0487bd | |
parent | 92655be7cf10f7551ee1a1ae7ea0f1bdcfa2ca6b (diff) | |
download | php-git-4514ba016ff158cd113deef1a215fcdcb6913b48.tar.gz |
Improved setlocale(). Eliminated locale comparison in ext/pcre if it's not necessary.
-rw-r--r-- | ext/pcre/php_pcre.c | 44 | ||||
-rw-r--r-- | ext/pcre/php_pcre.h | 2 | ||||
-rw-r--r-- | ext/standard/basic_functions.c | 4 | ||||
-rw-r--r-- | ext/standard/basic_functions.h | 2 | ||||
-rw-r--r-- | ext/standard/string.c | 67 |
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; |