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. Spring bean的自动装配属性

    bean的自动装配属性能简化xml文件配置. bean 的自动装配属性分为四种: 1.byName 2.byTyoe 3.constructor 4. autodetect byName: 它查找配置 ...

  2. windows一次无线网卡被关闭事件

    使用的是Dell的笔记本,fn+无线图标莫名的是蓝牙的启动. 有一天突然无线网卡无法上网,无法发现无线网络: 1. 在服务中开启"Wired AutoConfig"以及“WLAN ...

  3. JS单引号嵌套的问题,怎么改才能对呢!

    JS单引号嵌套的问题,怎么改才能对呢! https://zhidao.baidu.com/question/416584343.html document.getElementById(celbid) ...

  4. Android下Native的so编译:使用cmakelists.txt

    android studio的CMakeLists.txt写好后,在Studio中编译没问题,在命令编译时则需要配置很多参数才能成功 示例CMakeLists.txt文件: cmake_minimum ...

  5. C# 获取当前网页HTML

    //引用COM组件 //Microsoft HTML Object Library //Microsoft Internet Controls SHDocVw.ShellWindows shellWi ...

  6. HTML——超级链接 表格 框架

  7. MySQL学习-MySQL内置功能_索引与慢查询

    1.索引基础 1.1 介绍 (1.)为何要有索引? 一般的应用系统,读写比例在10:1左右,而且插入操作和一般的更新操作很少出现性能问题,在生产环境中,我们遇到最多的,也是最容易出问题的,还是一些复杂 ...

  8. CNN(卷积神经网络)原理讲解及简单代码

    一.原理讲解 1. 卷积神经网络的应用 分类(分类预测) 检索(检索出该物体的类别) 检测(检测出图像中的物体,并标注) 分割(将图像分割出来) 人脸识别 图像生成(生成不同状态的图像) 自动驾驶 等 ...

  9. 【Linux 环境搭建】ubuntu 的samba配置

    在/etc/samba/smb.conf的文件末尾增加下面的内容然后重启samba [home] comment = James Harden path = / browseable = yes wr ...

  10. D - Disjoint Set of Common Divisors

    https://atcoder.jp/contests/abc142/tasks/abc142_d 题意 求满足互素条件下的A和B的因子最多有几个 思路: 分解gcd(A,B)的质因子,再加上1: # ...