]> granicus.if.org Git - php/commitdiff
Revert "Simplify php_implode(). Fill the resulting string in direct order."
authorDmitry Stogov <dmitry@zend.com>
Tue, 23 Jun 2015 13:46:41 +0000 (16:46 +0300)
committerDmitry Stogov <dmitry@zend.com>
Tue, 23 Jun 2015 13:46:41 +0000 (16:46 +0300)
The patch slightly improved performance of string imploding, but reduced speed of integers imploding.

This reverts commit 36d39b70443dcefeeb62d189ce67b414caf5486a.

ext/standard/string.c

index a5e22842d48a1d5fae48818582bbc1d751540e90..186f68767bce7971baa10be7cb0d0e69da3f701a 100644 (file)
@@ -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);