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 ...
随机推荐
- virt-manager 使用 shh 远程访问配置方法
1.下载安装 Xming+Xshell 或者 Xming+putty,启动Xming服务 Xming下载地址 2.XMing的配置:打开XLaunch,记住Display Number,现在这里是0 ...
- React Native商城项目实战05 - 设置首页的导航条
1.Home.js /** * 首页 */ import React, { Component } from 'react'; import { AppRegistry, StyleSheet, Te ...
- spring boot 和 mybatis集成
1.pom.xml 添加mybatis和mysql依赖 <!-- 添加 MyBatis --> <dependency> <groupId>org.mybatis. ...
- Python 使用Qt进行开发(三)
下面我们实现日期时间框的添加,表示日期时间的文本框可以使用QtWidgets控件下的 QDateEdit() , QTimeEdit() , QDateTime() 三个方法实现. 1,使用QDate ...
- P1076 寻宝
P1076 寻宝 题解 这道题真是感人啊,废了蒟蒻一天的时间 关键 1. a[ k ][ ] 数组记录第k层有楼梯房间的编号 a[ k ][ 0 ] 第k层有几个有楼梯的房间 a[ k ][ i ] ...
- 【工具安装】BurpSuite 安装教程
日期:2019-07-14 17:23:53 介绍:安装 JDK,配置 JDK 的环境变量.安装 BurpSuite,抓包 0x01. 安装 JDK 安装 JDK BurpSuite 需要 JAVA ...
- 使用使用dockerfile构建webapi镜像然后使用link和bridge两种方式进行桥接
首先新增一个webapi的项目 项目核心代码 UserContext using Microsoft.EntityFrameworkCore; using System; using System.C ...
- myBatis 基于javaBean配置
MyBatis的持久化解决方案是将用户从原始的JDBC访问中解放出来,用户只需要定义需要操作的SQL语句, 无须关注底层的JDBC操作,就可以以面向对象的方式来进行持久化层操作.底层数据库连接的获取, ...
- 多线程18-QueueUserWorkItem
)); } ; ; )); ThreadPool.QueueUserWorkItem(A ...
- C#读取 *.exe.config
读语句: String str = ConfigurationManager.AppSettings["DemoKey"];写语句: Configuration cfa = Con ...