PHP_FUNCTION(range)
{
zval *zlow, *zhigh, *zstep = NULL, tmp;
int err = , is_step_double = ;
double step = 1.0; // 步长默认为1 if (zend_parse_parameters(ZEND_NUM_ARGS(), "zz|z", &zlow, &zhigh, &zstep) == FAILURE) {
RETURN_FALSE;
} // 步长
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, ) == IS_DOUBLE)
) {
is_step_double = ;
} step = zval_get_double(zstep); // 步长可以为负数。取绝对值
/* We only want positive step values. */
if (step < 0.0) {
step *= -;
}
} /* If the range is given as strings, generate an array of characters. */
/* start、end是字符串 */
if (Z_TYPE_P(zlow) == IS_STRING && Z_TYPE_P(zhigh) == IS_STRING && Z_STRLEN_P(zlow) >= && Z_STRLEN_P(zhigh) >= ) {
int type1, type2;
unsigned char low, high;
zend_long lstep = (zend_long) step; type1 = is_numeric_string(Z_STRVAL_P(zlow), Z_STRLEN_P(zlow), NULL, NULL, );
type2 = is_numeric_string(Z_STRVAL_P(zhigh), Z_STRLEN_P(zhigh), NULL, NULL, ); /* 填充数字 */
if (type1 == IS_DOUBLE || type2 == IS_DOUBLE || is_step_double) {
goto double_str;
} else if (type1 == IS_LONG || type2 == IS_LONG) {
goto long_str;
} /* 填充字符,只取字符串start和字符串end的第一个字符 */
low = (unsigned char)Z_STRVAL_P(zlow)[];
high = (unsigned char)Z_STRVAL_P(zhigh)[]; if (low > high) { /* Negative Steps */
if (lstep <= ) {
err = ;
goto err;
}
/* Initialize the return_value as an array. */
array_init_size(return_value, (uint32_t)(((low - high) / lstep) + ));
zend_hash_real_init(Z_ARRVAL_P(return_value), );
ZEND_HASH_FILL_PACKED(Z_ARRVAL_P(return_value)) {
for (; low >= high; low -= (unsigned int)lstep) {
if (CG(one_char_string)[low]) {
ZVAL_INTERNED_STR(&tmp, CG(one_char_string)[low]);
} else {
ZVAL_STRINGL(&tmp, (char*)&low, );
}
ZEND_HASH_FILL_ADD(&tmp);
if (((signed int)low - lstep) < ) {
break;
}
}
} ZEND_HASH_FILL_END();
} else if (high > low) { /* Positive Steps */
if (lstep <= ) {
err = ;
goto err;
}
// 初始化返回的数组
array_init_size(return_value, (uint32_t)(((high - low) / lstep) + ));
zend_hash_real_init(Z_ARRVAL_P(return_value), );
ZEND_HASH_FILL_PACKED(Z_ARRVAL_P(return_value)) {
// 将字符插入返回的数组
for (; low <= high; low += (unsigned int)lstep) {
if (CG(one_char_string)[low]) {
ZVAL_INTERNED_STR(&tmp, CG(one_char_string)[low]);
} else {
ZVAL_STRINGL(&tmp, (char*)&low, );
}
ZEND_HASH_FILL_ADD(&tmp);
if (((signed int)low + lstep) > ) {
break;
}
}
} ZEND_HASH_FILL_END();
} else {
array_init(return_value);
if (CG(one_char_string)[low]) {
ZVAL_INTERNED_STR(&tmp, CG(one_char_string)[low]);
} else {
ZVAL_STRINGL(&tmp, (char*)&low, );
}
zend_hash_next_index_insert_new(Z_ARRVAL_P(return_value), &tmp);
}
} else if (Z_TYPE_P(zlow) == IS_DOUBLE || Z_TYPE_P(zhigh) == IS_DOUBLE || is_step_double) { // start、end是浮点数
double low, high, value;
zend_long i;
double_str:
low = zval_get_double(zlow);
high = zval_get_double(zhigh);
i = ; // 浮点数范围检查
if (zend_isinf(high) || zend_isinf(low)) {
php_error_docref(NULL, E_WARNING, "Invalid range supplied: start=%0.0f end=%0.0f", low, high);
RETURN_FALSE;
} Z_TYPE_INFO(tmp) = IS_DOUBLE;
if (low > high) { /* Negative steps 第一个参数比第二大*/
if (low - high < step || step <= ) { // 范围差小于步长或步长取绝对值之后仍小于0。则报WARNING错误。
err = ;
goto err;
} // 检查并初始化返回的数组
RANGE_CHECK_INIT_ARRAY(low, high);
// 向返回的数组中填充值,降序
ZEND_HASH_FILL_PACKED(Z_ARRVAL_P(return_value)) {
for (value = low; value >= (high - DOUBLE_DRIFT_FIX); value = low - (++i * step)) {
Z_DVAL(tmp) = value;
ZEND_HASH_FILL_ADD(&tmp);
}
} ZEND_HASH_FILL_END();
} else if (high > low) { /* Positive steps 第一个参数比第二个小*/
if (high - low < step || step <= ) {
err = ;
goto err;
} // 检查并初始化返回的数组
RANGE_CHECK_INIT_ARRAY(high, low);
// 向返回的数组中填充值,升序
ZEND_HASH_FILL_PACKED(Z_ARRVAL_P(return_value)) {
for (value = low; value <= (high + DOUBLE_DRIFT_FIX); value = low + (++i * step)) {
Z_DVAL(tmp) = value;
ZEND_HASH_FILL_ADD(&tmp);
}
} ZEND_HASH_FILL_END();
} else { // low == high。则返回的数组只用一个元素:array(0=>low)
array_init(return_value);
Z_DVAL(tmp) = low;
zend_hash_next_index_insert_new(Z_ARRVAL_P(return_value), &tmp);
}
} else { // start、end是整数
double low, high;
zend_long lstep;
long_str:
low = zval_get_double(zlow);
high = zval_get_double(zhigh);
lstep = (zend_long) step; Z_TYPE_INFO(tmp) = IS_LONG;
if (low > high) { /* Negative steps */
if (low - high < lstep || lstep <= ) {
err = ;
goto err;
} RANGE_CHECK_INIT_ARRAY(low, high);
ZEND_HASH_FILL_PACKED(Z_ARRVAL_P(return_value)) {
for (; low >= high; low -= lstep) {
Z_LVAL(tmp) = (zend_long)low;
ZEND_HASH_FILL_ADD(&tmp);
}
} ZEND_HASH_FILL_END();
} else if (high > low) { /* Positive steps */
if (high - low < lstep || lstep <= ) {
err = ;
goto err;
} RANGE_CHECK_INIT_ARRAY(high, low);
ZEND_HASH_FILL_PACKED(Z_ARRVAL_P(return_value)) {
for (; low <= high; low += lstep) {
Z_LVAL(tmp) = (zend_long)low;
ZEND_HASH_FILL_ADD(&tmp);
}
} ZEND_HASH_FILL_END();
} else {
array_init(return_value);
Z_LVAL(tmp) = (zend_long)low;
zend_hash_next_index_insert_new(Z_ARRVAL_P(return_value), &tmp);
}
}
err:
if (err) {
php_error_docref(NULL, E_WARNING, "step exceeds the specified range");
RETURN_FALSE;
}
}

