]> granicus.if.org Git - php/commitdiff
Add support for negative values of limit of explode(). If limit is negative
authorAndrey Hristov <andrey@php.net>
Sun, 18 Jul 2004 11:34:28 +0000 (11:34 +0000)
committerAndrey Hristov <andrey@php.net>
Sun, 18 Jul 2004 11:34:28 +0000 (11:34 +0000)
then all components are returned except the last abs(limit) ones.

ext/standard/string.c
ext/standard/tests/strings/explode.phpt

index 4ee93264fbdd520f9ab3cc62e2b6c3b02b2a1f34..7a7020b852995580798ea23cff7134e928581d77 100644 (file)
@@ -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);
        }
index 9f9b61d5b8a3a8d7ebe271d944f27c1c0090b4ea..1198a09a9773cd56af60c48207a5611265caab65 100644 (file)
@@ -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"
+}