diff options
author | Ilia Alshanetsky <iliaa@php.net> | 2002-12-20 17:16:31 +0000 |
---|---|---|
committer | Ilia Alshanetsky <iliaa@php.net> | 2002-12-20 17:16:31 +0000 |
commit | 3a4bf3f904a4ac1df1bd24826a42081f1b2395eb (patch) | |
tree | d2efbb7efb32e9adeb96813de2a27f04ec6dc0eb /ext/standard/array.c | |
parent | d795243db34109d63f26ffbb9e26f07075092939 (diff) | |
download | php-git-3a4bf3f904a4ac1df1bd24826a42081f1b2395eb.tar.gz |
When low & high are the same return an array containing the low value.
Added support for float values and handling of numeric values being passed
as strings.
Added a test case for range().
Diffstat (limited to 'ext/standard/array.c')
-rw-r--r-- | ext/standard/array.c | 117 |
1 files changed, 86 insertions, 31 deletions
diff --git a/ext/standard/array.c b/ext/standard/array.c index c3c6c74063..187d457770 100644 --- a/ext/standard/array.c +++ b/ext/standard/array.c @@ -1421,78 +1421,133 @@ PHP_FUNCTION(array_fill) Create an array containing the range of integers or characters from low to high (inclusive) */ PHP_FUNCTION(range) { - zval *zlow, *zhigh; - long step = 1; + zval *zlow, *zhigh, *zstep = NULL; + int err = 0, is_step_double = 0; + double step = 1.0; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz|l", &zlow, - &zhigh, &step) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz|z", &zlow, &zhigh, &zstep) == FAILURE) { RETURN_FALSE; } - /* We only want positive step values. */ - if (step < 0) { - step *= -1; - } + if (zstep) { + if (Z_TYPE_P(zstep) == IS_DOUBLE || (Z_TYPE_P(zstep) == IS_STRING && is_numeric_string(Z_STRVAL_P(zstep), Z_STRLEN_P(zstep), NULL, NULL, 0) == IS_DOUBLE)) { + is_step_double = 1; + } + + convert_to_double_ex(&zstep); + step = Z_DVAL_P(zstep); + + /* We only want positive step values. */ + if (step < 0.0) { + step *= -1; + } + } /* Initialize the return_value as an array. */ array_init(return_value); /* 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) { + int type1, type2; unsigned char *low, *high; + long lstep = (long) step; + type1 = is_numeric_string(Z_STRVAL_P(zlow), Z_STRLEN_P(zlow), NULL, NULL, 0); + type2 = is_numeric_string(Z_STRVAL_P(zhigh), Z_STRLEN_P(zhigh), NULL, NULL, 0); + + if (type1 == IS_DOUBLE || type2 == IS_DOUBLE || is_step_double) { + goto double_str; + } else if (type1 == IS_LONG || type2 == IS_LONG) { + goto long_str; + } + convert_to_string_ex(&zlow); convert_to_string_ex(&zhigh); low = (unsigned char *)Z_STRVAL_P(zlow); high = (unsigned char *)Z_STRVAL_P(zhigh); if (*low > *high) { /* Negative steps */ - if (*low - *high < step || step <= 0) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "step exceeds the specified range"); - zval_dtor(return_value); - RETURN_FALSE; + if (*low - *high < lstep || lstep <= 0) { + err = 1; + goto err; } for (; *low >= *high; (*low) -= (unsigned int)step) { add_next_index_stringl(return_value, low, 1, 1); } - } else { /* Positive steps */ - if (*high - *low < step || step <= 0) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "step exceeds the specified range"); - zval_dtor(return_value); - RETURN_FALSE; + } else if (*high > *low) { /* Positive steps */ + if (*high - *low < lstep || lstep <= 0) { + err = 1; + goto err; } - for (; *low <= *high; (*low) += (unsigned int)step) { + for (; *low <= *high; (*low) += (unsigned int)lstep) { add_next_index_stringl(return_value, low, 1, 1); } + } else { + add_next_index_stringl(return_value, low, 1, 1); + } + } else if (Z_TYPE_P(zlow) == IS_DOUBLE || Z_TYPE_P(zhigh) == IS_DOUBLE || is_step_double) { + double low, high; +double_str: + convert_to_double_ex(&zlow); + convert_to_double_ex(&zhigh); + low = Z_DVAL_P(zlow); + high = Z_DVAL_P(zhigh); + + if (low > high) { /* Negative steps */ + if (low - high < step || step <= 0) { + err = 1; + goto err; + } + for (; low >= high; low -= step) { + add_next_index_double(return_value, low); + } + } else if (high > low) { /* Positive steps */ + if (high - low < step || step <= 0) { + err = 1; + goto err; + } + for (; low <= high; low += step) { + add_next_index_double(return_value, low); + } + } else { + add_next_index_double(return_value, low); } } else { int low, high; - + long lstep; +long_str: convert_to_long_ex(&zlow); convert_to_long_ex(&zhigh); low = Z_LVAL_P(zlow); high = Z_LVAL_P(zhigh); - + lstep = (long) step; + if (low > high) { /* Negative steps */ - if (low - high < step || step <= 0) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "step exceeds the specified range"); - zval_dtor(return_value); - RETURN_FALSE; + if (low - high < lstep || lstep <= 0) { + err = 1; + goto err; } - for (; low >= high; low -= step) { + for (; low >= high; low -= lstep) { add_next_index_long(return_value, low); } - } else { /* Positive steps */ - if (high - low < step || step <= 0) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "step exceeds the specified range"); - zval_dtor(return_value); - RETURN_FALSE; + } else if (high > low) { /* Positive steps */ + if (high - low < lstep || lstep <= 0) { + err = 1; + goto err; } - for (; low <= high; low += step) { + for (; low <= high; low += lstep) { add_next_index_long(return_value, low); } + } else { + add_next_index_long(return_value, low); } } +err: + if (err) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "step exceeds the specified range"); + zval_dtor(return_value); + RETURN_FALSE; + } } /* }}} */ |