php内置函数分析range()的更多相关文章

  1. Python内置函数(27)——range

    英文文档: range(stop) range(start, stop[, step]) Rather than being a function, range is actually an immu ...

  2. Python内置函数(52)——range

    英文文档: range(stop) range(start, stop[, step]) Rather than being a function, range is actually an immu ...

  3. map内置函数分析所得到的思路

    map:会根据提供的函数对指定序列做映射. map(func, *iterables) --> map object Make an iterator that computes the fun ...

  4. php内置函数分析之array_diff_assoc()

    static void php_array_diff_key(INTERNAL_FUNCTION_PARAMETERS, int data_compare_type) /* {{{ */ { uint ...

  5. php内置函数分析之trim()

    官方手册中: 类似函数还有两个:ltrim() 和 rtrim().分别处理字符串的左侧.右侧. trim()的具体实现位于:ext/standard/string.c /* {{{ proto st ...

  6. Python内置函数之range()

    range(stop)range(start,stop[,step]) 返回一个range对象,第三个参数的含义为:间隔的个数. range对象同时也是可迭代对象. >>> isin ...

  7. php内置函数分析之array_combine()

    PHP_FUNCTION(array_combine) { HashTable *values, *keys; uint32_t pos_values = ; zval *entry_keys, *e ...

  8. php内置函数分析之ucwords()

    PHP_FUNCTION(ucwords) { zend_string *str; char *delims = " \t\r\n\f\v"; register char *r, ...

  9. php内置函数分析之strtoupper()、strtolower()

    strtoupper(): PHP_FUNCTION(strtoupper) { zend_string *str; ZEND_PARSE_PARAMETERS_START(, ) Z_PARAM_S ...

随机推荐

  1. html上传文件

    不太懂Html 做备用 html的文件上传分两个 第一个是Html文件 浏览器加载用的 另一个是PHP文件 处理上传文件的 下面是Html文件 叫index.html <html> < ...

  2. 点云网格化算法---MPA

    MPA网格化算法思路 第一步:初始化一个种子三角面.(随机选点,基于该点进行临近搜索到第二点:在基于该线段中点临近搜索到第三点) 图1 第二步:在种子三角面的基础上,进行面片的扩充,利用边的中点进行临 ...

  3. VS2008重置默认环境

    Microsoft Visual Studio 2008 -> Visual Studio Tools -> Visual Studio 2008命令提示 进入Common7\IDE,然后 ...

  4. 原生js去除行内样式

    概述 今天我用js给dom元素设置样式,碰到了一些问题,记下来供以后开发时参考,相信对其他人也有用. 心得 js加上class: $dom.classList.add('some-class'); j ...

  5. 阶段3 1.Mybatis_01.Mybatis课程介绍及环境搭建_02.三层架构和ssm框架的对应关系

  6. delphi2010:按键 控制键 组合键的判断 响应

    procedure TForm7.FormShortCut(var Msg: TWMKey; var Handled: Boolean); var   aKey: TShortCut;   aShif ...

  7. windows 开启/关闭本地连接的批处理程序

    ::命令前加@符号,表示不显示@后面的命令. @echo off title Open / Close Network ::本地网络适配器名称 set name=以太网 ::查看网络状态,后反向设定 ...

  8. multiple datasource config

    Hi Harshit S. project structure: multiple datasource config as follows: step 1: step 2:add a datasou ...

  9. MACBOOK蓝牙连接丢失恢复

    MACBOOK用户可能会碰到一个神奇而无奈的问题: 某些情况下,很多时候从睡眠状态回来,会发现蓝牙设备再也无法连接,包括蓝牙鼠标.键盘等等... 恢复方法一般是,重启或注销后重新登陆,然后所有工作现场 ...

  10. 【MM系列】SAP 物料进销存报表查看

    公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[MM系列]在SAP里查看数据的方法   前言部 ...