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. 一、基础篇--1.1Java基础-抽象类和接口的区别

    抽象类和接口的区别 抽象类和接口在设计层面的区别主要体现在:接口是对动作的抽象,抽象类是对根源.类的抽象.抽象类表示的是,这个对象是什么,接口表示的是,这个对象可以做什么. 比如,男人.女人是人,人是 ...

  2. Linux_NFS/Samba服务器

    目录 目录 网络共享的解决方案 搭建NFS服务 服务器端19216801 客户端19216802 autofs自动挂载nfs共享 搭建Samba服务 服务器端 客户端 网络共享的解决方案 Linux/ ...

  3. Spring MVC的RequestContextHolder使用误区

    JShop简介:jshop是一套使用Java语言开发的B2C网店系统,致力于为个人和中小企业提供免费.好用的网店系统. 项目主页:http://git.oschina.net/dinguangx/js ...

  4. UVA11987 带删除并查集

    1~n,n个数,初始每个数独自作为一个集合,然后进行m次操作.操作有三种:1 p q :把 p 所在的集合合并到 q 所在的集合 2 p q :把 p 从 p 的集合中拿出,放到 q 的集合里 3 p ...

  5. Arm-linux-gcc-4.3.2安装步骤 (转)

    http://blog.chinaunix.net/uid-26119896-id-3302233.html 安装交叉编译工具链: 1.首先以root用户登入 2.复制arm-linux-gcc-4. ...

  6. 深入理解java:2.3.1. 并发编程concurrent包 之Atomic原子操作(循环CAS)

    java中,可能有一些场景,操作非常简单,但是容易存在并发问题,比如i++, 此时,如果依赖锁机制,可能带来性能损耗等问题, 于是,如何更加简单的实现原子性操作,就成为java中需要面对的一个问题. ...

  7. Java中字母大小写的转换

    例:String str = "AbC"; 把字符串所有字母变成小写: System.out.println(str.toLowerCase()); 把字符串所有字母大写: Sys ...

  8. STL 函数适配器(function adapter)

    函数适配器(function adapter):通过不同函数适配器的绑定,组合和修饰能力,可以实现强大的功能,配合STL泛型算法完成复杂功能. 绑定(bind) template <class ...

  9. Fedora添加软件桌面快捷方式

    以下以添加Eclipse为例 在桌面上新建Eclipse.desktop 文件,向其写入如下代码 [Desktop Entry] Name=Eclipse Comment=用Eclipse开发 Exe ...

  10. CDQ分治总结

    \(CDQ\)分治小结 标签:知识点总结 阅读体验:https://zybuluo.com/Junlier/note/1326395 身为一个资深菜鸡 \(CDQ\)分治一开始学了一晚上,后来某一天又 ...