• php内置函数分析range()


      1 PHP_FUNCTION(range)
      2 {
      3     zval *zlow, *zhigh, *zstep = NULL, tmp;
      4     int err = 0, is_step_double = 0;
      5     double step = 1.0; // 步长默认为1
      6 
      7     if (zend_parse_parameters(ZEND_NUM_ARGS(), "zz|z", &zlow, &zhigh, &zstep) == FAILURE) {
      8         RETURN_FALSE;
      9     }
     10 
     11     // 步长
     12     if (zstep) {
     13         if (Z_TYPE_P(zstep) == IS_DOUBLE ||
     14             (Z_TYPE_P(zstep) == IS_STRING && is_numeric_string(Z_STRVAL_P(zstep), Z_STRLEN_P(zstep), NULL, NULL, 0) == IS_DOUBLE)
     15         ) {
     16             is_step_double = 1;
     17         }
     18 
     19         step = zval_get_double(zstep);
     20 
     21         // 步长可以为负数。取绝对值
     22         /* We only want positive step values. */
     23         if (step < 0.0) {
     24             step *= -1;
     25         }
     26     }
     27 
     28     /* If the range is given as strings, generate an array of characters. */
     29     /* start、end是字符串 */
     30     if (Z_TYPE_P(zlow) == IS_STRING && Z_TYPE_P(zhigh) == IS_STRING && Z_STRLEN_P(zlow) >= 1 && Z_STRLEN_P(zhigh) >= 1) {
     31         int type1, type2;
     32         unsigned char low, high;
     33         zend_long lstep = (zend_long) step;
     34 
     35         type1 = is_numeric_string(Z_STRVAL_P(zlow), Z_STRLEN_P(zlow), NULL, NULL, 0);
     36         type2 = is_numeric_string(Z_STRVAL_P(zhigh), Z_STRLEN_P(zhigh), NULL, NULL, 0);
     37 
     38         /* 填充数字 */
     39         if (type1 == IS_DOUBLE || type2 == IS_DOUBLE || is_step_double) {
     40             goto double_str;
     41         } else if (type1 == IS_LONG || type2 == IS_LONG) {
     42             goto long_str;
     43         }
     44 
     45         /* 填充字符,只取字符串start和字符串end的第一个字符 */
     46         low = (unsigned char)Z_STRVAL_P(zlow)[0];  
     47         high = (unsigned char)Z_STRVAL_P(zhigh)[0];
     48 
     49         if (low > high) {        /* Negative Steps */
     50             if (lstep <= 0) {
     51                 err = 1;
     52                 goto err;
     53             }
     54             /* Initialize the return_value as an array. */
     55             array_init_size(return_value, (uint32_t)(((low - high) / lstep) + 1));
     56             zend_hash_real_init(Z_ARRVAL_P(return_value), 1);
     57             ZEND_HASH_FILL_PACKED(Z_ARRVAL_P(return_value)) {
     58                 for (; low >= high; low -= (unsigned int)lstep) {
     59                     if (CG(one_char_string)[low]) {
     60                         ZVAL_INTERNED_STR(&tmp, CG(one_char_string)[low]);
     61                     } else {
     62                         ZVAL_STRINGL(&tmp, (char*)&low, 1);
     63                     }
     64                     ZEND_HASH_FILL_ADD(&tmp);
     65                     if (((signed int)low - lstep) < 0) {
     66                         break;
     67                     }
     68                 }
     69             } ZEND_HASH_FILL_END();
     70         } else if (high > low) {    /* Positive Steps */
     71             if (lstep <= 0) {
     72                 err = 1;
     73                 goto err;
     74             }
     75             // 初始化返回的数组
     76             array_init_size(return_value, (uint32_t)(((high - low) / lstep) + 1));
     77             zend_hash_real_init(Z_ARRVAL_P(return_value), 1);
     78             ZEND_HASH_FILL_PACKED(Z_ARRVAL_P(return_value)) {
     79                 // 将字符插入返回的数组
     80                 for (; low <= high; low += (unsigned int)lstep) {
     81                     if (CG(one_char_string)[low]) {
     82                         ZVAL_INTERNED_STR(&tmp, CG(one_char_string)[low]);
     83                     } else {
     84                         ZVAL_STRINGL(&tmp, (char*)&low, 1);
     85                     }
     86                     ZEND_HASH_FILL_ADD(&tmp);
     87                     if (((signed int)low + lstep) > 255) {
     88                         break;
     89                     }
     90                 }
     91             } ZEND_HASH_FILL_END();
     92         } else {
     93             array_init(return_value);
     94             if (CG(one_char_string)[low]) {
     95                 ZVAL_INTERNED_STR(&tmp, CG(one_char_string)[low]);
     96             } else {
     97                 ZVAL_STRINGL(&tmp, (char*)&low, 1);
     98             }
     99             zend_hash_next_index_insert_new(Z_ARRVAL_P(return_value), &tmp);
    100         }
    101     } else if (Z_TYPE_P(zlow) == IS_DOUBLE || Z_TYPE_P(zhigh) == IS_DOUBLE || is_step_double) { // start、end是浮点数
    102         double low, high, value;
    103         zend_long i;
    104 double_str:
    105         low = zval_get_double(zlow);
    106         high = zval_get_double(zhigh);
    107         i = 0;
    108 
    109         // 浮点数范围检查
    110         if (zend_isinf(high) || zend_isinf(low)) {
    111             php_error_docref(NULL, E_WARNING, "Invalid range supplied: start=%0.0f end=%0.0f", low, high);
    112             RETURN_FALSE;
    113         }
    114 
    115         Z_TYPE_INFO(tmp) = IS_DOUBLE;
    116         if (low > high) {         /* Negative steps 第一个参数比第二大*/ 
    117             if (low - high < step || step <= 0) { // 范围差小于步长或步长取绝对值之后仍小于0。则报WARNING错误。
    118                 err = 1;
    119                 goto err;
    120             }
    121 
    122             // 检查并初始化返回的数组
    123             RANGE_CHECK_INIT_ARRAY(low, high);
    124             // 向返回的数组中填充值,降序
    125             ZEND_HASH_FILL_PACKED(Z_ARRVAL_P(return_value)) {
    126             for (value = low; value >= (high - DOUBLE_DRIFT_FIX); value = low - (++i * step)) {
    127                 Z_DVAL(tmp) = value;
    128                 ZEND_HASH_FILL_ADD(&tmp);
    129             }
    130             } ZEND_HASH_FILL_END();
    131         } else if (high > low) {     /* Positive steps 第一个参数比第二个小*/
    132             if (high - low < step || step <= 0) {
    133                 err = 1;
    134                 goto err;
    135             }
    136 
    137             // 检查并初始化返回的数组
    138             RANGE_CHECK_INIT_ARRAY(high, low);
    139             // 向返回的数组中填充值,升序
    140             ZEND_HASH_FILL_PACKED(Z_ARRVAL_P(return_value)) {
    141                 for (value = low; value <= (high + DOUBLE_DRIFT_FIX); value = low + (++i * step)) {
    142                     Z_DVAL(tmp) = value;
    143                     ZEND_HASH_FILL_ADD(&tmp);
    144                 }
    145             } ZEND_HASH_FILL_END();
    146         } else { // low == high。则返回的数组只用一个元素:array(0=>low)
    147             array_init(return_value);
    148             Z_DVAL(tmp) = low;
    149             zend_hash_next_index_insert_new(Z_ARRVAL_P(return_value), &tmp);
    150         }
    151     } else { // start、end是整数
    152         double low, high;
    153         zend_long lstep;
    154 long_str:
    155         low = zval_get_double(zlow);
    156         high = zval_get_double(zhigh);
    157         lstep = (zend_long) step;
    158 
    159         Z_TYPE_INFO(tmp) = IS_LONG;
    160         if (low > high) {         /* Negative steps */
    161             if (low - high < lstep || lstep <= 0) {
    162                 err = 1;
    163                 goto err;
    164             }
    165 
    166             RANGE_CHECK_INIT_ARRAY(low, high);
    167             ZEND_HASH_FILL_PACKED(Z_ARRVAL_P(return_value)) {
    168                 for (; low >= high; low -= lstep) {
    169                     Z_LVAL(tmp) = (zend_long)low;
    170                     ZEND_HASH_FILL_ADD(&tmp);
    171                 }
    172             } ZEND_HASH_FILL_END();
    173         } else if (high > low) {     /* Positive steps */
    174             if (high - low < lstep || lstep <= 0) {
    175                 err = 1;
    176                 goto err;
    177             }
    178 
    179             RANGE_CHECK_INIT_ARRAY(high, low);
    180             ZEND_HASH_FILL_PACKED(Z_ARRVAL_P(return_value)) {
    181                 for (; low <= high; low += lstep) {
    182                     Z_LVAL(tmp) = (zend_long)low;
    183                     ZEND_HASH_FILL_ADD(&tmp);
    184                 }
    185             } ZEND_HASH_FILL_END();
    186         } else {
    187             array_init(return_value);
    188             Z_LVAL(tmp) = (zend_long)low;
    189             zend_hash_next_index_insert_new(Z_ARRVAL_P(return_value), &tmp);
    190         }
    191     }
    192 err:
    193     if (err) {
    194         php_error_docref(NULL, E_WARNING, "step exceeds the specified range");
    195         RETURN_FALSE;
    196     }
    197 }
  • 相关阅读:
    centos7下vi的用法
    jQuery的hover方法搭配css的hover选择器,实现选中元素突出显示
    CSS3弹性伸缩布局(下)——flex布局
    什么是架构设计
    界面底部Tab实现
    一行代码实现圆形头像
    免费快速制作个人简历
    基于JS的问卷调查
    基于CSS的个人网页
    纯HTML课表
  • 原文地址:https://www.cnblogs.com/natian-ws/p/9156122.html
Copyright © 2020-2023  润新知