summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrey Hristov <andrey@php.net>2004-07-18 11:34:28 +0000
committerAndrey Hristov <andrey@php.net>2004-07-18 11:34:28 +0000
commit96f5c697ddbf663e0164a63d58d43d2dfd37a1f5 (patch)
treee6a37a686a4ed7f005272fc6114f7a1acdba5738
parent29ba20eea00a77e55531465f1f29659cc77fd973 (diff)
downloadphp-git-96f5c697ddbf663e0164a63d58d43d2dfd37a1f5.tar.gz
Add support for negative values of limit of explode(). If limit is negative
then all components are returned except the last abs(limit) ones.
-rw-r--r--ext/standard/string.c54
-rw-r--r--ext/standard/tests/strings/explode.phpt40
2 files changed, 93 insertions, 1 deletions
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"
+}