From b66b227b784f2066c74e861eb6282cc83d2a0805 Mon Sep 17 00:00:00 2001 From: Andres Gutierrez Date: Fri, 24 Oct 2014 14:28:00 -0500 Subject: [PATCH] Fixing str_replace optimizer with array search parameter --- Library/Optimizers/EvalExpression.php | 4 + .../FunctionCall/StrReplaceOptimizer.php | 2 +- .../FunctionCall/UniqueKeyOptimizer.php | 2 +- .../FunctionCall/UniquePathKeyOptimizer.php | 2 +- ext/kernel/fcall.h | 2 +- ext/kernel/string.c | 84 +++++++++++-------- 6 files changed, 55 insertions(+), 41 deletions(-) diff --git a/Library/Optimizers/EvalExpression.php b/Library/Optimizers/EvalExpression.php index ffcce004f6..9920efeb38 100644 --- a/Library/Optimizers/EvalExpression.php +++ b/Library/Optimizers/EvalExpression.php @@ -41,6 +41,8 @@ class EvalExpression protected $_usedVariables = array(); /** + * Skips the not operator by recursively optimizing the expression at its right + * * @param array $expr * @param CompilationContext $compilationContext */ @@ -54,6 +56,8 @@ public function optimizeNot($expr, $compilationContext) if ($conditions !== false) { if ($this->_unreachable !== null) { $this->_unreachable = !$this->_unreachable; + } + if ($this->_unreachableElse !== null) { $this->_unreachableElse = !$this->_unreachableElse; } return '!(' . $conditions . ')'; diff --git a/Library/Optimizers/FunctionCall/StrReplaceOptimizer.php b/Library/Optimizers/FunctionCall/StrReplaceOptimizer.php index e39f7a23d4..6b273b06d2 100644 --- a/Library/Optimizers/FunctionCall/StrReplaceOptimizer.php +++ b/Library/Optimizers/FunctionCall/StrReplaceOptimizer.php @@ -46,7 +46,7 @@ public function optimize(array $expression, Call $call, CompilationContext $cont } if (count($expression['parameters']) != 3) { - throw new CompilerException("'str_replace' only accepts three parameter"); + throw new CompilerException("'str_replace' only accepts three parameter", $expression); } /** diff --git a/Library/Optimizers/FunctionCall/UniqueKeyOptimizer.php b/Library/Optimizers/FunctionCall/UniqueKeyOptimizer.php index e699c2f0a3..a4e6995918 100644 --- a/Library/Optimizers/FunctionCall/UniqueKeyOptimizer.php +++ b/Library/Optimizers/FunctionCall/UniqueKeyOptimizer.php @@ -46,7 +46,7 @@ public function optimize(array $expression, Call $call, CompilationContext $cont } if (count($expression['parameters']) != 2) { - throw new CompilerException("'unique_key' only accepts three parameter"); + throw new CompilerException("'unique_key' only accepts three parameter", $expression); } /** diff --git a/Library/Optimizers/FunctionCall/UniquePathKeyOptimizer.php b/Library/Optimizers/FunctionCall/UniquePathKeyOptimizer.php index ca24da314a..5d6677f779 100644 --- a/Library/Optimizers/FunctionCall/UniquePathKeyOptimizer.php +++ b/Library/Optimizers/FunctionCall/UniquePathKeyOptimizer.php @@ -46,7 +46,7 @@ public function optimize(array $expression, Call $call, CompilationContext $cont } if (count($expression['parameters']) != 1) { - throw new CompilerException("'unique_path_key' only accepts three parameter"); + throw new CompilerException("'unique_path_key' only accepts three parameter", $expression); } /** diff --git a/ext/kernel/fcall.h b/ext/kernel/fcall.h index d0c9c36d4a..2e95d87dc9 100644 --- a/ext/kernel/fcall.h +++ b/ext/kernel/fcall.h @@ -428,7 +428,7 @@ typedef zend_function zephir_fcall_cache_entry; int zephir_call_func_aparams(zval **return_value_ptr, const char *func_name, uint func_length, zephir_fcall_cache_entry **cache_entry, - uint param_count, zval **params TSRMLS_DC) ZEPHIR_ATTR_WARN_UNUSED_RESULT; + uint param_count, zval **params TSRMLS_DC); int zephir_call_zval_func_aparams(zval **return_value_ptr, zval *func_name, zephir_fcall_cache_entry **cache_entry, diff --git a/ext/kernel/string.c b/ext/kernel/string.c index cd7a2003a1..9f8cbfca32 100644 --- a/ext/kernel/string.c +++ b/ext/kernel/string.c @@ -517,6 +517,17 @@ void zephir_fast_str_replace(zval *return_value, zval *search, zval *replace, zv return; } + /** + * Fallback to userland function if the first parameter is an array + */ + if (Z_TYPE_P(search) == IS_ARRAY) { + do { + zval *params[] = { search, replace, subject }; + zephir_call_func_aparams(&return_value, "str_replace", sizeof("str_replace")-1, NULL, 3, params TSRMLS_CC); + return; + } while(0); + } + if (Z_TYPE_P(replace) != IS_STRING) { zend_make_printable_zval(replace, &replace_copy, ©_replace); if (copy_replace) { @@ -922,54 +933,53 @@ void zephir_substr(zval *return_value, zval *str, long f, long l) { RETURN_FALSE; } - long str_len = Z_STRLEN_P(str); + long str_len = Z_STRLEN_P(str); - if ((l < 0 && -l > str_len)) { - RETURN_FALSE; - } else if (l > str_len) { - l = str_len; - } else if (l == 0) { - l = str_len; - } - - if (f > str_len) { - RETURN_FALSE; - } else if (f < 0 && -f > str_len) { - f = 0; - } + if ((l < 0 && -l > str_len)) { + RETURN_FALSE; + } else if (l > str_len) { + l = str_len; + } else if (l == 0) { + l = str_len; + } - if (l < 0 && (l + str_len - f) < 0) { - RETURN_FALSE; - } + if (f > str_len) { + RETURN_FALSE; + } else if (f < 0 && -f > str_len) { + f = 0; + } + if (l < 0 && (l + str_len - f) < 0) { + RETURN_FALSE; + } - /* if "from" position is negative, count start position from the end - * of the string - */ + /* if "from" position is negative, count start position from the end + * of the string + */ + if (f < 0) { + f = str_len + f; if (f < 0) { - f = str_len + f; - if (f < 0) { - f = 0; - } + f = 0; } + } - /* if "length" position is negative, set it to the length - * needed to stop that many chars from the end of the string - */ + /* if "length" position is negative, set it to the length + * needed to stop that many chars from the end of the string + */ + if (l < 0) { + l = (str_len - f) + l; if (l < 0) { - l = (str_len - f) + l; - if (l < 0) { - l = 0; - } + l = 0; } + } - if (f >= str_len) { - RETURN_FALSE; - } + if (f >= str_len) { + RETURN_FALSE; + } - if ((f + l) > str_len) { - l = str_len - f; - } + if ((f + l) > str_len) { + l = str_len - f; + } if (l <= 0){ RETURN_EMPTY_STRING();