From: Andrey Hristov Date: Sun, 18 Jul 2004 11:34:28 +0000 (+0000) Subject: Add support for negative values of limit of explode(). If limit is negative X-Git-Tag: PRE_ZEND_VM_DISPATCH_PATCH~476 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=96f5c697ddbf663e0164a63d58d43d2dfd37a1f5;p=php Add support for negative values of limit of explode(). If limit is negative then all components are returned except the last abs(limit) ones. --- diff --git a/ext/standard/string.c b/ext/standard/string.c index 4ee93264fb..7a7020b852 100644 --- a/ext/standard/string.c +++ b/ext/standard/string.c @@ -784,8 +784,52 @@ PHPAPI void php_explode(zval *delim, zval *str, zval *return_value, int limit) } /* }}} */ +/* {{{ php_explode_negative_limit + */ +PHPAPI void php_explode_negative_limit(zval *delim, zval *str, zval *return_value, int limit) +{ +#define EXPLODE_ALLOC_STEP 50 + char *p1, *p2, *endp; + int allocated = EXPLODE_ALLOC_STEP, found = 0, i = 0, to_return = 0; + char **positions = safe_emalloc(allocated, sizeof(char *), 0); + + endp = Z_STRVAL_P(str) + Z_STRLEN_P(str); + + p1 = Z_STRVAL_P(str); + p2 = php_memnstr(Z_STRVAL_P(str), Z_STRVAL_P(delim), Z_STRLEN_P(delim), endp); + + if (p2 == NULL) { + /* + do nothing since limit <= -1, thus if only one chunk - 1 + (limit) <= 0 + by doing nothing we return empty array + */ + } else { + positions[found++] = p1; + do { + if (found >= allocated) { + allocated = found + EXPLODE_ALLOC_STEP;/* make sure we have enough memory */ + positions = erealloc(positions, allocated*sizeof(char *)); + } + positions[found++] = p1 = p2 + Z_STRLEN_P(delim); + } while ((p2 = php_memnstr(p1, Z_STRVAL_P(delim), Z_STRLEN_P(delim), endp)) != NULL); + + to_return = limit + found; + /* limit is at least -1 therefore no need of bounds checking : i will be always less than found */ + for (i = 0;i < to_return;i++) { /* this checks also for to_return > 0 */ + add_next_index_stringl(return_value, positions[i], + (positions[i+1] - Z_STRLEN_P(delim)) - positions[i], + 1 + ); + } + } + efree(positions); +#undef EXPLODE_ALLOC_STEP +} +/* }}} */ + + /* {{{ proto array explode(string separator, string str [, int limit]) - Splits a string on string separator and return array of components */ + Splits a string on string separator and return array of components. If limit is positive only limit number of components is returned. If limit is negative all components except the last abs(limit) are returned. */ PHP_FUNCTION(explode) { zval **str, **delim, **zlimit = NULL; @@ -810,8 +854,16 @@ PHP_FUNCTION(explode) array_init(return_value); + if (! Z_STRLEN_PP(str)) { + add_next_index_stringl(return_value, "", sizeof("") - 1, 1); + return; + } + + if (limit == 0 || limit == 1) { add_index_stringl(return_value, 0, Z_STRVAL_PP(str), Z_STRLEN_PP(str), 1); + } else if (limit < 0 && argc == 3) { + php_explode_negative_limit(*delim, *str, return_value, limit); } else { php_explode(*delim, *str, return_value, limit); } diff --git a/ext/standard/tests/strings/explode.phpt b/ext/standard/tests/strings/explode.phpt index 9f9b61d5b8..1198a09a97 100644 --- a/ext/standard/tests/strings/explode.phpt +++ b/ext/standard/tests/strings/explode.phpt @@ -19,6 +19,14 @@ var_dump(@explode("somestring", "otherstring")); var_dump(@explode("a", "aaaaaa")); var_dump(@explode("==", str_repeat("-=".ord(0)."=-", 10))); var_dump(@explode("=", str_repeat("-=".ord(0)."=-", 10))); +////////////////////////////////////// +var_dump(explode(":","a lazy dog:jumps:over:",-1)); +var_dump(explode(":","a lazy dog:jumps:over", -1)); +var_dump(explode(":","a lazy dog:jumps:over", -2)); +var_dump(explode(":","a lazy dog:jumps:over:",-4)); +var_dump(explode(":","a lazy dog:jumps:over:",-40000000000000)); +var_dump(explode(":^:","a lazy dog:^:jumps::over:^:",-1)); +var_dump(explode(":^:","a lazy dog:^:jumps::over:^:",-2)); ?> --EXPECTF-- 26d4e18734cb2582df5055e2175223df @@ -112,3 +120,35 @@ array(21) { [20]=> string(1) "-" } +array(3) { + [0]=> + string(10) "a lazy dog" + [1]=> + string(5) "jumps" + [2]=> + string(4) "over" +} +array(2) { + [0]=> + string(10) "a lazy dog" + [1]=> + string(5) "jumps" +} +array(1) { + [0]=> + string(10) "a lazy dog" +} +array(0) { +} +array(0) { +} +array(2) { + [0]=> + string(10) "a lazy dog" + [1]=> + string(11) "jumps::over" +} +array(1) { + [0]=> + string(10) "a lazy dog" +}