diff options
| -rw-r--r-- | ext/standard/string.c | 172 | 
1 files changed, 142 insertions, 30 deletions
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 <zeev@php.net>   */  | 
