From: Andrei Zmievski Date: Mon, 22 Jan 2001 21:39:55 +0000 (+0000) Subject: @- Improved str_replace() to accept an array for any parameter - similar X-Git-Tag: php-4.0.5RC1~490 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=63f73bfe13d915020b0a8726d9c7fb635ed23536;p=php @- Improved str_replace() to accept an array for any parameter - similar @ to preg_replace(). (Andrei) --- diff --git a/ext/standard/string.c b/ext/standard/string.c index c68f5d35d5..321183103e 100644 --- a/ext/standard/string.c +++ b/ext/standard/string.c @@ -2159,49 +2159,161 @@ PHPAPI char *php_str_to_str(char *haystack, int length, } -/* {{{ proto string str_replace(string needle, string str, string haystack) - Replace all occurrences of needle in haystack with str */ +static void php_str_replace_in_subject(zval *search, zval *replace, zval **subject, zval *result) +{ + zval **search_entry, + **replace_entry = NULL, + temp_result; + char *replace_value = NULL; + int replace_len = 0; + + /* Make sure we're dealing with strings. */ + convert_to_string_ex(subject); + Z_TYPE_P(result) = IS_STRING; + if (Z_STRLEN_PP(subject) == 0) { + ZVAL_STRINGL(result, empty_string, 0, 1); + return; + } + + /* If search is an array */ + if (Z_TYPE_P(search) == IS_ARRAY) { + /* Duplicate subject string for repeated replacement */ + *result = **subject; + zval_copy_ctor(result); + + zend_hash_internal_pointer_reset(Z_ARRVAL_P(search)); + + if (Z_TYPE_P(replace) == IS_ARRAY) { + zend_hash_internal_pointer_reset(Z_ARRVAL_P(replace)); + } else { + /* Set replacement value to the passed one */ + replace_value = Z_STRVAL_P(replace); + replace_len = Z_STRLEN_P(replace); + } + + /* For each entry in the search array, get the entry */ + while (zend_hash_get_current_data(Z_ARRVAL_P(search), (void **)&search_entry) == SUCCESS) { + /* Make sure we're dealing with strings. */ + convert_to_string_ex(search_entry); + if(Z_STRLEN_PP(search_entry) == 0) { + zend_hash_move_forward(Z_ARRVAL_P(search)); + continue; + } + + /* If replace is an array. */ + if (Z_TYPE_P(replace) == IS_ARRAY) { + /* Get current entry */ + if (zend_hash_get_current_data(Z_ARRVAL_P(replace), (void **)&replace_entry) == SUCCESS) { + /* Make sure we're dealing with strings. */ + convert_to_string_ex(replace_entry); + + /* Set replacement value to the one we got from array */ + replace_value = Z_STRVAL_PP(replace_entry); + replace_len = Z_STRLEN_PP(replace_entry); + + zend_hash_move_forward(Z_ARRVAL_P(replace)); + } else { + /* We've run out of replacement strings, so use an empty one. */ + replace_value = empty_string; + replace_len = 0; + } + } + + if(Z_STRLEN_PP(search_entry) == 1) { + php_char_to_str(Z_STRVAL_P(result), + Z_STRLEN_P(result), + Z_STRVAL_PP(search_entry)[0], + replace_value, + replace_len, + &temp_result); + } else if (Z_STRLEN_PP(search_entry) > 1) { + Z_STRVAL(temp_result) = php_str_to_str(Z_STRVAL_P(result), Z_STRLEN_P(result), + Z_STRVAL_PP(search_entry), Z_STRLEN_PP(search_entry), + replace_value, replace_len, &Z_STRLEN(temp_result)); + } + + efree(Z_STRVAL_P(result)); + Z_STRVAL_P(result) = Z_STRVAL(temp_result); + Z_STRLEN_P(result) = Z_STRLEN(temp_result); + + zend_hash_move_forward(Z_ARRVAL_P(search)); + } + } else { + if (Z_STRLEN_P(search) == 1) { + php_char_to_str(Z_STRVAL_PP(subject), + Z_STRLEN_PP(subject), + Z_STRVAL_P(search)[0], + Z_STRVAL_P(replace), + Z_STRLEN_P(replace), + result); + } else if (Z_STRLEN_P(search) > 1) { + Z_STRVAL_P(result) = php_str_to_str(Z_STRVAL_PP(subject), Z_STRLEN_PP(subject), + Z_STRVAL_P(search), Z_STRLEN_P(search), + Z_STRVAL_P(replace), Z_STRLEN_P(replace), &Z_STRLEN_P(result)); + } else { + *result = **subject; + zval_copy_ctor(result); + } + } +} + + +/* {{{ proto mixed str_replace(mixed search, mixed replace, mixed subject) + Replace all occurrences of search in haystack with replace */ PHP_FUNCTION(str_replace) { - zval **haystack, **needle, **str; - char *result; - int len = 0; + zval **subject, **search, **replace, **subject_entry; + zval *result; + char *string_key; + ulong string_key_len, num_key; if(ZEND_NUM_ARGS() != 3 || - zend_get_parameters_ex(3, &needle, &str, &haystack) == FAILURE) { + zend_get_parameters_ex(3, &search, &replace, &subject) == FAILURE) { WRONG_PARAM_COUNT; } - convert_to_string_ex(haystack); - convert_to_string_ex(needle); - convert_to_string_ex(str); + SEPARATE_ZVAL(search); + SEPARATE_ZVAL(replace); + SEPARATE_ZVAL(subject); - if((*haystack)->value.str.len == 0) { - RETURN_STRING(empty_string,1); - } - - if((*needle)->value.str.len == 1) { - php_char_to_str((*haystack)->value.str.val, - (*haystack)->value.str.len, - (*needle)->value.str.val[0], - (*str)->value.str.val, - (*str)->value.str.len, - return_value); - return; - } + /* Make sure we're dealing with strings and do the replacement. */ + if (Z_TYPE_PP(search) != IS_ARRAY) { + convert_to_string_ex(search); + convert_to_string_ex(replace); + } else if (Z_TYPE_PP(replace) != IS_ARRAY) + convert_to_string_ex(replace); - if((*needle)->value.str.len == 0) { - php_error(E_WARNING, "The length of the needle must not be 0"); - RETURN_FALSE; - } + /* if subject is an array */ + if (Z_TYPE_PP(subject) == IS_ARRAY) { + array_init(return_value); + zend_hash_internal_pointer_reset(Z_ARRVAL_PP(subject)); + + /* For each subject entry, convert it to string, then perform replacement + and add the result to the return_value array. */ + while (zend_hash_get_current_data(Z_ARRVAL_PP(subject), (void **)&subject_entry) == SUCCESS) { + MAKE_STD_ZVAL(result); + php_str_replace_in_subject(*search, *replace, subject_entry, result); + /* Add to return array */ + switch(zend_hash_get_current_key_ex(Z_ARRVAL_PP(subject), &string_key, + &string_key_len, &num_key, 0, NULL)) { + case HASH_KEY_IS_STRING: + add_assoc_zval_ex(return_value, string_key, string_key_len, result); + break; - result = php_str_to_str((*haystack)->value.str.val, (*haystack)->value.str.len, - (*needle)->value.str.val, (*needle)->value.str.len, - (*str)->value.str.val, (*str)->value.str.len, &len); - RETURN_STRINGL(result, len, 0); + case HASH_KEY_IS_LONG: + add_index_zval(return_value, num_key, result); + break; + } + + zend_hash_move_forward(Z_ARRVAL_PP(subject)); + } + } else { /* if subject is not an array */ + php_str_replace_in_subject(*search, *replace, subject, return_value); + } } /* }}} */ + /* Converts Logical Hebrew text (Hebrew Windows style) to Visual text * Cheers/complaints/flames - Zeev Suraski */