Stepping on range()
| From: | Jon Parise | Date: | Mon, 11 Nov 2002 05:38:49 +0000 |
| Subject: | Stepping on range() | ||
| Groups: | php.dev | ||
| Request: | Send a blank email to php-dev+get-90758@lists.php.net to get a copy of this message | ||
Attached is a patch that adds an optional "step" parameter to the
range() function. This allows the generation of ranges based on a
non-one increment. For example:
range(0, 10, 2);
... would yield an array containing (0, 2, 4, 6, 8, 10).
The change is entirely backwards-compatible with the existing
behavior of range().
I've also attached a test script for the new functionality.
I haven't committed the changes in the interest of getting PHP 4.3.0
out the door, but I will if no one sees a problem. Otherwise, I can
hang onto this until after the release.
Documentation updates will accompany with the commit.
--
Jon Parise (jon@php.net) :: The PHP Project (http://www.php.net/)
Index: array.c =================================================================== RCS file: /repository/php4/ext/standard/array.c,v retrieving revision 1.198 diff -u -r1.198 array.c --- array.c 5 Nov 2002 16:19:19 -0000 1.198 +++ array.c 11 Nov 2002 05:31:16 -0000 @@ -1411,48 +1411,60 @@ } /* }}} */ -/* {{{ proto array range(mixed low, mixed high) +/* {{{ proto array range(mixed low, mixed high[, int step]) Create an array containing the range of integers or characters from low to high (inclusive) */ PHP_FUNCTION(range) { - zval **zlow, **zhigh; - - if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &zlow, &zhigh) == FAILURE) { - WRONG_PARAM_COUNT; + zval *zlow, *zhigh; + long step = 1; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz|l", &zlow, + &zhigh, &step) == FAILURE) { + RETURN_FALSE; } - /* allocate an array for return */ + /* We only want positive step values. */ + if (step < 0) { + step *= -1; + } + + /* Initialize the return_value as an array. */ if (array_init(return_value) == FAILURE) { RETURN_FALSE; } - if (Z_TYPE_PP(zlow)==IS_STRING && Z_TYPE_PP(zhigh)==IS_STRING) { + /* If the range is given as strings, generate an array of characters. */ + if (Z_TYPE_P(zlow) == IS_STRING && Z_TYPE_P(zhigh) == IS_STRING) { char *low, *high; - convert_to_string_ex(zlow); - convert_to_string_ex(zhigh); - low = Z_STRVAL_PP(zlow); - high = Z_STRVAL_PP(zhigh); - if (*low>*high) { - for (; *low >= *high; (*low)--) { + + convert_to_string_ex(&zlow); + convert_to_string_ex(&zhigh); + low = Z_STRVAL_P(zlow); + high = Z_STRVAL_P(zhigh); + + if (*low > *high) { /* Negative increments */ + for (; *low >= *high; (*low) -= step) { add_next_index_stringl(return_value, low, 1, 1); - } - } else { - for (; *low <= *high; (*low)++) { + } + } else { /* Positive increments */ + for (; *low <= *high; (*low) += step) { add_next_index_stringl(return_value, low, 1, 1); - } + } } } else { int low, high; - convert_to_long_ex(zlow); - convert_to_long_ex(zhigh); - low = Z_LVAL_PP(zlow); - high = Z_LVAL_PP(zhigh); - if (low > high) { - for (; low >= high; low--) { + + convert_to_long_ex(&zlow); + convert_to_long_ex(&zhigh); + low = Z_LVAL_P(zlow); + high = Z_LVAL_P(zhigh); + + if (low > high) { /* Negative increments */ + for (; low >= high; low -= step) { add_next_index_long(return_value, low); } - } else { - for (; low <= high; low++) { + } else { /* Positive increments */ + for (; low <= high; low += step) { add_next_index_long(return_value, low); } } --TEST-- range() --FILE-- <?php print_r(range(0, 10)); print_r(range(10, 0)); print_r(range(0, 10, 2)); print_r(range(10, 0, 2)); ?> --EXPECT-- Array ( [0] => 0 [1] => 1 [2] => 2 [3] => 3 [4] => 4 [5] => 5 [6] => 6 [7] => 7 [8] => 8 [9] => 9 [10] => 10 ) Array ( [0] => 10 [1] => 9 [2] => 8 [3] => 7 [4] => 6 [5] => 5 [6] => 4 [7] => 3 [8] => 2 [9] => 1 [10] => 0 ) Array ( [0] => 0 [1] => 2 [2] => 4 [3] => 6 [4] => 8 [5] => 10 ) Array ( [0] => 10 [1] => 8 [2] => 6 [3] => 4 [4] => 2 [5] => 0 )
Index: array.c =================================================================== RCS file: /repository/php4/ext/standard/array.c,v retrieving revision 1.198 diff -u -r1.198 array.c --- array.c 5 Nov 2002 16:19:19 -0000 1.198 +++ array.c 11 Nov 2002 05:31:16 -0000 @@ -1411,48 +1411,60 @@ } /* }}} */ -/* {{{ proto array range(mixed low, mixed high) +/* {{{ proto array range(mixed low, mixed high[, int step]) Create an array containing the range of integers or characters from low to high (inclusive) */ PHP_FUNCTION(range) { - zval **zlow, **zhigh; - - if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &zlow, &zhigh) == FAILURE) { - WRONG_PARAM_COUNT; + zval *zlow, *zhigh; + long step = 1; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz|l", &zlow, + &zhigh, &step) == FAILURE) { + RETURN_FALSE; } - /* allocate an array for return */ + /* We only want positive step values. */ + if (step < 0) { + step *= -1; + } + + /* Initialize the return_value as an array. */ if (array_init(return_value) == FAILURE) { RETURN_FALSE; } - if (Z_TYPE_PP(zlow)==IS_STRING && Z_TYPE_PP(zhigh)==IS_STRING) { + /* If the range is given as strings, generate an array of characters. */ + if (Z_TYPE_P(zlow) == IS_STRING && Z_TYPE_P(zhigh) == IS_STRING) { char *low, *high; - convert_to_string_ex(zlow); - convert_to_string_ex(zhigh); - low = Z_STRVAL_PP(zlow); - high = Z_STRVAL_PP(zhigh); - if (*low>*high) { - for (; *low >= *high; (*low)--) { + + convert_to_string_ex(&zlow); + convert_to_string_ex(&zhigh); + low = Z_STRVAL_P(zlow); + high = Z_STRVAL_P(zhigh); + + if (*low > *high) { /* Negative increments */ + for (; *low >= *high; (*low) -= step) { add_next_index_stringl(return_value, low, 1, 1); - } - } else { - for (; *low <= *high; (*low)++) { + } + } else { /* Positive increments */ + for (; *low <= *high; (*low) += step) { add_next_index_stringl(return_value, low, 1, 1); - } + } } } else { int low, high; - convert_to_long_ex(zlow); - convert_to_long_ex(zhigh); - low = Z_LVAL_PP(zlow); - high = Z_LVAL_PP(zhigh); - if (low > high) { - for (; low >= high; low--) { + + convert_to_long_ex(&zlow); + convert_to_long_ex(&zhigh); + low = Z_LVAL_P(zlow); + high = Z_LVAL_P(zhigh); + + if (low > high) { /* Negative increments */ + for (; low >= high; low -= step) { add_next_index_long(return_value, low); } - } else { - for (; low <= high; low++) { + } else { /* Positive increments */ + for (; low <= high; low += step) { add_next_index_long(return_value, low); } } --TEST-- range() --FILE-- <?php print_r(range(0, 10)); print_r(range(10, 0)); print_r(range(0, 10, 2)); print_r(range(10, 0, 2)); ?> --EXPECT-- Array ( [0] => 0 [1] => 1 [2] => 2 [3] => 3 [4] => 4 [5] => 5 [6] => 6 [7] => 7 [8] => 8 [9] => 9 [10] => 10 ) Array ( [0] => 10 [1] => 9 [2] => 8 [3] => 7 [4] => 6 [5] => 5 [6] => 4 [7] => 3 [8] => 2 [9] => 1 [10] => 0 ) Array ( [0] => 0 [1] => 2 [2] => 4 [3] => 6 [4] => 8 [5] => 10 ) Array ( [0] => 10 [1] => 8 [2] => 6 [3] => 4 [4] => 2 [5] => 0 )