From: Dmitry Stogov Date: Tue, 23 Jun 2015 13:46:41 +0000 (+0300) Subject: Revert "Simplify php_implode(). Fill the resulting string in direct order." X-Git-Tag: php-7.0.0alpha2~2^2~6 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=6bf3ecf69a76789c31415d4f7dbca818614285f5;p=php Revert "Simplify php_implode(). Fill the resulting string in direct order." The patch slightly improved performance of string imploding, but reduced speed of integers imploding. This reverts commit 36d39b70443dcefeeb62d189ce67b414caf5486a. --- diff --git a/ext/standard/string.c b/ext/standard/string.c index a5e22842d4..186f68767b 100644 --- a/ext/standard/string.c +++ b/ext/standard/string.c @@ -1200,12 +1200,12 @@ PHP_FUNCTION(explode) */ PHPAPI void php_implode(const zend_string *delim, zval *arr, zval *return_value) { - zval *tmp; + zval *tmp; int numelems; zend_string *str; char *cptr; size_t len = 0; - zend_string **strings, **strptr, **s; + zend_string **strings, **strptr; numelems = zend_hash_num_elements(Z_ARRVAL_P(arr)); @@ -1222,24 +1222,54 @@ PHPAPI void php_implode(const zend_string *delim, zval *arr, zval *return_value) strptr = strings - 1; ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(arr), tmp) { - *++strptr = zval_get_string(tmp); - len += (*strptr)->len; + if (Z_TYPE_P(tmp) == IS_LONG) { + double val = Z_LVAL_P(tmp); + *++strptr = NULL; + ((zend_long *) (strings + numelems))[strptr - strings] = Z_LVAL_P(tmp); + if (val < 0) { + val = -10 * val; + } + if (val < 10) { + len++; + } else { + len += (int) log10(10 * (double) val); + } + } else { + *++strptr = zval_get_string(tmp); + len += (*strptr)->len; + } } ZEND_HASH_FOREACH_END(); str = zend_string_alloc(len + (numelems - 1) * delim->len, 0); - cptr = str->val; + cptr = str->val + str->len; + *cptr = 0; - for (s = strings; s < strptr; s++) { - memcpy(cptr, (*s)->val, (*s)->len); - cptr += (*s)->len; - zend_string_release(*s); + do { + if (*strptr) { + cptr -= (*strptr)->len; + memcpy(cptr, (*strptr)->val, (*strptr)->len); + zend_string_release(*strptr); + } else { + char *oldPtr = cptr; + char oldVal = *cptr; + zend_long val = ((zend_long *) (strings + numelems))[strptr - strings]; + cptr = zend_print_long_to_buf(cptr, val); + *oldPtr = oldVal; + } + cptr -= delim->len; memcpy(cptr, delim->val, delim->len); - cptr += delim->len; - } + } while (--strptr > strings); - memcpy(cptr, (*s)->val, (*s)->len + 1); - zend_string_release(*s); + if (*strptr) { + memcpy(str->val, (*strptr)->val, (*strptr)->len); + zend_string_release(*strptr); + } else { + char *oldPtr = cptr; + char oldVal = *cptr; + zend_print_long_to_buf(cptr, ((zend_long *) (strings + numelems))[strptr - strings]); + *oldPtr = oldVal; + } efree(strings); RETURN_NEW_STR(str);