summaryrefslogtreecommitdiff
path: root/ext/standard/array.c
diff options
context:
space:
mode:
authorIlia Alshanetsky <iliaa@php.net>2002-12-20 17:16:31 +0000
committerIlia Alshanetsky <iliaa@php.net>2002-12-20 17:16:31 +0000
commit3a4bf3f904a4ac1df1bd24826a42081f1b2395eb (patch)
treed2efbb7efb32e9adeb96813de2a27f04ec6dc0eb /ext/standard/array.c
parentd795243db34109d63f26ffbb9e26f07075092939 (diff)
downloadphp-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.c117
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;
+ }
}
/* }}} */