Index: string.c =================================================================== RCS file: /repository/php-src/ext/standard/string.c,v retrieving revision 1.422 diff -u -r1.422 string.c --- string.c 19 Jul 2004 07:19:45 -0000 1.422 +++ string.c 15 Aug 2004 13:49:57 -0000 @@ -1970,22 +1970,53 @@ zval **from; zval **len = NULL; zval **repl; + zval **modify_origin; char *result; int result_len; int l = 0; int f; int argc = ZEND_NUM_ARGS(); + zend_bool mod_orig = 0; HashPosition pos_str, pos_from, pos_repl, pos_len; zval **tmp_str = NULL, **tmp_from = NULL, **tmp_repl = NULL, **tmp_len= NULL; - - if (argc < 3 || argc > 4 || zend_get_parameters_ex(argc, &str, &repl, &from, &len) == FAILURE) { + if (argc < 3 || argc > 5 || zend_get_parameters_ex(argc, &str, &repl, &from, &len, &modify_origin) == FAILURE) { WRONG_PARAM_COUNT; } - + + + if (argc > 3) { + switch (argc) { + case 5: + convert_to_boolean_ex(modify_origin); + mod_orig = Z_LVAL_PP(modify_origin); + if (mod_orig && !PZVAL_IS_REF(*str)) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "When modify_origin mode is enabled first element must be passed by reference"); + RETURN_FALSE; + } + /* user may pass NULL and then "len" is not used */ + if (Z_TYPE_PP(len) == IS_NULL) + break; + /* fall-through */ + case 4: + if (Z_TYPE_PP(len) == IS_ARRAY) + break; + l = Z_LVAL_PP(len); + break; + } + } else { + if (Z_TYPE_PP(str) != IS_ARRAY) { + l = Z_STRLEN_PP(str); + } + } + if (Z_TYPE_PP(str) != IS_ARRAY) { - convert_to_string_ex(str); + if (!mod_orig) { + convert_to_string_ex(str); + } else { + convert_to_string(*str); + } } if (Z_TYPE_PP(repl) != IS_ARRAY) { convert_to_string_ex(repl); @@ -1994,16 +2025,6 @@ convert_to_long_ex(from); } - if (argc > 3) { - if (Z_TYPE_PP(len) != IS_ARRAY) { - convert_to_long_ex(len); - l = Z_LVAL_PP(len); - } - } else { - if (Z_TYPE_PP(str) != IS_ARRAY) { - l = Z_STRLEN_PP(str); - } - } if (Z_TYPE_PP(str) == IS_STRING) { if ( @@ -2012,12 +2033,14 @@ (argc == 4 && Z_TYPE_PP(from) != Z_TYPE_PP(len)) ) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "'from' and 'len' should be of same type - numerical or array "); - RETURN_STRINGL(Z_STRVAL_PP(str), Z_STRLEN_PP(str), 1); + RETURN_FALSE; +/* RETURN_STRINGL(Z_STRVAL_PP(str), Z_STRLEN_PP(str), 1);*/ } if (argc == 4 && Z_TYPE_PP(from) == IS_ARRAY) { if (zend_hash_num_elements(Z_ARRVAL_PP(from)) != zend_hash_num_elements(Z_ARRVAL_PP(len))) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "'from' and 'len' should have the same number of elements"); - RETURN_STRINGL(Z_STRVAL_PP(str), Z_STRLEN_PP(str), 1); + RETURN_FALSE; +/* RETURN_STRINGL(Z_STRVAL_PP(str), Z_STRLEN_PP(str), 1);*/ } } } @@ -2063,21 +2086,35 @@ repl_len = Z_STRLEN_PP(repl); } result_len = Z_STRLEN_PP(str) - l + repl_len; - result = emalloc(result_len + 1); + /* if not modifying origin - return the new string. when modifying origin return void */ + if (!mod_orig) { + result = emalloc(result_len + 1); - memcpy(result, Z_STRVAL_PP(str), f); - if (repl_len) { - memcpy((result + f), (Z_TYPE_PP(repl) == IS_ARRAY ? Z_STRVAL_PP(tmp_repl) : Z_STRVAL_PP(repl)), repl_len); - } - memcpy((result + f + repl_len), Z_STRVAL_PP(str) + f + l, Z_STRLEN_PP(str) - f - l); - result[result_len] = '\0'; - RETURN_STRINGL(result, result_len, 0); + memcpy(result, Z_STRVAL_PP(str), f); + if (repl_len) { + memcpy((result + f), (Z_TYPE_PP(repl) == IS_ARRAY ? Z_STRVAL_PP(tmp_repl) : Z_STRVAL_PP(repl)), repl_len); + } + memcpy((result + f + repl_len), Z_STRVAL_PP(str) + f + l, Z_STRLEN_PP(str) - f - l); + result[result_len] = '\0'; + RETURN_STRINGL(result, result_len, 0); + } else { + memcpy(Z_STRVAL_PP(str) + f, (Z_TYPE_PP(repl) == IS_ARRAY ? Z_STRVAL_PP(tmp_repl) : Z_STRVAL_PP(repl)), repl_len); + memmove((Z_STRVAL_PP(str) + f + repl_len), Z_STRVAL_PP(str) + f + l, Z_STRLEN_PP(str) - f - l); + if (Z_STRLEN_PP(str) != result_len) { + zend_printf("erealloc()\n"); + Z_STRVAL_PP(str) = erealloc(Z_STRVAL_PP(str), result_len + 1); + } + Z_STRVAL_PP(str)[result_len] = '\0'; + Z_STRLEN_PP(str) = result_len; + RETURN_NULL(); + } } else { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Functionality of 'from' and 'len' as arrays is not implemented."); RETURN_STRINGL(Z_STRVAL_PP(str), Z_STRLEN_PP(str), 1); } } else { /* str is array of strings */ - array_init(return_value); + if (!mod_orig) + array_init(return_value); if (Z_TYPE_PP(from) == IS_ARRAY) { zend_hash_internal_pointer_reset_ex(Z_ARRVAL_PP(from), &pos_from); @@ -2093,7 +2130,11 @@ zend_hash_internal_pointer_reset_ex(Z_ARRVAL_PP(str), &pos_str); while (zend_hash_get_current_data_ex(Z_ARRVAL_PP(str), (void **) &tmp_str, &pos_str) == SUCCESS) { - convert_to_string_ex(tmp_str); + if (!mod_orig) { + convert_to_string_ex(tmp_str); + } else { + convert_to_string(*tmp_str); + } if (Z_TYPE_PP(from) == IS_ARRAY) { if (SUCCESS == zend_hash_get_current_data_ex(Z_ARRVAL_PP(from), (void **) &tmp_from, &pos_from)) { @@ -2154,35 +2195,72 @@ if (Z_TYPE_PP(repl) == IS_ARRAY) { if (SUCCESS == zend_hash_get_current_data_ex(Z_ARRVAL_PP(repl), (void **) &tmp_repl, &pos_repl)) { + convert_to_string_ex(tmp_repl); result_len += Z_STRLEN_PP(tmp_repl); zend_hash_move_forward_ex(Z_ARRVAL_PP(repl), &pos_repl); result = emalloc(result_len + 1); - - memcpy(result, Z_STRVAL_PP(tmp_str), f); - memcpy((result + f), Z_STRVAL_PP(tmp_repl), Z_STRLEN_PP(tmp_repl)); - memcpy((result + f + Z_STRLEN_PP(tmp_repl)), Z_STRVAL_PP(tmp_str) + f + l, Z_STRLEN_PP(tmp_str) - f - l); + if (!mod_orig) { + memcpy(result, Z_STRVAL_PP(tmp_str), f); + memcpy((result + f), Z_STRVAL_PP(tmp_repl), Z_STRLEN_PP(tmp_repl)); + memcpy((result + f + Z_STRLEN_PP(tmp_repl)), Z_STRVAL_PP(tmp_str) + f + l, Z_STRLEN_PP(tmp_str) - f - l); + } else { + memcpy(Z_STRVAL_PP(tmp_str) + f, Z_STRVAL_PP(tmp_repl), Z_STRLEN_PP(tmp_repl)); + memmove((Z_STRVAL_PP(tmp_str) + f + Z_STRLEN_PP(tmp_repl)), Z_STRVAL_PP(tmp_str) + f + l, Z_STRLEN_PP(tmp_str) - f - l); + if (Z_STRLEN_PP(tmp_str) != result_len) { + zend_printf("erealloc()\n"); + Z_STRVAL_PP(tmp_str) = erealloc(Z_STRVAL_PP(tmp_str), result_len + 1); + } + Z_STRVAL_PP(tmp_str)[result_len] = '\0'; + Z_STRLEN_PP(tmp_str) = result_len; + } } else { - result = emalloc(result_len + 1); - - memcpy(result, Z_STRVAL_PP(tmp_str), f); - memcpy((result + f), Z_STRVAL_PP(tmp_str) + f + l, Z_STRLEN_PP(tmp_str) - f - l); + /* no more elements in "repl" array, use empty string "" -> delete segments from original string */ + + if (!mod_orig) { + result = emalloc(result_len + 1); + + memcpy(result, Z_STRVAL_PP(tmp_str), f); + memcpy((result + f), Z_STRVAL_PP(tmp_str) + f + l, Z_STRLEN_PP(tmp_str) - f - l); + } else { + memmove((Z_STRVAL_PP(tmp_str) + f), Z_STRVAL_PP(tmp_str) + f + l, Z_STRLEN_PP(tmp_str) - f - l); + if (Z_STRLEN_PP(tmp_str) != result_len) { + zend_printf("erealloc()\n"); + Z_STRVAL_PP(tmp_str) = erealloc(Z_STRVAL_PP(tmp_str), result_len + 1); + } + Z_STRVAL_PP(tmp_str)[result_len] = '\0'; + Z_STRLEN_PP(tmp_str) = result_len; + } } - } else { + } else { /* repl is not an array - string */ result_len += Z_STRLEN_PP(repl); + + if (!mod_orig) { + result = emalloc(result_len + 1); - result = emalloc(result_len + 1); - - memcpy(result, Z_STRVAL_PP(tmp_str), f); - memcpy((result + f), Z_STRVAL_PP(repl), Z_STRLEN_PP(repl)); - memcpy((result + f + Z_STRLEN_PP(repl)), Z_STRVAL_PP(tmp_str) + f + l, Z_STRLEN_PP(tmp_str) - f - l); + memcpy(result, Z_STRVAL_PP(tmp_str), f); + memcpy((result + f), Z_STRVAL_PP(repl), Z_STRLEN_PP(repl)); + memcpy((result + f + Z_STRLEN_PP(repl)), Z_STRVAL_PP(tmp_str) + f + l, Z_STRLEN_PP(tmp_str) - f - l); + } else { + memcpy(Z_STRVAL_PP(tmp_str) + f, Z_STRVAL_PP(repl), Z_STRLEN_PP(repl)); + memmove((Z_STRVAL_PP(tmp_str) + f + Z_STRLEN_PP(repl)), Z_STRVAL_PP(tmp_str) + f + l, Z_STRLEN_PP(tmp_str) - f - l); + if (Z_STRLEN_PP(tmp_str) != result_len) { + zend_printf("erealloc()\n"); + Z_STRVAL_PP(tmp_str) = erealloc(Z_STRVAL_PP(tmp_str), result_len + 1); + } + Z_STRVAL_PP(tmp_str)[result_len] = '\0'; + Z_STRLEN_PP(tmp_str) = result_len; + } + } + + if (!mod_orig) { + result[result_len] = '\0'; + add_next_index_stringl(return_value, result, result_len, 0); } - - result[result_len] = '\0'; - add_next_index_stringl(return_value, result, result_len, 0); zend_hash_move_forward_ex(Z_ARRVAL_PP(str), &pos_str); } /*while*/ + } /* if */ } /* }}} */