php内置函数分析range()
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()的更多相关文章
- Python内置函数(27)——range
英文文档: range(stop) range(start, stop[, step]) Rather than being a function, range is actually an immu ...
- Python内置函数(52)——range
英文文档: range(stop) range(start, stop[, step]) Rather than being a function, range is actually an immu ...
- map内置函数分析所得到的思路
map:会根据提供的函数对指定序列做映射. map(func, *iterables) --> map object Make an iterator that computes the fun ...
- php内置函数分析之array_diff_assoc()
static void php_array_diff_key(INTERNAL_FUNCTION_PARAMETERS, int data_compare_type) /* {{{ */ { uint ...
- php内置函数分析之trim()
官方手册中: 类似函数还有两个:ltrim() 和 rtrim().分别处理字符串的左侧.右侧. trim()的具体实现位于:ext/standard/string.c /* {{{ proto st ...
- Python内置函数之range()
range(stop)range(start,stop[,step]) 返回一个range对象,第三个参数的含义为:间隔的个数. range对象同时也是可迭代对象. >>> isin ...
- php内置函数分析之array_combine()
PHP_FUNCTION(array_combine) { HashTable *values, *keys; uint32_t pos_values = ; zval *entry_keys, *e ...
- php内置函数分析之ucwords()
PHP_FUNCTION(ucwords) { zend_string *str; char *delims = " \t\r\n\f\v"; register char *r, ...
- php内置函数分析之strtoupper()、strtolower()
strtoupper(): PHP_FUNCTION(strtoupper) { zend_string *str; ZEND_PARSE_PARAMETERS_START(, ) Z_PARAM_S ...
随机推荐
- 一、基础篇--1.1Java基础-抽象类和接口的区别
抽象类和接口的区别 抽象类和接口在设计层面的区别主要体现在:接口是对动作的抽象,抽象类是对根源.类的抽象.抽象类表示的是,这个对象是什么,接口表示的是,这个对象可以做什么. 比如,男人.女人是人,人是 ...
- 清北学堂2019.7.18 & 清北学堂2019.7.19
Day 6 钟皓曦 经典题目:石子合并 可以合并任意两堆,代价为数量的异或(^)和 f[s]把s的二进制所对应石子合并成一堆所花代价 枚举s的子集 #include<iostream> u ...
- 洛谷 P3865 ST表
ST表 ST表的功能很简单 它是解决RMQ问题(区间最值问题)的一种强有力的工具 它可以做到O(nlogn)预处理,O(1)查询最值 是一种处理静态区间可重复计算问题的数据结构,一般也就求求最大最小值 ...
- SetWindowsHookEx失败
使用下面代码hook鼠标 res = SetWindowsHookEx(WH_MOUSE_LL, _mouseHookProcedure, Marshal.GetHINSTANCE(System.Re ...
- JS遍历二维数组
//求平均数 var pjs=[ ['小明',87], ['小红',81], ['小花',97], ['小天',76], ['小张',74], ['小小',94], ['小西',90], ['小武', ...
- 设计模式(2): 响应store中数据的变化
概述 最近最近做项目的时候总会思考一些大的应用设计模式相关的问题,我把自己的思考记录下来,供以后开发时参考,相信对其他人也有用. store里面响应数据变化 通常情况下,我们会把数据存在store里面 ...
- javascript 访问 webservice
xml: <?xml version="1.0" encoding="UTF-8"?> <boolean xmlns="http:/ ...
- Snow的追寻--线段树维护树的直径
Snow终于得知母亲是谁,他现在要出发寻找母亲.王国中的路由于某种特殊原因,成为了一棵有n个节点的根节点为1的树,但由于"Birds are everywhere.",他得到了种种 ...
- 第二次课程总结&学习总结
Java实验报告 班级 计算机科学与技术一班 学号 20188390 姓名 宋志豪 实验 写一个名为Rectangle的类表示矩形.其属性包括宽width.高height和颜色color,width和 ...
- Nginx代理自动上线下线
Nginx基于连接探测,如果发现后端异常,在单位周期为fail_timeout设置的时间,中达到max_fails次数,这个周期次数内,如果后端同一个节点不可用,那么接将把节点标记为不可用,并等待下一 ...