I've read CODING_STANDARDS (thanks to Christian Schneider) and corrected my code according to your standards.
Also I've improved speed of algorithm. Now it is not duplicate the string value of array item, if it is has string type already:
if (Z_TYPE_PP(tmp) != IS_STRING) { /* create new instance of a var, then convert it to a string */ SEPARATE_ZVAL(tmp); convert_to_string(*tmp); }
unified diff: =========cut=========== --- string.c Thu May 13 20:44:32 2004 +++ string_implode.c Mon Jun 14 14:28:29 2004 @@ -827,31 +827,84 @@ { zval **tmp; HashPosition pos; - smart_str implstr = {0}; - int numelems, i = 0; + int numelems, i; + size_t result_len, delim_len, tmp_len; + char *result_str, *delim_str, *ptr; + char **str_arr; + size_t *len_arr;
numelems = zend_hash_num_elements(Z_ARRVAL_P(arr)); - - if(numelems == 0) { - RETURN_EMPTY_STRING(); + if (numelems < 1) RETURN_EMPTY_STRING(); + str_arr = (char **) emalloc(numelems * sizeof(char *)); + len_arr = (size_t *) emalloc(numelems * sizeof(size_t)); + if (str_arr == NULL || len_arr == NULL) { + TSRMLS_FETCH(); + php_error_docref(NULL TSRMLS_CC, E_ERROR, "Out of memory"); + RETURN_FALSE; } + delim_str = Z_STRVAL_P(delim); + delim_len = Z_STRLEN_P(delim);
+ /* the first pass: calculate size of memory to allocate */
+ i = 0;
+ result_len = 0;
zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(arr), &pos);
while (zend_hash_get_current_data_ex(Z_ARRVAL_P(arr),
(void **) &tmp,
&pos) == SUCCESS) {
+ if (Z_TYPE_PP(tmp) != IS_STRING) {
+ /* create new instance of a var, then convert it to a string */
SEPARATE_ZVAL(tmp);
convert_to_string(*tmp);
-
- smart_str_appendl(&implstr, Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp));
- if (++i != numelems) {
- smart_str_appendl(&implstr, Z_STRVAL_P(delim), Z_STRLEN_P(delim));
}
+ str_arr[i] = Z_STRVAL_PP(tmp); /* save pointer to string for the second pass (see below) */
+ len_arr[i] = Z_STRLEN_PP(tmp); /* length of the string */
+ result_len += len_arr[i];
+ i++;
+ if (delim_len && i < numelems) result_len += delim_len;
zend_hash_move_forward_ex(Z_ARRVAL_P(arr), &pos);
}
- smart_str_0(&implstr);
+ if (result_len == 0) {
+ /* result_len could be 0 in two cases:
+ 1) both delimiter & array values have nul length
+ 2) array contains one element with nul length
+ */
+ efree(len_arr);
+ efree(str_arr);
+ RETURN_EMPTY_STRING();
+ }
+
+ /* allocate memory */
+ ptr = result_str = emalloc(result_len + 1);
+ if (ptr == NULL) {
+ efree(len_arr);
+ efree(str_arr);
+ TSRMLS_FETCH();
+ php_error_docref(NULL TSRMLS_CC, E_ERROR, "Out of memory");
+ RETURN_FALSE;
+ }
- RETURN_STRINGL(implstr.c, implstr.len, 0); + /* the second pass: implode array into allocated memory */ + for (i = 0; i < numelems - 1; i++) { + if (tmp_len = len_arr[i]) { + memcpy(ptr, str_arr[i], tmp_len); + ptr += tmp_len; + } + if (delim_len) { + memcpy(ptr, delim_str, delim_len); + ptr += delim_len; + } + } + /* copy the last element of the array */ + if (tmp_len = len_arr[i]) { + memcpy(ptr, str_arr[i], tmp_len); + ptr += tmp_len; + } + *ptr = '\0'; + + efree(len_arr); + efree(str_arr); + RETURN_STRINGL(result_str, result_len, 0); } /* }}} */ =========cut===========
-- Using Opera's revolutionary e-mail client: http://www.opera.com/m2/
-- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php