PHP  
 PHP: Test and Code Coverage Analysis
downloads | QA | documentation | faq | getting help | mailing lists | reporting bugs | php.net sites | links | my php.net 
 

LCOV - code coverage report
Current view: top level - ext/standard - array.c (source / functions) Hit Total Coverage
Test: PHP Code Coverage Lines: 2262 2426 93.2 %
Date: 2015-06-27 Functions: 110 110 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :    +----------------------------------------------------------------------+
       3             :    | PHP Version 7                                                        |
       4             :    +----------------------------------------------------------------------+
       5             :    | Copyright (c) 1997-2015 The PHP Group                                |
       6             :    +----------------------------------------------------------------------+
       7             :    | This source file is subject to version 3.01 of the PHP license,      |
       8             :    | that is bundled with this package in the file LICENSE, and is        |
       9             :    | available through the world-wide-web at the following url:           |
      10             :    | http://www.php.net/license/3_01.txt                                  |
      11             :    | If you did not receive a copy of the PHP license and are unable to   |
      12             :    | obtain it through the world-wide-web, please send a note to          |
      13             :    | license@php.net so we can mail you a copy immediately.               |
      14             :    +----------------------------------------------------------------------+
      15             :    | Authors: Andi Gutmans <andi@zend.com>                                |
      16             :    |          Zeev Suraski <zeev@zend.com>                                |
      17             :    |          Rasmus Lerdorf <rasmus@php.net>                             |
      18             :    |          Andrei Zmievski <andrei@php.net>                            |
      19             :    |          Stig Venaas <venaas@php.net>                                |
      20             :    |          Jason Greene <jason@php.net>                                |
      21             :    +----------------------------------------------------------------------+
      22             : */
      23             : 
      24             : /* $Id$ */
      25             : 
      26             : #include "php.h"
      27             : #include "php_ini.h"
      28             : #include <stdarg.h>
      29             : #include <stdlib.h>
      30             : #include <math.h>
      31             : #include <time.h>
      32             : #include <stdio.h>
      33             : #if HAVE_STRING_H
      34             : #include <string.h>
      35             : #else
      36             : #include <strings.h>
      37             : #endif
      38             : #ifdef PHP_WIN32
      39             : #include "win32/unistd.h"
      40             : #endif
      41             : #include "zend_globals.h"
      42             : #include "zend_interfaces.h"
      43             : #include "php_globals.h"
      44             : #include "php_array.h"
      45             : #include "basic_functions.h"
      46             : #include "php_string.h"
      47             : #include "php_rand.h"
      48             : #include "zend_smart_str.h"
      49             : #ifdef HAVE_SPL
      50             : #include "ext/spl/spl_array.h"
      51             : #endif
      52             : 
      53             : /* {{{ defines */
      54             : #define EXTR_OVERWRITE                  0
      55             : #define EXTR_SKIP                               1
      56             : #define EXTR_PREFIX_SAME                2
      57             : #define EXTR_PREFIX_ALL                 3
      58             : #define EXTR_PREFIX_INVALID             4
      59             : #define EXTR_PREFIX_IF_EXISTS   5
      60             : #define EXTR_IF_EXISTS                  6
      61             : 
      62             : #define EXTR_REFS                               0x100
      63             : 
      64             : #define CASE_LOWER                              0
      65             : #define CASE_UPPER                              1
      66             : 
      67             : #define DIFF_NORMAL                     1
      68             : #define DIFF_KEY                        2
      69             : #define DIFF_ASSOC                      6
      70             : #define DIFF_COMP_DATA_NONE    -1
      71             : #define DIFF_COMP_DATA_INTERNAL 0
      72             : #define DIFF_COMP_DATA_USER     1
      73             : #define DIFF_COMP_KEY_INTERNAL  0
      74             : #define DIFF_COMP_KEY_USER      1
      75             : 
      76             : #define INTERSECT_NORMAL                1
      77             : #define INTERSECT_KEY                   2
      78             : #define INTERSECT_ASSOC                 6
      79             : #define INTERSECT_COMP_DATA_NONE    -1
      80             : #define INTERSECT_COMP_DATA_INTERNAL 0
      81             : #define INTERSECT_COMP_DATA_USER     1
      82             : #define INTERSECT_COMP_KEY_INTERNAL  0
      83             : #define INTERSECT_COMP_KEY_USER      1
      84             : 
      85             : #define DOUBLE_DRIFT_FIX        0.000000000000001
      86             : /* }}} */
      87             : 
      88             : ZEND_DECLARE_MODULE_GLOBALS(array)
      89             : 
      90             : /* {{{ php_array_init_globals
      91             : */
      92       21049 : static void php_array_init_globals(zend_array_globals *array_globals)
      93             : {
      94       21049 :         memset(array_globals, 0, sizeof(zend_array_globals));
      95       21049 : }
      96             : /* }}} */
      97             : 
      98       21049 : PHP_MINIT_FUNCTION(array) /* {{{ */
      99             : {
     100       21049 :         ZEND_INIT_MODULE_GLOBALS(array, php_array_init_globals, NULL);
     101             : 
     102       21049 :         REGISTER_LONG_CONSTANT("EXTR_OVERWRITE", EXTR_OVERWRITE, CONST_CS | CONST_PERSISTENT);
     103       21049 :         REGISTER_LONG_CONSTANT("EXTR_SKIP", EXTR_SKIP, CONST_CS | CONST_PERSISTENT);
     104       21049 :         REGISTER_LONG_CONSTANT("EXTR_PREFIX_SAME", EXTR_PREFIX_SAME, CONST_CS | CONST_PERSISTENT);
     105       21049 :         REGISTER_LONG_CONSTANT("EXTR_PREFIX_ALL", EXTR_PREFIX_ALL, CONST_CS | CONST_PERSISTENT);
     106       21049 :         REGISTER_LONG_CONSTANT("EXTR_PREFIX_INVALID", EXTR_PREFIX_INVALID, CONST_CS | CONST_PERSISTENT);
     107       21049 :         REGISTER_LONG_CONSTANT("EXTR_PREFIX_IF_EXISTS", EXTR_PREFIX_IF_EXISTS, CONST_CS | CONST_PERSISTENT);
     108       21049 :         REGISTER_LONG_CONSTANT("EXTR_IF_EXISTS", EXTR_IF_EXISTS, CONST_CS | CONST_PERSISTENT);
     109       21049 :         REGISTER_LONG_CONSTANT("EXTR_REFS", EXTR_REFS, CONST_CS | CONST_PERSISTENT);
     110             : 
     111       21049 :         REGISTER_LONG_CONSTANT("SORT_ASC", PHP_SORT_ASC, CONST_CS | CONST_PERSISTENT);
     112       21049 :         REGISTER_LONG_CONSTANT("SORT_DESC", PHP_SORT_DESC, CONST_CS | CONST_PERSISTENT);
     113             : 
     114       21049 :         REGISTER_LONG_CONSTANT("SORT_REGULAR", PHP_SORT_REGULAR, CONST_CS | CONST_PERSISTENT);
     115       21049 :         REGISTER_LONG_CONSTANT("SORT_NUMERIC", PHP_SORT_NUMERIC, CONST_CS | CONST_PERSISTENT);
     116       21049 :         REGISTER_LONG_CONSTANT("SORT_STRING", PHP_SORT_STRING, CONST_CS | CONST_PERSISTENT);
     117       21049 :         REGISTER_LONG_CONSTANT("SORT_LOCALE_STRING", PHP_SORT_LOCALE_STRING, CONST_CS | CONST_PERSISTENT);
     118       21049 :         REGISTER_LONG_CONSTANT("SORT_NATURAL", PHP_SORT_NATURAL, CONST_CS | CONST_PERSISTENT);
     119       21049 :         REGISTER_LONG_CONSTANT("SORT_FLAG_CASE", PHP_SORT_FLAG_CASE, CONST_CS | CONST_PERSISTENT);
     120             : 
     121       21049 :         REGISTER_LONG_CONSTANT("CASE_LOWER", CASE_LOWER, CONST_CS | CONST_PERSISTENT);
     122       21049 :         REGISTER_LONG_CONSTANT("CASE_UPPER", CASE_UPPER, CONST_CS | CONST_PERSISTENT);
     123             : 
     124       21049 :         REGISTER_LONG_CONSTANT("COUNT_NORMAL", COUNT_NORMAL, CONST_CS | CONST_PERSISTENT);
     125       21049 :         REGISTER_LONG_CONSTANT("COUNT_RECURSIVE", COUNT_RECURSIVE, CONST_CS | CONST_PERSISTENT);
     126             : 
     127       21049 :         REGISTER_LONG_CONSTANT("ARRAY_FILTER_USE_BOTH", ARRAY_FILTER_USE_BOTH, CONST_CS | CONST_PERSISTENT);
     128       21049 :         REGISTER_LONG_CONSTANT("ARRAY_FILTER_USE_KEY", ARRAY_FILTER_USE_KEY, CONST_CS | CONST_PERSISTENT);
     129             : 
     130       21049 :         return SUCCESS;
     131             : }
     132             : /* }}} */
     133             : 
     134       21085 : PHP_MSHUTDOWN_FUNCTION(array) /* {{{ */
     135             : {
     136             : #ifdef ZTS
     137             :         ts_free_id(array_globals_id);
     138             : #endif
     139             : 
     140       21085 :         return SUCCESS;
     141             : }
     142             : /* }}} */
     143             : 
     144        3111 : static void php_set_compare_func(zend_long sort_type) /* {{{ */
     145             : {
     146        3111 :         switch (sort_type & ~PHP_SORT_FLAG_CASE) {
     147             :                 case PHP_SORT_NUMERIC:
     148         107 :                         ARRAYG(compare_func) = numeric_compare_function;
     149         107 :                         break;
     150             : 
     151             :                 case PHP_SORT_STRING:
     152        1360 :                         ARRAYG(compare_func) = sort_type & PHP_SORT_FLAG_CASE ? string_case_compare_function : string_compare_function;
     153        1360 :                         break;
     154             : 
     155             :                 case PHP_SORT_NATURAL:
     156          55 :                         ARRAYG(compare_func) = sort_type & PHP_SORT_FLAG_CASE ? string_natural_case_compare_function : string_natural_compare_function;
     157          55 :                         break;
     158             : 
     159             : #if HAVE_STRCOLL
     160             :                 case PHP_SORT_LOCALE_STRING:
     161           1 :                         ARRAYG(compare_func) = string_locale_compare_function;
     162           1 :                         break;
     163             : #endif
     164             : 
     165             :                 case PHP_SORT_REGULAR:
     166             :                 default:
     167        1588 :                         ARRAYG(compare_func) = zval_compare_function;
     168             :                         break;
     169             :         }
     170        3111 : }
     171             : /* }}} */
     172             : 
     173        2821 : static int php_array_key_compare(const void *a, const void *b) /* {{{ */
     174             : {
     175             :         Bucket *f;
     176             :         Bucket *s;
     177             :         zval result;
     178             :         zval first;
     179             :         zval second;
     180             : 
     181        2821 :         f = (Bucket *) a;
     182        2821 :         s = (Bucket *) b;
     183             : 
     184        2821 :         if (f->key == NULL) {
     185        1638 :                 ZVAL_LONG(&first, f->h);
     186             :         } else {
     187        1183 :                 ZVAL_STR(&first, f->key);
     188             :         }
     189             : 
     190        2821 :         if (s->key == NULL) {
     191        1640 :                 ZVAL_LONG(&second, s->h);
     192             :         } else {
     193        1181 :                 ZVAL_STR(&second, s->key);
     194             :         }
     195             : 
     196        2821 :         if (ARRAYG(compare_func)(&result, &first, &second) == FAILURE) {
     197           0 :                 return 0;
     198             :         }
     199             : 
     200        2821 :         if (EXPECTED(Z_TYPE(result) == IS_LONG)) {
     201        2821 :                 return ZEND_NORMALIZE_BOOL(Z_LVAL(result));
     202           0 :         } else if (Z_TYPE(result) == IS_DOUBLE) {
     203           0 :                 return ZEND_NORMALIZE_BOOL(Z_DVAL(result));
     204             :         }
     205             : 
     206           0 :         return ZEND_NORMALIZE_BOOL(zval_get_long(&result));
     207             : }
     208             : /* }}} */
     209             : 
     210        1256 : static int php_array_reverse_key_compare(const void *a, const void *b) /* {{{ */
     211             : {
     212        1256 :         return php_array_key_compare(a, b) * -1;
     213             : }
     214             : /* }}} */
     215             : 
     216             : /* {{{ proto bool krsort(array &array_arg [, int sort_flags])
     217             :    Sort an array by key value in reverse order */
     218         199 : PHP_FUNCTION(krsort)
     219             : {
     220             :         zval *array;
     221         199 :         zend_long sort_type = PHP_SORT_REGULAR;
     222             : 
     223             : #ifndef FAST_ZPP
     224             :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "a/|l", &array, &sort_type) == FAILURE) {
     225             :                 RETURN_FALSE;
     226             :         }
     227             : #else
     228         199 :         ZEND_PARSE_PARAMETERS_START(1, 2)
     229         774 :                 Z_PARAM_ARRAY_EX(array, 0, 1)
     230         103 :                 Z_PARAM_OPTIONAL
     231         229 :                 Z_PARAM_LONG(sort_type)
     232         199 :         ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE);
     233             : #endif
     234             : 
     235          95 :         php_set_compare_func(sort_type);
     236             : 
     237          95 :         if (zend_hash_sort(Z_ARRVAL_P(array), php_array_reverse_key_compare, 0) == FAILURE) {
     238           0 :                 RETURN_FALSE;
     239             :         }
     240          95 :         RETURN_TRUE;
     241             : }
     242             : /* }}} */
     243             : 
     244             : /* {{{ proto bool ksort(array &array_arg [, int sort_flags])
     245             :    Sort an array by key */
     246         483 : PHP_FUNCTION(ksort)
     247             : {
     248             :         zval *array;
     249         483 :         zend_long sort_type = PHP_SORT_REGULAR;
     250             : 
     251             : #ifndef FAST_ZPP
     252             :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "a/|l", &array, &sort_type) == FAILURE) {
     253             :                 RETURN_FALSE;
     254             :         }
     255             : #else
     256         483 :         ZEND_PARSE_PARAMETERS_START(1, 2)
     257        1909 :                 Z_PARAM_ARRAY_EX(array, 0, 1)
     258         387 :                 Z_PARAM_OPTIONAL
     259         533 :                 Z_PARAM_LONG(sort_type)
     260         483 :         ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE);
     261             : #endif
     262             : 
     263         378 :         php_set_compare_func(sort_type);
     264             : 
     265         378 :         if (zend_hash_sort(Z_ARRVAL_P(array), php_array_key_compare, 0) == FAILURE) {
     266           0 :                 RETURN_FALSE;
     267             :         }
     268         378 :         RETURN_TRUE;
     269             : }
     270             : /* }}} */
     271             : 
     272         248 : PHPAPI zend_long php_count_recursive(zval *array, zend_long mode) /* {{{ */
     273             : {
     274         248 :         zend_long cnt = 0;
     275             :         zval *element;
     276             : 
     277         248 :         if (Z_TYPE_P(array) == IS_ARRAY) {
     278          59 :                 if (Z_ARRVAL_P(array)->u.v.nApplyCount > 1) {
     279           1 :                         php_error_docref(NULL, E_WARNING, "recursion detected");
     280           1 :                         return 0;
     281             :                 }
     282             : 
     283          58 :                 cnt = zend_hash_num_elements(Z_ARRVAL_P(array));
     284          58 :                 if (mode == COUNT_RECURSIVE) {
     285          58 :                     if (ZEND_HASH_APPLY_PROTECTION(Z_ARRVAL_P(array))) {
     286          58 :                                 Z_ARRVAL_P(array)->u.v.nApplyCount++;
     287             :                         }
     288         270 :                         ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(array), element) {
     289         106 :                                 ZVAL_DEREF(element);
     290         106 :                                 cnt += php_count_recursive(element, COUNT_RECURSIVE);
     291             :                         } ZEND_HASH_FOREACH_END();
     292          58 :                     if (ZEND_HASH_APPLY_PROTECTION(Z_ARRVAL_P(array))) {
     293          58 :                                 Z_ARRVAL_P(array)->u.v.nApplyCount--;
     294             :                         }
     295             :                 }
     296             :         }
     297             : 
     298         247 :         return cnt;
     299             : }
     300             : /* }}} */
     301             : 
     302             : /* {{{ proto int count(mixed var [, int mode])
     303             :    Count the number of elements in a variable (usually an array) */
     304      209750 : PHP_FUNCTION(count)
     305             : {
     306             :         zval *array;
     307      209750 :         zend_long mode = COUNT_NORMAL;
     308             :         zend_long cnt;
     309             :         zval *element;
     310             : 
     311             : #ifndef FAST_ZPP
     312             :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "z|l", &array, &mode) == FAILURE) {
     313             :                 return;
     314             :         }
     315             : #else
     316      209750 :         ZEND_PARSE_PARAMETERS_START(1, 2)
     317      209743 :                 Z_PARAM_ZVAL(array)
     318      209743 :                 Z_PARAM_OPTIONAL
     319      210191 :                 Z_PARAM_LONG(mode)
     320      209750 :         ZEND_PARSE_PARAMETERS_END();
     321             : #endif
     322             : 
     323      419454 :         switch (Z_TYPE_P(array)) {
     324             :                 case IS_NULL:
     325      162039 :                         RETURN_LONG(0);
     326             :                         break;
     327             :                 case IS_ARRAY:
     328       19994 :                         cnt = zend_hash_num_elements(Z_ARRVAL_P(array));
     329       19994 :                         if (mode == COUNT_RECURSIVE) {
     330         333 :                                 ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(array), element) {
     331         142 :                                         ZVAL_DEREF(element);
     332         142 :                                         cnt += php_count_recursive(element, COUNT_RECURSIVE);
     333             :                                 } ZEND_HASH_FOREACH_END();
     334             :                         }
     335       19994 :                         RETURN_LONG(cnt);
     336             :                         break;
     337             :                 case IS_OBJECT: {
     338             : #ifdef HAVE_SPL
     339             :                         zval retval;
     340             : #endif
     341             :                         /* first, we check if the handler is defined */
     342         107 :                         if (Z_OBJ_HT_P(array)->count_elements) {
     343          66 :                                 RETVAL_LONG(1);
     344          66 :                                 if (SUCCESS == Z_OBJ_HT(*array)->count_elements(array, &Z_LVAL_P(return_value))) {
     345          65 :                                         return;
     346             :                                 }
     347             :                         }
     348             : #ifdef HAVE_SPL
     349             :                         /* if not and the object implements Countable we call its count() method */
     350          42 :                         if (instanceof_function(Z_OBJCE_P(array), spl_ce_Countable)) {
     351          26 :                                 zend_call_method_with_0_params(array, NULL, NULL, "count", &retval);
     352          26 :                                 if (Z_TYPE(retval) != IS_UNDEF) {
     353          48 :                                         RETVAL_LONG(zval_get_long(&retval));
     354          24 :                                         zval_ptr_dtor(&retval);
     355             :                                 }
     356          26 :                                 return;
     357             :                         }
     358             : #endif
     359             :                 }
     360             :                 default:
     361       27603 :                         RETURN_LONG(1);
     362             :                         break;
     363             :         }
     364             : }
     365             : /* }}} */
     366             : 
     367             : /* Numbers are always smaller than strings int this function as it
     368             :  * anyway doesn't make much sense to compare two different data types.
     369             :  * This keeps it consistent and simple.
     370             :  *
     371             :  * This is not correct any more, depends on what compare_func is set to.
     372             :  */
     373      242974 : static int php_array_data_compare(const void *a, const void *b) /* {{{ */
     374             : {
     375             :         Bucket *f;
     376             :         Bucket *s;
     377             :         zval result;
     378             :         zval *first;
     379             :         zval *second;
     380             : 
     381      242974 :         f = (Bucket *) a;
     382      242974 :         s = (Bucket *) b;
     383             : 
     384      242974 :         first = &f->val;
     385      242974 :         second = &s->val;
     386             : 
     387      242974 :         if (Z_TYPE_P(first) == IS_INDIRECT) {
     388           7 :                 first = Z_INDIRECT_P(first);
     389             :         }
     390      242974 :         if (Z_TYPE_P(second) == IS_INDIRECT) {
     391           9 :                 second = Z_INDIRECT_P(second);
     392             :         }
     393      242974 :         if (ARRAYG(compare_func)(&result, first, second) == FAILURE) {
     394           0 :                 return 0;
     395             :         }
     396             : 
     397      242974 :         if (EXPECTED(Z_TYPE(result) == IS_LONG)) {
     398      242974 :                 return ZEND_NORMALIZE_BOOL(Z_LVAL(result));
     399           0 :         } else if (Z_TYPE(result) == IS_DOUBLE) {
     400           0 :                 return ZEND_NORMALIZE_BOOL(Z_DVAL(result));
     401             :         }
     402             : 
     403           0 :         return ZEND_NORMALIZE_BOOL(zval_get_long(&result));
     404             : }
     405             : /* }}} */
     406             : 
     407        1803 : static int php_array_reverse_data_compare(const void *a, const void *b) /* {{{ */
     408             : {
     409        1803 :         return php_array_data_compare(a, b) * -1;
     410             : }
     411             : /* }}} */
     412             : 
     413         396 : static int php_array_natural_general_compare(const void *a, const void *b, int fold_case) /* {{{ */
     414             : {
     415         396 :         Bucket *f = (Bucket *) a;
     416         396 :         Bucket *s = (Bucket *) b;
     417         792 :         zend_string *str1 = zval_get_string(&f->val);
     418         792 :         zend_string *str2 = zval_get_string(&s->val);
     419             : 
     420         396 :         int result = strnatcmp_ex(str1->val, str1->len, str2->val, str2->len, fold_case);
     421             : 
     422             :         zend_string_release(str1);
     423             :         zend_string_release(str2);
     424         396 :         return result;
     425             : }
     426             : /* }}} */
     427             : 
     428          66 : static int php_array_natural_compare(const void *a, const void *b) /* {{{ */
     429             : {
     430          66 :         return php_array_natural_general_compare(a, b, 0);
     431             : }
     432             : /* }}} */
     433             : 
     434         330 : static int php_array_natural_case_compare(const void *a, const void *b) /* {{{ */
     435             : {
     436         330 :         return php_array_natural_general_compare(a, b, 1);
     437             : }
     438             : /* }}} */
     439             : 
     440          73 : static void php_natsort(INTERNAL_FUNCTION_PARAMETERS, int fold_case) /* {{{ */
     441             : {
     442             :         zval *array;
     443             : 
     444          73 :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "a/", &array) == FAILURE) {
     445          26 :                 return;
     446             :         }
     447             : 
     448          47 :         if (fold_case) {
     449          42 :                 if (zend_hash_sort(Z_ARRVAL_P(array), php_array_natural_case_compare, 0) == FAILURE) {
     450           0 :                         return;
     451             :                 }
     452             :         } else {
     453           5 :                 if (zend_hash_sort(Z_ARRVAL_P(array), php_array_natural_compare, 0) == FAILURE) {
     454           0 :                         return;
     455             :                 }
     456             :         }
     457             : 
     458          47 :         RETURN_TRUE;
     459             : }
     460             : /* }}} */
     461             : 
     462             : /* {{{ proto void natsort(array &array_arg)
     463             :    Sort an array using natural sort */
     464           5 : PHP_FUNCTION(natsort)
     465             : {
     466           5 :         php_natsort(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
     467           5 : }
     468             : /* }}} */
     469             : 
     470             : /* {{{ proto void natcasesort(array &array_arg)
     471             :    Sort an array using case-insensitive natural sort */
     472          68 : PHP_FUNCTION(natcasesort)
     473             : {
     474          68 :         php_natsort(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
     475          68 : }
     476             : /* }}} */
     477             : 
     478             : /* {{{ proto bool asort(array &array_arg [, int sort_flags])
     479             :    Sort an array and maintain index association */
     480         245 : PHP_FUNCTION(asort)
     481             : {
     482             :         zval *array;
     483         245 :         zend_long sort_type = PHP_SORT_REGULAR;
     484             : 
     485         245 :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "a/|l", &array, &sort_type) == FAILURE) {
     486         105 :                 RETURN_FALSE;
     487             :         }
     488             : 
     489         140 :         php_set_compare_func(sort_type);
     490             : 
     491         140 :         if (zend_hash_sort(Z_ARRVAL_P(array), php_array_data_compare, 0) == FAILURE) {
     492           0 :                 RETURN_FALSE;
     493             :         }
     494         140 :         RETURN_TRUE;
     495             : }
     496             : /* }}} */
     497             : 
     498             : /* {{{ proto bool arsort(array &array_arg [, int sort_flags])
     499             :    Sort an array in reverse order and maintain index association */
     500         184 : PHP_FUNCTION(arsort)
     501             : {
     502             :         zval *array;
     503         184 :         zend_long sort_type = PHP_SORT_REGULAR;
     504             : 
     505         184 :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "a/|l", &array, &sort_type) == FAILURE) {
     506         104 :                 RETURN_FALSE;
     507             :         }
     508             : 
     509          80 :         php_set_compare_func(sort_type);
     510             : 
     511          80 :         if (zend_hash_sort(Z_ARRVAL_P(array), php_array_reverse_data_compare, 0) == FAILURE) {
     512           0 :                 RETURN_FALSE;
     513             :         }
     514          80 :         RETURN_TRUE;
     515             : }
     516             : /* }}} */
     517             : 
     518             : /* {{{ proto bool sort(array &array_arg [, int sort_flags])
     519             :    Sort an array */
     520         237 : PHP_FUNCTION(sort)
     521             : {
     522             :         zval *array;
     523         237 :         zend_long sort_type = PHP_SORT_REGULAR;
     524             : 
     525         237 :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "a/|l", &array, &sort_type) == FAILURE) {
     526         104 :                 RETURN_FALSE;
     527             :         }
     528             : 
     529         133 :         php_set_compare_func(sort_type);
     530             : 
     531         133 :         if (zend_hash_sort(Z_ARRVAL_P(array), php_array_data_compare, 1) == FAILURE) {
     532           0 :                 RETURN_FALSE;
     533             :         }
     534         133 :         RETURN_TRUE;
     535             : }
     536             : /* }}} */
     537             : 
     538             : /* {{{ proto bool rsort(array &array_arg [, int sort_flags])
     539             :    Sort an array in reverse order */
     540         182 : PHP_FUNCTION(rsort)
     541             : {
     542             :         zval *array;
     543         182 :         zend_long sort_type = PHP_SORT_REGULAR;
     544             : 
     545         182 :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "a/|l", &array, &sort_type) == FAILURE) {
     546         105 :                 RETURN_FALSE;
     547             :         }
     548             : 
     549          77 :         php_set_compare_func(sort_type);
     550             : 
     551          77 :         if (zend_hash_sort(Z_ARRVAL_P(array), php_array_reverse_data_compare, 1) == FAILURE) {
     552           0 :                 RETURN_FALSE;
     553             :         }
     554          77 :         RETURN_TRUE;
     555             : }
     556             : /* }}} */
     557             : 
     558      191249 : static int php_array_user_compare(const void *a, const void *b) /* {{{ */
     559             : {
     560             :         Bucket *f;
     561             :         Bucket *s;
     562             :         zval args[2];
     563             :         zval retval;
     564             : 
     565      191249 :         f = (Bucket *) a;
     566      191249 :         s = (Bucket *) b;
     567             : 
     568      191249 :         ZVAL_COPY(&args[0], &f->val);
     569      191249 :         ZVAL_COPY(&args[1], &s->val);
     570             : 
     571      191249 :         BG(user_compare_fci).param_count = 2;
     572      191249 :         BG(user_compare_fci).params = args;
     573      191249 :         BG(user_compare_fci).retval = &retval;
     574      191249 :         BG(user_compare_fci).no_separation = 0;
     575      382498 :         if (zend_call_function(&BG(user_compare_fci), &BG(user_compare_fci_cache)) == SUCCESS && Z_TYPE(retval) != IS_UNDEF) {
     576      191249 :                 zend_long ret = zval_get_long(&retval);
     577      191249 :                 zval_ptr_dtor(&retval);
     578      191249 :                 zval_ptr_dtor(&args[1]);
     579      191249 :                 zval_ptr_dtor(&args[0]);
     580      191249 :                 return ret < 0 ? -1 : ret > 0 ? 1 : 0;
     581             :         } else {
     582           0 :                 zval_ptr_dtor(&args[1]);
     583           0 :                 zval_ptr_dtor(&args[0]);
     584           0 :                 return 0;
     585             :         }
     586             : }
     587             : /* }}} */
     588             : 
     589             : /* check if comparison function is valid */
     590             : #define PHP_ARRAY_CMP_FUNC_CHECK(func_name)     \
     591             :         if (!zend_is_callable(*func_name, 0, NULL)) {   \
     592             :                 php_error_docref(NULL, E_WARNING, "Invalid comparison function");     \
     593             :                 BG(user_compare_fci) = old_user_compare_fci; \
     594             :                 BG(user_compare_fci_cache) = old_user_compare_fci_cache; \
     595             :                 RETURN_FALSE;   \
     596             :         }       \
     597             : 
     598             :         /* Clear FCI cache otherwise : for example the same or other array with
     599             :          * (partly) the same key values has been sorted with uasort() or
     600             :          * other sorting function the comparison is cached, however the name
     601             :          * of the function for comparison is not respected. see bug #28739 AND #33295
     602             :          *
     603             :          * Following defines will assist in backup / restore values. */
     604             : 
     605             : #define PHP_ARRAY_CMP_FUNC_VARS \
     606             :         zend_fcall_info old_user_compare_fci; \
     607             :         zend_fcall_info_cache old_user_compare_fci_cache \
     608             : 
     609             : #define PHP_ARRAY_CMP_FUNC_BACKUP() \
     610             :         old_user_compare_fci = BG(user_compare_fci); \
     611             :         old_user_compare_fci_cache = BG(user_compare_fci_cache); \
     612             :         BG(user_compare_fci_cache) = empty_fcall_info_cache; \
     613             : 
     614             : #define PHP_ARRAY_CMP_FUNC_RESTORE() \
     615             :         BG(user_compare_fci) = old_user_compare_fci; \
     616             :         BG(user_compare_fci_cache) = old_user_compare_fci_cache; \
     617             : 
     618             : /* {{{ proto bool usort(array array_arg, string cmp_function)
     619             :    Sort an array by values using a user-defined comparison function */
     620         104 : PHP_FUNCTION(usort)
     621             : {
     622             :         zval *array;
     623             :         zend_refcounted *arr;
     624             :         unsigned int refcount;
     625             :         PHP_ARRAY_CMP_FUNC_VARS;
     626             : 
     627         104 :         PHP_ARRAY_CMP_FUNC_BACKUP();
     628             : 
     629         104 :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "a/f", &array, &BG(user_compare_fci), &BG(user_compare_fci_cache)) == FAILURE) {
     630          58 :                 PHP_ARRAY_CMP_FUNC_RESTORE();
     631          58 :                 return;
     632             :         }
     633             : 
     634             :         /* Increase reference counter, so the attempts to modify the array in user
     635             :          * comparison function will create a copy of array and won't affect the
     636             :          * original array. The fact of modification is detected using refcount
     637             :          * comparison. The result of sorting in such case is undefined and the
     638             :          * function returns FALSE.
     639             :          */
     640          46 :         Z_ADDREF_P(array);
     641          92 :         refcount = Z_REFCOUNT_P(array);
     642          46 :         arr = Z_COUNTED_P(array);
     643             : 
     644          46 :         if (zend_hash_sort(Z_ARRVAL_P(array), php_array_user_compare, 1) == FAILURE) {
     645           0 :                 RETVAL_FALSE;
     646             :         } else {
     647          92 :                 if (refcount > Z_REFCOUNT_P(array)) {
     648           1 :                         php_error_docref(NULL, E_WARNING, "Array was modified by the user comparison function");
     649           1 :                         if (--GC_REFCOUNT(arr) <= 0) {
     650           1 :                                 _zval_dtor_func(arr ZEND_FILE_LINE_CC);
     651             :                         }
     652           1 :                         RETVAL_FALSE;
     653             :                 } else {
     654          45 :                         Z_DELREF_P(array);
     655          45 :                         RETVAL_TRUE;
     656             :                 }
     657             :         }
     658             : 
     659          46 :         PHP_ARRAY_CMP_FUNC_RESTORE();
     660             : }
     661             : /* }}} */
     662             : 
     663             : /* {{{ proto bool uasort(array array_arg, string cmp_function)
     664             :    Sort an array with a user-defined comparison function and maintain index association */
     665          94 : PHP_FUNCTION(uasort)
     666             : {
     667             :         zval *array;
     668             :         zend_refcounted *arr;
     669             :         unsigned int refcount;
     670             :         PHP_ARRAY_CMP_FUNC_VARS;
     671             : 
     672          94 :         PHP_ARRAY_CMP_FUNC_BACKUP();
     673             : 
     674          94 :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "a/f", &array, &BG(user_compare_fci), &BG(user_compare_fci_cache)) == FAILURE) {
     675          57 :                 PHP_ARRAY_CMP_FUNC_RESTORE();
     676          57 :                 return;
     677             :         }
     678             : 
     679             :         /* Increase reference counter, so the attempts to modify the array in user
     680             :          * comparison function will create a copy of array and won't affect the
     681             :          * original array. The fact of modification is detected using refcount
     682             :          * comparison. The result of sorting in such case is undefined and the
     683             :          * function returns FALSE.
     684             :          */
     685          37 :         Z_ADDREF_P(array);
     686          74 :         refcount = Z_REFCOUNT_P(array);
     687          37 :         arr = Z_COUNTED_P(array);
     688             : 
     689          37 :         if (zend_hash_sort(Z_ARRVAL_P(array), php_array_user_compare, 0) == FAILURE) {
     690           0 :                 RETVAL_FALSE;
     691             :         } else {
     692          74 :                 if (refcount > Z_REFCOUNT_P(array)) {
     693           0 :                         php_error_docref(NULL, E_WARNING, "Array was modified by the user comparison function");
     694           0 :                         if (--GC_REFCOUNT(arr) <= 0) {
     695           0 :                                 _zval_dtor_func(arr ZEND_FILE_LINE_CC);
     696             :                         }
     697           0 :                         RETVAL_FALSE;
     698             :                 } else {
     699          37 :                         Z_DELREF_P(array);
     700          37 :                         RETVAL_TRUE;
     701             :                 }
     702             :         }
     703             : 
     704          37 :         PHP_ARRAY_CMP_FUNC_RESTORE();
     705             : }
     706             : /* }}} */
     707             : 
     708        5090 : static int php_array_user_key_compare(const void *a, const void *b) /* {{{ */
     709             : {
     710             :         Bucket *f;
     711             :         Bucket *s;
     712             :         zval args[2];
     713             :         zval retval;
     714             :         zend_long result;
     715             : 
     716        5090 :         ZVAL_NULL(&args[0]);
     717        5090 :         ZVAL_NULL(&args[1]);
     718             : 
     719        5090 :         f = (Bucket *) a;
     720        5090 :         s = (Bucket *) b;
     721             : 
     722        5090 :         if (f->key == NULL) {
     723        1804 :                 ZVAL_LONG(&args[0], f->h);
     724             :         } else {
     725        3286 :                 ZVAL_STR_COPY(&args[0], f->key);
     726             :         }
     727        5090 :         if (s->key == NULL) {
     728        2031 :                 ZVAL_LONG(&args[1], s->h);
     729             :         } else {
     730        3059 :                 ZVAL_STR_COPY(&args[1], s->key);
     731             :         }
     732             : 
     733        5090 :         BG(user_compare_fci).param_count = 2;
     734        5090 :         BG(user_compare_fci).params = args;
     735        5090 :         BG(user_compare_fci).retval = &retval;
     736        5090 :         BG(user_compare_fci).no_separation = 0;
     737       15270 :         if (zend_call_function(&BG(user_compare_fci), &BG(user_compare_fci_cache)) == SUCCESS && Z_TYPE(retval) != IS_UNDEF) {
     738        5090 :                 result = zval_get_long(&retval);
     739        5090 :                 zval_ptr_dtor(&retval);
     740             :         } else {
     741           0 :                 result = 0;
     742             :         }
     743             : 
     744        5090 :         zval_ptr_dtor(&args[0]);
     745        5090 :         zval_ptr_dtor(&args[1]);
     746             : 
     747        5090 :         return result < 0 ? -1 : result > 0 ? 1 : 0;
     748             : }
     749             : /* }}} */
     750             : 
     751             : /* {{{ proto bool uksort(array array_arg, string cmp_function)
     752             :    Sort an array by keys using a user-defined comparison function */
     753          62 : PHP_FUNCTION(uksort)
     754             : {
     755             :         zval *array;
     756             :         zend_refcounted *arr;
     757             :         unsigned int refcount;
     758             :         PHP_ARRAY_CMP_FUNC_VARS;
     759             : 
     760          62 :         PHP_ARRAY_CMP_FUNC_BACKUP();
     761             : 
     762          62 :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "a/f", &array, &BG(user_compare_fci), &BG(user_compare_fci_cache)) == FAILURE) {
     763          53 :                 PHP_ARRAY_CMP_FUNC_RESTORE();
     764          53 :                 return;
     765             :         }
     766             : 
     767             :         /* Increase reference counter, so the attempts to modify the array in user
     768             :          * comparison function will create a copy of array and won't affect the
     769             :          * original array. The fact of modification is detected using refcount
     770             :          * comparison. The result of sorting in such case is undefined and the
     771             :          * function returns FALSE.
     772             :          */
     773           9 :         Z_ADDREF_P(array);
     774          18 :         refcount = Z_REFCOUNT_P(array);
     775           9 :         arr = Z_COUNTED_P(array);
     776             : 
     777           9 :         if (zend_hash_sort(Z_ARRVAL_P(array), php_array_user_key_compare, 0) == FAILURE) {
     778           0 :                 RETVAL_FALSE;
     779             :         } else {
     780          18 :                 if (refcount > Z_REFCOUNT_P(array)) {
     781           0 :                         php_error_docref(NULL, E_WARNING, "Array was modified by the user comparison function");
     782           0 :                         if (--GC_REFCOUNT(arr) <= 0) {
     783           0 :                                 _zval_dtor_func(arr ZEND_FILE_LINE_CC);
     784             :                         }
     785           0 :                         RETVAL_FALSE;
     786             :                 } else {
     787           9 :                         Z_DELREF_P(array);
     788           9 :                         RETVAL_TRUE;
     789             :                 }
     790             :         }
     791             : 
     792           9 :         PHP_ARRAY_CMP_FUNC_RESTORE();
     793             : }
     794             : /* }}} */
     795             : 
     796             : /* {{{ proto mixed end(array array_arg)
     797             :    Advances array argument's internal pointer to the last element and return it */
     798          76 : PHP_FUNCTION(end)
     799             : {
     800             :         HashTable *array;
     801             :         zval *entry;
     802             : 
     803             : #ifndef FAST_ZPP
     804             :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "H/", &array) == FAILURE) {
     805             :                 return;
     806             :         }
     807             : #else
     808          76 :         ZEND_PARSE_PARAMETERS_START(1, 1)
     809         281 :                 Z_PARAM_ARRAY_OR_OBJECT_HT_EX(array, 0, 1)
     810          76 :         ZEND_PARSE_PARAMETERS_END();
     811             : #endif
     812             : 
     813          47 :         zend_hash_internal_pointer_end(array);
     814             : 
     815          47 :         if (USED_RET()) {
     816          34 :                 if ((entry = zend_hash_get_current_data(array)) == NULL) {
     817           2 :                         RETURN_FALSE;
     818             :                 }
     819             : 
     820          32 :                 if (Z_TYPE_P(entry) == IS_INDIRECT) {
     821           1 :                         entry = Z_INDIRECT_P(entry);
     822             :                 }
     823             : 
     824          32 :                 ZVAL_DEREF(entry);
     825          32 :                 ZVAL_COPY(return_value, entry);
     826             :         }
     827             : }
     828             : /* }}} */
     829             : 
     830             : /* {{{ proto mixed prev(array array_arg)
     831             :    Move array argument's internal pointer to the previous element and return it */
     832          46 : PHP_FUNCTION(prev)
     833             : {
     834             :         HashTable *array;
     835             :         zval *entry;
     836             : 
     837             : #ifndef FAST_ZPP
     838             :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "H/", &array) == FAILURE) {
     839             :                 return;
     840             :         }
     841             : #else
     842          46 :         ZEND_PARSE_PARAMETERS_START(1, 1)
     843         154 :                 Z_PARAM_ARRAY_OR_OBJECT_HT_EX(array, 0, 1)
     844          46 :         ZEND_PARSE_PARAMETERS_END();
     845             : #endif
     846             : 
     847          21 :         zend_hash_move_backwards(array);
     848             : 
     849          21 :         if (USED_RET()) {
     850          19 :                 if ((entry = zend_hash_get_current_data(array)) == NULL) {
     851           6 :                         RETURN_FALSE;
     852             :                 }
     853             : 
     854          13 :                 if (Z_TYPE_P(entry) == IS_INDIRECT) {
     855           0 :                         entry = Z_INDIRECT_P(entry);
     856             :                 }
     857             : 
     858          13 :                 ZVAL_DEREF(entry);
     859          13 :                 ZVAL_COPY(return_value, entry);
     860             :         }
     861             : }
     862             : /* }}} */
     863             : 
     864             : /* {{{ proto mixed next(array array_arg)
     865             :    Move array argument's internal pointer to the next element and return it */
     866        2304 : PHP_FUNCTION(next)
     867             : {
     868             :         HashTable *array;
     869             :         zval *entry;
     870             : 
     871             : #ifndef FAST_ZPP
     872             :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "H/", &array) == FAILURE) {
     873             :                 return;
     874             :         }
     875             : #else
     876        2304 :         ZEND_PARSE_PARAMETERS_START(1, 1)
     877        9205 :                 Z_PARAM_ARRAY_OR_OBJECT_HT_EX(array, 0, 1)
     878        2304 :         ZEND_PARSE_PARAMETERS_END();
     879             : #endif
     880             : 
     881        2273 :         zend_hash_move_forward(array);
     882             : 
     883        2273 :         if (USED_RET()) {
     884        2226 :                 if ((entry = zend_hash_get_current_data(array)) == NULL) {
     885         388 :                         RETURN_FALSE;
     886             :                 }
     887             : 
     888        1838 :                 if (Z_TYPE_P(entry) == IS_INDIRECT) {
     889           0 :                         entry = Z_INDIRECT_P(entry);
     890             :                 }
     891             : 
     892        1838 :                 ZVAL_DEREF(entry);
     893        1838 :                 ZVAL_COPY(return_value, entry);
     894             :         }
     895             : }
     896             : /* }}} */
     897             : 
     898             : /* {{{ proto mixed reset(array array_arg)
     899             :    Set array argument's internal pointer to the first element and return it */
     900         512 : PHP_FUNCTION(reset)
     901             : {
     902             :         HashTable *array;
     903             :         zval *entry;
     904             : 
     905             : #ifndef FAST_ZPP
     906             :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "H/", &array) == FAILURE) {
     907             :                 return;
     908             :         }
     909             : #else
     910         512 :         ZEND_PARSE_PARAMETERS_START(1, 1)
     911        2027 :                 Z_PARAM_ARRAY_OR_OBJECT_HT_EX(array, 0, 1)
     912         512 :         ZEND_PARSE_PARAMETERS_END();
     913             : #endif
     914             : 
     915         481 :         zend_hash_internal_pointer_reset(array);
     916             : 
     917         481 :         if (USED_RET()) {
     918          69 :                 if ((entry = zend_hash_get_current_data(array)) == NULL) {
     919           3 :                         RETURN_FALSE;
     920             :                 }
     921             : 
     922          66 :                 if (Z_TYPE_P(entry) == IS_INDIRECT) {
     923           0 :                         entry = Z_INDIRECT_P(entry);
     924             :                 }
     925             : 
     926          66 :                 ZVAL_DEREF(entry);
     927          66 :                 ZVAL_COPY(return_value, entry);
     928             :         }
     929             : }
     930             : /* }}} */
     931             : 
     932             : /* {{{ proto mixed current(array array_arg)
     933             :    Return the element currently pointed to by the internal array pointer */
     934        2445 : PHP_FUNCTION(current)
     935             : {
     936             :         HashTable *array;
     937             :         zval *entry;
     938             : 
     939             : #ifndef FAST_ZPP
     940             :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "H", &array) == FAILURE) {
     941             :                 return;
     942             :         }
     943             : #else
     944        2445 :         ZEND_PARSE_PARAMETERS_START(1, 1)
     945        7323 :                 Z_PARAM_ARRAY_OR_OBJECT_HT(array)
     946        2445 :         ZEND_PARSE_PARAMETERS_END();
     947             : #endif
     948             : 
     949        2414 :         if ((entry = zend_hash_get_current_data(array)) == NULL) {
     950          23 :                 RETURN_FALSE;
     951             :         }
     952             : 
     953        2391 :         if (Z_TYPE_P(entry) == IS_INDIRECT) {
     954           1 :                 entry = Z_INDIRECT_P(entry);
     955             :         }
     956             : 
     957        2391 :         ZVAL_DEREF(entry);
     958        2391 :         ZVAL_COPY(return_value, entry);
     959             : }
     960             : /* }}} */
     961             : 
     962             : /* {{{ proto mixed key(array array_arg)
     963             :    Return the key of the element currently pointed to by the internal array pointer */
     964        2406 : PHP_FUNCTION(key)
     965             : {
     966             :         HashTable *array;
     967             : 
     968             : #ifndef FAST_ZPP
     969             :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "H", &array) == FAILURE) {
     970             :                 return;
     971             :         }
     972             : #else
     973        2406 :         ZEND_PARSE_PARAMETERS_START(1, 1)
     974        7206 :                 Z_PARAM_ARRAY_OR_OBJECT_HT(array)
     975        2406 :         ZEND_PARSE_PARAMETERS_END();
     976             : #endif
     977             : 
     978        2375 :         zend_hash_get_current_key_zval(array, return_value);
     979             : }
     980             : /* }}} */
     981             : 
     982             : /* {{{ proto mixed min(mixed arg1 [, mixed arg2 [, mixed ...]])
     983             :    Return the lowest value in an array or a series of arguments */
     984         667 : PHP_FUNCTION(min)
     985             : {
     986             :         int argc;
     987         667 :         zval *args = NULL;
     988             : 
     989         667 :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "+", &args, &argc) == FAILURE) {
     990           2 :                 return;
     991             :         }
     992             : 
     993         665 :         php_set_compare_func(PHP_SORT_REGULAR);
     994             : 
     995             :         /* mixed min ( array $values ) */
     996         665 :         if (argc == 1) {
     997             :                 zval *result;
     998             : 
     999          46 :                 if (Z_TYPE(args[0]) != IS_ARRAY) {
    1000           4 :                         php_error_docref(NULL, E_WARNING, "When only one parameter is given, it must be an array");
    1001           4 :                         RETVAL_NULL();
    1002             :                 } else {
    1003          19 :                         if ((result = zend_hash_minmax(Z_ARRVAL(args[0]), php_array_data_compare, 0)) != NULL) {
    1004          17 :                                 ZVAL_DEREF(result);
    1005          17 :                                 ZVAL_COPY(return_value, result);
    1006             :                         } else {
    1007           2 :                                 php_error_docref(NULL, E_WARNING, "Array must contain at least one element");
    1008           2 :                                 RETVAL_FALSE;
    1009             :                         }
    1010             :                 }
    1011             :         } else {
    1012             :                 /* mixed min ( mixed $value1 , mixed $value2 [, mixed $value3... ] ) */
    1013             :                 zval *min, result;
    1014             :                 int i;
    1015             : 
    1016         642 :                 min = &args[0];
    1017             : 
    1018        2535 :                 for (i = 1; i < argc; i++) {
    1019        1893 :                         is_smaller_function(&result, &args[i], min);
    1020        1893 :                         if (Z_TYPE(result) == IS_TRUE) {
    1021         583 :                                 min = &args[i];
    1022             :                         }
    1023             :                 }
    1024             : 
    1025         642 :                 ZVAL_DEREF(min);
    1026         642 :                 ZVAL_COPY(return_value, min);
    1027             :         }
    1028             : }
    1029             : /* }}} */
    1030             : 
    1031             : /* {{{ proto mixed max(mixed arg1 [, mixed arg2 [, mixed ...]])
    1032             :    Return the highest value in an array or a series of arguments */
    1033          96 : PHP_FUNCTION(max)
    1034             : {
    1035          96 :         zval *args = NULL;
    1036             :         int argc;
    1037             : 
    1038          96 :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "+", &args, &argc) == FAILURE) {
    1039           2 :                 return;
    1040             :         }
    1041             : 
    1042          94 :         php_set_compare_func(PHP_SORT_REGULAR);
    1043             : 
    1044             :         /* mixed max ( array $values ) */
    1045          94 :         if (argc == 1) {
    1046             :                 zval *result;
    1047             : 
    1048         134 :                 if (Z_TYPE(args[0]) != IS_ARRAY) {
    1049           4 :                         php_error_docref(NULL, E_WARNING, "When only one parameter is given, it must be an array");
    1050           4 :                         RETVAL_NULL();
    1051             :                 } else {
    1052          63 :                         if ((result = zend_hash_minmax(Z_ARRVAL(args[0]), php_array_data_compare, 1)) != NULL) {
    1053          61 :                                 ZVAL_DEREF(result);
    1054          61 :                                 ZVAL_COPY(return_value, result);
    1055             :                         } else {
    1056           2 :                                 php_error_docref(NULL, E_WARNING, "Array must contain at least one element");
    1057           2 :                                 RETVAL_FALSE;
    1058             :                         }
    1059             :                 }
    1060             :         } else {
    1061             :                 /* mixed max ( mixed $value1 , mixed $value2 [, mixed $value3... ] ) */
    1062             :                 zval *max, result;
    1063             :                 int i;
    1064             : 
    1065          27 :                 max = &args[0];
    1066             : 
    1067        1305 :                 for (i = 1; i < argc; i++) {
    1068        1278 :                         is_smaller_or_equal_function(&result, &args[i], max);
    1069        1278 :                         if (Z_TYPE(result) == IS_FALSE) {
    1070          43 :                                 max = &args[i];
    1071             :                         }
    1072             :                 }
    1073             : 
    1074          27 :                 ZVAL_DEREF(max);
    1075          27 :                 ZVAL_COPY(return_value, max);
    1076             :         }
    1077             : }
    1078             : /* }}} */
    1079             : 
    1080         260 : static int php_array_walk(HashTable *target_hash, zval *userdata, int recursive) /* {{{ */
    1081             : {
    1082             :         zval args[3],           /* Arguments to userland function */
    1083             :                  retval,                /* Return value - unused */
    1084             :                  *zv;
    1085             : 
    1086             :         /* Set up known arguments */
    1087         260 :         ZVAL_UNDEF(&retval);
    1088         260 :         ZVAL_UNDEF(&args[1]);
    1089         260 :         if (userdata) {
    1090         151 :                 ZVAL_COPY(&args[2], userdata);
    1091             :         }
    1092             : 
    1093         260 :         BG(array_walk_fci).retval = &retval;
    1094         260 :         BG(array_walk_fci).param_count = userdata ? 3 : 2;
    1095         260 :         BG(array_walk_fci).params = args;
    1096         260 :         BG(array_walk_fci).no_separation = 0;
    1097             : 
    1098             :         /* Iterate through hash */
    1099         260 :         zend_hash_internal_pointer_reset(target_hash);
    1100        1527 :         while (!EG(exception) && (zv = zend_hash_get_current_data(target_hash)) != NULL) {
    1101        1008 :                 if (Z_TYPE_P(zv) == IS_INDIRECT) {
    1102          12 :                         zv = Z_INDIRECT_P(zv);
    1103          12 :                         if (Z_TYPE_P(zv) == IS_UNDEF) {
    1104           0 :                                 zend_hash_move_forward(target_hash);
    1105           0 :                                 continue;
    1106             :                         }
    1107             :                 }
    1108        1884 :                 if (recursive &&
    1109             :                     (Z_TYPE_P(zv) == IS_ARRAY ||
    1110           8 :                      (Z_ISREF_P(zv) && Z_TYPE_P(Z_REFVAL_P(zv)) == IS_ARRAY))) {
    1111             :                         HashTable *thash;
    1112             :                         zend_fcall_info orig_array_walk_fci;
    1113             :                         zend_fcall_info_cache orig_array_walk_fci_cache;
    1114             : 
    1115         110 :                         if (Z_ISREF_P(zv)) {
    1116           0 :                                 thash = Z_ARRVAL_P(Z_REFVAL_P(zv));
    1117             :                         } else {
    1118         300 :                                 SEPARATE_ZVAL(zv);
    1119         110 :                                 thash = Z_ARRVAL_P(zv);
    1120             :                         }
    1121         110 :                         if (thash->u.v.nApplyCount > 1) {
    1122           0 :                                 php_error_docref(NULL, E_WARNING, "recursion detected");
    1123           0 :                                 if (userdata) {
    1124           0 :                                         zval_ptr_dtor(&args[2]);
    1125             :                                 }
    1126           0 :                                 return 0;
    1127             :                         }
    1128             : 
    1129             :                         /* backup the fcall info and cache */
    1130         110 :                         orig_array_walk_fci = BG(array_walk_fci);
    1131         110 :                         orig_array_walk_fci_cache = BG(array_walk_fci_cache);
    1132             : 
    1133         110 :                         thash->u.v.nApplyCount++;
    1134         110 :                         php_array_walk(thash, userdata, recursive);
    1135         110 :                         thash->u.v.nApplyCount--;
    1136             : 
    1137             :                         /* restore the fcall info and cache */
    1138         110 :                         BG(array_walk_fci) = orig_array_walk_fci;
    1139         110 :                         BG(array_walk_fci_cache) = orig_array_walk_fci_cache;
    1140             :                 } else {
    1141         898 :                         int was_ref = Z_ISREF_P(zv);
    1142             : 
    1143         898 :                         ZVAL_COPY(&args[0], zv);
    1144             : 
    1145             :                         /* Allocate space for key */
    1146         898 :                         zend_hash_get_current_key_zval(target_hash, &args[1]);
    1147             : 
    1148             :                         /* Call the userland function */
    1149         898 :                         if (zend_call_function(&BG(array_walk_fci), &BG(array_walk_fci_cache)) == SUCCESS) {
    1150        1793 :                                 if (!was_ref && Z_ISREF(args[0])) {
    1151             :                                         /* copy reference back */
    1152             :                                         zval garbage;
    1153             : 
    1154          20 :                                         ZVAL_COPY_VALUE(&garbage, zv);
    1155          20 :                                         ZVAL_COPY_VALUE(zv, &args[0]);
    1156          20 :                                         zval_ptr_dtor(&garbage);
    1157             :                                 } else {
    1158         877 :                                         zval_ptr_dtor(&args[0]);
    1159             :                                 }
    1160         897 :                                 zval_ptr_dtor(&retval);
    1161             :                         } else {
    1162           0 :                                 zval_ptr_dtor(&args[0]);
    1163           0 :                                 if (Z_TYPE(args[1]) != IS_UNDEF) {
    1164           0 :                                         zval_ptr_dtor(&args[1]);
    1165           0 :                                         ZVAL_UNDEF(&args[1]);
    1166             :                                 }
    1167           0 :                                 break;
    1168             :                         }
    1169             :                 }
    1170             : 
    1171        1007 :                 if (Z_TYPE(args[1]) != IS_UNDEF) {
    1172         897 :                         zval_ptr_dtor(&args[1]);
    1173         897 :                         ZVAL_UNDEF(&args[1]);
    1174             :                 }
    1175        1007 :                 zend_hash_move_forward(target_hash);
    1176             :         }
    1177             : 
    1178         259 :         if (userdata) {
    1179         150 :                 zval_ptr_dtor(&args[2]);
    1180             :         }
    1181         259 :         return 0;
    1182             : }
    1183             : /* }}} */
    1184             : 
    1185             : /* {{{ proto bool array_walk(array input, string funcname [, mixed userdata])
    1186             :    Apply a user function to every member of an array */
    1187         209 : PHP_FUNCTION(array_walk)
    1188             : {
    1189             :         HashTable *array;
    1190         209 :         zval *userdata = NULL;
    1191             :         zend_fcall_info orig_array_walk_fci;
    1192             :         zend_fcall_info_cache orig_array_walk_fci_cache;
    1193             : 
    1194         209 :         orig_array_walk_fci = BG(array_walk_fci);
    1195         209 :         orig_array_walk_fci_cache = BG(array_walk_fci_cache);
    1196             : 
    1197             : #ifndef FAST_ZPP
    1198             :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "H/f|z/", &array, &BG(array_walk_fci), &BG(array_walk_fci_cache), &userdata) == FAILURE) {
    1199             :                 BG(array_walk_fci) = orig_array_walk_fci;
    1200             :                 BG(array_walk_fci_cache) = orig_array_walk_fci_cache;
    1201             :                 return;
    1202             :         }
    1203             : #else
    1204         209 :         ZEND_PARSE_PARAMETERS_START(2, 3)
    1205         806 :                 Z_PARAM_ARRAY_OR_OBJECT_HT_EX(array, 0, 1)
    1206         465 :                 Z_PARAM_FUNC(BG(array_walk_fci), BG(array_walk_fci_cache))
    1207         101 :                 Z_PARAM_OPTIONAL
    1208         210 :                 Z_PARAM_ZVAL_EX(userdata, 0, 1)
    1209         209 :         ZEND_PARSE_PARAMETERS_END_EX(
    1210             :                 BG(array_walk_fci) = orig_array_walk_fci;
    1211             :                 BG(array_walk_fci_cache) = orig_array_walk_fci_cache;
    1212             :                 return
    1213             :         );
    1214             : #endif
    1215             : 
    1216         101 :         php_array_walk(array, userdata, 0);
    1217         100 :         BG(array_walk_fci) = orig_array_walk_fci;
    1218         100 :         BG(array_walk_fci_cache) = orig_array_walk_fci_cache;
    1219         100 :         RETURN_TRUE;
    1220             : }
    1221             : /* }}} */
    1222             : 
    1223             : /* {{{ proto bool array_walk_recursive(array input, string funcname [, mixed userdata])
    1224             :    Apply a user function recursively to every member of an array */
    1225         153 : PHP_FUNCTION(array_walk_recursive)
    1226             : {
    1227             :         HashTable *array;
    1228         153 :         zval *userdata = NULL;
    1229             :         zend_fcall_info orig_array_walk_fci;
    1230             :         zend_fcall_info_cache orig_array_walk_fci_cache;
    1231             : 
    1232         153 :         orig_array_walk_fci = BG(array_walk_fci);
    1233         153 :         orig_array_walk_fci_cache = BG(array_walk_fci_cache);
    1234             : 
    1235         153 :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "H/f|z/", &array, &BG(array_walk_fci), &BG(array_walk_fci_cache), &userdata) == FAILURE) {
    1236         104 :                 BG(array_walk_fci) = orig_array_walk_fci;
    1237         104 :                 BG(array_walk_fci_cache) = orig_array_walk_fci_cache;
    1238         104 :                 return;
    1239             :         }
    1240             : 
    1241          49 :         php_array_walk(array, userdata, 1);
    1242          49 :         BG(array_walk_fci) = orig_array_walk_fci;
    1243          49 :         BG(array_walk_fci_cache) = orig_array_walk_fci_cache;
    1244          49 :         RETURN_TRUE;
    1245             : }
    1246             : /* }}} */
    1247             : 
    1248             : /* void php_search_array(INTERNAL_FUNCTION_PARAMETERS, int behavior)
    1249             :  * 0 = return boolean
    1250             :  * 1 = return key
    1251             :  */
    1252        6638 : static inline void php_search_array(INTERNAL_FUNCTION_PARAMETERS, int behavior) /* {{{ */
    1253             : {
    1254             :         zval *value,                            /* value to check for */
    1255             :                  *array,                                /* array to check in */
    1256             :                  *entry;                                /* pointer to array entry */
    1257             :         zend_ulong num_idx;
    1258             :         zend_string *str_idx;
    1259        6638 :         zend_bool strict = 0;           /* strict comparison or not */
    1260             : 
    1261             : #ifndef FAST_ZPP
    1262             :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "za|b", &value, &array, &strict) == FAILURE) {
    1263             :                 return;
    1264             :         }
    1265             : #else
    1266        6638 :         ZEND_PARSE_PARAMETERS_START(2, 3)
    1267        6631 :                 Z_PARAM_ZVAL(value)
    1268       19893 :                 Z_PARAM_ARRAY(array)
    1269        6622 :                 Z_PARAM_OPTIONAL
    1270        7900 :                 Z_PARAM_BOOL(strict)
    1271        6638 :         ZEND_PARSE_PARAMETERS_END();
    1272             : #endif
    1273             : 
    1274        6622 :         if (strict) {
    1275        2814 :                 ZEND_HASH_FOREACH_KEY_VAL(Z_ARRVAL_P(array), num_idx, str_idx, entry) {
    1276        1262 :                         ZVAL_DEREF(entry);
    1277        2524 :                         if (fast_is_identical_function(value, entry)) {
    1278          36 :                                 if (behavior == 0) {
    1279          18 :                                         RETURN_TRUE;
    1280             :                                 } else {
    1281          18 :                                         if (str_idx) {
    1282           4 :                                                 RETVAL_STR_COPY(str_idx);
    1283             :                                         } else {
    1284          14 :                                                 RETVAL_LONG(num_idx);
    1285             :                                         }
    1286          18 :                                         return;
    1287             :                                 }
    1288             :                         }
    1289             :                 } ZEND_HASH_FOREACH_END();
    1290             :         } else {
    1291       12592 :                 ZVAL_DEREF(value);
    1292       12592 :                 if (Z_TYPE_P(value) == IS_LONG) {
    1293       17285 :                         ZEND_HASH_FOREACH_KEY_VAL(Z_ARRVAL_P(array), num_idx, str_idx, entry) {
    1294       16126 :                                 if (fast_equal_check_long(value, entry)) {
    1295          79 :                                         if (behavior == 0) {
    1296          44 :                                                 RETURN_TRUE;
    1297             :                                         } else {
    1298          35 :                                                 if (str_idx) {
    1299           5 :                                                         RETVAL_STR_COPY(str_idx);
    1300             :                                                 } else {
    1301          30 :                                                         RETVAL_LONG(num_idx);
    1302             :                                                 }
    1303          35 :                                                 return;
    1304             :                                         }
    1305             :                                 }
    1306             :                         } ZEND_HASH_FOREACH_END();
    1307       10116 :                 } else if (Z_TYPE_P(value) == IS_STRING) {
    1308      956162 :                         ZEND_HASH_FOREACH_KEY_VAL(Z_ARRVAL_P(array), num_idx, str_idx, entry) {
    1309      954958 :                                 if (fast_equal_check_string(value, entry)) {
    1310        2690 :                                         if (behavior == 0) {
    1311        2616 :                                                 RETURN_TRUE;
    1312             :                                         } else {
    1313          74 :                                                 if (str_idx) {
    1314           8 :                                                         RETVAL_STR_COPY(str_idx);
    1315             :                                                 } else {
    1316          66 :                                                         RETVAL_LONG(num_idx);
    1317             :                                                 }
    1318          74 :                                                 return;
    1319             :                                         }
    1320             :                                 }
    1321             :                         } ZEND_HASH_FOREACH_END();
    1322             :                 } else {
    1323       28767 :                         ZEND_HASH_FOREACH_KEY_VAL(Z_ARRVAL_P(array), num_idx, str_idx, entry) {
    1324       28630 :                                 if (fast_equal_check_function(value, entry)) {
    1325        1045 :                                         if (behavior == 0) {
    1326         983 :                                                 RETURN_TRUE;
    1327             :                                         } else {
    1328          62 :                                                 if (str_idx) {
    1329          12 :                                                         RETVAL_STR_COPY(str_idx);
    1330             :                                                 } else {
    1331          50 :                                                         RETVAL_LONG(num_idx);
    1332             :                                                 }
    1333          62 :                                                 return;
    1334             :                                         }
    1335             :                                 }
    1336             :                         } ZEND_HASH_FOREACH_END();
    1337             :                 }
    1338             :         }
    1339             : 
    1340        2772 :         RETURN_FALSE;
    1341             : }
    1342             : /* }}} */
    1343             : 
    1344             : /* {{{ proto bool in_array(mixed needle, array haystack [, bool strict])
    1345             :    Checks if the given value exists in the array */
    1346        6118 : PHP_FUNCTION(in_array)
    1347             : {
    1348        6118 :         php_search_array(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
    1349        6118 : }
    1350             : /* }}} */
    1351             : 
    1352             : /* {{{ proto mixed array_search(mixed needle, array haystack [, bool strict])
    1353             :    Searches the array for a given value and returns the corresponding key if successful */
    1354         520 : PHP_FUNCTION(array_search)
    1355             : {
    1356         520 :         php_search_array(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
    1357         520 : }
    1358             : /* }}} */
    1359             : 
    1360             : static zend_always_inline int php_valid_var_name(char *var_name, size_t var_name_len) /* {{{ */
    1361             : {
    1362             : #if 1
    1363             :         /* first 256 bits for first character, and second 256 bits for the next */
    1364             :         static const uint32_t charset[16] = {
    1365             :              /*  31      0   63     32   95     64   127    96 */
    1366             :                         0x00000000, 0x00000000, 0x87fffffe, 0x07fffffe,
    1367             :                         0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
    1368             :              /*  31      0   63     32   95     64   127    96 */
    1369             :                         0x00000000, 0x03ff0000, 0x87fffffe, 0x07fffffe,
    1370             :                         0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff
    1371             :                 };
    1372             : #endif
    1373             :         size_t i;
    1374             :         uint32_t ch;
    1375             : 
    1376         428 :         if (UNEXPECTED(!var_name_len)) {
    1377           4 :                 return 0;
    1378             :         }
    1379             : 
    1380             :         /* These are allowed as first char: [a-zA-Z_\x7f-\xff] */
    1381         424 :         ch = (uint32_t)((unsigned char *)var_name)[0];
    1382             : #if 1
    1383         424 :         if (UNEXPECTED(!(charset[ch >> 5] & (1 << (ch & 0x1f))))) {
    1384             : #else
    1385             :         if (var_name[0] != '_' &&
    1386             :                 (ch < 65  /* A    */ || /* Z    */ ch > 90)  &&
    1387             :                 (ch < 97  /* a    */ || /* z    */ ch > 122) &&
    1388             :                 (ch < 127 /* 0x7f */ || /* 0xff */ ch > 255)
    1389             :         ) {
    1390             : #endif
    1391          15 :                 return 0;
    1392             :         }
    1393             : 
    1394             :         /* And these as the rest: [a-zA-Z0-9_\x7f-\xff] */
    1395         409 :         if (var_name_len > 1) {
    1396         356 :                 i = 1;
    1397             :                 do {
    1398        1115 :                         ch = (uint32_t)((unsigned char *)var_name)[i];
    1399             : #if 1
    1400        1115 :                         if (UNEXPECTED(!(charset[8 + (ch >> 5)] & (1 << (ch & 0x1f))))) {
    1401             : #else
    1402             :                         if (var_name[i] != '_' &&
    1403             :                                 (ch < 48  /* 0    */ || /* 9    */ ch > 57)  &&
    1404             :                                 (ch < 65  /* A    */ || /* Z    */ ch > 90)  &&
    1405             :                                 (ch < 97  /* a    */ || /* z    */ ch > 122) &&
    1406             :                                 (ch < 127 /* 0x7f */ || /* 0xff */ ch > 255)
    1407             :                         ) {
    1408             : #endif
    1409           6 :                                 return 0;
    1410             :                         }
    1411        1109 :                 } while (++i < var_name_len);
    1412             :         }
    1413         403 :         return 1;
    1414             : }
    1415             : /* }}} */
    1416             : 
    1417         237 : PHPAPI int php_prefix_varname(zval *result, zval *prefix, char *var_name, size_t var_name_len, zend_bool add_underscore) /* {{{ */
    1418             : {
    1419         474 :         ZVAL_NEW_STR(result, zend_string_alloc(Z_STRLEN_P(prefix) + (add_underscore ? 1 : 0) + var_name_len, 0));
    1420         237 :         memcpy(Z_STRVAL_P(result), Z_STRVAL_P(prefix), Z_STRLEN_P(prefix));
    1421             : 
    1422         237 :         if (add_underscore) {
    1423         237 :                 Z_STRVAL_P(result)[Z_STRLEN_P(prefix)] = '_';
    1424             :         }
    1425             : 
    1426         237 :         memcpy(Z_STRVAL_P(result) + Z_STRLEN_P(prefix) + (add_underscore ? 1 : 0), var_name, var_name_len + 1);
    1427             : 
    1428         237 :         return SUCCESS;
    1429             : }
    1430             : /* }}} */
    1431             : 
    1432             : /* {{{ proto int extract(array var_array [, int extract_type [, string prefix]])
    1433             :    Imports variables into symbol table from an array */
    1434         137 : PHP_FUNCTION(extract)
    1435             : {
    1436         137 :         zval *var_array, *prefix = NULL;
    1437         137 :         zend_long extract_type = EXTR_OVERWRITE;
    1438             :         zval *entry;
    1439             :         zend_string *var_name;
    1440             :         zend_ulong num_key;
    1441         137 :         int var_exists, count = 0;
    1442         137 :         int extract_refs = 0;
    1443             :         zend_array *symbol_table;
    1444             : 
    1445             : #ifndef FAST_ZPP
    1446             :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "a|lz/", &var_array, &extract_type, &prefix) == FAILURE) {
    1447             :                 return;
    1448             :         }
    1449             : #else
    1450         137 :         ZEND_PARSE_PARAMETERS_START(1, 3)
    1451         405 :                 Z_PARAM_ARRAY(var_array)
    1452         133 :                 Z_PARAM_OPTIONAL
    1453         363 :                 Z_PARAM_LONG(extract_type)
    1454         179 :                 Z_PARAM_ZVAL_EX(prefix, 0, 1)
    1455         137 :         ZEND_PARSE_PARAMETERS_END();
    1456             : #endif
    1457             : 
    1458         133 :         extract_refs = (extract_type & EXTR_REFS);
    1459         133 :         if (extract_refs) {
    1460          30 :                 SEPARATE_ZVAL(var_array);
    1461             :         }
    1462         133 :         extract_type &= 0xff;
    1463             : 
    1464         133 :         if (extract_type < EXTR_OVERWRITE || extract_type > EXTR_IF_EXISTS) {
    1465           2 :                 php_error_docref(NULL, E_WARNING, "Invalid extract type");
    1466           2 :                 return;
    1467             :         }
    1468             : 
    1469         131 :         if (extract_type > EXTR_SKIP && extract_type <= EXTR_PREFIX_IF_EXISTS && ZEND_NUM_ARGS() < 3) {
    1470           1 :                 php_error_docref(NULL, E_WARNING, "specified extract type requires the prefix parameter");
    1471           1 :                 return;
    1472             :         }
    1473             : 
    1474         130 :         if (prefix) {
    1475         126 :                 convert_to_string(prefix);
    1476         115 :                 if (Z_STRLEN_P(prefix) && !php_valid_var_name(Z_STRVAL_P(prefix), Z_STRLEN_P(prefix))) {
    1477           0 :                         php_error_docref(NULL, E_WARNING, "prefix is not a valid identifier");
    1478           0 :                         return;
    1479             :                 }
    1480             :         }
    1481             : 
    1482         130 :         symbol_table = zend_rebuild_symbol_table();
    1483             : #if 0
    1484             :         if (!symbol_table) {
    1485             :                 php_error_docref(NULL, E_WARNING, "failed to build symbol table");
    1486             :                 return;
    1487             :         }
    1488             : #endif
    1489             : 
    1490        2284 :         ZEND_HASH_FOREACH_KEY_VAL_IND(Z_ARRVAL_P(var_array), num_key, var_name, entry) {
    1491             :                 zval final_name;
    1492             : 
    1493         699 :                 ZVAL_NULL(&final_name);
    1494         699 :                 var_exists = 0;
    1495             : 
    1496         699 :                 if (var_name) {
    1497         219 :                         var_exists = zend_hash_exists_ind(symbol_table, var_name);
    1498         651 :                 } else if (extract_type == EXTR_PREFIX_ALL || extract_type == EXTR_PREFIX_INVALID) {
    1499         171 :                         zend_string *str = zend_long_to_str(num_key);
    1500         171 :                         php_prefix_varname(&final_name, prefix, str->val, str->len, 1);
    1501             :                         zend_string_release(str);
    1502             :                 } else {
    1503         309 :                         continue;
    1504             :                 }
    1505             : 
    1506         390 :                 switch (extract_type) {
    1507             :                         case EXTR_IF_EXISTS:
    1508          15 :                                 if (!var_exists) break;
    1509             :                                 /* break omitted intentionally */
    1510             : 
    1511             :                         case EXTR_OVERWRITE:
    1512             :                                 /* GLOBALS protection */
    1513         109 :                                 if (var_exists && var_name->len == sizeof("GLOBALS")-1 && !strcmp(var_name->val, "GLOBALS")) {
    1514           3 :                                         break;
    1515             :                                 }
    1516         106 :                                 if (var_exists && var_name->len == sizeof("this")-1  && !strcmp(var_name->val, "this") && EG(scope) && EG(scope)->name->len != 0) {
    1517           0 :                                         break;
    1518             :                                 }
    1519         106 :                                 ZVAL_STR_COPY(&final_name, var_name);
    1520         106 :                                 break;
    1521             : 
    1522             :                         case EXTR_PREFIX_IF_EXISTS:
    1523          15 :                                 if (var_exists) {
    1524          11 :                                         php_prefix_varname(&final_name, prefix, var_name->val, var_name->len, 1);
    1525             :                                 }
    1526          15 :                                 break;
    1527             : 
    1528             :                         case EXTR_PREFIX_SAME:
    1529          17 :                                 if (!var_exists && var_name->len != 0) {
    1530           3 :                                         ZVAL_STR_COPY(&final_name, var_name);
    1531             :                                 }
    1532             :                                 /* break omitted intentionally */
    1533             : 
    1534             :                         case EXTR_PREFIX_ALL:
    1535         181 :                                 if (Z_TYPE(final_name) == IS_NULL && var_name->len != 0) {
    1536          51 :                                         php_prefix_varname(&final_name, prefix, var_name->val, var_name->len, 1);
    1537             :                                 }
    1538         181 :                                 break;
    1539             : 
    1540             :                         case EXTR_PREFIX_INVALID:
    1541          66 :                                 if (Z_TYPE(final_name) == IS_NULL) {
    1542          30 :                                         if (!php_valid_var_name(var_name->val, var_name->len)) {
    1543           4 :                                                 php_prefix_varname(&final_name, prefix, var_name->val, var_name->len, 1);
    1544             :                                         } else {
    1545          11 :                                                 ZVAL_STR_COPY(&final_name, var_name);
    1546             :                                         }
    1547             :                                 }
    1548          66 :                                 break;
    1549             : 
    1550             :                         default:
    1551          15 :                                 if (!var_exists) {
    1552           4 :                                         ZVAL_STR_COPY(&final_name, var_name);
    1553             :                                 }
    1554             :                                 break;
    1555             :                 }
    1556             : 
    1557         751 :                 if (Z_TYPE(final_name) == IS_STRING && php_valid_var_name(Z_STRVAL(final_name), Z_STRLEN(final_name))) {
    1558         340 :                         if (extract_refs) {
    1559             :                                 zval *orig_var;
    1560             : 
    1561         108 :                                 ZVAL_MAKE_REF(entry);
    1562             :                                 Z_ADDREF_P(entry);
    1563             : 
    1564          54 :                                 if ((orig_var = zend_hash_find(symbol_table, Z_STR(final_name))) != NULL) {
    1565          31 :                                         if (Z_TYPE_P(orig_var) == IS_INDIRECT) {
    1566          17 :                                                 orig_var = Z_INDIRECT_P(orig_var);
    1567             :                                         }
    1568          31 :                                         zval_ptr_dtor(orig_var);
    1569          31 :                                         ZVAL_COPY_VALUE(orig_var, entry);
    1570             :                                 } else {
    1571          23 :                                         zend_hash_update(symbol_table, Z_STR(final_name), entry);
    1572             :                                 }
    1573             :                         } else {
    1574         286 :                                 if (Z_REFCOUNTED_P(entry)) Z_ADDREF_P(entry);
    1575         286 :                                 zend_hash_update_ind(symbol_table, Z_STR(final_name), entry);
    1576             :                         }
    1577         340 :                         count++;
    1578             :                 }
    1579             :                 zval_dtor(&final_name);
    1580             :         } ZEND_HASH_FOREACH_END();
    1581             : 
    1582         130 :         RETURN_LONG(count);
    1583             : }
    1584             : /* }}} */
    1585             : 
    1586          73 : static void php_compact_var(HashTable *eg_active_symbol_table, zval *return_value, zval *entry) /* {{{ */
    1587             : {
    1588             :         zval *value_ptr, data;
    1589             : 
    1590          73 :         ZVAL_DEREF(entry);
    1591          73 :         if (Z_TYPE_P(entry) == IS_STRING) {
    1592          68 :                 if ((value_ptr = zend_hash_find_ind(eg_active_symbol_table, Z_STR_P(entry))) != NULL) {
    1593          29 :                         ZVAL_DUP(&data, value_ptr);
    1594          29 :                         zend_hash_update(Z_ARRVAL_P(return_value), Z_STR_P(entry), &data);
    1595             :                 }
    1596          39 :         } else if (Z_TYPE_P(entry) == IS_ARRAY) {
    1597          28 :                 if ((Z_ARRVAL_P(entry)->u.v.nApplyCount > 1)) {
    1598           5 :                         php_error_docref(NULL, E_WARNING, "recursion detected");
    1599           5 :                         return;
    1600             :                 }
    1601             : 
    1602          23 :             if (ZEND_HASH_APPLY_PROTECTION(Z_ARRVAL_P(entry))) {
    1603          23 :                         Z_ARRVAL_P(entry)->u.v.nApplyCount++;
    1604             :                 }
    1605         167 :                 ZEND_HASH_FOREACH_VAL_IND(Z_ARRVAL_P(entry), value_ptr) {
    1606          48 :                         php_compact_var(eg_active_symbol_table, return_value, value_ptr);
    1607             :                 } ZEND_HASH_FOREACH_END();
    1608          23 :             if (ZEND_HASH_APPLY_PROTECTION(Z_ARRVAL_P(entry))) {
    1609          23 :                         Z_ARRVAL_P(entry)->u.v.nApplyCount--;
    1610             :                 }
    1611             :         }
    1612             : }
    1613             : /* }}} */
    1614             : 
    1615             : /* {{{ proto array compact(mixed var_names [, mixed ...])
    1616             :    Creates a hash containing variables and their values */
    1617          14 : PHP_FUNCTION(compact)
    1618             : {
    1619          14 :         zval *args = NULL;      /* function arguments array */
    1620             :         uint32_t num_args, i;
    1621             :         zend_array *symbol_table;
    1622             : 
    1623          14 :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "+", &args, &num_args) == FAILURE) {
    1624           1 :                 return;
    1625             :         }
    1626             : 
    1627          13 :         symbol_table = zend_rebuild_symbol_table();
    1628             : 
    1629             :         /* compact() is probably most used with a single array of var_names
    1630             :            or multiple string names, rather than a combination of both.
    1631             :            So quickly guess a minimum result size based on that */
    1632          30 :         if (ZEND_NUM_ARGS() == 1 && Z_TYPE(args[0]) == IS_ARRAY) {
    1633           8 :                 array_init_size(return_value, zend_hash_num_elements(Z_ARRVAL(args[0])));
    1634             :         } else {
    1635           5 :                 array_init_size(return_value, ZEND_NUM_ARGS());
    1636             :         }
    1637             : 
    1638          38 :         for (i=0; i<ZEND_NUM_ARGS(); i++) {
    1639          25 :                 php_compact_var(symbol_table, return_value, &args[i]);
    1640             :         }
    1641             : }
    1642             : /* }}} */
    1643             : 
    1644             : /* {{{ proto array array_fill(int start_key, int num, mixed val)
    1645             :    Create an array containing num elements starting with index start_key each initialized to val */
    1646         166 : PHP_FUNCTION(array_fill)
    1647             : {
    1648             :         zval *val;
    1649             :         zend_long start_key, num;
    1650             : 
    1651         166 :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "llz", &start_key, &num, &val) == FAILURE) {
    1652          24 :                 return;
    1653             :         }
    1654             : 
    1655         142 :         if (num < 0) {
    1656           2 :                 php_error_docref(NULL, E_WARNING, "Number of elements can't be negative");
    1657           2 :                 RETURN_FALSE;
    1658             :         }
    1659             : 
    1660             :         /* allocate an array for return */
    1661         140 :         array_init_size(return_value, (uint32_t)num);
    1662             : 
    1663         140 :         if (num == 0) {
    1664          26 :                 return;
    1665             :         }
    1666             : 
    1667         114 :         num--;
    1668         114 :         zend_hash_index_update(Z_ARRVAL_P(return_value), start_key, val);
    1669         114 :         Z_TRY_ADDREF_P(val);
    1670             : 
    1671      191161 :         while (num--) {
    1672      190934 :                 if (zend_hash_next_index_insert(Z_ARRVAL_P(return_value), val) != NULL) {
    1673      190933 :                         Z_TRY_ADDREF_P(val);
    1674             :                 } else {
    1675             :                         zval_dtor(return_value);
    1676           1 :                         php_error_docref(NULL, E_WARNING, "Cannot add element to the array as the next element is already occupied");
    1677           1 :                         RETURN_FALSE;
    1678             :                 }
    1679             :         }
    1680             : }
    1681             : /* }}} */
    1682             : 
    1683             : /* {{{ proto array array_fill_keys(array keys, mixed val)
    1684             :    Create an array using the elements of the first parameter as keys each initialized to val */
    1685          24 : PHP_FUNCTION(array_fill_keys)
    1686             : {
    1687             :         zval *keys, *val, *entry;
    1688             : 
    1689          24 :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "az", &keys, &val) == FAILURE) {
    1690           6 :                 return;
    1691             :         }
    1692             : 
    1693             :         /* Initialize return array */
    1694          18 :         array_init_size(return_value, zend_hash_num_elements(Z_ARRVAL_P(keys)));
    1695             : 
    1696          98 :         ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(keys), entry) {
    1697          40 :                 ZVAL_DEREF(entry);
    1698          40 :                 Z_TRY_ADDREF_P(val);
    1699          40 :                 if (Z_TYPE_P(entry) == IS_LONG) {
    1700           8 :                         zend_hash_index_update(Z_ARRVAL_P(return_value), Z_LVAL_P(entry), val);
    1701             :                 } else {
    1702          32 :                         zend_string *key = zval_get_string(entry);
    1703          32 :                         zend_symtable_update(Z_ARRVAL_P(return_value), key, val);
    1704             :                         zend_string_release(key);
    1705             :                 }
    1706             :         } ZEND_HASH_FOREACH_END();
    1707             : }
    1708             : /* }}} */
    1709             : 
    1710             : /* {{{ proto array range(mixed low, mixed high[, int step])
    1711             :    Create an array containing the range of integers or characters from low to high (inclusive) */
    1712      100255 : PHP_FUNCTION(range)
    1713             : {
    1714      100255 :         zval *zlow, *zhigh, *zstep = NULL, tmp;
    1715      100255 :         int err = 0, is_step_double = 0;
    1716      100255 :         double step = 1.0;
    1717             : 
    1718      100255 :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "zz|z", &zlow, &zhigh, &zstep) == FAILURE) {
    1719           3 :                 RETURN_FALSE;
    1720             :         }
    1721             : 
    1722      100252 :         if (zstep) {
    1723          73 :                 if (Z_TYPE_P(zstep) == IS_DOUBLE ||
    1724          23 :                         (Z_TYPE_P(zstep) == IS_STRING && is_numeric_string(Z_STRVAL_P(zstep), Z_STRLEN_P(zstep), NULL, NULL, 0) == IS_DOUBLE)
    1725             :                 ) {
    1726           8 :                         is_step_double = 1;
    1727             :                 }
    1728             : 
    1729          50 :                 step = zval_get_double(zstep);
    1730             : 
    1731             :                 /* We only want positive step values. */
    1732          25 :                 if (step < 0.0) {
    1733           0 :                         step *= -1;
    1734             :                 }
    1735             :         }
    1736             : 
    1737             :         /* If the range is given as strings, generate an array of characters. */
    1738      200632 :         if (Z_TYPE_P(zlow) == IS_STRING && Z_TYPE_P(zhigh) == IS_STRING && Z_STRLEN_P(zlow) >= 1 && Z_STRLEN_P(zhigh) >= 1) {
    1739             :                 int type1, type2;
    1740             :                 unsigned char low, high;
    1741          63 :                 zend_long lstep = (zend_long) step;
    1742             : 
    1743         126 :                 type1 = is_numeric_string(Z_STRVAL_P(zlow), Z_STRLEN_P(zlow), NULL, NULL, 0);
    1744         126 :                 type2 = is_numeric_string(Z_STRVAL_P(zhigh), Z_STRLEN_P(zhigh), NULL, NULL, 0);
    1745             : 
    1746          63 :                 if (type1 == IS_DOUBLE || type2 == IS_DOUBLE || is_step_double) {
    1747             :                         goto double_str;
    1748          59 :                 } else if (type1 == IS_LONG || type2 == IS_LONG) {
    1749             :                         goto long_str;
    1750             :                 }
    1751             : 
    1752          54 :                 low = (unsigned char)Z_STRVAL_P(zlow)[0];
    1753          54 :                 high = (unsigned char)Z_STRVAL_P(zhigh)[0];
    1754             : 
    1755          54 :                 if (low > high) {            /* Negative Steps */
    1756           2 :                         if (lstep <= 0) {
    1757           1 :                                 err = 1;
    1758           1 :                                 goto err;
    1759             :                         }
    1760             :                         /* Initialize the return_value as an array. */
    1761           1 :                         array_init_size(return_value, (uint32_t)(((low - high) / lstep) + 1));
    1762           1 :                         zend_hash_real_init(Z_ARRVAL_P(return_value), 1);
    1763           1 :                         ZEND_HASH_FILL_PACKED(Z_ARRVAL_P(return_value)) {
    1764          27 :                                 for (; low >= high; low -= (unsigned int)lstep) {
    1765          26 :                                         if (CG(one_char_string)[low]) {
    1766           0 :                                                 ZVAL_INTERNED_STR(&tmp, CG(one_char_string)[low]);
    1767             :                                         } else {
    1768          52 :                                                 ZVAL_STRINGL(&tmp, (char*)&low, 1);
    1769             :                                         }
    1770          26 :                                         ZEND_HASH_FILL_ADD(&tmp);
    1771          26 :                                         if (((signed int)low - lstep) < 0) {
    1772           0 :                                                 break;
    1773             :                                         }
    1774             :                                 }
    1775           1 :                         } ZEND_HASH_FILL_END();
    1776          52 :                 } else if (high > low) {     /* Positive Steps */
    1777          50 :                         if (lstep <= 0) {
    1778           2 :                                 err = 1;
    1779           2 :                                 goto err;
    1780             :                         }
    1781          48 :                         array_init_size(return_value, (uint32_t)(((high - low) / lstep) + 1));
    1782          48 :                         zend_hash_real_init(Z_ARRVAL_P(return_value), 1);
    1783          48 :                         ZEND_HASH_FILL_PACKED(Z_ARRVAL_P(return_value)) {
    1784        1242 :                                 for (; low <= high; low += (unsigned int)lstep) {
    1785        1194 :                                         if (CG(one_char_string)[low]) {
    1786           0 :                                                 ZVAL_INTERNED_STR(&tmp, CG(one_char_string)[low]);
    1787             :                                         } else {
    1788        2388 :                                                 ZVAL_STRINGL(&tmp, (char*)&low, 1);
    1789             :                                         }
    1790        1194 :                                         ZEND_HASH_FILL_ADD(&tmp);
    1791        1194 :                                         if (((signed int)low + lstep) > 255) {
    1792           0 :                                                 break;
    1793             :                                         }
    1794             :                                 }
    1795          48 :                         } ZEND_HASH_FILL_END();
    1796             :                 } else {
    1797           2 :                         array_init(return_value);
    1798           2 :                         if (CG(one_char_string)[low]) {
    1799           0 :                                 ZVAL_INTERNED_STR(&tmp, CG(one_char_string)[low]);
    1800             :                         } else {
    1801           4 :                                 ZVAL_STRINGL(&tmp, (char*)&low, 1);
    1802             :                         }
    1803           2 :                         zend_hash_next_index_insert_new(Z_ARRVAL_P(return_value), &tmp);
    1804             :                 }
    1805      300579 :         } else if (Z_TYPE_P(zlow) == IS_DOUBLE || Z_TYPE_P(zhigh) == IS_DOUBLE || is_step_double) {
    1806             :                 double low, high, value;
    1807             :                 zend_long i;
    1808             : double_str:
    1809          50 :                 low = zval_get_double(zlow);
    1810          50 :                 high = zval_get_double(zhigh);
    1811          25 :                 i = 0;
    1812             : 
    1813          25 :                 Z_TYPE_INFO(tmp) = IS_DOUBLE;
    1814          25 :                 if (low > high) {            /* Negative steps */
    1815          10 :                         if (low - high < step || step <= 0) {
    1816           1 :                                 err = 1;
    1817           1 :                                 goto err;
    1818             :                         }
    1819             : 
    1820           9 :                         array_init_size(return_value, (uint32_t)(((low - high) / step) + 1));
    1821           9 :                         zend_hash_real_init(Z_ARRVAL_P(return_value), 1);
    1822           9 :                         ZEND_HASH_FILL_PACKED(Z_ARRVAL_P(return_value)) {
    1823         100 :                         for (value = low; value >= (high - DOUBLE_DRIFT_FIX); value = low - (++i * step)) {
    1824          91 :                                 Z_DVAL(tmp) = value;
    1825          91 :                                 ZEND_HASH_FILL_ADD(&tmp);
    1826             :                         }
    1827           9 :                         } ZEND_HASH_FILL_END();
    1828          15 :                 } else if (high > low) {     /* Positive steps */
    1829          14 :                         if (high - low < step || step <= 0) {
    1830           1 :                                 err = 1;
    1831           1 :                                 goto err;
    1832             :                         }
    1833             : 
    1834          13 :                         array_init_size(return_value, (uint32_t)(((high - low) / step) + 1));
    1835          13 :                         zend_hash_real_init(Z_ARRVAL_P(return_value), 1);
    1836          13 :                         ZEND_HASH_FILL_PACKED(Z_ARRVAL_P(return_value)) {
    1837         328 :                                 for (value = low; value <= (high + DOUBLE_DRIFT_FIX); value = low + (++i * step)) {
    1838         315 :                                         Z_DVAL(tmp) = value;
    1839         315 :                                         ZEND_HASH_FILL_ADD(&tmp);
    1840             :                                 }
    1841          13 :                         } ZEND_HASH_FILL_END();
    1842             :                 } else {
    1843           1 :                         array_init(return_value);
    1844           1 :                         Z_DVAL(tmp) = low;
    1845           1 :                         zend_hash_next_index_insert_new(Z_ARRVAL_P(return_value), &tmp);
    1846             :                 }
    1847             :         } else {
    1848             :                 double low, high;
    1849             :                 zend_long lstep;
    1850             : long_str:
    1851      200346 :                 low = zval_get_double(zlow);
    1852      200346 :                 high = zval_get_double(zhigh);
    1853      100173 :                 lstep = (zend_long) step;
    1854             : 
    1855      100173 :                 Z_TYPE_INFO(tmp) = IS_LONG;
    1856      100173 :                 if (low > high) {            /* Negative steps */
    1857          14 :                         if (low - high < lstep || lstep <= 0) {
    1858           2 :                                 err = 1;
    1859           2 :                                 goto err;
    1860             :                         }
    1861          12 :                         array_init_size(return_value, (uint32_t)(((low - high) / lstep) + 1));
    1862          12 :                         zend_hash_real_init(Z_ARRVAL_P(return_value), 1);
    1863          12 :                         ZEND_HASH_FILL_PACKED(Z_ARRVAL_P(return_value)) {
    1864          68 :                                 for (; low >= high; low -= lstep) {
    1865          56 :                                         Z_LVAL(tmp) = (zend_long)low;
    1866          56 :                                         ZEND_HASH_FILL_ADD(&tmp);
    1867             :                                 }
    1868          12 :                         } ZEND_HASH_FILL_END();
    1869      100159 :                 } else if (high > low) {     /* Positive steps */
    1870      100138 :                         if (high - low < lstep || lstep <= 0) {
    1871           6 :                                 err = 1;
    1872           6 :                                 goto err;
    1873             :                         }
    1874      100132 :                         array_init_size(return_value, (uint32_t)(((high - low) / lstep) + 1));
    1875      100132 :                         zend_hash_real_init(Z_ARRVAL_P(return_value), 1);
    1876      100132 :                         ZEND_HASH_FILL_PACKED(Z_ARRVAL_P(return_value)) {
    1877      493571 :                                 for (; low <= high; low += lstep) {
    1878      393439 :                                         Z_LVAL(tmp) = (zend_long)low;
    1879      393439 :                                         ZEND_HASH_FILL_ADD(&tmp);
    1880             :                                 }
    1881      100132 :                         } ZEND_HASH_FILL_END();
    1882             :                 } else {
    1883          21 :                         array_init(return_value);
    1884          21 :                         Z_LVAL(tmp) = (zend_long)low;
    1885          21 :                         zend_hash_next_index_insert_new(Z_ARRVAL_P(return_value), &tmp);
    1886             :                 }
    1887             :         }
    1888             : err:
    1889      100252 :         if (err) {
    1890          13 :                 php_error_docref(NULL, E_WARNING, "step exceeds the specified range");
    1891          13 :                 RETURN_FALSE;
    1892             :         }
    1893             : }
    1894             : /* }}} */
    1895             : 
    1896       90054 : static void php_array_data_shuffle(zval *array) /* {{{ */
    1897             : {
    1898             :         uint32_t idx, j, n_elems;
    1899             :         Bucket *p, temp;
    1900             :         HashTable *hash;
    1901             :         zend_long rnd_idx;
    1902             :         uint32_t n_left;
    1903             : 
    1904       90054 :         n_elems = zend_hash_num_elements(Z_ARRVAL_P(array));
    1905             : 
    1906       90054 :         if (n_elems < 1) {
    1907           1 :                 return;
    1908             :         }
    1909             : 
    1910       90053 :         hash = Z_ARRVAL_P(array);
    1911       90053 :         n_left = n_elems;
    1912             : 
    1913       90053 :         if (EXPECTED(hash->u.v.nIteratorsCount == 0)) {
    1914       90053 :                 if (hash->nNumUsed != hash->nNumOfElements) {
    1915           7 :                         for (j = 0, idx = 0; idx < hash->nNumUsed; idx++) {
    1916           5 :                                 p = hash->arData + idx;
    1917          10 :                                 if (Z_TYPE(p->val) == IS_UNDEF) continue;
    1918           2 :                                 if (j != idx) {
    1919           2 :                                         hash->arData[j] = *p;
    1920             :                                 }
    1921           2 :                                 j++;
    1922             :                         }
    1923             :                 }
    1924      451493 :                 while (--n_left) {
    1925      271387 :                         rnd_idx = php_rand();
    1926      271387 :                         RAND_RANGE(rnd_idx, 0, n_left, PHP_RAND_MAX);
    1927      271387 :                         if (rnd_idx != n_left) {
    1928      173854 :                                 temp = hash->arData[n_left];
    1929      173854 :                                 hash->arData[n_left] = hash->arData[rnd_idx];
    1930      173854 :                                 hash->arData[rnd_idx] = temp;
    1931             :                         }
    1932             :                 }
    1933             :         } else {
    1934           0 :                 uint32_t iter_pos = zend_hash_iterators_lower_pos(hash, 0);
    1935             : 
    1936           0 :                 if (hash->nNumUsed != hash->nNumOfElements) {
    1937           0 :                         for (j = 0, idx = 0; idx < hash->nNumUsed; idx++) {
    1938           0 :                                 p = hash->arData + idx;
    1939           0 :                                 if (Z_TYPE(p->val) == IS_UNDEF) continue;
    1940           0 :                                 if (j != idx) {
    1941           0 :                                         hash->arData[j] = *p;
    1942           0 :                                         if (idx == iter_pos) {
    1943             :                                                 zend_hash_iterators_update(hash, idx, j);
    1944           0 :                                                 iter_pos = zend_hash_iterators_lower_pos(hash, iter_pos + 1);
    1945             :                                         }
    1946             :                                 }
    1947           0 :                                 j++;
    1948             :                         }
    1949             :                 }
    1950           0 :                 while (--n_left) {
    1951           0 :                         rnd_idx = php_rand();
    1952           0 :                         RAND_RANGE(rnd_idx, 0, n_left, PHP_RAND_MAX);
    1953           0 :                         if (rnd_idx != n_left) {
    1954           0 :                                 temp = hash->arData[n_left];
    1955           0 :                                 hash->arData[n_left] = hash->arData[rnd_idx];
    1956           0 :                                 hash->arData[rnd_idx] = temp;
    1957           0 :                                 zend_hash_iterators_update(hash, (uint32_t)rnd_idx, n_left);
    1958             :                         }
    1959             :                 }
    1960             :         }
    1961       90053 :         HANDLE_BLOCK_INTERRUPTIONS();
    1962       90053 :         hash->nNumUsed = n_elems;
    1963       90053 :         hash->nInternalPointer = 0;
    1964             : 
    1965      451493 :         for (j = 0; j < n_elems; j++) {
    1966      361440 :                 p = hash->arData + j;
    1967      361440 :                 if (p->key) {
    1968          41 :                         zend_string_release(p->key);
    1969             :                 }
    1970      361440 :                 p->h = j;
    1971      361440 :                 p->key = NULL;
    1972             :         }
    1973       90053 :         hash->nNextFreeElement = n_elems;
    1974       90053 :         if (!(hash->u.flags & HASH_FLAG_PACKED)) {
    1975          15 :                 zend_hash_to_packed(hash);
    1976             :         }
    1977       90053 :         HANDLE_UNBLOCK_INTERRUPTIONS();
    1978             : }
    1979             : /* }}} */
    1980             : 
    1981             : /* {{{ proto bool shuffle(array array_arg)
    1982             :    Randomly shuffle the contents of an array */
    1983       90079 : PHP_FUNCTION(shuffle)
    1984             : {
    1985             :         zval *array;
    1986             : 
    1987       90079 :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "a/", &array) == FAILURE) {
    1988          25 :                 RETURN_FALSE;
    1989             :         }
    1990             : 
    1991       90054 :         php_array_data_shuffle(array);
    1992             : 
    1993       90054 :         RETURN_TRUE;
    1994             : }
    1995             : /* }}} */
    1996             : 
    1997          63 : static void php_splice(HashTable *in_hash, int offset, int length, HashTable *replace, HashTable *removed) /* {{{ */
    1998             : {
    1999             :         HashTable        out_hash;                      /* Output hashtable */
    2000             :         int                      num_in,                        /* Number of entries in the input hashtable */
    2001             :                                  pos;                           /* Current position in the hashtable */
    2002             :         uint         idx;
    2003             :         Bucket          *p;                                     /* Pointer to hash bucket */
    2004             :         zval            *entry;                         /* Hash entry */
    2005          63 :         uint32_t    iter_pos = zend_hash_iterators_lower_pos(in_hash, 0);
    2006             : 
    2007             :         /* Get number of entries in the input hash */
    2008          63 :         num_in = zend_hash_num_elements(in_hash);
    2009             : 
    2010             :         /* Clamp the offset.. */
    2011          63 :         if (offset > num_in) {
    2012           0 :                 offset = num_in;
    2013          63 :         } else if (offset < 0 && (offset = (num_in + offset)) < 0) {
    2014           0 :                 offset = 0;
    2015             :         }
    2016             : 
    2017             :         /* ..and the length */
    2018          63 :         if (length < 0) {
    2019          15 :                 length = num_in - offset + length;
    2020          48 :         } else if (((unsigned)offset + (unsigned)length) > (unsigned)num_in) {
    2021          10 :                 length = num_in - offset;
    2022             :         }
    2023             : 
    2024             :         /* Create and initialize output hash */
    2025          63 :         zend_hash_init(&out_hash, (length > 0 ? num_in - length : 0) + (replace ? zend_hash_num_elements(replace) : 0), NULL, ZVAL_PTR_DTOR, 0);
    2026             : 
    2027             :         /* Start at the beginning of the input hash and copy entries to output hash until offset is reached */
    2028         165 :         for (pos = 0, idx = 0; pos < offset && idx < in_hash->nNumUsed; idx++) {
    2029         102 :                 p = in_hash->arData + idx;
    2030         204 :                 if (Z_TYPE(p->val) == IS_UNDEF) continue;
    2031             :                 /* Get entry and increase reference count */
    2032         102 :                 entry = &p->val;
    2033             : 
    2034             :                 /* Update output hash depending on key type */
    2035         102 :                 if (p->key == NULL) {
    2036         101 :                         zend_hash_next_index_insert_new(&out_hash, entry);
    2037             :                 } else {
    2038           1 :                         zend_hash_add_new(&out_hash, p->key, entry);
    2039             :                 }
    2040         102 :                 if (idx == iter_pos) {
    2041           2 :                         if (idx != pos) {
    2042           0 :                                 zend_hash_iterators_update(in_hash, idx, pos);
    2043             :                         }
    2044           2 :                         iter_pos = zend_hash_iterators_lower_pos(in_hash, iter_pos + 1);
    2045             :                 }
    2046         102 :                 pos++;
    2047             :         }
    2048             : 
    2049             :         /* If hash for removed entries exists, go until offset+length and copy the entries to it */
    2050          63 :         if (removed != NULL) {
    2051         145 :                 for ( ; pos < offset + length && idx < in_hash->nNumUsed; idx++) {
    2052          93 :                         p = in_hash->arData + idx;
    2053         186 :                         if (Z_TYPE(p->val) == IS_UNDEF) continue;
    2054          93 :                         pos++;
    2055          93 :                         entry = &p->val;
    2056          93 :                         if (Z_REFCOUNTED_P(entry)) {
    2057             :                                 Z_ADDREF_P(entry);
    2058             :                         }
    2059          93 :                         if (p->key == NULL) {
    2060          92 :                                 zend_hash_next_index_insert_new(removed, entry);
    2061          92 :                                 zend_hash_index_del(in_hash, p->h);
    2062             :                         } else {
    2063           1 :                                 zend_hash_add_new(removed, p->key, entry);
    2064           1 :                                 if (in_hash == &EG(symbol_table)) {
    2065           0 :                                         zend_delete_global_variable(p->key);
    2066             :                                 } else {
    2067           1 :                                         zend_hash_del(in_hash, p->key);
    2068             :                                 }
    2069             :                         }
    2070             :                 }
    2071             :         } else { /* otherwise just skip those entries */
    2072          11 :                 int pos2 = pos;
    2073             : 
    2074          41 :                 for ( ; pos2 < offset + length && idx < in_hash->nNumUsed; idx++) {
    2075          30 :                         p = in_hash->arData + idx;
    2076          60 :                         if (Z_TYPE(p->val) == IS_UNDEF) continue;
    2077          30 :                         pos2++;
    2078          30 :                         if (p->key == NULL) {
    2079          21 :                                 zend_hash_index_del(in_hash, p->h);
    2080             :                         } else {
    2081           9 :                                 if (in_hash == &EG(symbol_table)) {
    2082           9 :                                         zend_delete_global_variable(p->key);
    2083             :                                 } else {
    2084           0 :                                         zend_hash_del(in_hash, p->key);
    2085             :                                 }
    2086             :                         }
    2087             :                 }
    2088             :         }
    2089          63 :         iter_pos = zend_hash_iterators_lower_pos(in_hash, iter_pos);
    2090             : 
    2091             :         /* If there are entries to insert.. */
    2092          63 :         if (replace) {
    2093         256 :                 ZEND_HASH_FOREACH_VAL_IND(replace, entry) {
    2094          75 :                         if (Z_REFCOUNTED_P(entry)) Z_ADDREF_P(entry);
    2095          75 :                         zend_hash_next_index_insert_new(&out_hash, entry);
    2096          75 :                         pos++;
    2097             :                 } ZEND_HASH_FOREACH_END();
    2098             :         }
    2099             : 
    2100             :         /* Copy the remaining input hash entries to the output hash */
    2101         173 :         for ( ; idx < in_hash->nNumUsed ; idx++) {
    2102         110 :                 p = in_hash->arData + idx;
    2103         220 :                 if (Z_TYPE(p->val) == IS_UNDEF) continue;
    2104         110 :                 entry = &p->val;
    2105         110 :                 if (p->key == NULL) {
    2106         109 :                         zend_hash_next_index_insert_new(&out_hash, entry);
    2107             :                 } else {
    2108           1 :                         zend_hash_add_new(&out_hash, p->key, entry);
    2109             :                 }
    2110         110 :                 if (idx == iter_pos) {
    2111           3 :                         if (idx != pos) {
    2112           2 :                                 zend_hash_iterators_update(in_hash, idx, pos);
    2113             :                         }
    2114           3 :                         iter_pos = zend_hash_iterators_lower_pos(in_hash, iter_pos + 1);
    2115             :                 }
    2116         110 :                 pos++;
    2117             :         }
    2118             : 
    2119             :         /* replace HashTable data */
    2120          63 :         in_hash->u.v.nIteratorsCount = 0;
    2121          63 :         in_hash->pDestructor = NULL;
    2122          63 :         zend_hash_destroy(in_hash);
    2123             : 
    2124          63 :         in_hash->u.v.flags         = out_hash.u.v.flags;
    2125          63 :         in_hash->nTableSize        = out_hash.nTableSize;
    2126          63 :         in_hash->nTableMask        = out_hash.nTableMask;
    2127          63 :         in_hash->nNumUsed          = out_hash.nNumUsed;
    2128          63 :         in_hash->nNumOfElements    = out_hash.nNumOfElements;
    2129          63 :         in_hash->nNextFreeElement  = out_hash.nNextFreeElement;
    2130          63 :         in_hash->arData            = out_hash.arData;
    2131          63 :         in_hash->pDestructor       = out_hash.pDestructor;
    2132             : 
    2133          63 :         zend_hash_internal_pointer_reset(in_hash);
    2134          63 : }
    2135             : /* }}} */
    2136             : 
    2137             : /* {{{ proto int array_push(array stack, mixed var [, mixed ...])
    2138             :    Pushes elements onto the end of the array */
    2139         700 : PHP_FUNCTION(array_push)
    2140             : {
    2141             :         zval   *args,           /* Function arguments array */
    2142             :                    *stack,              /* Input array */
    2143             :                     new_var;    /* Variable to be pushed */
    2144             :         int i,                          /* Loop counter */
    2145             :                 argc;                   /* Number of function arguments */
    2146             : 
    2147             : 
    2148         700 :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "a/+", &stack, &args, &argc) == FAILURE) {
    2149          28 :                 return;
    2150             :         }
    2151             : 
    2152             :         /* For each subsequent argument, make it a reference, increase refcount, and add it to the end of the array */
    2153        1359 :         for (i = 0; i < argc; i++) {
    2154         688 :                 ZVAL_COPY(&new_var, &args[i]);
    2155             : 
    2156         688 :                 if (zend_hash_next_index_insert(Z_ARRVAL_P(stack), &new_var) == NULL) {
    2157           1 :                         if (Z_REFCOUNTED(new_var)) Z_DELREF(new_var);
    2158           1 :                         php_error_docref(NULL, E_WARNING, "Cannot add element to the array as the next element is already occupied");
    2159           1 :                         RETURN_FALSE;
    2160             :                 }
    2161             :         }
    2162             : 
    2163             :         /* Clean up and return the number of values in the stack */
    2164         671 :         RETVAL_LONG(zend_hash_num_elements(Z_ARRVAL_P(stack)));
    2165             : }
    2166             : /* }}} */
    2167             : 
    2168             : /* {{{ proto mixed array_pop(array stack)
    2169             :    Pops an element off the end of the array */
    2170          76 : PHP_FUNCTION(array_pop)
    2171             : {
    2172             :         zval *stack,    /* Input stack */
    2173             :                  *val;          /* Value to be popped */
    2174             :         uint32_t idx;
    2175             :         Bucket *p;
    2176             : 
    2177             : #ifndef FAST_ZPP
    2178             :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "a/", &stack) == FAILURE) {
    2179             :                 return;
    2180             :         }
    2181             : #else
    2182          76 :         ZEND_PARSE_PARAMETERS_START(1, 1)
    2183         313 :                 Z_PARAM_ARRAY_EX(stack, 0, 1)
    2184          76 :         ZEND_PARSE_PARAMETERS_END();
    2185             : #endif
    2186             : 
    2187          72 :         if (zend_hash_num_elements(Z_ARRVAL_P(stack)) == 0) {
    2188           2 :                 return;
    2189             :         }
    2190             : 
    2191             :         /* Get the last value and copy it into the return value */
    2192          70 :         idx = Z_ARRVAL_P(stack)->nNumUsed;
    2193             :         while (1) {
    2194          79 :                 if (idx == 0) {
    2195           0 :                         return;
    2196             :                 }
    2197          79 :                 idx--;
    2198          79 :                 p = Z_ARRVAL_P(stack)->arData + idx;
    2199          79 :                 val = &p->val;
    2200          79 :                 if (Z_TYPE_P(val) == IS_INDIRECT) {
    2201          10 :                         val = Z_INDIRECT_P(val);
    2202             :                 }
    2203          79 :                 if (Z_TYPE_P(val) != IS_UNDEF) {
    2204          70 :                         break;
    2205             :                 }
    2206           9 :         }
    2207          70 :         ZVAL_DEREF(val);
    2208          70 :         ZVAL_COPY(return_value, val);
    2209             : 
    2210          70 :         if (!p->key && Z_ARRVAL_P(stack)->nNextFreeElement > 0 && p->h >= (zend_ulong)(Z_ARRVAL_P(stack)->nNextFreeElement - 1)) {
    2211          61 :                 Z_ARRVAL_P(stack)->nNextFreeElement = Z_ARRVAL_P(stack)->nNextFreeElement - 1;
    2212             :         }
    2213             : 
    2214             :         /* Delete the last value */
    2215          70 :         if (p->key) {
    2216           7 :                 if (Z_ARRVAL_P(stack) == &EG(symbol_table)) {
    2217           3 :                         zend_delete_global_variable(p->key);
    2218             :                 } else {
    2219           4 :                         zend_hash_del(Z_ARRVAL_P(stack), p->key);
    2220             :                 }
    2221             :         } else {
    2222          63 :                 zend_hash_index_del(Z_ARRVAL_P(stack), p->h);
    2223             :         }
    2224             : 
    2225          70 :         zend_hash_internal_pointer_reset(Z_ARRVAL_P(stack));
    2226             : }
    2227             : /* }}} */
    2228             : 
    2229             : /* {{{ proto mixed array_shift(array stack)
    2230             :    Pops an element off the beginning of the array */
    2231         228 : PHP_FUNCTION(array_shift)
    2232             : {
    2233             :         zval *stack,    /* Input stack */
    2234             :                  *val;          /* Value to be popped */
    2235             :         uint32_t idx;
    2236             :         Bucket *p;
    2237             : 
    2238             : #ifndef FAST_ZPP
    2239             :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "a/", &stack) == FAILURE) {
    2240             :                 return;
    2241             :         }
    2242             : #else
    2243         228 :         ZEND_PARSE_PARAMETERS_START(1, 1)
    2244         944 :                 Z_PARAM_ARRAY_EX(stack, 0, 1)
    2245         228 :         ZEND_PARSE_PARAMETERS_END();
    2246             : #endif
    2247             : 
    2248         198 :         if (zend_hash_num_elements(Z_ARRVAL_P(stack)) == 0) {
    2249           3 :                 return;
    2250             :         }
    2251             : 
    2252             :         /* Get the first value and copy it into the return value */
    2253         195 :         idx = 0;
    2254             :         while (1) {
    2255         203 :                 if (idx == Z_ARRVAL_P(stack)->nNumUsed) {
    2256           0 :                         return;
    2257             :                 }
    2258         203 :                 p = Z_ARRVAL_P(stack)->arData + idx;
    2259         203 :                 val = &p->val;
    2260         203 :                 if (Z_TYPE_P(val) == IS_INDIRECT) {
    2261           0 :                         val = Z_INDIRECT_P(val);
    2262             :                 }
    2263         203 :                 if (Z_TYPE_P(val) != IS_UNDEF) {
    2264         195 :                         break;
    2265             :                 }
    2266           8 :                 idx++;
    2267           8 :         }
    2268         195 :         ZVAL_DEREF(val);
    2269         195 :         ZVAL_COPY(return_value, val);
    2270             : 
    2271             :         /* Delete the first value */
    2272         195 :         if (p->key) {
    2273          26 :                 if (Z_ARRVAL_P(stack) == &EG(symbol_table)) {
    2274           1 :                         zend_delete_global_variable(p->key);
    2275             :                 } else {
    2276          25 :                         zend_hash_del(Z_ARRVAL_P(stack), p->key);
    2277             :                 }
    2278             :         } else {
    2279         169 :                 zend_hash_index_del(Z_ARRVAL_P(stack), p->h);
    2280             :         }
    2281             : 
    2282             :         /* re-index like it did before */
    2283         195 :         if (Z_ARRVAL_P(stack)->u.flags & HASH_FLAG_PACKED) {
    2284         163 :                 uint32_t k = 0;
    2285             : 
    2286         163 :                 if (EXPECTED(Z_ARRVAL_P(stack)->u.v.nIteratorsCount == 0)) {
    2287         583 :                         for (idx = 0; idx < Z_ARRVAL_P(stack)->nNumUsed; idx++) {
    2288         444 :                                 p = Z_ARRVAL_P(stack)->arData + idx;
    2289         888 :                                 if (Z_TYPE(p->val) == IS_UNDEF) continue;
    2290         328 :                                 if (idx != k) {
    2291         328 :                                         Bucket *q = Z_ARRVAL_P(stack)->arData + k;
    2292         328 :                                         q->h = k;
    2293         328 :                                         q->key = NULL;
    2294         328 :                                         ZVAL_COPY_VALUE(&q->val, &p->val);
    2295         328 :                                         ZVAL_UNDEF(&p->val);
    2296             :                                 }
    2297         328 :                                 k++;
    2298             :                         }
    2299             :                 } else {
    2300          24 :                         uint32_t iter_pos = zend_hash_iterators_lower_pos(Z_ARRVAL_P(stack), 0);
    2301             : 
    2302          65 :                         for (idx = 0; idx < Z_ARRVAL_P(stack)->nNumUsed; idx++) {
    2303          41 :                                 p = Z_ARRVAL_P(stack)->arData + idx;
    2304          82 :                                 if (Z_TYPE(p->val) == IS_UNDEF) continue;
    2305          26 :                                 if (idx != k) {
    2306          26 :                                         Bucket *q = Z_ARRVAL_P(stack)->arData + k;
    2307          26 :                                         q->h = k;
    2308          26 :                                         q->key = NULL;
    2309          26 :                                         ZVAL_COPY_VALUE(&q->val, &p->val);
    2310          26 :                                         ZVAL_UNDEF(&p->val);
    2311          26 :                                         if (idx == iter_pos) {
    2312          15 :                                                 zend_hash_iterators_update(Z_ARRVAL_P(stack), idx, k);
    2313          15 :                                                 iter_pos = zend_hash_iterators_lower_pos(Z_ARRVAL_P(stack), iter_pos + 1);
    2314             :                                         }
    2315             :                                 }
    2316          26 :                                 k++;
    2317             :                         }
    2318             :                 }
    2319         163 :                 Z_ARRVAL_P(stack)->nNumUsed = k;
    2320         163 :                 Z_ARRVAL_P(stack)->nNextFreeElement = k;
    2321             :         } else {
    2322          32 :                 uint32_t k = 0;
    2323          32 :                 int should_rehash = 0;
    2324             : 
    2325         501 :                 for (idx = 0; idx < Z_ARRVAL_P(stack)->nNumUsed; idx++) {
    2326         469 :                         p = Z_ARRVAL_P(stack)->arData + idx;
    2327         938 :                         if (Z_TYPE(p->val) == IS_UNDEF) continue;
    2328         437 :                         if (p->key == NULL) {
    2329          22 :                                 if (p->h != k) {
    2330          15 :                                         p->h = k++;
    2331          15 :                                         should_rehash = 1;
    2332             :                                 } else {
    2333           7 :                                         k++;
    2334             :                                 }
    2335             :                         }
    2336             :                 }
    2337          32 :                 Z_ARRVAL_P(stack)->nNextFreeElement = k;
    2338          32 :                 if (should_rehash) {
    2339           5 :                         zend_hash_rehash(Z_ARRVAL_P(stack));
    2340             :                 }
    2341             :         }
    2342             : 
    2343         195 :         zend_hash_internal_pointer_reset(Z_ARRVAL_P(stack));
    2344             : }
    2345             : /* }}} */
    2346             : 
    2347             : /* {{{ proto int array_unshift(array stack, mixed var [, mixed ...])
    2348             :    Pushes elements onto the beginning of the array */
    2349         277 : PHP_FUNCTION(array_unshift)
    2350             : {
    2351             :         zval   *args,                   /* Function arguments array */
    2352             :                    *stack;                      /* Input stack */
    2353             :         HashTable new_hash;             /* New hashtable for the stack */
    2354             :         int argc;                               /* Number of function arguments */
    2355             :         int i;
    2356             :         zend_string *key;
    2357             :         zval *value;
    2358             : 
    2359         277 :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "a/+", &stack, &args, &argc) == FAILURE) {
    2360          51 :                 return;
    2361             :         }
    2362             : 
    2363         226 :         zend_hash_init(&new_hash, zend_hash_num_elements(Z_ARRVAL_P(stack)) + argc, NULL, ZVAL_PTR_DTOR, 0);
    2364         647 :         for (i = 0; i < argc; i++) {
    2365         421 :                 if (Z_REFCOUNTED(args[i])) {
    2366          79 :                         Z_ADDREF(args[i]);
    2367             :                 }
    2368         421 :                 zend_hash_next_index_insert_new(&new_hash, &args[i]);
    2369             :         }
    2370         226 :         if (EXPECTED(Z_ARRVAL_P(stack)->u.v.nIteratorsCount == 0)) {
    2371        1755 :                 ZEND_HASH_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(stack), key, value) {
    2372         755 :                         if (key) {
    2373         310 :                                 zend_hash_add_new(&new_hash, key, value);
    2374             :                         } else {
    2375         445 :                                 zend_hash_next_index_insert_new(&new_hash, value);
    2376             :                         }
    2377             :                 } ZEND_HASH_FOREACH_END();
    2378             :         } else {
    2379             :                 uint32_t old_idx;
    2380           9 :                 uint32_t new_idx = i;
    2381           9 :                 uint32_t iter_pos = zend_hash_iterators_lower_pos(Z_ARRVAL_P(stack), 0);
    2382             : 
    2383          55 :                 ZEND_HASH_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(stack), key, value) {
    2384          23 :                         if (key) {
    2385           0 :                                 zend_hash_add_new(&new_hash, key, value);
    2386             :                         } else {
    2387          23 :                                 zend_hash_next_index_insert_new(&new_hash, value);
    2388             :                         }
    2389          23 :                         old_idx = (Bucket*)value - Z_ARRVAL_P(stack)->arData;
    2390          23 :                         if (old_idx == iter_pos) {
    2391          13 :                                 zend_hash_iterators_update(Z_ARRVAL_P(stack), old_idx, new_idx);
    2392          13 :                                 iter_pos = zend_hash_iterators_lower_pos(Z_ARRVAL_P(stack), iter_pos + 1);
    2393             :                         }
    2394          23 :                         new_idx++;
    2395             :                 } ZEND_HASH_FOREACH_END();
    2396             :         }
    2397             : 
    2398             :         /* replace HashTable data */
    2399         226 :         Z_ARRVAL_P(stack)->u.v.nIteratorsCount = 0;
    2400         226 :         Z_ARRVAL_P(stack)->pDestructor = NULL;
    2401         226 :         zend_hash_destroy(Z_ARRVAL_P(stack));
    2402             : 
    2403         226 :         Z_ARRVAL_P(stack)->u.v.flags         = new_hash.u.v.flags;
    2404         226 :         Z_ARRVAL_P(stack)->nTableSize        = new_hash.nTableSize;
    2405         226 :         Z_ARRVAL_P(stack)->nTableMask        = new_hash.nTableMask;
    2406         226 :         Z_ARRVAL_P(stack)->nNumUsed          = new_hash.nNumUsed;
    2407         226 :         Z_ARRVAL_P(stack)->nNumOfElements    = new_hash.nNumOfElements;
    2408         226 :         Z_ARRVAL_P(stack)->nNextFreeElement  = new_hash.nNextFreeElement;
    2409         226 :         Z_ARRVAL_P(stack)->arData            = new_hash.arData;
    2410         226 :         Z_ARRVAL_P(stack)->pDestructor       = new_hash.pDestructor;
    2411             :         
    2412         226 :         zend_hash_internal_pointer_reset(Z_ARRVAL_P(stack));
    2413             : 
    2414             :         /* Clean up and return the number of elements in the stack */
    2415         226 :         RETVAL_LONG(zend_hash_num_elements(Z_ARRVAL_P(stack)));
    2416             : }
    2417             : /* }}} */
    2418             : 
    2419             : /* {{{ proto array array_splice(array input, int offset [, int length [, array replacement]])
    2420             :    Removes the elements designated by offset and length and replace them with supplied array */
    2421          69 : PHP_FUNCTION(array_splice)
    2422             : {
    2423             :         zval *array,                            /* Input array */
    2424          69 :                  *repl_array = NULL;    /* Replacement array */
    2425          69 :         HashTable  *rem_hash = NULL;
    2426             :         zend_long offset,
    2427          69 :                         length = 0;
    2428             :         int             num_in;                         /* Number of elements in the input array */
    2429             : 
    2430          69 :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "a/l|lz/", &array, &offset, &length, &repl_array) == FAILURE) {
    2431           6 :                 return;
    2432             :         }
    2433             : 
    2434          63 :         num_in = zend_hash_num_elements(Z_ARRVAL_P(array));
    2435             : 
    2436          63 :         if (ZEND_NUM_ARGS() < 3) {
    2437           1 :                 length = num_in;
    2438             :         }
    2439             : 
    2440          63 :         if (ZEND_NUM_ARGS() == 4) {
    2441             :                 /* Make sure the last argument, if passed, is an array */
    2442          62 :                 convert_to_array_ex(repl_array);
    2443             :         }
    2444             : 
    2445             :         /* Don't create the array of removed elements if it's not going
    2446             :          * to be used; e.g. only removing and/or replacing elements */
    2447          63 :         if (USED_RET()) {
    2448          52 :                 zend_long size = length;
    2449             : 
    2450             :                 /* Clamp the offset.. */
    2451          52 :                 if (offset > num_in) {
    2452           0 :                         offset = num_in;
    2453          52 :                 } else if (offset < 0 && (offset = (num_in + offset)) < 0) {
    2454           0 :                         offset = 0;
    2455             :                 }
    2456             : 
    2457             :                 /* ..and the length */
    2458          52 :                 if (length < 0) {
    2459          15 :                         size = num_in - offset + length;
    2460          37 :                 } else if (((zend_ulong) offset + (zend_ulong) length) > (uint32_t) num_in) {
    2461          10 :                         size = num_in - offset;
    2462             :                 }
    2463             : 
    2464             :                 /* Initialize return value */
    2465          52 :                 array_init_size(return_value, size > 0 ? (uint32_t)size : 0);
    2466          52 :                 rem_hash = Z_ARRVAL_P(return_value);
    2467             :         }
    2468             : 
    2469             :         /* Perform splice */
    2470          63 :         php_splice(Z_ARRVAL_P(array), (int)offset, (int)length, repl_array ? Z_ARRVAL_P(repl_array) : NULL, rem_hash);
    2471             : }
    2472             : /* }}} */
    2473             : 
    2474             : /* {{{ proto array array_slice(array input, int offset [, int length [, bool preserve_keys]])
    2475             :    Returns elements specified by offset and length */
    2476         376 : PHP_FUNCTION(array_slice)
    2477             : {
    2478             :         zval     *input,                /* Input array */
    2479         376 :                          *z_length = NULL, /* How many elements to get */
    2480             :                          *entry;                /* An array entry */
    2481             :         zend_long        offset,                /* Offset to get elements from */
    2482         376 :                          length = 0;
    2483         376 :         zend_bool preserve_keys = 0; /* Whether to preserve keys while copying to the new array or not */
    2484             :         int              num_in,                /* Number of elements in the input array */
    2485             :                          pos;                   /* Current position in the array */
    2486             :         zend_string *string_key;
    2487             :         zend_ulong num_key;
    2488             : 
    2489             : #ifndef FAST_ZPP
    2490             :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "al|zb", &input, &offset, &z_length, &preserve_keys) == FAILURE) {
    2491             :                 return;
    2492             :         }
    2493             : #else
    2494         376 :         ZEND_PARSE_PARAMETERS_START(2, 4)
    2495        1113 :                 Z_PARAM_ARRAY(input)
    2496        1035 :                 Z_PARAM_LONG(offset)
    2497         345 :                 Z_PARAM_OPTIONAL
    2498         345 :                 Z_PARAM_ZVAL(z_length)
    2499         597 :                 Z_PARAM_BOOL(preserve_keys)
    2500         376 :         ZEND_PARSE_PARAMETERS_END();
    2501             : #endif
    2502             : 
    2503             :         /* Get number of entries in the input hash */
    2504         343 :         num_in = zend_hash_num_elements(Z_ARRVAL_P(input));
    2505             : 
    2506             :         /* We want all entries from offset to the end if length is not passed or is null */
    2507         696 :         if (ZEND_NUM_ARGS() < 3 || Z_TYPE_P(z_length) == IS_NULL) {
    2508          62 :                 length = num_in;
    2509             :         } else {
    2510         562 :                 length = zval_get_long(z_length);
    2511             :         }
    2512             : 
    2513             :         /* Clamp the offset.. */
    2514         343 :         if (offset > num_in) {
    2515          11 :                 array_init(return_value);
    2516          11 :                 return;
    2517         332 :         } else if (offset < 0 && (offset = (num_in + offset)) < 0) {
    2518          10 :                 offset = 0;
    2519             :         }
    2520             : 
    2521             :         /* ..and the length */
    2522         332 :         if (length < 0) {
    2523          71 :                 length = num_in - offset + length;
    2524         261 :         } else if (((zend_ulong) offset + (zend_ulong) length) > (unsigned) num_in) {
    2525          95 :                 length = num_in - offset;
    2526             :         }
    2527             : 
    2528         332 :         if (length <= 0) {
    2529         117 :                 array_init(return_value);
    2530         117 :                 return;
    2531             :         }
    2532             : 
    2533             :         /* Initialize returned array */
    2534         215 :         array_init_size(return_value, (uint32_t)length);
    2535             : 
    2536             :         /* Start at the beginning and go until we hit offset */
    2537         215 :         pos = 0;
    2538         278 :         if (!preserve_keys && (Z_ARRVAL_P(input)->u.flags & HASH_FLAG_PACKED)) {
    2539          63 :                 zend_hash_real_init(Z_ARRVAL_P(return_value), 1);
    2540          63 :                 ZEND_HASH_FILL_PACKED(Z_ARRVAL_P(return_value)) {
    2541         665 :                         ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(input), entry) {
    2542         298 :                                 pos++;
    2543         298 :                                 if (pos <= offset) {
    2544          80 :                                         continue;
    2545             :                                 }
    2546         218 :                                 if (pos > offset + length) {
    2547          26 :                                         break;
    2548             :                                 }
    2549         192 :                                 ZEND_HASH_FILL_ADD(entry);
    2550         192 :                                 zval_add_ref(entry);
    2551             :                         } ZEND_HASH_FOREACH_END();
    2552          63 :                 } ZEND_HASH_FILL_END();
    2553             :         } else {
    2554        1361 :                 ZEND_HASH_FOREACH_KEY_VAL(Z_ARRVAL_P(input), num_key, string_key, entry) {
    2555         630 :                         pos++;
    2556         630 :                         if (pos <= offset) {
    2557         149 :                                 continue;
    2558             :                         }
    2559         481 :                         if (pos > offset + length) {
    2560          71 :                                 break;
    2561             :                         }
    2562             : 
    2563         410 :                         if (string_key) {
    2564         136 :                                 entry = zend_hash_add_new(Z_ARRVAL_P(return_value), string_key, entry);
    2565             :                         } else {
    2566         274 :                                 if (preserve_keys) {
    2567         150 :                                         entry = zend_hash_index_add_new(Z_ARRVAL_P(return_value), num_key, entry);
    2568             :                                 } else {
    2569         124 :                                         entry = zend_hash_next_index_insert_new(Z_ARRVAL_P(return_value), entry);
    2570             :                                 }
    2571             :                         }
    2572         410 :                         zval_add_ref(entry);
    2573             :                 } ZEND_HASH_FOREACH_END();
    2574             :         }
    2575             : }
    2576             : /* }}} */
    2577             : 
    2578          82 : PHPAPI int php_array_merge_recursive(HashTable *dest, HashTable *src) /* {{{ */
    2579             : {
    2580             :         zval *src_entry, *dest_entry;
    2581             :         zend_string *string_key;
    2582             : 
    2583         530 :         ZEND_HASH_FOREACH_STR_KEY_VAL(src, string_key, src_entry) {
    2584         229 :                 if (string_key) {
    2585         115 :                         if ((dest_entry = zend_hash_find(dest, string_key)) != NULL) {
    2586          38 :                                 zval *src_zval = src_entry;
    2587          38 :                                 zval *dest_zval = dest_entry;
    2588             :                                 HashTable *thash;
    2589             :                                 zval tmp;
    2590             :                                 int ret;
    2591             : 
    2592          38 :                                 ZVAL_DEREF(src_zval);
    2593          38 :                                 ZVAL_DEREF(dest_zval);
    2594          38 :                                 thash = Z_TYPE_P(dest_zval) == IS_ARRAY ? Z_ARRVAL_P(dest_zval) : NULL;
    2595          38 :                                 if ((thash && thash->u.v.nApplyCount > 1) || (src_entry == dest_entry && Z_ISREF_P(dest_entry) && (Z_REFCOUNT_P(dest_entry) % 2))) {
    2596           2 :                                         php_error_docref(NULL, E_WARNING, "recursion detected");
    2597           2 :                                         return 0;
    2598             :                                 }
    2599             : 
    2600          36 :                                 if (Z_ISREF_P(dest_entry)) {
    2601           5 :                                         if (Z_REFCOUNT_P(dest_entry) == 1) {
    2602           0 :                                                 ZVAL_UNREF(dest_entry);
    2603             :                                         } else {
    2604             :                                                 Z_DELREF_P(dest_entry);
    2605           5 :                                                 ZVAL_DUP(dest_entry, dest_zval);
    2606             :                                         }
    2607           5 :                                         dest_zval = dest_entry;
    2608             :                                 } else {
    2609          73 :                                         SEPARATE_ZVAL(dest_zval);
    2610             :                                 }
    2611          36 :                                 if (Z_TYPE_P(dest_zval) == IS_NULL) {
    2612           2 :                                         convert_to_array_ex(dest_zval);
    2613           2 :                                         add_next_index_null(dest_zval);
    2614             :                                 } else {
    2615          34 :                                         convert_to_array_ex(dest_zval);
    2616             :                                 }
    2617          36 :                                 ZVAL_UNDEF(&tmp);
    2618          36 :                                 if (Z_TYPE_P(src_zval) == IS_OBJECT) {
    2619           0 :                                         ZVAL_COPY(&tmp, src_zval);
    2620           0 :                                         convert_to_array(&tmp);
    2621           0 :                                         src_zval = &tmp;
    2622             :                                 }
    2623          36 :                                 if (Z_TYPE_P(src_zval) == IS_ARRAY) {
    2624          18 :                                         if (thash && ZEND_HASH_APPLY_PROTECTION(thash)) {
    2625          16 :                                                 thash->u.v.nApplyCount++;
    2626             :                                         }
    2627          18 :                                         ret = php_array_merge_recursive(Z_ARRVAL_P(dest_zval), Z_ARRVAL_P(src_zval));
    2628          18 :                                         if (thash && ZEND_HASH_APPLY_PROTECTION(thash)) {
    2629          16 :                                                 thash->u.v.nApplyCount--;
    2630             :                                         }
    2631          18 :                                         if (!ret) {
    2632           8 :                                                 return 0;
    2633             :                                         }
    2634             :                                 } else {
    2635          18 :                                         if (Z_REFCOUNTED_P(src_entry)) {
    2636             :                                                 Z_ADDREF_P(src_entry);
    2637             :                                         }
    2638          18 :                                         zend_hash_next_index_insert(Z_ARRVAL_P(dest_zval), src_zval);
    2639             :                                 }
    2640          28 :                                 zval_ptr_dtor(&tmp);
    2641             :                         } else {
    2642          77 :                                 if (Z_REFCOUNTED_P(src_entry)) {
    2643             :                                         Z_ADDREF_P(src_entry);
    2644             :                                 }
    2645          77 :                                 zend_hash_add_new(dest, string_key, src_entry);
    2646             :                         }
    2647             :                 } else {
    2648         114 :                         if (Z_REFCOUNTED_P(src_entry)) {
    2649             :                                 Z_ADDREF_P(src_entry);
    2650             :                         }
    2651         114 :                         zend_hash_next_index_insert_new(dest, src_entry);
    2652             :                 }
    2653             :         } ZEND_HASH_FOREACH_END();
    2654          72 :         return 1;
    2655             : }
    2656             : /* }}} */
    2657             : 
    2658         194 : PHPAPI int php_array_merge(HashTable *dest, HashTable *src) /* {{{ */
    2659             : {
    2660             :         zval *src_entry;
    2661             :         zend_string *string_key;
    2662             : 
    2663       31596 :         ZEND_HASH_FOREACH_STR_KEY_VAL(src, string_key, src_entry) {
    2664       15689 :                 if (string_key) {
    2665         117 :                         if (Z_REFCOUNTED_P(src_entry)) {
    2666             :                                 Z_ADDREF_P(src_entry);
    2667             :                         }
    2668         117 :                         zend_hash_update(dest, string_key, src_entry);
    2669             :                 } else {
    2670       15572 :                         if (Z_REFCOUNTED_P(src_entry)) {
    2671             :                                 Z_ADDREF_P(src_entry);
    2672             :                         }
    2673       15572 :                         zend_hash_next_index_insert_new(dest, src_entry);
    2674             :                 }
    2675             :         } ZEND_HASH_FOREACH_END();
    2676         194 :         return 1;
    2677             : }
    2678             : /* }}} */
    2679             : 
    2680           5 : PHPAPI int php_array_replace_recursive(HashTable *dest, HashTable *src) /* {{{ */
    2681             : {
    2682             :         zval *src_entry, *dest_entry, *src_zval, *dest_zval;
    2683             :         zend_string *string_key;
    2684             :         zend_ulong num_key;
    2685             :         int ret;
    2686             : 
    2687          16 :         ZEND_HASH_FOREACH_KEY_VAL(src, num_key, string_key, src_entry) {
    2688           7 :                 src_zval = src_entry;
    2689           7 :                 ZVAL_DEREF(src_zval);
    2690           7 :                 if (string_key) {
    2691           6 :                         if (Z_TYPE_P(src_zval) != IS_ARRAY ||
    2692           2 :                                 (dest_entry = zend_hash_find(dest, string_key)) == NULL ||
    2693             :                                 (Z_TYPE_P(dest_entry) != IS_ARRAY &&
    2694           0 :                                  (!Z_ISREF_P(dest_entry) || Z_TYPE_P(Z_REFVAL_P(dest_entry)) != IS_ARRAY))) {
    2695             : 
    2696           2 :                                 if (Z_REFCOUNTED_P(src_entry)) {
    2697             :                                         Z_ADDREF_P(src_entry);
    2698             :                                 }
    2699           2 :                                 zend_hash_update(dest, string_key, src_entry);
    2700             : 
    2701           2 :                                 continue;
    2702             :                         }
    2703             :                 } else {
    2704          10 :                         if (Z_TYPE_P(src_zval) != IS_ARRAY ||
    2705           3 :                                 (dest_entry = zend_hash_index_find(dest, num_key)) == NULL ||
    2706             :                                 (Z_TYPE_P(dest_entry) != IS_ARRAY &&
    2707           0 :                                  (!Z_ISREF_P(dest_entry) || Z_TYPE_P(Z_REFVAL_P(dest_entry)) != IS_ARRAY))) {
    2708             : 
    2709           1 :                                 if (Z_REFCOUNTED_P(src_entry)) {
    2710             :                                         Z_ADDREF_P(src_entry);
    2711             :                                 }
    2712           1 :                                 zend_hash_index_update(dest, num_key, src_entry);
    2713             : 
    2714           1 :                                 continue;
    2715             :                         }
    2716             :                 }
    2717             : 
    2718           4 :                 dest_zval = dest_entry;
    2719           4 :                 ZVAL_DEREF(dest_zval);
    2720          13 :                 if (Z_ARRVAL_P(dest_zval)->u.v.nApplyCount > 1 ||
    2721           4 :                     Z_ARRVAL_P(src_zval)->u.v.nApplyCount > 1 ||
    2722           0 :                     (Z_ISREF_P(src_entry) && Z_ISREF_P(dest_entry) && Z_REF_P(src_entry) == Z_REF_P(dest_entry) && (Z_REFCOUNT_P(dest_entry) % 2))) {
    2723           1 :                         php_error_docref(NULL, E_WARNING, "recursion detected");
    2724           1 :                         return 0;
    2725             :                 }
    2726           9 :                 SEPARATE_ZVAL(dest_zval);
    2727             : 
    2728           3 :                 if (ZEND_HASH_APPLY_PROTECTION(Z_ARRVAL_P(dest_zval))) {
    2729           3 :                         Z_ARRVAL_P(dest_zval)->u.v.nApplyCount++;
    2730             :                 }
    2731           3 :                 if (ZEND_HASH_APPLY_PROTECTION(Z_ARRVAL_P(src_zval))) {
    2732           3 :                         Z_ARRVAL_P(src_zval)->u.v.nApplyCount++;
    2733             :                 }
    2734             : 
    2735           3 :                 ret = php_array_replace_recursive(Z_ARRVAL_P(dest_zval), Z_ARRVAL_P(src_zval));
    2736             : 
    2737           3 :                 if (ZEND_HASH_APPLY_PROTECTION(Z_ARRVAL_P(dest_zval))) {
    2738           3 :                         Z_ARRVAL_P(dest_zval)->u.v.nApplyCount--;
    2739             :                 }
    2740           3 :                 if (ZEND_HASH_APPLY_PROTECTION(Z_ARRVAL_P(src_zval))) {
    2741           3 :                         Z_ARRVAL_P(src_zval)->u.v.nApplyCount--;
    2742             :                 }
    2743             : 
    2744           3 :                 if (!ret) {
    2745           2 :                         return 0;
    2746             :                 }
    2747             :         } ZEND_HASH_FOREACH_END();
    2748             : 
    2749           2 :         return 1;
    2750             : }
    2751             : /* }}} */
    2752             : 
    2753         428 : static inline void php_array_merge_or_replace_wrapper(INTERNAL_FUNCTION_PARAMETERS, int recursive, int replace) /* {{{ */
    2754             : {
    2755         428 :         zval *args = NULL;
    2756             :         zval *arg;
    2757         428 :         int argc, i, init_size = 0;
    2758             : 
    2759             : #ifndef FAST_ZPP
    2760             :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "+", &args, &argc) == FAILURE) {
    2761             :                 return;
    2762             :         }
    2763             : #else
    2764         428 :         ZEND_PARSE_PARAMETERS_START(1, -1)
    2765         425 :                 Z_PARAM_VARIADIC('+', args, argc)
    2766         428 :         ZEND_PARSE_PARAMETERS_END();
    2767             : #endif
    2768             : 
    2769        1040 :         for (i = 0; i < argc; i++) {
    2770         738 :                 zval *arg = args + i;
    2771             : 
    2772         738 :                 ZVAL_DEREF(arg);
    2773         738 :                 if (Z_TYPE_P(arg) != IS_ARRAY) {
    2774         123 :                         php_error_docref(NULL, E_WARNING, "Argument #%d is not an array", i + 1);
    2775         123 :                         RETURN_NULL();
    2776             :                 } else {
    2777         615 :                         int num = zend_hash_num_elements(Z_ARRVAL_P(arg));
    2778             : 
    2779         615 :                         if (num > init_size) {
    2780         445 :                                 init_size = num;
    2781             :                         }
    2782             :                 }
    2783             :         }
    2784             : 
    2785         302 :         array_init_size(return_value, init_size);
    2786             : 
    2787         302 :         if (replace) {
    2788             :                 zend_string *string_key;
    2789             :                 zval *src_entry;
    2790             :                 zend_ulong idx;
    2791             :                 HashTable *src, *dest;
    2792             : 
    2793             :                 /* copy first array */
    2794           3 :                 arg = args;
    2795           3 :                 ZVAL_DEREF(arg);
    2796           3 :                 src  = Z_ARRVAL_P(arg);
    2797           3 :                 dest = Z_ARRVAL_P(return_value);
    2798          21 :                 ZEND_HASH_FOREACH_KEY_VAL(src, idx, string_key, src_entry) {
    2799           9 :                         if (string_key) {
    2800           4 :                                 if (Z_REFCOUNTED_P(src_entry)) {
    2801             :                                         Z_ADDREF_P(src_entry);
    2802             :                                 }
    2803           4 :                                 zend_hash_add_new(dest, string_key, src_entry);
    2804             :                         } else {
    2805           5 :                                 if (Z_REFCOUNTED_P(src_entry)) {
    2806             :                                         Z_ADDREF_P(src_entry);
    2807             :                                 }
    2808           5 :                                 zend_hash_index_add_new(dest, idx, src_entry);
    2809             :                         }
    2810             :                 } ZEND_HASH_FOREACH_END();
    2811             : 
    2812           3 :                 if (recursive) {
    2813           4 :                         for (i = 1; i < argc; i++) {
    2814           2 :                                 arg = args + i;
    2815           2 :                                 ZVAL_DEREF(arg);
    2816           2 :                                 php_array_replace_recursive(Z_ARRVAL_P(return_value), Z_ARRVAL_P(arg));
    2817             :                         }
    2818             :                 } else {
    2819           2 :                         for (i = 1; i < argc; i++) {
    2820           1 :                                 arg = args + i;
    2821           1 :                                 ZVAL_DEREF(arg);
    2822           1 :                                 zend_hash_merge(Z_ARRVAL_P(return_value), Z_ARRVAL_P(arg), zval_add_ref, 1);
    2823             :                         }
    2824             :                 }
    2825             :         } else {
    2826             :                 zend_string *string_key;
    2827             :                 zval *src_entry;
    2828             :                 HashTable *src, *dest;
    2829             : 
    2830             :                 /* copy first array */
    2831         299 :                 arg = args;
    2832         299 :                 ZVAL_DEREF(arg);
    2833         299 :                 src  = Z_ARRVAL_P(arg);
    2834         299 :                 dest = Z_ARRVAL_P(return_value);
    2835       15849 :                 ZEND_HASH_FOREACH_STR_KEY_VAL(src, string_key, src_entry) {
    2836        7753 :                         if (string_key) {
    2837         739 :                                 if (Z_REFCOUNTED_P(src_entry)) {
    2838             :                                         Z_ADDREF_P(src_entry);
    2839             :                                 }
    2840         739 :                                 zend_hash_add_new(dest, string_key, src_entry);
    2841             :                         } else {
    2842        7014 :                                 if (Z_REFCOUNTED_P(src_entry)) {
    2843             :                                         Z_ADDREF_P(src_entry);
    2844             :                                 }
    2845        7014 :                                 zend_hash_next_index_insert_new(dest, src_entry);
    2846             :                         }
    2847             :                 } ZEND_HASH_FOREACH_END();
    2848             : 
    2849         299 :                 if (recursive) {
    2850         169 :                         for (i = 1; i < argc; i++) {
    2851          64 :                                 arg = args + i;
    2852          64 :                                 ZVAL_DEREF(arg);
    2853          64 :                                 php_array_merge_recursive(Z_ARRVAL_P(return_value), Z_ARRVAL_P(arg));
    2854             :                         }
    2855             :                 } else {
    2856         388 :                         for (i = 1; i < argc; i++) {
    2857         194 :                                 arg = args + i;
    2858         194 :                                 ZVAL_DEREF(arg);
    2859         194 :                                 php_array_merge(Z_ARRVAL_P(return_value), Z_ARRVAL_P(arg));
    2860             :                         }
    2861             :                 }
    2862             :         }
    2863             : }
    2864             : /* }}} */
    2865             : 
    2866             : /* {{{ proto array array_merge(array arr1, array arr2 [, array ...])
    2867             :    Merges elements from passed arrays into one array */
    2868         247 : PHP_FUNCTION(array_merge)
    2869             : {
    2870         247 :         php_array_merge_or_replace_wrapper(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0, 0);
    2871         247 : }
    2872             : /* }}} */
    2873             : 
    2874             : /* {{{ proto array array_merge_recursive(array arr1, array arr2 [, array ...])
    2875             :    Recursively merges elements from passed arrays into one array */
    2876         178 : PHP_FUNCTION(array_merge_recursive)
    2877             : {
    2878         178 :         php_array_merge_or_replace_wrapper(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1, 0);
    2879         178 : }
    2880             : /* }}} */
    2881             : 
    2882             : /* {{{ proto array array_replace(array arr1, array arr2 [, array ...])
    2883             :    Replaces elements from passed arrays into one array */
    2884           1 : PHP_FUNCTION(array_replace)
    2885             : {
    2886           1 :         php_array_merge_or_replace_wrapper(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0, 1);
    2887           1 : }
    2888             : /* }}} */
    2889             : 
    2890             : /* {{{ proto array array_replace_recursive(array arr1, array arr2 [, array ...])
    2891             :    Recursively replaces elements from passed arrays into one array */
    2892           2 : PHP_FUNCTION(array_replace_recursive)
    2893             : {
    2894           2 :         php_array_merge_or_replace_wrapper(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1, 1);
    2895           2 : }
    2896             : /* }}} */
    2897             : 
    2898             : /* {{{ proto array array_keys(array input [, mixed search_value[, bool strict]])
    2899             :    Return just the keys from the input array, optionally only for the specified search_value */
    2900         469 : PHP_FUNCTION(array_keys)
    2901             : {
    2902             :         zval *input,                            /* Input array */
    2903         469 :              *search_value = NULL,      /* Value to search for */
    2904             :              *entry,                            /* An entry in the input array */
    2905             :                new_val;                         /* New value */
    2906         469 :         zend_bool strict = 0;           /* do strict comparison */
    2907             :         zend_ulong num_idx;
    2908             :         zend_string *str_idx;
    2909             : 
    2910             : #ifndef FAST_ZPP
    2911             :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "a|zb", &input, &search_value, &strict) == FAILURE) {
    2912             :                 return;
    2913             :         }
    2914             : #else
    2915         469 :         ZEND_PARSE_PARAMETERS_START(1, 3)
    2916        1401 :                 Z_PARAM_ARRAY(input)
    2917         464 :                 Z_PARAM_OPTIONAL
    2918         464 :                 Z_PARAM_ZVAL(search_value)
    2919          56 :                 Z_PARAM_BOOL(strict)
    2920         469 :         ZEND_PARSE_PARAMETERS_END();
    2921             : #endif
    2922             : 
    2923             :         /* Initialize return array */
    2924         464 :         if (search_value != NULL) {
    2925          28 :                 array_init(return_value);
    2926             : 
    2927          28 :                 if (strict) {
    2928         278 :                         ZEND_HASH_FOREACH_KEY_VAL_IND(Z_ARRVAL_P(input), num_idx, str_idx, entry) {
    2929         176 :                                 if (fast_is_identical_function(search_value, entry)) {
    2930           9 :                                         if (str_idx) {
    2931           2 :                                                 ZVAL_STR_COPY(&new_val, str_idx);
    2932             :                                         } else {
    2933           7 :                                                 ZVAL_LONG(&new_val, num_idx);
    2934             :                                         }
    2935           9 :                                         zend_hash_next_index_insert_new(Z_ARRVAL_P(return_value), &new_val);
    2936             :                                 }
    2937             :                         } ZEND_HASH_FOREACH_END();
    2938             :                 } else {
    2939         278 :                         ZEND_HASH_FOREACH_KEY_VAL_IND(Z_ARRVAL_P(input), num_idx, str_idx, entry) {
    2940         176 :                                 if (fast_equal_check_function(search_value, entry)) {
    2941          26 :                                         if (str_idx) {
    2942           7 :                                                 ZVAL_STR_COPY(&new_val, str_idx);
    2943             :                                         } else {
    2944          19 :                                                 ZVAL_LONG(&new_val, num_idx);
    2945             :                                         }
    2946          26 :                                         zend_hash_next_index_insert_new(Z_ARRVAL_P(return_value), &new_val);
    2947             :                                 }
    2948             :                         } ZEND_HASH_FOREACH_END();
    2949             :                 }
    2950             :         } else {
    2951         436 :                 array_init_size(return_value, zend_hash_num_elements(Z_ARRVAL_P(input)));
    2952         436 :                 zend_hash_real_init(Z_ARRVAL_P(return_value), 1);
    2953         436 :                 ZEND_HASH_FILL_PACKED(Z_ARRVAL_P(return_value)) {
    2954             :                         /* Go through input array and add keys to the return array */
    2955       20920 :                         ZEND_HASH_FOREACH_KEY_VAL_IND(Z_ARRVAL_P(input), num_idx, str_idx, entry) {
    2956        6823 :                                 if (str_idx) {
    2957        4925 :                                         ZVAL_STR_COPY(&new_val, str_idx);
    2958             :                                 } else {
    2959        1898 :                                         ZVAL_LONG(&new_val, num_idx);
    2960             :                                 }
    2961        6823 :                                 ZEND_HASH_FILL_ADD(&new_val);
    2962             :                         } ZEND_HASH_FOREACH_END();
    2963         436 :                 } ZEND_HASH_FILL_END();
    2964             :         }
    2965             : }
    2966             : /* }}} */
    2967             : 
    2968             : /* {{{ proto array array_values(array input)
    2969             :    Return just the values from the input array */
    2970          91 : PHP_FUNCTION(array_values)
    2971             : {
    2972             :         zval     *input,                /* Input array */
    2973             :                          *entry;                /* An entry in the input array */
    2974             : 
    2975             : #ifndef FAST_ZPP
    2976             :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "a", &input) == FAILURE) {
    2977             :                 return;
    2978             :         }
    2979             : #else
    2980          91 :         ZEND_PARSE_PARAMETERS_START(1, 1)
    2981         261 :                 Z_PARAM_ARRAY(input)
    2982          91 :         ZEND_PARSE_PARAMETERS_END();
    2983             : #endif
    2984             : 
    2985             :         /* Initialize return array */
    2986          60 :         array_init_size(return_value, zend_hash_num_elements(Z_ARRVAL_P(input)));
    2987          60 :         zend_hash_real_init(Z_ARRVAL_P(return_value), 1);
    2988             : 
    2989             :         /* Go through input array and add values to the return array */
    2990          60 :         ZEND_HASH_FILL_PACKED(Z_ARRVAL_P(return_value)) {
    2991         400 :                 ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(input), entry) {
    2992         178 :                         if (UNEXPECTED(Z_ISREF_P(entry) && Z_REFCOUNT_P(entry) == 1)) {
    2993           3 :                                 entry = Z_REFVAL_P(entry);
    2994             :                         }
    2995         170 :                         Z_TRY_ADDREF_P(entry);
    2996         170 :                         ZEND_HASH_FILL_ADD(entry);
    2997             :                 } ZEND_HASH_FOREACH_END();
    2998          60 :         } ZEND_HASH_FILL_END();
    2999             : }
    3000             : /* }}} */
    3001             : 
    3002             : /* {{{ proto array array_count_values(array input)
    3003             :    Return the value as key and the frequency of that value in input as value */
    3004          20 : PHP_FUNCTION(array_count_values)
    3005             : {
    3006             :         zval    *input,         /* Input array */
    3007             :                         *entry,         /* An entry in the input array */
    3008             :                         *tmp;
    3009             :         HashTable *myht;
    3010             : 
    3011          20 :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "a", &input) == FAILURE) {
    3012           3 :                 return;
    3013             :         }
    3014             : 
    3015             :         /* Initialize return array */
    3016          17 :         array_init(return_value);
    3017             : 
    3018             :         /* Go through input array and add values to the return array */
    3019          17 :         myht = Z_ARRVAL_P(input);
    3020         135 :         ZEND_HASH_FOREACH_VAL(myht, entry) {
    3021          59 :                 ZVAL_DEREF(entry);
    3022          59 :                 if (Z_TYPE_P(entry) == IS_LONG) {
    3023          17 :                         if ((tmp = zend_hash_index_find(Z_ARRVAL_P(return_value), Z_LVAL_P(entry))) == NULL) {
    3024             :                                 zval data;
    3025          13 :                                 ZVAL_LONG(&data, 1);
    3026          13 :                                 zend_hash_index_update(Z_ARRVAL_P(return_value), Z_LVAL_P(entry), &data);
    3027             :                         } else {
    3028           4 :                                 Z_LVAL_P(tmp)++;
    3029             :                         }
    3030          42 :                 } else if (Z_TYPE_P(entry) == IS_STRING) {
    3031          66 :                         if ((tmp = zend_symtable_find(Z_ARRVAL_P(return_value), Z_STR_P(entry))) == NULL) {
    3032             :                                 zval data;
    3033          24 :                                 ZVAL_LONG(&data, 1);
    3034          24 :                                 zend_symtable_update(Z_ARRVAL_P(return_value), Z_STR_P(entry), &data);
    3035             :                         } else {
    3036           9 :                                 Z_LVAL_P(tmp)++;
    3037             :                         }
    3038             :                 } else {
    3039           9 :                         php_error_docref(NULL, E_WARNING, "Can only count STRING and INTEGER values!");
    3040             :                 }
    3041             :         } ZEND_HASH_FOREACH_END();
    3042             : }
    3043             : /* }}} */
    3044             : 
    3045             : /* {{{ array_column_param_helper
    3046             :  * Specialized conversion rules for array_column() function
    3047             :  */
    3048             : static inline
    3049          47 : zend_bool array_column_param_helper(zval *param,
    3050             :                                     const char *name) {
    3051          47 :         switch (Z_TYPE_P(param)) {
    3052             :                 case IS_DOUBLE:
    3053           2 :                         convert_to_long_ex(param);
    3054             :                         /* fallthrough */
    3055             :                 case IS_LONG:
    3056          11 :                         return 1;
    3057             : 
    3058             :                 case IS_OBJECT:
    3059          10 :                         convert_to_string_ex(param);
    3060             :                         /* fallthrough */
    3061             :                 case IS_STRING:
    3062          32 :                         return 1;
    3063             : 
    3064             :                 default:
    3065           4 :                         php_error_docref(NULL, E_WARNING, "The %s key should be either a string or an integer", name);
    3066           4 :                         return 0;
    3067             :         }
    3068             : }
    3069             : /* }}} */
    3070             : 
    3071             : /* {{{ proto array array_column(array input, mixed column_key[, mixed index_key])
    3072             :    Return the values from a single column in the input array, identified by the
    3073             :    value_key and optionally indexed by the index_key */
    3074          37 : PHP_FUNCTION(array_column)
    3075             : {
    3076          37 :         zval *zcolumn = NULL, *zkey = NULL, *data;
    3077             :         HashTable *arr_hash;
    3078          37 :         zval *zcolval = NULL, *zkeyval = NULL;
    3079             :         HashTable *ht;
    3080             : 
    3081          37 :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "hz!|z!", &arr_hash, &zcolumn, &zkey) == FAILURE) {
    3082           4 :                 return;
    3083             :         }
    3084             : 
    3085          81 :         if ((zcolumn && !array_column_param_helper(zcolumn, "column")) ||
    3086          48 :             (zkey && !array_column_param_helper(zkey, "index"))) {
    3087           4 :                 RETURN_FALSE;
    3088             :         }
    3089             : 
    3090          29 :         array_init(return_value);
    3091         211 :         ZEND_HASH_FOREACH_VAL(arr_hash, data) {
    3092          91 :                 ZVAL_DEREF(data);
    3093          91 :                 if (Z_TYPE_P(data) != IS_ARRAY) {
    3094             :                         /* Skip elemens which are not sub-arrays */
    3095           3 :                         continue;
    3096             :                 }
    3097          88 :                 ht = Z_ARRVAL_P(data);
    3098             : 
    3099          88 :                 if (!zcolumn) {
    3100             :                         /* NULL column ID means use entire subarray as data */
    3101           6 :                         zcolval = data;
    3102             : 
    3103             :                         /* Otherwise, skip if the value doesn't exist in our subarray */
    3104         225 :                 } else if ((Z_TYPE_P(zcolumn) == IS_STRING) &&
    3105          61 :                     ((zcolval = zend_hash_find(ht, Z_STR_P(zcolumn))) == NULL)) {
    3106           9 :                         continue;
    3107         167 :                 } else if ((Z_TYPE_P(zcolumn) == IS_LONG) &&
    3108          21 :                     ((zcolval = zend_hash_index_find(ht, Z_LVAL_P(zcolumn))) == NULL)) {
    3109           6 :                         continue;
    3110             :                 }
    3111             : 
    3112             :                 /* Failure will leave zkeyval alone which will land us on the final else block below
    3113             :                  * which is to append the value as next_index
    3114             :                  */
    3115         152 :                 if (zkey && (Z_TYPE_P(zkey) == IS_STRING)) {
    3116          35 :                         zkeyval = zend_hash_find(ht, Z_STR_P(zkey));
    3117          47 :                 } else if (zkey && (Z_TYPE_P(zkey) == IS_LONG)) {
    3118           9 :                         zkeyval = zend_hash_index_find(ht, Z_LVAL_P(zkey));
    3119             :                 }
    3120             : 
    3121          73 :                 Z_TRY_ADDREF_P(zcolval);
    3122         128 :                 if (zkeyval && Z_TYPE_P(zkeyval) == IS_STRING) {
    3123          21 :                         zend_symtable_update(Z_ARRVAL_P(return_value), Z_STR_P(zkeyval), zcolval);
    3124          77 :                 } else if (zkeyval && Z_TYPE_P(zkeyval) == IS_LONG) {
    3125          12 :                         add_index_zval(return_value, Z_LVAL_P(zkeyval), zcolval);
    3126          42 :                 } else if (zkeyval && Z_TYPE_P(zkeyval) == IS_OBJECT) {
    3127           1 :                         zend_string *key = zval_get_string(zkeyval);
    3128           1 :                         zend_symtable_update(Z_ARRVAL_P(return_value), key, zcolval);
    3129             :                         zend_string_release(key);
    3130             :                 } else {
    3131          39 :                         add_next_index_zval(return_value, zcolval);
    3132             :                 }
    3133             :         } ZEND_HASH_FOREACH_END();
    3134             : }
    3135             : /* }}} */
    3136             : 
    3137             : /* {{{ proto array array_reverse(array input [, bool preserve keys])
    3138             :    Return input as a new array with the order of the entries reversed */
    3139         235 : PHP_FUNCTION(array_reverse)
    3140             : {
    3141             :         zval     *input,                                /* Input array */
    3142             :                          *entry;                                /* An entry in the input array */
    3143             :         zend_string *string_key;
    3144             :         zend_ulong        num_key;
    3145         235 :         zend_bool preserve_keys = 0;    /* whether to preserve keys */
    3146             : 
    3147         235 :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "a|b", &input, &preserve_keys) == FAILURE) {
    3148          82 :                 return;
    3149             :         }
    3150             : 
    3151             :         /* Initialize return array */
    3152         153 :         array_init_size(return_value, zend_hash_num_elements(Z_ARRVAL_P(input)));
    3153             : 
    3154        1227 :         ZEND_HASH_REVERSE_FOREACH_KEY_VAL(Z_ARRVAL_P(input), num_key, string_key, entry) {
    3155         516 :                 if (string_key) {
    3156         175 :                         entry = zend_hash_add_new(Z_ARRVAL_P(return_value), string_key, entry);
    3157             :                 } else {
    3158         341 :                         if (preserve_keys) {
    3159         129 :                                 entry = zend_hash_index_add_new(Z_ARRVAL_P(return_value), num_key, entry);
    3160             :                         } else {
    3161         212 :                                 entry = zend_hash_next_index_insert_new(Z_ARRVAL_P(return_value), entry);
    3162             :                         }
    3163             :                 }
    3164             : 
    3165         516 :                 zval_add_ref(entry);
    3166             :         } ZEND_HASH_FOREACH_END();
    3167             : }
    3168             : /* }}} */
    3169             : 
    3170             : /* {{{ proto array array_pad(array input, int pad_size, mixed pad_value)
    3171             :    Returns a copy of input array padded with pad_value to size pad_size */
    3172         199 : PHP_FUNCTION(array_pad)
    3173             : {
    3174             :         zval  *input;           /* Input array */
    3175             :         zval  *pad_value;       /* Padding value obviously */
    3176             :         zend_long pad_size;             /* Size to pad to */
    3177             :         zend_long pad_size_abs; /* Absolute value of pad_size */
    3178             :         zend_long input_size;           /* Size of the input array */
    3179             :         zend_long num_pads;             /* How many pads do we need */
    3180             :         zend_long i;
    3181             :         zend_string *key;
    3182             :         zval *value;
    3183             : 
    3184         199 :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "alz", &input, &pad_size, &pad_value) == FAILURE) {
    3185          66 :                 return;
    3186             :         }
    3187             : 
    3188             :         /* Do some initial calculations */
    3189         133 :         input_size = zend_hash_num_elements(Z_ARRVAL_P(input));
    3190         133 :         pad_size_abs = ZEND_ABS(pad_size);
    3191         133 :         if (pad_size_abs < 0 || pad_size_abs - input_size > Z_L(1048576)) {
    3192           3 :                 php_error_docref(NULL, E_WARNING, "You may only pad up to 1048576 elements at a time");
    3193           3 :                 RETURN_FALSE;
    3194             :         }
    3195             : 
    3196         130 :         if (input_size >= pad_size_abs) {
    3197             :                 /* Copy the original array */
    3198          15 :                 ZVAL_COPY(return_value, input);
    3199          15 :                 return;
    3200             :         }
    3201             : 
    3202         115 :         num_pads = pad_size_abs - input_size;
    3203         115 :         array_init_size(return_value, pad_size_abs);
    3204         115 :         if (Z_REFCOUNTED_P(pad_value)) {
    3205          18 :                 GC_REFCOUNT(Z_COUNTED_P(pad_value)) += num_pads;
    3206             :         }
    3207             : 
    3208         115 :         if (pad_size < 0) {
    3209         198 :                 for (i = 0; i < num_pads; i++) {
    3210         141 :                         zend_hash_next_index_insert_new(Z_ARRVAL_P(return_value), pad_value);
    3211             :                 }
    3212             :         }
    3213             : 
    3214         916 :         ZEND_HASH_FOREACH_STR_KEY_VAL_IND(Z_ARRVAL_P(input), key, value) {
    3215         265 :                 if (Z_REFCOUNTED_P(value)) {
    3216             :                         Z_ADDREF_P(value);
    3217             :                 }
    3218         265 :                 if (key) {
    3219          44 :                         zend_hash_add_new(Z_ARRVAL_P(return_value), key, value);
    3220             :                 } else {
    3221         221 :                         zend_hash_next_index_insert_new(Z_ARRVAL_P(return_value), value);
    3222             :                 }
    3223             :         } ZEND_HASH_FOREACH_END();
    3224             : 
    3225         115 :         if (pad_size > 0) {
    3226         202 :                 for (i = 0; i < num_pads; i++) {
    3227         144 :                         zend_hash_next_index_insert_new(Z_ARRVAL_P(return_value), pad_value);
    3228             :                 }
    3229             :         }
    3230             : }
    3231             : /* }}} */
    3232             : 
    3233             : /* {{{ proto array array_flip(array input)
    3234             :    Return array with key <-> value flipped */
    3235          69 : PHP_FUNCTION(array_flip)
    3236             : {
    3237             :         zval *array, *entry, data;
    3238             :         zend_ulong num_idx;
    3239             :         zend_string *str_idx;
    3240             : 
    3241          69 :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "a", &array) == FAILURE) {
    3242          25 :                 return;
    3243             :         }
    3244             : 
    3245          44 :         array_init_size(return_value, zend_hash_num_elements(Z_ARRVAL_P(array)));
    3246             : 
    3247         402 :         ZEND_HASH_FOREACH_KEY_VAL(Z_ARRVAL_P(array), num_idx, str_idx, entry) {
    3248         177 :                 ZVAL_DEREF(entry);
    3249         177 :                 if (Z_TYPE_P(entry) == IS_LONG) {
    3250          80 :                         if (str_idx) {
    3251          17 :                                 ZVAL_STR_COPY(&data, str_idx);
    3252             :                         } else {
    3253          63 :                                 ZVAL_LONG(&data, num_idx);
    3254             :                         }
    3255          80 :                         zend_hash_index_update(Z_ARRVAL_P(return_value), Z_LVAL_P(entry), &data);
    3256          97 :                 } else if (Z_TYPE_P(entry) == IS_STRING) {
    3257          82 :                         if (str_idx) {
    3258          35 :                                 ZVAL_STR_COPY(&data, str_idx);
    3259             :                         } else {
    3260          47 :                                 ZVAL_LONG(&data, num_idx);
    3261             :                         }
    3262          82 :                         zend_symtable_update(Z_ARRVAL_P(return_value), Z_STR_P(entry), &data);
    3263             :                 } else {
    3264          15 :                         php_error_docref(NULL, E_WARNING, "Can only flip STRING and INTEGER values!");
    3265             :                 }
    3266             :         } ZEND_HASH_FOREACH_END();
    3267             : }
    3268             : /* }}} */
    3269             : 
    3270             : /* {{{ proto array array_change_key_case(array input [, int case=CASE_LOWER])
    3271             :    Retuns an array with all string keys lowercased [or uppercased] */
    3272         200 : PHP_FUNCTION(array_change_key_case)
    3273             : {
    3274             :         zval *array, *entry;
    3275             :         zend_string *string_key;
    3276             :         zend_string *new_key;
    3277             :         zend_ulong num_key;
    3278         200 :         zend_long change_to_upper=0;
    3279             : 
    3280         200 :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "a|l", &array, &change_to_upper) == FAILURE) {
    3281          36 :                 return;
    3282             :         }
    3283             : 
    3284         164 :         array_init_size(return_value, zend_hash_num_elements(Z_ARRVAL_P(array)));
    3285             : 
    3286         970 :         ZEND_HASH_FOREACH_KEY_VAL(Z_ARRVAL_P(array), num_key, string_key, entry) {
    3287         403 :                 if (!string_key) {
    3288          64 :                         entry = zend_hash_index_update(Z_ARRVAL_P(return_value), num_key, entry);
    3289             :                 } else {
    3290         339 :                         if (change_to_upper) {
    3291         166 :                                 new_key = php_string_toupper(string_key);
    3292             :                         } else {
    3293         173 :                                 new_key = php_string_tolower(string_key);
    3294             :                         }
    3295         339 :                         entry = zend_hash_update(Z_ARRVAL_P(return_value), new_key, entry);
    3296             :                         zend_string_release(new_key);
    3297             :                 }
    3298             : 
    3299         403 :                 zval_add_ref(entry);
    3300             :         } ZEND_HASH_FOREACH_END();
    3301             : }
    3302             : /* }}} */
    3303             : 
    3304             : struct bucketindex {
    3305             :         Bucket b;
    3306             :         unsigned int i;
    3307             : };
    3308             : 
    3309       65880 : static void array_bucketindex_swap(void *p, void *q) /* {{{ */
    3310             : {
    3311       65880 :         struct bucketindex *f = (struct bucketindex *)p;
    3312       65880 :         struct bucketindex *g = (struct bucketindex *)q;
    3313             :         struct bucketindex t;
    3314       65880 :         t = *f;
    3315       65880 :         *f = *g;
    3316       65880 :         *g = t;
    3317       65880 : }
    3318             : /* }}} */
    3319             : 
    3320             : /* {{{ proto array array_unique(array input [, int sort_flags])
    3321             :    Removes duplicate values from array */
    3322          72 : PHP_FUNCTION(array_unique)
    3323             : {
    3324             :         zval *array;
    3325             :         uint idx;
    3326             :         Bucket *p;
    3327             :         struct bucketindex *arTmp, *cmpdata, *lastkept;
    3328             :         unsigned int i;
    3329          72 :         zend_long sort_type = PHP_SORT_STRING;
    3330             : 
    3331          72 :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "a|l", &array, &sort_type) == FAILURE) {
    3332          27 :                 return;
    3333             :         }
    3334             : 
    3335          45 :         php_set_compare_func(sort_type);
    3336             : 
    3337          45 :         RETVAL_ARR(zend_array_dup(Z_ARRVAL_P(array)));
    3338             : 
    3339          45 :         if (Z_ARRVAL_P(array)->nNumOfElements <= 1) {     /* nothing to do */
    3340           2 :                 return;
    3341             :         }
    3342             : 
    3343             :         /* create and sort array with pointers to the target_hash buckets */
    3344          86 :         arTmp = (struct bucketindex *) pemalloc((Z_ARRVAL_P(array)->nNumOfElements + 1) * sizeof(struct bucketindex), Z_ARRVAL_P(array)->u.flags & HASH_FLAG_PERSISTENT);
    3345          43 :         if (!arTmp) {
    3346             :                 zval_dtor(return_value);
    3347           0 :                 RETURN_FALSE;
    3348             :         }
    3349       13609 :         for (i = 0, idx = 0; idx < Z_ARRVAL_P(array)->nNumUsed; idx++) {
    3350       13566 :                 p = Z_ARRVAL_P(array)->arData + idx;
    3351       27132 :                 if (Z_TYPE(p->val) == IS_UNDEF) continue;
    3352       27118 :                 if (Z_TYPE(p->val) == IS_INDIRECT && Z_TYPE_P(Z_INDIRECT(p->val)) == IS_UNDEF) continue;
    3353       13558 :                 arTmp[i].b = *p;
    3354       13558 :                 arTmp[i].i = i;
    3355       13558 :                 i++;
    3356             :         }
    3357          43 :         ZVAL_UNDEF(&arTmp[i].b.val);
    3358          43 :         zend_sort((void *) arTmp, i, sizeof(struct bucketindex),
    3359             :                         php_array_data_compare, (swap_func_t)array_bucketindex_swap);
    3360             :         /* go through the sorted array and delete duplicates from the copy */
    3361          43 :         lastkept = arTmp;
    3362       27116 :         for (cmpdata = arTmp + 1; Z_TYPE(cmpdata->b.val) != IS_UNDEF; cmpdata++) {
    3363       13515 :                 if (php_array_data_compare(lastkept, cmpdata)) {
    3364       13414 :                         lastkept = cmpdata;
    3365             :                 } else {
    3366         101 :                         if (lastkept->i > cmpdata->i) {
    3367          10 :                                 p = &lastkept->b;
    3368          10 :                                 lastkept = cmpdata;
    3369             :                         } else {
    3370          91 :                                 p = &cmpdata->b;
    3371             :                         }
    3372         101 :                         if (p->key == NULL) {
    3373          85 :                                 zend_hash_index_del(Z_ARRVAL_P(return_value), p->h);
    3374             :                         } else {
    3375          16 :                                 if (Z_ARRVAL_P(return_value) == &EG(symbol_table)) {
    3376           0 :                                         zend_delete_global_variable(p->key);
    3377             :                                 } else {
    3378          16 :                                         zend_hash_del(Z_ARRVAL_P(return_value), p->key);
    3379             :                                 }
    3380             :                         }
    3381             :                 }
    3382             :         }
    3383          43 :         pefree(arTmp, Z_ARRVAL_P(array)->u.flags & HASH_FLAG_PERSISTENT);
    3384             : }
    3385             : /* }}} */
    3386             : 
    3387        1106 : static int zval_compare(zval *first, zval *second) /* {{{ */
    3388             : {
    3389             :         zval result;
    3390             : 
    3391        1106 :         if (Z_TYPE_P(first) == IS_INDIRECT) {
    3392           2 :                 first = Z_INDIRECT_P(first);
    3393             :         }
    3394        1106 :         if (Z_TYPE_P(second) == IS_INDIRECT) {
    3395           2 :                 second = Z_INDIRECT_P(second);
    3396             :         }
    3397        1106 :         if (string_compare_function(&result, first, second) == FAILURE) {
    3398           0 :                 return 0;
    3399             :         }
    3400             : 
    3401        1106 :         if (Z_TYPE(result) == IS_DOUBLE) {
    3402           0 :                 return ZEND_NORMALIZE_BOOL(Z_DVAL(result));
    3403             :         }
    3404             : 
    3405        1106 :         convert_to_long(&result);
    3406        1106 :         return ZEND_NORMALIZE_BOOL(Z_LVAL(result));
    3407             : }
    3408             : /* }}} */
    3409             : 
    3410          44 : static int zval_user_compare(zval *a, zval *b) /* {{{ */
    3411             : {
    3412             :         zval args[2];
    3413             :         zval retval;
    3414             : 
    3415          44 :         if (Z_TYPE_P(a) == IS_INDIRECT) {
    3416           0 :                 a = Z_INDIRECT_P(a);
    3417             :         }
    3418          44 :         if (Z_TYPE_P(b) == IS_INDIRECT) {
    3419           0 :                 b = Z_INDIRECT_P(b);
    3420             :         }
    3421             : 
    3422          44 :         ZVAL_COPY_VALUE(&args[0], a);
    3423          44 :         ZVAL_COPY_VALUE(&args[1], b);
    3424             : 
    3425          44 :         BG(user_compare_fci).param_count = 2;
    3426          44 :         BG(user_compare_fci).params = args;
    3427          44 :         BG(user_compare_fci).retval = &retval;
    3428          44 :         BG(user_compare_fci).no_separation = 0;
    3429             : 
    3430          88 :         if (zend_call_function(&BG(user_compare_fci), &BG(user_compare_fci_cache)) == SUCCESS && Z_TYPE(retval) != IS_UNDEF) {
    3431          44 :                 zend_long ret = zval_get_long(&retval);
    3432          44 :                 zval_ptr_dtor(&retval);
    3433          44 :                 return ret < 0 ? -1 : ret > 0 ? 1 : 0;;
    3434             :         } else {
    3435           0 :                 return 0;
    3436             :         }
    3437             : }
    3438             : /* }}} */
    3439             : 
    3440         572 : static void php_array_intersect_key(INTERNAL_FUNCTION_PARAMETERS, int data_compare_type) /* {{{ */
    3441             : {
    3442             :     uint idx;
    3443             :         Bucket *p;
    3444             :         int argc, i;
    3445             :         zval *args;
    3446         572 :         int (*intersect_data_compare_func)(zval *, zval *) = NULL;
    3447             :         zend_bool ok;
    3448             :         zval *val, *data;
    3449             :         int req_args;
    3450             :         char *param_spec;
    3451             : 
    3452             :         /* Get the argument count */
    3453         572 :         argc = ZEND_NUM_ARGS();
    3454         572 :         if (data_compare_type == INTERSECT_COMP_DATA_USER) {
    3455             :                 /* INTERSECT_COMP_DATA_USER - array_uintersect_assoc() */
    3456         112 :                 req_args = 3;
    3457         112 :                 param_spec = "+f";
    3458         112 :                 intersect_data_compare_func = zval_user_compare;
    3459             :         } else {
    3460             :                 /*      INTERSECT_COMP_DATA_NONE - array_intersect_key()
    3461             :                         INTERSECT_COMP_DATA_INTERNAL - array_intersect_assoc() */
    3462         460 :                 req_args = 2;
    3463         460 :                 param_spec = "+";
    3464             : 
    3465         460 :                 if (data_compare_type == INTERSECT_COMP_DATA_INTERNAL) {
    3466         279 :                         intersect_data_compare_func = zval_compare;
    3467             :                 }
    3468             :         }
    3469             : 
    3470         572 :         if (argc < req_args) {
    3471           5 :                 php_error_docref(NULL, E_WARNING, "at least %d parameters are required, %d given", req_args, argc);
    3472           5 :                 return;
    3473             :         }
    3474             : 
    3475         567 :         if (zend_parse_parameters(ZEND_NUM_ARGS(), param_spec, &args, &argc, &BG(user_compare_fci), &BG(user_compare_fci_cache)) == FAILURE) {
    3476          30 :                 return;
    3477             :         }
    3478             : 
    3479        1332 :         for (i = 0; i < argc; i++) {
    3480        2192 :                 if (Z_TYPE(args[i]) != IS_ARRAY) {
    3481         301 :                         php_error_docref(NULL, E_WARNING, "Argument #%d is not an array", i + 1);
    3482         301 :                         RETURN_NULL();
    3483             :                 }
    3484             :         }
    3485             : 
    3486         236 :         array_init(return_value);
    3487             : 
    3488        2443 :         for (idx = 0; idx < Z_ARRVAL(args[0])->nNumUsed; idx++) {
    3489        2207 :                 p = Z_ARRVAL(args[0])->arData + idx;
    3490        2207 :                 val = &p->val;
    3491        2207 :                 if (Z_TYPE_P(val) == IS_UNDEF) continue;
    3492        2214 :                 if (Z_ISREF_P(val) && Z_REFCOUNT_P(val) == 1) {
    3493          12 :                         ZVAL_UNREF(val);
    3494             :                 }
    3495        2193 :                 if (p->key == NULL) {
    3496        1141 :                         ok = 1;
    3497        1345 :                         for (i = 1; i < argc; i++) {
    3498        1562 :                                 if ((data = zend_hash_index_find(Z_ARRVAL(args[i]), p->h)) == NULL ||
    3499             :                                         (intersect_data_compare_func &&
    3500         354 :                                         intersect_data_compare_func(val, data) != 0)
    3501             :                                 ) {
    3502        1004 :                                         ok = 0;
    3503        1004 :                                         break;
    3504             :                                 }
    3505             :                         }
    3506        1141 :                         if (ok) {
    3507         137 :                                 if (Z_REFCOUNTED_P(val)) {
    3508             :                                         Z_ADDREF_P(val);
    3509             :                                 }
    3510         137 :                                 zend_hash_index_update(Z_ARRVAL_P(return_value), p->h, val);
    3511             :                         }
    3512             :                 } else {
    3513        1052 :                         ok = 1;
    3514        1191 :                         for (i = 1; i < argc; i++) {
    3515        1245 :                                 if ((data = zend_hash_find(Z_ARRVAL(args[i]), p->key)) == NULL ||
    3516             :                                         (intersect_data_compare_func &&
    3517         153 :                                         intersect_data_compare_func(val, data) != 0)
    3518             :                                 ) {
    3519         953 :                                         ok = 0;
    3520         953 :                                         break;
    3521             :                                 }
    3522             :                         }
    3523        1052 :                         if (ok) {
    3524          99 :                                 if (Z_REFCOUNTED_P(val)) {
    3525             :                                         Z_ADDREF_P(val);
    3526             :                                 }
    3527          99 :                                 zend_hash_update(Z_ARRVAL_P(return_value), p->key, val);
    3528             :                         }
    3529             :                 }
    3530             :         }
    3531             : }
    3532             : /* }}} */
    3533             : 
    3534         965 : static void php_array_intersect(INTERNAL_FUNCTION_PARAMETERS, int behavior, int data_compare_type, int key_compare_type) /* {{{ */
    3535             : {
    3536         965 :         zval *args = NULL;
    3537             :         HashTable *hash;
    3538         965 :         int arr_argc, i, c = 0;
    3539             :         uint idx;
    3540             :         Bucket **lists, *list, **ptrs, *p;
    3541             :         uint32_t req_args;
    3542             :         char *param_spec;
    3543             :         zend_fcall_info fci1, fci2;
    3544         965 :         zend_fcall_info_cache fci1_cache = empty_fcall_info_cache, fci2_cache = empty_fcall_info_cache;
    3545         965 :         zend_fcall_info *fci_key = NULL, *fci_data;
    3546         965 :         zend_fcall_info_cache *fci_key_cache = NULL, *fci_data_cache;
    3547             :         PHP_ARRAY_CMP_FUNC_VARS;
    3548             : 
    3549             :         int (*intersect_key_compare_func)(const void *, const void *);
    3550             :         int (*intersect_data_compare_func)(const void *, const void *);
    3551             : 
    3552         965 :         if (behavior == INTERSECT_NORMAL) {
    3553         397 :                 intersect_key_compare_func = php_array_key_compare;
    3554             : 
    3555         397 :                 if (data_compare_type == INTERSECT_COMP_DATA_INTERNAL) {
    3556             :                         /* array_intersect() */
    3557         283 :                         req_args = 2;
    3558         283 :                         param_spec = "+";
    3559         283 :                         intersect_data_compare_func = php_array_data_compare;
    3560         114 :                 } else if (data_compare_type == INTERSECT_COMP_DATA_USER) {
    3561             :                         /* array_uintersect() */
    3562         114 :                         req_args = 3;
    3563         114 :                         param_spec = "+f";
    3564         114 :                         intersect_data_compare_func = php_array_user_compare;
    3565             :                 } else {
    3566           0 :                         php_error_docref(NULL, E_WARNING, "data_compare_type is %d. This should never happen. Please report as a bug", data_compare_type);
    3567           0 :                         return;
    3568             :                 }
    3569             : 
    3570         397 :                 if (ZEND_NUM_ARGS() < req_args) {
    3571           3 :                         php_error_docref(NULL, E_WARNING, "at least %d parameters are required, %d given", req_args, ZEND_NUM_ARGS());
    3572           3 :                         return;
    3573             :                 }
    3574             : 
    3575         394 :                 if (zend_parse_parameters(ZEND_NUM_ARGS(), param_spec, &args, &arr_argc, &fci1, &fci1_cache) == FAILURE) {
    3576          30 :                         return;
    3577             :                 }
    3578         364 :                 fci_data = &fci1;
    3579         364 :                 fci_data_cache = &fci1_cache;
    3580             : 
    3581         568 :         } else if (behavior & INTERSECT_ASSOC) { /* triggered also when INTERSECT_KEY */
    3582             :                 /* INTERSECT_KEY is subset of INTERSECT_ASSOC. When having the former
    3583             :                  * no comparison of the data is done (part of INTERSECT_ASSOC) */
    3584         568 :                 intersect_key_compare_func = php_array_key_compare;
    3585             : 
    3586         568 :                 if (data_compare_type == INTERSECT_COMP_DATA_INTERNAL && key_compare_type == INTERSECT_COMP_KEY_INTERNAL) {
    3587             :                         /* array_intersect_assoc() or array_intersect_key() */
    3588           0 :                         req_args = 2;
    3589           0 :                         param_spec = "+";
    3590           0 :                         intersect_key_compare_func = php_array_key_compare;
    3591           0 :                         intersect_data_compare_func = php_array_data_compare;
    3592         568 :                 } else if (data_compare_type == INTERSECT_COMP_DATA_USER && key_compare_type == INTERSECT_COMP_KEY_INTERNAL) {
    3593             :                         /* array_uintersect_assoc() */
    3594           0 :                         req_args = 3;
    3595           0 :                         param_spec = "+f";
    3596           0 :                         intersect_key_compare_func = php_array_key_compare;
    3597           0 :                         intersect_data_compare_func = php_array_user_compare;
    3598           0 :                         fci_data = &fci1;
    3599           0 :                         fci_data_cache = &fci1_cache;
    3600         995 :                 } else if (data_compare_type == INTERSECT_COMP_DATA_INTERNAL && key_compare_type == INTERSECT_COMP_KEY_USER) {
    3601             :                         /* array_intersect_uassoc() or array_intersect_ukey() */
    3602         427 :                         req_args = 3;
    3603         427 :                         param_spec = "+f";
    3604         427 :                         intersect_key_compare_func = php_array_user_key_compare;
    3605         427 :                         intersect_data_compare_func = php_array_data_compare;
    3606         427 :                         fci_key = &fci1;
    3607         427 :                         fci_key_cache = &fci1_cache;
    3608         282 :                 } else if (data_compare_type == INTERSECT_COMP_DATA_USER && key_compare_type == INTERSECT_COMP_KEY_USER) {
    3609             :                         /* array_uintersect_uassoc() */
    3610         141 :                         req_args = 4;
    3611         141 :                         param_spec = "+ff";
    3612         141 :                         intersect_key_compare_func = php_array_user_key_compare;
    3613         141 :                         intersect_data_compare_func = php_array_user_compare;
    3614         141 :                         fci_data = &fci1;
    3615         141 :                         fci_data_cache = &fci1_cache;
    3616         141 :                         fci_key = &fci2;
    3617         141 :                         fci_key_cache = &fci2_cache;
    3618             :                 } else {
    3619           0 :                         php_error_docref(NULL, E_WARNING, "data_compare_type is %d. key_compare_type is %d. This should never happen. Please report as a bug", data_compare_type, key_compare_type);
    3620           0 :                         return;
    3621             :                 }
    3622             : 
    3623         568 :                 if (ZEND_NUM_ARGS() < req_args) {
    3624           5 :                         php_error_docref(NULL, E_WARNING, "at least %d parameters are required, %d given", req_args, ZEND_NUM_ARGS());
    3625           5 :                         return;
    3626             :                 }
    3627             : 
    3628         563 :                 if (zend_parse_parameters(ZEND_NUM_ARGS(), param_spec, &args, &arr_argc, &fci1, &fci1_cache, &fci2, &fci2_cache) == FAILURE) {
    3629         160 :                         return;
    3630             :                 }
    3631             : 
    3632             :         } else {
    3633           0 :                 php_error_docref(NULL, E_WARNING, "behavior is %d. This should never happen. Please report as a bug", behavior);
    3634           0 :                 return;
    3635             :         }
    3636             : 
    3637         767 :         PHP_ARRAY_CMP_FUNC_BACKUP();
    3638             : 
    3639             :         /* for each argument, create and sort list with pointers to the hash buckets */
    3640         767 :         lists = (Bucket **)safe_emalloc(arr_argc, sizeof(Bucket *), 0);
    3641         767 :         ptrs = (Bucket **)safe_emalloc(arr_argc, sizeof(Bucket *), 0);
    3642         767 :         php_set_compare_func(PHP_SORT_STRING);
    3643             : 
    3644         850 :         if (behavior == INTERSECT_NORMAL && data_compare_type == INTERSECT_COMP_DATA_USER) {
    3645          83 :                 BG(user_compare_fci) = *fci_data;
    3646          83 :                 BG(user_compare_fci_cache) = *fci_data_cache;
    3647         684 :         } else if (behavior & INTERSECT_ASSOC && key_compare_type == INTERSECT_COMP_KEY_USER) {
    3648         403 :                 BG(user_compare_fci) = *fci_key;
    3649         403 :                 BG(user_compare_fci_cache) = *fci_key_cache;
    3650             :         }
    3651             : 
    3652        1795 :         for (i = 0; i < arr_argc; i++) {
    3653        3120 :                 if (Z_TYPE(args[i]) != IS_ARRAY) {
    3654         532 :                         php_error_docref(NULL, E_WARNING, "Argument #%d is not an array", i + 1);
    3655         532 :                         arr_argc = i; /* only free up to i - 1 */
    3656         532 :                         goto out;
    3657             :                 }
    3658        1028 :                 hash = Z_ARRVAL(args[i]);
    3659        2056 :                 list = (Bucket *) pemalloc((hash->nNumOfElements + 1) * sizeof(Bucket), hash->u.flags & HASH_FLAG_PERSISTENT);
    3660        1028 :                 if (!list) {
    3661           0 :                         PHP_ARRAY_CMP_FUNC_RESTORE();
    3662             : 
    3663           0 :                         efree(ptrs);
    3664           0 :                         efree(lists);
    3665           0 :                         RETURN_FALSE;
    3666             :                 }
    3667        1028 :                 lists[i] = list;
    3668        1028 :                 ptrs[i] = list;
    3669        6593 :                 for (idx = 0; idx < hash->nNumUsed; idx++) {
    3670        5565 :                         p = hash->arData + idx;
    3671       11130 :                         if (Z_TYPE(p->val) == IS_UNDEF) continue;
    3672        5530 :                         *list++ = *p;
    3673             :                 }
    3674        1028 :                 ZVAL_UNDEF(&list->val);
    3675        1028 :                 if (hash->nNumOfElements > 1) {
    3676         967 :                         if (behavior == INTERSECT_NORMAL) {
    3677         546 :                                 zend_sort((void *) lists[i], hash->nNumOfElements, 
    3678             :                                                 sizeof(Bucket), intersect_data_compare_func, (swap_func_t)zend_hash_bucket_swap);
    3679         421 :                         } else if (behavior & INTERSECT_ASSOC) { /* triggered also when INTERSECT_KEY */
    3680         421 :                                 zend_sort((void *) lists[i], hash->nNumOfElements,
    3681             :                                                 sizeof(Bucket), intersect_key_compare_func, (swap_func_t)zend_hash_bucket_swap);
    3682             :                         }
    3683             :                 }
    3684             :         }
    3685             : 
    3686             :         /* copy the argument array */
    3687         235 :         RETVAL_ARR(zend_array_dup(Z_ARRVAL(args[0])));
    3688             : 
    3689             :         /* go through the lists and look for common values */
    3690        1741 :         while (Z_TYPE(ptrs[0]->val) != IS_UNDEF) {
    3691         747 :                 if ((behavior & INTERSECT_ASSOC) /* triggered also when INTERSECT_KEY */
    3692             :                         && key_compare_type == INTERSECT_COMP_KEY_USER) {
    3693         148 :                         BG(user_compare_fci) = *fci_key;
    3694         148 :                         BG(user_compare_fci_cache) = *fci_key_cache;
    3695             :                 }
    3696             : 
    3697        1250 :                 for (i = 1; i < arr_argc; i++) {
    3698         906 :                         if (behavior & INTERSECT_NORMAL) {
    3699        3974 :                                 while (Z_TYPE(ptrs[i]->val) != IS_UNDEF && (0 < (c = intersect_data_compare_func(ptrs[0], ptrs[i])))) {
    3700         874 :                                         ptrs[i]++;
    3701             :                                 }
    3702         164 :                         } else if (behavior & INTERSECT_ASSOC) { /* triggered also when INTERSECT_KEY */
    3703         640 :                                 while (Z_TYPE(ptrs[i]->val) != IS_UNDEF && (0 < (c = intersect_key_compare_func(ptrs[0], ptrs[i])))) {
    3704          74 :                                         ptrs[i]++;
    3705             :                                 }
    3706         266 :                                 if ((!c && Z_TYPE(ptrs[i]->val) != IS_UNDEF) && (behavior == INTERSECT_ASSOC)) { /* only when INTERSECT_ASSOC */
    3707             :                                         /* this means that ptrs[i] is not NULL so we can compare
    3708             :                                          * and "c==0" is from last operation
    3709             :                                          * in this branch of code we enter only when INTERSECT_ASSOC
    3710             :                                          * since when we have INTERSECT_KEY compare of data is not wanted. */
    3711          40 :                                         if (data_compare_type == INTERSECT_COMP_DATA_USER) {
    3712          12 :                                                 BG(user_compare_fci) = *fci_data;
    3713          12 :                                                 BG(user_compare_fci_cache) = *fci_data_cache;
    3714             :                                         }
    3715          40 :                                         if (intersect_data_compare_func(ptrs[0], ptrs[i]) != 0) {
    3716          19 :                                                 c = 1;
    3717          19 :                                                 if (key_compare_type == INTERSECT_COMP_KEY_USER) {
    3718          19 :                                                         BG(user_compare_fci) = *fci_key;
    3719          19 :                                                         BG(user_compare_fci_cache) = *fci_key_cache;
    3720             :                                                         /* When KEY_USER, the last parameter is always the callback */
    3721             :                                                 }
    3722             :                                                 /* we are going to the break */
    3723             :                                         } else {
    3724             :                                                 /* continue looping */
    3725             :                                         }
    3726             :                                 }
    3727             :                         }
    3728        1812 :                         if (Z_TYPE(ptrs[i]->val) == IS_UNDEF) {
    3729             :                                 /* delete any values corresponding to remains of ptrs[0] */
    3730             :                                 /* and exit because they do not present in at least one of */
    3731             :                                 /* the other arguments */
    3732             :                                 for (;;) {
    3733         698 :                                         p = ptrs[0]++;
    3734        1396 :                                         if (Z_TYPE(p->val) == IS_UNDEF) {
    3735         109 :                                                 goto out;
    3736             :                                         }
    3737         589 :                                         if (p->key == NULL) {
    3738         522 :                                                 zend_hash_index_del(Z_ARRVAL_P(return_value), p->h);
    3739             :                                         } else {
    3740          67 :                                                 zend_hash_del(Z_ARRVAL_P(return_value), p->key);
    3741             :                                         }
    3742         589 :                                 }
    3743             :                         }
    3744         797 :                         if (c) /* here we get if not all are equal */
    3745         294 :                                 break;
    3746         503 :                         ptrs[i]++;
    3747             :                 }
    3748         638 :                 if (c) {
    3749             :                         /* Value of ptrs[0] not in all arguments, delete all entries */
    3750             :                         /* with value < value of ptrs[i] */
    3751             :                         for (;;) {
    3752         678 :                                 p = ptrs[0];
    3753         678 :                                 if (p->key == NULL) {
    3754         564 :                                         zend_hash_index_del(Z_ARRVAL_P(return_value), p->h);
    3755             :                                 } else {
    3756         114 :                                         zend_hash_del(Z_ARRVAL_P(return_value), p->key);
    3757             :                                 }
    3758        1356 :                                 if (Z_TYPE((++ptrs[0])->val) == IS_UNDEF) {
    3759          54 :                                         goto out;
    3760             :                                 }
    3761         624 :                                 if (behavior == INTERSECT_NORMAL) {
    3762         567 :                                         if (0 <= intersect_data_compare_func(ptrs[0], ptrs[i])) {
    3763         183 :                                                 break;
    3764             :                                         }
    3765          57 :                                 } else if (behavior & INTERSECT_ASSOC) { /* triggered also when INTERSECT_KEY */
    3766             :                                         /* no need of looping because indexes are unique */
    3767          57 :                                         break;
    3768             :                                 }
    3769         384 :                         }
    3770             :                 } else {
    3771             :                         /* ptrs[0] is present in all the arguments */
    3772             :                         /* Skip all entries with same value as ptrs[0] */
    3773             :                         for (;;) {
    3774         804 :                                 if (Z_TYPE((++ptrs[0])->val) == IS_UNDEF) {
    3775          66 :                                         goto out;
    3776             :                                 }
    3777         336 :                                 if (behavior == INTERSECT_NORMAL) {
    3778         287 :                                         if (intersect_data_compare_func(ptrs[0] - 1, ptrs[0])) {
    3779         229 :                                                 break;
    3780             :                                         }
    3781          49 :                                 } else if (behavior & INTERSECT_ASSOC) { /* triggered also when INTERSECT_KEY */
    3782             :                                         /* no need of looping because indexes are unique */
    3783          49 :                                         break;
    3784             :                                 }
    3785          58 :                         }
    3786             :                 }
    3787             :         }
    3788             : out:
    3789        1795 :         for (i = 0; i < arr_argc; i++) {
    3790        1028 :                 hash = Z_ARRVAL(args[i]);
    3791        1028 :                 pefree(lists[i], hash->u.flags & HASH_FLAG_PERSISTENT);
    3792             :         }
    3793             : 
    3794         767 :         PHP_ARRAY_CMP_FUNC_RESTORE();
    3795             : 
    3796         767 :         efree(ptrs);
    3797         767 :         efree(lists);
    3798             : }
    3799             : /* }}} */
    3800             : 
    3801             : /* {{{ proto array array_intersect_key(array arr1, array arr2 [, array ...])
    3802             :    Returns the entries of arr1 that have keys which are present in all the other arguments. Kind of equivalent to array_diff(array_keys($arr1), array_keys($arr2)[,array_keys(...)]). Equivalent of array_intersect_assoc() but does not do compare of the data. */
    3803         181 : PHP_FUNCTION(array_intersect_key)
    3804             : {
    3805         181 :         php_array_intersect_key(INTERNAL_FUNCTION_PARAM_PASSTHRU, INTERSECT_COMP_DATA_NONE);
    3806         181 : }
    3807             : /* }}} */
    3808             : 
    3809             : /* {{{ proto array array_intersect_ukey(array arr1, array arr2 [, array ...], callback key_compare_func)
    3810             :    Returns the entries of arr1 that have keys which are present in all the other arguments. Kind of equivalent to array_diff(array_keys($arr1), array_keys($arr2)[,array_keys(...)]). The comparison of the keys is performed by a user supplied function. Equivalent of array_intersect_uassoc() but does not do compare of the data. */
    3811         233 : PHP_FUNCTION(array_intersect_ukey)
    3812             : {
    3813         233 :         php_array_intersect(INTERNAL_FUNCTION_PARAM_PASSTHRU, INTERSECT_KEY, INTERSECT_COMP_DATA_INTERNAL, INTERSECT_COMP_KEY_USER);
    3814         233 : }
    3815             : /* }}} */
    3816             : 
    3817             : /* {{{ proto array array_intersect(array arr1, array arr2 [, array ...])
    3818             :    Returns the entries of arr1 that have values which are present in all the other arguments */
    3819         283 : PHP_FUNCTION(array_intersect)
    3820             : {
    3821         283 :         php_array_intersect(INTERNAL_FUNCTION_PARAM_PASSTHRU, INTERSECT_NORMAL, INTERSECT_COMP_DATA_INTERNAL, INTERSECT_COMP_KEY_INTERNAL);
    3822         283 : }
    3823             : /* }}} */
    3824             : 
    3825             : /* {{{ proto array array_uintersect(array arr1, array arr2 [, array ...], callback data_compare_func)
    3826             :    Returns the entries of arr1 that have values which are present in all the other arguments. Data is compared by using a user-supplied callback. */
    3827         114 : PHP_FUNCTION(array_uintersect)
    3828             : {
    3829         114 :         php_array_intersect(INTERNAL_FUNCTION_PARAM_PASSTHRU, INTERSECT_NORMAL, INTERSECT_COMP_DATA_USER, INTERSECT_COMP_KEY_INTERNAL);
    3830         114 : }
    3831             : /* }}} */
    3832             : 
    3833             : /* {{{ proto array array_intersect_assoc(array arr1, array arr2 [, array ...])
    3834             :    Returns the entries of arr1 that have values which are present in all the other arguments. Keys are used to do more restrictive check */
    3835         279 : PHP_FUNCTION(array_intersect_assoc)
    3836             : {
    3837         279 :         php_array_intersect_key(INTERNAL_FUNCTION_PARAM_PASSTHRU, INTERSECT_COMP_DATA_INTERNAL);
    3838         279 : }
    3839             : /* }}} */
    3840             : 
    3841             : /* {{{ proto array array_intersect_uassoc(array arr1, array arr2 [, array ...], callback key_compare_func) U
    3842             :    Returns the entries of arr1 that have values which are present in all the other arguments. Keys are used to do more restrictive check and they are compared by using a user-supplied callback. */
    3843         194 : PHP_FUNCTION(array_intersect_uassoc)
    3844             : {
    3845         194 :         php_array_intersect(INTERNAL_FUNCTION_PARAM_PASSTHRU, INTERSECT_ASSOC, INTERSECT_COMP_DATA_INTERNAL, INTERSECT_COMP_KEY_USER);
    3846         194 : }
    3847             : /* }}} */
    3848             : 
    3849             : /* {{{ proto array array_uintersect_assoc(array arr1, array arr2 [, array ...], callback data_compare_func) U
    3850             :    Returns the entries of arr1 that have values which are present in all the other arguments. Keys are used to do more restrictive check. Data is compared by using a user-supplied callback. */
    3851         112 : PHP_FUNCTION(array_uintersect_assoc)
    3852             : {
    3853         112 :         php_array_intersect_key(INTERNAL_FUNCTION_PARAM_PASSTHRU, INTERSECT_COMP_DATA_USER);
    3854         112 : }
    3855             : /* }}} */
    3856             : 
    3857             : /* {{{ proto array array_uintersect_uassoc(array arr1, array arr2 [, array ...], callback data_compare_func, callback key_compare_func)
    3858             :    Returns the entries of arr1 that have values which are present in all the other arguments. Keys are used to do more restrictive check. Both data and keys are compared by using user-supplied callbacks. */
    3859         141 : PHP_FUNCTION(array_uintersect_uassoc)
    3860             : {
    3861         141 :         php_array_intersect(INTERNAL_FUNCTION_PARAM_PASSTHRU, INTERSECT_ASSOC, INTERSECT_COMP_DATA_USER, INTERSECT_COMP_KEY_USER);
    3862         141 : }
    3863             : /* }}} */
    3864             : 
    3865         420 : static void php_array_diff_key(INTERNAL_FUNCTION_PARAMETERS, int data_compare_type) /* {{{ */
    3866             : {
    3867             :     uint idx;
    3868             :         Bucket *p;
    3869             :         int argc, i;
    3870             :         zval *args;
    3871         420 :         int (*diff_data_compare_func)(zval *, zval *) = NULL;
    3872             :         zend_bool ok;
    3873             :         zval *val, *data;
    3874             : 
    3875             :         /* Get the argument count */
    3876         420 :         argc = ZEND_NUM_ARGS();
    3877         420 :         if (data_compare_type == DIFF_COMP_DATA_USER) {
    3878         114 :                 if (argc < 3) {
    3879           1 :                         php_error_docref(NULL, E_WARNING, "at least 3 parameters are required, %d given", ZEND_NUM_ARGS());
    3880           1 :                         return;
    3881             :                 }
    3882         113 :                 if (zend_parse_parameters(ZEND_NUM_ARGS(), "+f", &args, &argc, &BG(user_compare_fci), &BG(user_compare_fci_cache)) == FAILURE) {
    3883          30 :                         return;
    3884             :                 }
    3885          83 :                 diff_data_compare_func = zval_user_compare;
    3886             :         } else {
    3887         306 :                 if (argc < 2) {
    3888           4 :                         php_error_docref(NULL, E_WARNING, "at least 2 parameters are required, %d given", ZEND_NUM_ARGS());
    3889           4 :                         return;
    3890             :                 }
    3891         302 :                 if (zend_parse_parameters(ZEND_NUM_ARGS(), "+", &args, &argc) == FAILURE) {
    3892           0 :                         return;
    3893             :                 }
    3894         302 :                 if (data_compare_type == DIFF_COMP_DATA_INTERNAL) {
    3895         140 :                         diff_data_compare_func = zval_compare;
    3896             :                 }
    3897             :         }
    3898             : 
    3899         859 :         for (i = 0; i < argc; i++) {
    3900        1462 :                 if (Z_TYPE(args[i]) != IS_ARRAY) {
    3901         257 :                         php_error_docref(NULL, E_WARNING, "Argument #%d is not an array", i + 1);
    3902         257 :                         RETURN_NULL();
    3903             :                 }
    3904             :         }
    3905             : 
    3906         128 :         array_init(return_value);
    3907             : 
    3908         995 :         for (idx = 0; idx < Z_ARRVAL(args[0])->nNumUsed; idx++) {
    3909         867 :                 p = Z_ARRVAL(args[0])->arData + idx;
    3910         867 :                 val = &p->val;
    3911         867 :                 if (Z_TYPE_P(val) == IS_UNDEF) continue;
    3912         886 :                 if (Z_ISREF_P(val) && Z_REFCOUNT_P(val) == 1) {
    3913          12 :                         ZVAL_UNREF(val);
    3914             :                 }
    3915         863 :                 if (p->key == NULL) {
    3916         740 :                         ok = 1;
    3917        1364 :                         for (i = 1; i < argc; i++) {
    3918        1375 :                                 if ((data = zend_hash_index_find(Z_ARRVAL(args[i]), p->h)) != NULL &&
    3919             :                                         (!diff_data_compare_func ||
    3920         601 :                                         diff_data_compare_func(val, data) == 0)
    3921             :                                 ) {
    3922         150 :                                         ok = 0;
    3923         150 :                                         break;
    3924             :                                 }
    3925             :                         }
    3926         740 :                         if (ok) {
    3927         590 :                                 if (Z_REFCOUNTED_P(val)) {
    3928             :                                         Z_ADDREF_P(val);
    3929             :                                 }
    3930         590 :                                 zend_hash_index_update(Z_ARRVAL_P(return_value), p->h, val);
    3931             :                         }
    3932             :                 } else {
    3933         123 :                         ok = 1;
    3934         212 :                         for (i = 1; i < argc; i++) {
    3935         179 :                                 if ((data = zend_hash_find(Z_ARRVAL(args[i]), p->key)) != NULL &&
    3936             :                                         (!diff_data_compare_func ||
    3937          42 :                                         diff_data_compare_func(val, data) == 0)
    3938             :                                 ) {
    3939          48 :                                         ok = 0;
    3940          48 :                                         break;
    3941             :                                 }
    3942             :                         }
    3943         123 :                         if (ok) {
    3944          75 :                                 if (Z_REFCOUNTED_P(val)) {
    3945             :                                         Z_ADDREF_P(val);
    3946             :                                 }
    3947          75 :                                 zend_hash_update(Z_ARRVAL_P(return_value), p->key, val);
    3948             :                         }
    3949             :                 }
    3950             :         }
    3951             : }
    3952             : /* }}} */
    3953             : 
    3954         608 : static void php_array_diff(INTERNAL_FUNCTION_PARAMETERS, int behavior, int data_compare_type, int key_compare_type) /* {{{ */
    3955             : {
    3956         608 :         zval *args = NULL;
    3957             :         HashTable *hash;
    3958             :         int arr_argc, i, c;
    3959             :         uint idx;
    3960             :         Bucket **lists, *list, **ptrs, *p;
    3961             :         uint32_t req_args;
    3962             :         char *param_spec;
    3963             :         zend_fcall_info fci1, fci2;
    3964         608 :         zend_fcall_info_cache fci1_cache = empty_fcall_info_cache, fci2_cache = empty_fcall_info_cache;
    3965         608 :         zend_fcall_info *fci_key = NULL, *fci_data;
    3966         608 :         zend_fcall_info_cache *fci_key_cache = NULL, *fci_data_cache;
    3967             :         PHP_ARRAY_CMP_FUNC_VARS;
    3968             : 
    3969             :         int (*diff_key_compare_func)(const void *, const void *);
    3970             :         int (*diff_data_compare_func)(const void *, const void *);
    3971             : 
    3972         608 :         if (behavior == DIFF_NORMAL) {
    3973         112 :                 diff_key_compare_func = php_array_key_compare;
    3974             : 
    3975         112 :                 if (data_compare_type == DIFF_COMP_DATA_INTERNAL) {
    3976             :                         /* array_diff */
    3977           0 :                         req_args = 2;
    3978           0 :                         param_spec = "+";
    3979           0 :                         diff_data_compare_func = php_array_data_compare;
    3980         112 :                 } else if (data_compare_type == DIFF_COMP_DATA_USER) {
    3981             :                         /* array_udiff */
    3982         112 :                         req_args = 3;
    3983         112 :                         param_spec = "+f";
    3984         112 :                         diff_data_compare_func = php_array_user_compare;
    3985             :                 } else {
    3986           0 :                         php_error_docref(NULL, E_WARNING, "data_compare_type is %d. This should never happen. Please report as a bug", data_compare_type);
    3987           0 :                         return;
    3988             :                 }
    3989             : 
    3990         112 :                 if (ZEND_NUM_ARGS() < req_args) {
    3991           1 :                         php_error_docref(NULL, E_WARNING, "at least %d parameters are required, %d given", req_args, ZEND_NUM_ARGS());
    3992           1 :                         return;
    3993             :                 }
    3994             : 
    3995         111 :                 if (zend_parse_parameters(ZEND_NUM_ARGS(), param_spec, &args, &arr_argc, &fci1, &fci1_cache) == FAILURE) {
    3996          30 :                         return;
    3997             :                 }
    3998          81 :                 fci_data = &fci1;
    3999          81 :                 fci_data_cache = &fci1_cache;
    4000             : 
    4001         496 :         } else if (behavior & DIFF_ASSOC) { /* triggered also if DIFF_KEY */
    4002             :                 /* DIFF_KEY is subset of DIFF_ASSOC. When having the former
    4003             :                  * no comparison of the data is done (part of DIFF_ASSOC) */
    4004             : 
    4005         496 :                 if (data_compare_type == DIFF_COMP_DATA_INTERNAL && key_compare_type == DIFF_COMP_KEY_INTERNAL) {
    4006             :                         /* array_diff_assoc() or array_diff_key() */
    4007           0 :                         req_args = 2;
    4008           0 :                         param_spec = "+";
    4009           0 :                         diff_key_compare_func = php_array_key_compare;
    4010           0 :                         diff_data_compare_func = php_array_data_compare;
    4011         496 :                 } else if (data_compare_type == DIFF_COMP_DATA_USER && key_compare_type == DIFF_COMP_KEY_INTERNAL) {
    4012             :                         /* array_udiff_assoc() */
    4013           0 :                         req_args = 3;
    4014           0 :                         param_spec = "+f";
    4015           0 :                         diff_key_compare_func = php_array_key_compare;
    4016           0 :                         diff_data_compare_func = php_array_user_compare;
    4017           0 :                         fci_data = &fci1;
    4018           0 :                         fci_data_cache = &fci1_cache;
    4019         851 :                 } else if (data_compare_type == DIFF_COMP_DATA_INTERNAL && key_compare_type == DIFF_COMP_KEY_USER) {
    4020             :                         /* array_diff_uassoc() or array_diff_ukey() */
    4021         355 :                         req_args = 3;
    4022         355 :                         param_spec = "+f";
    4023         355 :                         diff_key_compare_func = php_array_user_key_compare;
    4024         355 :                         diff_data_compare_func = php_array_data_compare;
    4025         355 :                         fci_key = &fci1;
    4026         355 :                         fci_key_cache = &fci1_cache;
    4027         282 :                 } else if (data_compare_type == DIFF_COMP_DATA_USER && key_compare_type == DIFF_COMP_KEY_USER) {
    4028             :                         /* array_udiff_uassoc() */
    4029         141 :                         req_args = 4;
    4030         141 :                         param_spec = "+ff";
    4031         141 :                         diff_key_compare_func = php_array_user_key_compare;
    4032         141 :                         diff_data_compare_func = php_array_user_compare;
    4033         141 :                         fci_data = &fci1;
    4034         141 :                         fci_data_cache = &fci1_cache;
    4035         141 :                         fci_key = &fci2;
    4036         141 :                         fci_key_cache = &fci2_cache;
    4037             :                 } else {
    4038           0 :                         php_error_docref(NULL, E_WARNING, "data_compare_type is %d. key_compare_type is %d. This should never happen. Please report as a bug", data_compare_type, key_compare_type);
    4039           0 :                         return;
    4040             :                 }
    4041             : 
    4042         496 :                 if (ZEND_NUM_ARGS() < req_args) {
    4043           5 :                         php_error_docref(NULL, E_WARNING, "at least %d parameters are required, %d given", req_args, ZEND_NUM_ARGS());
    4044           5 :                         return;
    4045             :                 }
    4046             : 
    4047         491 :                 if (zend_parse_parameters(ZEND_NUM_ARGS(), param_spec, &args, &arr_argc, &fci1, &fci1_cache, &fci2, &fci2_cache) == FAILURE) {
    4048         138 :                         return;
    4049             :                 }
    4050             : 
    4051             :         } else {
    4052           0 :                 php_error_docref(NULL, E_WARNING, "behavior is %d. This should never happen. Please report as a bug", behavior);
    4053           0 :                 return;
    4054             :         }
    4055             : 
    4056         434 :         PHP_ARRAY_CMP_FUNC_BACKUP();
    4057             : 
    4058             :         /* for each argument, create and sort list with pointers to the hash buckets */
    4059         434 :         lists = (Bucket **)safe_emalloc(arr_argc, sizeof(Bucket *), 0);
    4060         434 :         ptrs = (Bucket **)safe_emalloc(arr_argc, sizeof(Bucket *), 0);
    4061         434 :         php_set_compare_func(PHP_SORT_STRING);
    4062             : 
    4063         515 :         if (behavior == DIFF_NORMAL && data_compare_type == DIFF_COMP_DATA_USER) {
    4064          81 :                 BG(user_compare_fci) = *fci_data;
    4065          81 :                 BG(user_compare_fci_cache) = *fci_data_cache;
    4066         353 :         } else if (behavior & DIFF_ASSOC && key_compare_type == DIFF_COMP_KEY_USER) {
    4067         353 :                 BG(user_compare_fci) = *fci_key;
    4068         353 :                 BG(user_compare_fci_cache) = *fci_key_cache;
    4069             :         }
    4070             : 
    4071         923 :         for (i = 0; i < arr_argc; i++) {
    4072        1694 :                 if (Z_TYPE(args[i]) != IS_ARRAY) {
    4073         358 :                         php_error_docref(NULL, E_WARNING, "Argument #%d is not an array", i + 1);
    4074         358 :                         arr_argc = i; /* only free up to i - 1 */
    4075         358 :                         goto out;
    4076             :                 }
    4077         489 :                 hash = Z_ARRVAL(args[i]);
    4078         978 :                 list = (Bucket *) pemalloc((hash->nNumOfElements + 1) * sizeof(Bucket), hash->u.flags & HASH_FLAG_PERSISTENT);
    4079         489 :                 if (!list) {
    4080           0 :                         PHP_ARRAY_CMP_FUNC_RESTORE();
    4081             : 
    4082           0 :                         efree(ptrs);
    4083           0 :                         efree(lists);
    4084           0 :                         RETURN_FALSE;
    4085             :                 }
    4086         489 :                 lists[i] = list;
    4087         489 :                 ptrs[i] = list;
    4088        1981 :                 for (idx = 0; idx < hash->nNumUsed; idx++) {
    4089        1492 :                         p = hash->arData + idx;
    4090        2984 :                         if (Z_TYPE(p->val) == IS_UNDEF) continue;
    4091        1492 :                         *list++ = *p;
    4092             :                 }
    4093         489 :                 ZVAL_UNDEF(&list->val);
    4094         489 :                 if (hash->nNumOfElements > 1) {
    4095         465 :                         if (behavior == DIFF_NORMAL) {
    4096          81 :                                 zend_sort((void *) lists[i], hash->nNumOfElements,
    4097             :                                                 sizeof(Bucket), diff_data_compare_func, (swap_func_t)zend_hash_bucket_swap);
    4098         384 :                         } else if (behavior & DIFF_ASSOC) { /* triggered also when DIFF_KEY */
    4099         384 :                                 zend_sort((void *) lists[i], hash->nNumOfElements,
    4100             :                                                 sizeof(Bucket), diff_key_compare_func, (swap_func_t)zend_hash_bucket_swap);
    4101             :                         }
    4102             :                 }
    4103             :         }
    4104             : 
    4105             :         /* copy the argument array */
    4106          76 :         RETVAL_ARR(zend_array_dup(Z_ARRVAL(args[0])));
    4107             : 
    4108             :         /* go through the lists and look for values of ptr[0] that are not in the others */
    4109         532 :         while (Z_TYPE(ptrs[0]->val) != IS_UNDEF) {
    4110         228 :                 if ((behavior & DIFF_ASSOC) /* triggered also when DIFF_KEY */
    4111             :                         &&
    4112             :                         key_compare_type == DIFF_COMP_KEY_USER
    4113             :                 ) {
    4114         212 :                         BG(user_compare_fci) = *fci_key;
    4115         212 :                         BG(user_compare_fci_cache) = *fci_key_cache;
    4116             :                 }
    4117         228 :                 c = 1;
    4118         365 :                 for (i = 1; i < arr_argc; i++) {
    4119         246 :                         Bucket *ptr = ptrs[i];
    4120         246 :                         if (behavior == DIFF_NORMAL) {
    4121          58 :                                 while (Z_TYPE(ptrs[i]->val) != IS_UNDEF && (0 < (c = diff_data_compare_func(ptrs[0], ptrs[i])))) {
    4122           5 :                                         ptrs[i]++;
    4123             :                                 }
    4124         230 :                         } else if (behavior & DIFF_ASSOC) { /* triggered also when DIFF_KEY */
    4125        1938 :                                 while (Z_TYPE(ptr->val) != IS_UNDEF && (0 != (c = diff_key_compare_func(ptrs[0], ptr)))) {
    4126         624 :                                         ptr++;
    4127             :                                 }
    4128             :                         }
    4129         246 :                         if (!c) {
    4130         134 :                                 if (behavior == DIFF_NORMAL) {
    4131          20 :                                         if (Z_TYPE(ptrs[i]->val) != IS_UNDEF) {
    4132          10 :                                                 ptrs[i]++;
    4133             :                                         }
    4134          10 :                                         break;
    4135         124 :                                 } else if (behavior == DIFF_ASSOC) {  /* only when DIFF_ASSOC */
    4136             :                                         /* In this branch is execute only when DIFF_ASSOC. If behavior == DIFF_KEY
    4137             :                                          * data comparison is not needed - skipped. */
    4138         140 :                                         if (Z_TYPE(ptr->val) != IS_UNDEF) {
    4139          70 :                                                 if (data_compare_type == DIFF_COMP_DATA_USER) {
    4140          12 :                                                         BG(user_compare_fci) = *fci_data;
    4141          12 :                                                         BG(user_compare_fci_cache) = *fci_data_cache;
    4142             :                                                 }
    4143          70 :                                                 if (diff_data_compare_func(ptrs[0], ptr) != 0) {
    4144             :                                                         /* the data is not the same */
    4145          25 :                                                         c = -1;
    4146          25 :                                                         if (key_compare_type == DIFF_COMP_KEY_USER) {
    4147          25 :                                                                 BG(user_compare_fci) = *fci_key;
    4148          25 :                                                                 BG(user_compare_fci_cache) = *fci_key_cache;
    4149             :                                                         }
    4150             :                                                 } else {
    4151          45 :                                                         break;
    4152             :                                                         /* we have found the element in other arrays thus we don't want it
    4153             :                                                          * in the return_value -> delete from there */
    4154             :                                                 }
    4155             :                                         }
    4156          54 :                                 } else if (behavior == DIFF_KEY) { /* only when DIFF_KEY */
    4157             :                                         /* the behavior here differs from INTERSECT_KEY in php_intersect
    4158             :                                          * since in the "diff" case we have to remove the entry from
    4159             :                                          * return_value while when doing intersection the entry must not
    4160             :                                          * be deleted. */
    4161          54 :                                         break; /* remove the key */
    4162             :                                 }
    4163             :                         }
    4164             :                 }
    4165         228 :                 if (!c) {
    4166             :                         /* ptrs[0] in one of the other arguments */
    4167             :                         /* delete all entries with value as ptrs[0] */
    4168             :                         for (;;) {
    4169         109 :                                 p = ptrs[0];
    4170         109 :                                 if (p->key == NULL) {
    4171          85 :                                         zend_hash_index_del(Z_ARRVAL_P(return_value), p->h);
    4172             :                                 } else {
    4173          24 :                                         zend_hash_del(Z_ARRVAL_P(return_value), p->key);
    4174             :                                 }
    4175         218 :                                 if (Z_TYPE((++ptrs[0])->val) == IS_UNDEF) {
    4176          30 :                                         goto out;
    4177             :                                 }
    4178          79 :                                 if (behavior == DIFF_NORMAL) {
    4179           7 :                                         if (diff_data_compare_func(ptrs[0] - 1, ptrs[0])) {
    4180           7 :                                                 break;
    4181             :                                         }
    4182          72 :                                 } else if (behavior & DIFF_ASSOC) { /* triggered also when DIFF_KEY */
    4183             :                                         /* in this case no array_key_compare is needed */
    4184          72 :                                         break;
    4185             :                                 }
    4186           0 :                         }
    4187             :                 } else {
    4188             :                         /* ptrs[0] in none of the other arguments */
    4189             :                         /* skip all entries with value as ptrs[0] */
    4190             :                         for (;;) {
    4191         238 :                                 if (Z_TYPE((++ptrs[0])->val) == IS_UNDEF) {
    4192          46 :                                         goto out;
    4193             :                                 }
    4194          73 :                                 if (behavior == DIFF_NORMAL) {
    4195           3 :                                         if (diff_data_compare_func(ptrs[0] - 1, ptrs[0])) {
    4196           3 :                                                 break;
    4197             :                                         }
    4198          70 :                                 } else if (behavior & DIFF_ASSOC) { /* triggered also when DIFF_KEY */
    4199             :                                         /* in this case no array_key_compare is needed */
    4200          70 :                                         break;
    4201             :                                 }
    4202           0 :                         }
    4203             :                 }
    4204             :         }
    4205             : out:
    4206         923 :         for (i = 0; i < arr_argc; i++) {
    4207         489 :                 hash = Z_ARRVAL(args[i]);
    4208         489 :                 pefree(lists[i], hash->u.flags & HASH_FLAG_PERSISTENT);
    4209             :         }
    4210             : 
    4211         434 :         PHP_ARRAY_CMP_FUNC_RESTORE();
    4212             : 
    4213         434 :         efree(ptrs);
    4214         434 :         efree(lists);
    4215             : }
    4216             : /* }}} */
    4217             : 
    4218             : /* {{{ proto array array_diff_key(array arr1, array arr2 [, array ...])
    4219             :    Returns the entries of arr1 that have keys which are not present in any of the others arguments. This function is like array_diff() but works on the keys instead of the values. The associativity is preserved. */
    4220         164 : PHP_FUNCTION(array_diff_key)
    4221             : {
    4222         164 :         php_array_diff_key(INTERNAL_FUNCTION_PARAM_PASSTHRU, DIFF_COMP_DATA_NONE);
    4223         164 : }
    4224             : /* }}} */
    4225             : 
    4226             : /* {{{ proto array array_diff_ukey(array arr1, array arr2 [, array ...], callback key_comp_func)
    4227             :    Returns the entries of arr1 that have keys which are not present in any of the others arguments. User supplied function is used for comparing the keys. This function is like array_udiff() but works on the keys instead of the values. The associativity is preserved. */
    4228         206 : PHP_FUNCTION(array_diff_ukey)
    4229             : {
    4230         206 :         php_array_diff(INTERNAL_FUNCTION_PARAM_PASSTHRU, DIFF_KEY, DIFF_COMP_DATA_INTERNAL, DIFF_COMP_KEY_USER);
    4231         206 : }
    4232             : /* }}} */
    4233             : 
    4234             : /* {{{ proto array array_diff(array arr1, array arr2 [, array ...])
    4235             :    Returns the entries of arr1 that have values which are not present in any of the others arguments. */
    4236         138 : PHP_FUNCTION(array_diff)
    4237             : {
    4238             :         zval *args;
    4239             :         int argc, i;
    4240             :         uint32_t num;
    4241             :         HashTable exclude;
    4242             :         zval *value;
    4243             :         zend_string *str, *key;
    4244             :         zend_long idx;
    4245             :         zval dummy;
    4246             : 
    4247         138 :         if (ZEND_NUM_ARGS() < 2) {
    4248           2 :                 php_error_docref(NULL, E_WARNING, "at least 2 parameters are required, %d given", ZEND_NUM_ARGS());
    4249           2 :                 return;
    4250             :         }
    4251             : 
    4252         136 :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "+", &args, &argc) == FAILURE) {
    4253           0 :                 return;
    4254             :         }
    4255             : 
    4256         272 :         if (Z_TYPE(args[0]) != IS_ARRAY) {
    4257          26 :                 php_error_docref(NULL, E_WARNING, "Argument #1 is not an array");
    4258          26 :                 RETURN_NULL();
    4259             :         }
    4260             : 
    4261             :         /* count number of elements */
    4262         110 :         num = 0;
    4263         197 :         for (i = 1; i < argc; i++) {
    4264         228 :                 if (Z_TYPE(args[i]) != IS_ARRAY) {
    4265          27 :                         php_error_docref(NULL, E_WARNING, "Argument #%d is not an array", i + 1);
    4266          27 :                         RETURN_NULL();
    4267             :                 }
    4268          87 :                 num += zend_hash_num_elements(Z_ARRVAL(args[i]));
    4269             :         }
    4270             : 
    4271          83 :         if (num == 0) {
    4272           1 :                 ZVAL_COPY(return_value, &args[0]);
    4273           1 :                 return;
    4274             :         }
    4275             : 
    4276          82 :         ZVAL_NULL(&dummy);
    4277             :         /* create exclude map */
    4278          82 :         zend_hash_init(&exclude, num, NULL, NULL, 0);
    4279         168 :         for (i = 1; i < argc; i++) {
    4280        8381 :                 ZEND_HASH_FOREACH_VAL_IND(Z_ARRVAL(args[i]), value) {
    4281        2764 :                         str = zval_get_string(value);
    4282        2764 :                         zend_hash_add(&exclude, str, &dummy);
    4283             :                         zend_string_release(str);
    4284             :                 } ZEND_HASH_FOREACH_END();
    4285             :         }
    4286             : 
    4287             :         /* copy all elements of first array that are not in exclude set */
    4288          82 :         array_init_size(return_value, zend_hash_num_elements(Z_ARRVAL(args[0])));
    4289        8353 :         ZEND_HASH_FOREACH_KEY_VAL_IND(Z_ARRVAL(args[0]), idx, key, value) {
    4290        2756 :                 str = zval_get_string(value);
    4291        2756 :                 if (!zend_hash_exists(&exclude, str)) {
    4292         156 :                         if (key) {
    4293          48 :                                 value = zend_hash_add_new(Z_ARRVAL_P(return_value), key, value);
    4294             :                         } else {
    4295         108 :                                 value = zend_hash_index_add_new(Z_ARRVAL_P(return_value), idx, value);
    4296             :                         }
    4297         156 :                         zval_add_ref(value);
    4298             :                 }
    4299             :                 zend_string_release(str);
    4300             :         } ZEND_HASH_FOREACH_END();
    4301             : 
    4302          82 :         zend_hash_destroy(&exclude);
    4303             : }
    4304             : /* }}} */
    4305             : 
    4306             : /* {{{ proto array array_udiff(array arr1, array arr2 [, array ...], callback data_comp_func)
    4307             :    Returns the entries of arr1 that have values which are not present in any of the others arguments. Elements are compared by user supplied function. */
    4308         112 : PHP_FUNCTION(array_udiff)
    4309             : {
    4310         112 :         php_array_diff(INTERNAL_FUNCTION_PARAM_PASSTHRU, DIFF_NORMAL, DIFF_COMP_DATA_USER, DIFF_COMP_KEY_INTERNAL);
    4311         112 : }
    4312             : /* }}} */
    4313             : 
    4314             : /* {{{ proto array array_diff_assoc(array arr1, array arr2 [, array ...])
    4315             :    Returns the entries of arr1 that have values which are not present in any of the others arguments but do additional checks whether the keys are equal */
    4316         142 : PHP_FUNCTION(array_diff_assoc)
    4317             : {
    4318         142 :         php_array_diff_key(INTERNAL_FUNCTION_PARAM_PASSTHRU, DIFF_COMP_DATA_INTERNAL);
    4319         142 : }
    4320             : /* }}} */
    4321             : 
    4322             : /* {{{ proto array array_diff_uassoc(array arr1, array arr2 [, array ...], callback data_comp_func)
    4323             :    Returns the entries of arr1 that have values which are not present in any of the others arguments but do additional checks whether the keys are equal. Elements are compared by user supplied function. */
    4324         149 : PHP_FUNCTION(array_diff_uassoc)
    4325             : {
    4326         149 :         php_array_diff(INTERNAL_FUNCTION_PARAM_PASSTHRU, DIFF_ASSOC, DIFF_COMP_DATA_INTERNAL, DIFF_COMP_KEY_USER);
    4327         149 : }
    4328             : /* }}} */
    4329             : 
    4330             : /* {{{ proto array array_udiff_assoc(array arr1, array arr2 [, array ...], callback key_comp_func)
    4331             :    Returns the entries of arr1 that have values which are not present in any of the others arguments but do additional checks whether the keys are equal. Keys are compared by user supplied function. */
    4332         114 : PHP_FUNCTION(array_udiff_assoc)
    4333             : {
    4334         114 :         php_array_diff_key(INTERNAL_FUNCTION_PARAM_PASSTHRU, DIFF_COMP_DATA_USER);
    4335         114 : }
    4336             : /* }}} */
    4337             : 
    4338             : /* {{{ proto array array_udiff_uassoc(array arr1, array arr2 [, array ...], callback data_comp_func, callback key_comp_func)
    4339             :    Returns the entries of arr1 that have values which are not present in any of the others arguments but do additional checks whether the keys are equal. Keys and elements are compared by user supplied functions. */
    4340         141 : PHP_FUNCTION(array_udiff_uassoc)
    4341             : {
    4342         141 :         php_array_diff(INTERNAL_FUNCTION_PARAM_PASSTHRU, DIFF_ASSOC, DIFF_COMP_DATA_USER, DIFF_COMP_KEY_USER);
    4343         141 : }
    4344             : /* }}} */
    4345             : 
    4346             : #define MULTISORT_ORDER 0
    4347             : #define MULTISORT_TYPE  1
    4348             : #define MULTISORT_LAST  2
    4349             : 
    4350         197 : PHPAPI int php_multisort_compare(const void *a, const void *b) /* {{{ */
    4351             : {
    4352         197 :         Bucket *ab = *(Bucket **)a;
    4353         197 :         Bucket *bb = *(Bucket **)b;
    4354             :         int r;
    4355             :         zend_long result;
    4356             :         zval temp;
    4357             : 
    4358         197 :         r = 0;
    4359             :         do {
    4360             : 
    4361         203 :                 php_set_compare_func(ARRAYG(multisort_flags)[MULTISORT_TYPE][r]);
    4362             : 
    4363         203 :                 ARRAYG(compare_func)(&temp, &ab[r].val, &bb[r].val);
    4364         203 :                 result = ARRAYG(multisort_flags)[MULTISORT_ORDER][r] * Z_LVAL(temp);
    4365         203 :                 if (result != 0) {
    4366         173 :                         return result > 0 ? 1 : -1;
    4367             :                 }
    4368          30 :                 r++;
    4369          60 :         } while (Z_TYPE(ab[r].val) != IS_UNDEF);
    4370             : 
    4371          24 :         return 0;
    4372             : }
    4373             : /* }}} */
    4374             : 
    4375             : #define MULTISORT_ABORT                                         \
    4376             :         for (k = 0; k < MULTISORT_LAST; k++) \
    4377             :                 efree(ARRAYG(multisort_flags)[k]);      \
    4378             :         efree(arrays);                                                  \
    4379             :         RETURN_FALSE;
    4380             : 
    4381         165 : static void array_bucket_p_sawp(void *p, void *q) /* {{{ */ {
    4382             :         Bucket *t;
    4383         165 :         Bucket **f = (Bucket **)p;
    4384         165 :         Bucket **g = (Bucket **)q;
    4385             : 
    4386         165 :         t = *f;
    4387         165 :         *f = *g;
    4388         165 :         *g = t;
    4389         165 : }
    4390             : /* }}} */
    4391             : 
    4392             : /* {{{ proto bool array_multisort(array &$array1 [, mixed $array1_sort_order [, mixed $array1_sort_flags [, mixed ... ]]]
    4393             :    Sort multiple arrays at once similar to how ORDER BY clause works in SQL */
    4394         109 : PHP_FUNCTION(array_multisort)
    4395             : {
    4396             :         zval*                   args;
    4397             :         zval**                  arrays;
    4398             :         Bucket**                indirect;
    4399             :         uint            idx;
    4400             :         Bucket*                 p;
    4401             :         HashTable*              hash;
    4402             :         int                             argc;
    4403             :         int                             array_size;
    4404         109 :         int                             num_arrays = 0;
    4405             :         int                             parse_state[MULTISORT_LAST];   /* 0 - flag not allowed 1 - flag allowed */
    4406         109 :         int                             sort_order = PHP_SORT_ASC;
    4407         109 :         int                             sort_type  = PHP_SORT_REGULAR;
    4408             :         int                             i, k, n;
    4409             : 
    4410         109 :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "+", &args, &argc) == FAILURE) {
    4411           1 :                 return;
    4412             :         }
    4413             : 
    4414             :         /* Allocate space for storing pointers to input arrays and sort flags. */
    4415         108 :         arrays = (zval **)ecalloc(argc, sizeof(zval *));
    4416         324 :         for (i = 0; i < MULTISORT_LAST; i++) {
    4417         216 :                 parse_state[i] = 0;
    4418         216 :                 ARRAYG(multisort_flags)[i] = (int *)ecalloc(argc, sizeof(int));
    4419             :         }
    4420             : 
    4421             :         /* Here we go through the input arguments and parse them. Each one can
    4422             :          * be either an array or a sort flag which follows an array. If not
    4423             :          * specified, the sort flags defaults to PHP_SORT_ASC and PHP_SORT_REGULAR
    4424             :          * accordingly. There can't be two sort flags of the same type after an
    4425             :          * array, and the very first argument has to be an array. */
    4426         268 :         for (i = 0; i < argc; i++) {
    4427         235 :                 zval *arg = &args[i];
    4428             : 
    4429         235 :                 ZVAL_DEREF(arg);
    4430         235 :                 if (Z_TYPE_P(arg) == IS_ARRAY) {
    4431         100 :                         SEPARATE_ARRAY(arg);
    4432             :                         /* We see the next array, so we update the sort flags of
    4433             :                          * the previous array and reset the sort flags. */
    4434         100 :                         if (i > 0) {
    4435          17 :                                 ARRAYG(multisort_flags)[MULTISORT_ORDER][num_arrays - 1] = sort_order;
    4436          17 :                                 ARRAYG(multisort_flags)[MULTISORT_TYPE][num_arrays - 1] = sort_type;
    4437          17 :                                 sort_order = PHP_SORT_ASC;
    4438          17 :                                 sort_type = PHP_SORT_REGULAR;
    4439             :                         }
    4440         100 :                         arrays[num_arrays++] = arg;
    4441             : 
    4442             :                         /* Next one may be an array or a list of sort flags. */
    4443         300 :                         for (k = 0; k < MULTISORT_LAST; k++) {
    4444         200 :                                 parse_state[k] = 1;
    4445             :                         }
    4446         135 :                 } else if (Z_TYPE_P(arg) == IS_LONG) {
    4447          72 :                         switch (Z_LVAL_P(arg) & ~PHP_SORT_FLAG_CASE) {
    4448             :                                 case PHP_SORT_ASC:
    4449             :                                 case PHP_SORT_DESC:
    4450             :                                         /* flag allowed here */
    4451          15 :                                         if (parse_state[MULTISORT_ORDER] == 1) {
    4452             :                                                 /* Save the flag and make sure then next arg is not the current flag. */
    4453          14 :                                                 sort_order = Z_LVAL_P(arg) == PHP_SORT_DESC ? -1 : 1;
    4454          14 :                                                 parse_state[MULTISORT_ORDER] = 0;
    4455             :                                         } else {
    4456           1 :                                                 php_error_docref(NULL, E_WARNING, "Argument #%d is expected to be an array or sorting flag that has not already been specified", i + 1);
    4457           1 :                                                 MULTISORT_ABORT;
    4458             :                                         }
    4459          14 :                                         break;
    4460             : 
    4461             :                                 case PHP_SORT_REGULAR:
    4462             :                                 case PHP_SORT_NUMERIC:
    4463             :                                 case PHP_SORT_STRING:
    4464             :                                 case PHP_SORT_NATURAL:
    4465             : #if HAVE_STRCOLL
    4466             :                                 case PHP_SORT_LOCALE_STRING:
    4467             : #endif
    4468             :                                         /* flag allowed here */
    4469          51 :                                         if (parse_state[MULTISORT_TYPE] == 1) {
    4470             :                                                 /* Save the flag and make sure then next arg is not the current flag. */
    4471          46 :                                                 sort_type = (int)Z_LVAL_P(arg);
    4472          46 :                                                 parse_state[MULTISORT_TYPE] = 0;
    4473             :                                         } else {
    4474           5 :                                                 php_error_docref(NULL, E_WARNING, "Argument #%d is expected to be an array or sorting flag that has not already been specified", i + 1);
    4475           5 :                                                 MULTISORT_ABORT;
    4476             :                                         }
    4477          46 :                                         break;
    4478             : 
    4479             :                                 default:
    4480           6 :                                         php_error_docref(NULL, E_WARNING, "Argument #%d is an unknown sort flag", i + 1);
    4481           6 :                                         MULTISORT_ABORT;
    4482             :                                         break;
    4483             : 
    4484             :                         }
    4485             :                 } else {
    4486          63 :                         php_error_docref(NULL, E_WARNING, "Argument #%d is expected to be an array or a sort flag", i + 1);
    4487          63 :                         MULTISORT_ABORT;
    4488             :                 }
    4489             :         }
    4490             :         /* Take care of the last array sort flags. */
    4491          33 :         ARRAYG(multisort_flags)[MULTISORT_ORDER][num_arrays - 1] = sort_order;
    4492          33 :         ARRAYG(multisort_flags)[MULTISORT_TYPE][num_arrays - 1] = sort_type;
    4493             : 
    4494             :         /* Make sure the arrays are of the same size. */
    4495          33 :         array_size = zend_hash_num_elements(Z_ARRVAL_P(arrays[0]));
    4496          80 :         for (i = 0; i < num_arrays; i++) {
    4497          50 :                 if (zend_hash_num_elements(Z_ARRVAL_P(arrays[i])) != array_size) {
    4498           3 :                         php_error_docref(NULL, E_WARNING, "Array sizes are inconsistent");
    4499           3 :                         MULTISORT_ABORT;
    4500             :                 }
    4501             :         }
    4502             : 
    4503             :         /* If all arrays are empty we don't need to do anything. */
    4504          30 :         if (array_size < 1) {
    4505           6 :                 for (k = 0; k < MULTISORT_LAST; k++) {
    4506           4 :                         efree(ARRAYG(multisort_flags)[k]);
    4507             :                 }
    4508           2 :                 efree(arrays);
    4509           2 :                 RETURN_TRUE;
    4510             :         }
    4511             : 
    4512             :         /* Create the indirection array. This array is of size MxN, where
    4513             :          * M is the number of entries in each input array and N is the number
    4514             :          * of the input arrays + 1. The last column is NULL to indicate the end
    4515             :          * of the row. */
    4516          28 :         indirect = (Bucket **)safe_emalloc(array_size, sizeof(Bucket *), 0);
    4517         149 :         for (i = 0; i < array_size; i++) {
    4518         121 :                 indirect[i] = (Bucket *)safe_emalloc((num_arrays + 1), sizeof(Bucket), 0);
    4519             :         }
    4520          68 :         for (i = 0; i < num_arrays; i++) {
    4521          40 :                 k = 0;
    4522         221 :                 for (idx = 0; idx < Z_ARRVAL_P(arrays[i])->nNumUsed; idx++) {
    4523         181 :                         p = Z_ARRVAL_P(arrays[i])->arData + idx;
    4524         362 :                         if (Z_TYPE(p->val) == IS_UNDEF) continue;
    4525         180 :                         indirect[k][i] = *p;
    4526         180 :                         k++;
    4527             :                 }
    4528             :         }
    4529         149 :         for (k = 0; k < array_size; k++) {
    4530         121 :                 ZVAL_UNDEF(&indirect[k][num_arrays].val);
    4531             :         }
    4532             : 
    4533             :         /* Do the actual sort magic - bada-bim, bada-boom. */
    4534          28 :         zend_qsort(indirect, array_size, sizeof(Bucket *), php_multisort_compare, (swap_func_t)array_bucket_p_sawp);
    4535             : 
    4536             :         /* Restructure the arrays based on sorted indirect - this is mostly taken from zend_hash_sort() function. */
    4537          28 :         HANDLE_BLOCK_INTERRUPTIONS();
    4538          68 :         for (i = 0; i < num_arrays; i++) {
    4539             :                 int repack;
    4540             : 
    4541          40 :                 hash = Z_ARRVAL_P(arrays[i]);
    4542          40 :                 hash->nNumUsed = array_size;
    4543          40 :                 hash->nInternalPointer = 0;
    4544          40 :                 repack = !(hash->u.flags & HASH_FLAG_PACKED);
    4545             : 
    4546         220 :                 for (n = 0, k = 0; k < array_size; k++) {
    4547         180 :                         hash->arData[k] = indirect[k][i];
    4548         180 :                         if (hash->arData[k].key == NULL) {
    4549         130 :                                 hash->arData[k].h = n++;
    4550             :                         } else {
    4551          50 :                                 repack = 0;
    4552             :                         }
    4553             :                 }
    4554          40 :                 hash->nNextFreeElement = array_size;
    4555          40 :                 if (repack) {
    4556           0 :                         zend_hash_to_packed(hash);
    4557             :                 } else {
    4558          40 :                         zend_hash_rehash(hash);
    4559             :                 }
    4560             :         }
    4561          28 :         HANDLE_UNBLOCK_INTERRUPTIONS();
    4562             : 
    4563             :         /* Clean up. */
    4564         149 :         for (i = 0; i < array_size; i++) {
    4565         121 :                 efree(indirect[i]);
    4566             :         }
    4567          28 :         efree(indirect);
    4568          84 :         for (k = 0; k < MULTISORT_LAST; k++) {
    4569          56 :                 efree(ARRAYG(multisort_flags)[k]);
    4570             :         }
    4571          28 :         efree(arrays);
    4572          28 :         RETURN_TRUE;
    4573             : }
    4574             : /* }}} */
    4575             : 
    4576             : /* {{{ proto mixed array_rand(array input [, int num_req])
    4577             :    Return key/keys for random entry/entries in the array */
    4578         363 : PHP_FUNCTION(array_rand)
    4579             : {
    4580             :         zval *input;
    4581         363 :         zend_long randval, num_req = 1;
    4582             :         int num_avail;
    4583             :         zend_string *string_key;
    4584             :         zend_ulong num_key;
    4585             : 
    4586         363 :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "a|l", &input, &num_req) == FAILURE) {
    4587          32 :                 return;
    4588             :         }
    4589             : 
    4590         331 :         num_avail = zend_hash_num_elements(Z_ARRVAL_P(input));
    4591             : 
    4592         331 :         if (ZEND_NUM_ARGS() > 1) {
    4593         313 :                 if (num_req <= 0 || num_req > num_avail) {
    4594          21 :                         php_error_docref(NULL, E_WARNING, "Second argument has to be between 1 and the number of elements in the array");
    4595          21 :                         return;
    4596             :                 }
    4597             :         }
    4598             : 
    4599             :         /* Make the return value an array only if we need to pass back more than one result. */
    4600         310 :         if (num_req > 1) {
    4601          25 :                 array_init_size(return_value, (uint32_t)num_req);
    4602             :         }
    4603             : 
    4604             :         /* We can't use zend_hash_index_find() because the array may have string keys or gaps. */
    4605        2342 :         ZEND_HASH_FOREACH_KEY(Z_ARRVAL_P(input), num_key, string_key) {
    4606        1162 :                 if (!num_req) {
    4607           8 :                         break;
    4608             :                 }
    4609             : 
    4610        1154 :                 randval = php_rand();
    4611             : 
    4612        1154 :                 if ((double) (randval / (PHP_RAND_MAX + 1.0)) < (double) num_req / (double) num_avail) {
    4613             :                         /* If we are returning a single result, just do it. */
    4614         760 :                         if (Z_TYPE_P(return_value) != IS_ARRAY) {
    4615         284 :                                 if (string_key) {
    4616           7 :                                         RETURN_STR_COPY(string_key);
    4617             :                                 } else {
    4618         277 :                                         RETURN_LONG(num_key);
    4619             :                                 }
    4620             :                         } else {
    4621             :                                 /* Append the result to the return value. */
    4622         476 :                                 if (string_key) {
    4623          19 :                                         add_next_index_str(return_value, zend_string_copy(string_key));
    4624             :                                 } else {
    4625         457 :                                         add_next_index_long(return_value, num_key);
    4626             :                                 }
    4627             :                         }
    4628         476 :                         num_req--;
    4629             :                 }
    4630         870 :                 num_avail--;
    4631             :         } ZEND_HASH_FOREACH_END();
    4632             : }
    4633             : /* }}} */
    4634             : 
    4635             : /* {{{ proto mixed array_sum(array input)
    4636             :    Returns the sum of the array entries */
    4637          64 : PHP_FUNCTION(array_sum)
    4638             : {
    4639             :         zval *input,
    4640             :                  *entry,
    4641             :                  entry_n;
    4642             : 
    4643          64 :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "a", &input) == FAILURE) {
    4644          25 :                 return;
    4645             :         }
    4646             : 
    4647          39 :         ZVAL_LONG(return_value, 0);
    4648             : 
    4649      404355 :         ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(input), entry) {
    4650      404312 :                 if (Z_TYPE_P(entry) == IS_ARRAY || Z_TYPE_P(entry) == IS_OBJECT) {
    4651           8 :                         continue;
    4652             :                 }
    4653      202150 :                 ZVAL_COPY(&entry_n, entry);
    4654      202150 :                 convert_scalar_to_number(&entry_n);
    4655             :                 fast_add_function(return_value, return_value, &entry_n);
    4656             :         } ZEND_HASH_FOREACH_END();
    4657             : }
    4658             : /* }}} */
    4659             : 
    4660             : /* {{{ proto mixed array_product(array input)
    4661             :    Returns the product of the array entries */
    4662          53 : PHP_FUNCTION(array_product)
    4663             : {
    4664             :         zval *input,
    4665             :                  *entry,
    4666             :                  entry_n;
    4667             :         double dval;
    4668             : 
    4669          53 :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "a", &input) == FAILURE) {
    4670          29 :                 return;
    4671             :         }
    4672             : 
    4673          24 :         ZVAL_LONG(return_value, 1);
    4674          24 :         if (!zend_hash_num_elements(Z_ARRVAL_P(input))) {
    4675           2 :                 return;
    4676             :         }
    4677             : 
    4678        2086 :         ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(input), entry) {
    4679        2063 :                 if (Z_TYPE_P(entry) == IS_ARRAY || Z_TYPE_P(entry) == IS_OBJECT) {
    4680           2 :                         continue;
    4681             :                 }
    4682        1030 :                 ZVAL_COPY(&entry_n, entry);
    4683        1030 :                 convert_scalar_to_number(&entry_n);
    4684             : 
    4685        2053 :                 if (Z_TYPE(entry_n) == IS_LONG && Z_TYPE_P(return_value) == IS_LONG) {
    4686          28 :                         dval = (double)Z_LVAL_P(return_value) * (double)Z_LVAL(entry_n);
    4687          28 :                         if ( (double)ZEND_LONG_MIN <= dval && dval <= (double)ZEND_LONG_MAX ) {
    4688          27 :                                 Z_LVAL_P(return_value) *= Z_LVAL(entry_n);
    4689          27 :                                 continue;
    4690             :                         }
    4691             :                 }
    4692        1003 :                 convert_to_double(return_value);
    4693        1003 :                 convert_to_double(&entry_n);
    4694        1003 :                 Z_DVAL_P(return_value) *= Z_DVAL(entry_n);
    4695             :         } ZEND_HASH_FOREACH_END();
    4696             : }
    4697             : /* }}} */
    4698             : 
    4699             : /* {{{ proto mixed array_reduce(array input, mixed callback [, mixed initial])
    4700             :    Iteratively reduce the array to a single value via the callback. */
    4701          73 : PHP_FUNCTION(array_reduce)
    4702             : {
    4703             :         zval *input;
    4704             :         zval args[2];
    4705             :         zval *operand;
    4706             :         zval result;
    4707             :         zval retval;
    4708             :         zend_fcall_info fci;
    4709          73 :         zend_fcall_info_cache fci_cache = empty_fcall_info_cache;
    4710          73 :         zval *initial = NULL;
    4711             :         HashTable *htbl;
    4712             : 
    4713          73 :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "af|z", &input, &fci, &fci_cache, &initial) == FAILURE) {
    4714           5 :                 return;
    4715             :         }
    4716             : 
    4717             : 
    4718          68 :         if (ZEND_NUM_ARGS() > 2) {
    4719          16 :                 ZVAL_DUP(&result, initial);
    4720             :         } else {
    4721          52 :                 ZVAL_NULL(&result);
    4722             :         }
    4723             : 
    4724             :         /* (zval **)input points to an element of argument stack
    4725             :          * the base pointer of which is subject to change.
    4726             :          * thus we need to keep the pointer to the hashtable for safety */
    4727          68 :         htbl = Z_ARRVAL_P(input);
    4728             : 
    4729          68 :         if (zend_hash_num_elements(htbl) == 0) {
    4730           1 :                 ZVAL_COPY_VALUE(return_value, &result);
    4731           1 :                 return;
    4732             :         }
    4733             : 
    4734          67 :         fci.retval = &retval;
    4735          67 :         fci.param_count = 2;
    4736          67 :         fci.no_separation = 0;
    4737             : 
    4738       43555 :         ZEND_HASH_FOREACH_VAL(htbl, operand) {
    4739       21744 :                 ZVAL_COPY(&args[0], &result);
    4740       21744 :                 ZVAL_COPY(&args[1], operand);
    4741       21744 :                 fci.params = args;
    4742             : 
    4743       65232 :                 if (zend_call_function(&fci, &fci_cache) == SUCCESS && Z_TYPE(retval) != IS_UNDEF) {
    4744       21744 :                         zval_ptr_dtor(&args[1]);
    4745       21744 :                         zval_ptr_dtor(&args[0]);
    4746       21744 :                         zval_ptr_dtor(&result);
    4747       21744 :                         ZVAL_COPY_VALUE(&result, &retval);
    4748             :                 } else {
    4749           0 :                         zval_ptr_dtor(&args[1]);
    4750           0 :                         zval_ptr_dtor(&args[0]);
    4751           0 :                         return;
    4752             :                 }
    4753             :         } ZEND_HASH_FOREACH_END();
    4754             : 
    4755         134 :         RETVAL_ZVAL(&result, 1, 1);
    4756             : }
    4757             : /* }}} */
    4758             : 
    4759             : /* {{{ proto array array_filter(array input [, mixed callback])
    4760             :    Filters elements from the array via the callback. */
    4761         124 : PHP_FUNCTION(array_filter)
    4762             : {
    4763             :         zval *array;
    4764             :         zval *operand;
    4765             :         zval *key;
    4766             :         zval args[2];
    4767             :         zval retval;
    4768         124 :         zend_bool have_callback = 0;
    4769         124 :         zend_long use_type = 0;
    4770             :         zend_string *string_key;
    4771         124 :         zend_fcall_info fci = empty_fcall_info;
    4772         124 :         zend_fcall_info_cache fci_cache = empty_fcall_info_cache;
    4773             :         zend_ulong num_key;
    4774             : 
    4775         124 :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "a|fl", &array, &fci, &fci_cache, &use_type) == FAILURE) {
    4776          59 :                 return;
    4777             :         }
    4778             : 
    4779          65 :         array_init(return_value);
    4780          65 :         if (zend_hash_num_elements(Z_ARRVAL_P(array)) == 0) {
    4781           1 :                 return;
    4782             :         }
    4783             : 
    4784          64 :         if (ZEND_NUM_ARGS() > 1) {
    4785          52 :                 have_callback = 1;
    4786          52 :                 fci.no_separation = 0;
    4787          52 :                 fci.retval = &retval;
    4788          52 :                 if (use_type == ARRAY_FILTER_USE_BOTH) {
    4789           4 :                         fci.param_count = 2;
    4790           4 :                         key = &args[1];
    4791             :                 } else {
    4792          48 :                         fci.param_count = 1;
    4793          48 :                         key = &args[0];
    4794             :                 }
    4795             :         }
    4796             : 
    4797        2262 :         ZEND_HASH_FOREACH_KEY_VAL(Z_ARRVAL_P(array), num_key, string_key, operand) {
    4798        1099 :                 if (have_callback) {
    4799        1038 :                         if (use_type) {
    4800             :                                 /* Set up the key */
    4801          26 :                                 if (!string_key) {
    4802          20 :                                         ZVAL_LONG(key, num_key);
    4803             :                                 } else {
    4804           6 :                                         ZVAL_STR_COPY(key, string_key);
    4805             :                                 }
    4806             :                         }
    4807        1038 :                         if (use_type != ARRAY_FILTER_USE_KEY) {
    4808        1034 :                                 ZVAL_COPY(&args[0], operand);
    4809             :                         }
    4810        1038 :                         fci.params = args;
    4811             : 
    4812        1038 :                         if (zend_call_function(&fci, &fci_cache) == SUCCESS) {
    4813        1038 :                                 zval_ptr_dtor(&args[0]);
    4814        1038 :                                 if (use_type == ARRAY_FILTER_USE_BOTH) {
    4815          22 :                                         zval_ptr_dtor(&args[1]);
    4816             :                                 }
    4817        1038 :                                 if (!Z_ISUNDEF(retval)) {
    4818        1038 :                                         int retval_true = zend_is_true(&retval);
    4819             : 
    4820        1038 :                                         zval_ptr_dtor(&retval);
    4821        1038 :                                         if (!retval_true) {
    4822         145 :                                                 continue;
    4823             :                                         }
    4824             :                                 } else {
    4825           0 :                                         continue;
    4826             :                                 }
    4827             :                         } else {
    4828           0 :                                 zval_ptr_dtor(&args[0]);
    4829           0 :                                 if (use_type == ARRAY_FILTER_USE_BOTH) {
    4830           0 :                                         zval_ptr_dtor(&args[1]);
    4831             :                                 }
    4832           0 :                                 return;
    4833             :                         }
    4834          61 :                 } else if (!zend_is_true(operand)) {
    4835          26 :                         continue;
    4836             :                 }
    4837             : 
    4838         928 :                 if (string_key) {
    4839          17 :                         operand = zend_hash_update(Z_ARRVAL_P(return_value), string_key, operand);
    4840             :                 } else {
    4841         911 :                         operand = zend_hash_index_update(Z_ARRVAL_P(return_value), num_key, operand);
    4842             :                 }
    4843         928 :                 zval_add_ref(operand);
    4844             :         } ZEND_HASH_FOREACH_END();
    4845             : }
    4846             : /* }}} */
    4847             : 
    4848             : /* {{{ proto array array_map(mixed callback, array input1 [, array input2 ,...])
    4849             :    Applies the callback to the elements in given arrays. */
    4850         281 : PHP_FUNCTION(array_map)
    4851             : {
    4852         281 :         zval *arrays = NULL;
    4853         281 :         int n_arrays = 0;
    4854             :         zval result;
    4855         281 :         zend_fcall_info fci = empty_fcall_info;
    4856         281 :         zend_fcall_info_cache fci_cache = empty_fcall_info_cache;
    4857             :         int i;
    4858         281 :         uint32_t k, maxlen = 0;
    4859             : 
    4860             : #ifndef FAST_ZPP
    4861             :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "f!+", &fci, &fci_cache, &arrays, &n_arrays) == FAILURE) {
    4862             :                 return;
    4863             :         }
    4864             : #else
    4865         281 :         ZEND_PARSE_PARAMETERS_START(2, -1)
    4866         837 :                 Z_PARAM_FUNC_EX(fci, fci_cache, 1, 0)
    4867         237 :                 Z_PARAM_VARIADIC('+', arrays, n_arrays)
    4868         281 :         ZEND_PARSE_PARAMETERS_END();
    4869             : #endif
    4870             : 
    4871         237 :         RETVAL_NULL();
    4872             : 
    4873         237 :         if (n_arrays == 1) {
    4874             :                 zend_ulong num_key;
    4875             :                 zend_string *str_key;
    4876             :                 zval *zv, arg;
    4877             : 
    4878         213 :                 if (Z_TYPE(arrays[0]) != IS_ARRAY) {
    4879          26 :                         php_error_docref(NULL, E_WARNING, "Argument #%d should be an array", 2);
    4880          26 :                         return;
    4881             :                 }
    4882         187 :                 maxlen = zend_hash_num_elements(Z_ARRVAL(arrays[0]));
    4883             : 
    4884             :                 /* Short-circuit: if no callback and only one array, just return it. */
    4885         187 :                 if (!ZEND_FCI_INITIALIZED(fci)) {
    4886           3 :                         ZVAL_COPY(return_value, &arrays[0]);
    4887           3 :                         return;
    4888             :                 }
    4889             : 
    4890         184 :                 array_init_size(return_value, maxlen);
    4891             : 
    4892        1865 :                 ZEND_HASH_FOREACH_KEY_VAL(Z_ARRVAL(arrays[0]), num_key, str_key, zv) {
    4893         834 :                         fci.retval = &result;
    4894         834 :                         fci.param_count = 1;
    4895         834 :                         fci.params = &arg;
    4896         834 :                         fci.no_separation = 0;
    4897             : 
    4898         834 :                         ZVAL_COPY(&arg, zv);
    4899             : 
    4900        1668 :                         if (zend_call_function(&fci, &fci_cache) != SUCCESS || Z_TYPE(result) == IS_UNDEF) {
    4901             :                                 zval_dtor(return_value);
    4902           1 :                                 zval_ptr_dtor(&arg);
    4903           1 :                                 RETURN_NULL();
    4904             :                         } else {
    4905         833 :                                 zval_ptr_dtor(&arg);
    4906             :                         }
    4907         833 :                         if (str_key) {
    4908          96 :                                 zend_hash_add_new(Z_ARRVAL_P(return_value), str_key, &result);
    4909             :                         } else {
    4910         737 :                                 zend_hash_index_add_new(Z_ARRVAL_P(return_value), num_key, &result);
    4911             :                         }
    4912             :                 } ZEND_HASH_FOREACH_END();
    4913             :         } else {
    4914          24 :                 uint32_t *array_pos = (HashPosition *)ecalloc(n_arrays, sizeof(HashPosition));
    4915             : 
    4916          79 :                 for (i = 0; i < n_arrays; i++) {
    4917         110 :                         if (Z_TYPE(arrays[i]) != IS_ARRAY) {
    4918           0 :                                 php_error_docref(NULL, E_WARNING, "Argument #%d should be an array", i + 2);
    4919           0 :                                 efree(array_pos);
    4920           0 :                                 return;
    4921             :                         }
    4922          55 :                         if (zend_hash_num_elements(Z_ARRVAL(arrays[i])) > maxlen) {
    4923          24 :                                 maxlen = zend_hash_num_elements(Z_ARRVAL(arrays[i]));
    4924             :                         }
    4925             :                 }
    4926             : 
    4927          24 :                 array_init_size(return_value, maxlen);
    4928             : 
    4929          24 :                 if (!ZEND_FCI_INITIALIZED(fci)) {
    4930             :                         zval zv;
    4931             : 
    4932             :                         /* We iterate through all the arrays at once. */
    4933          24 :                         for (k = 0; k < maxlen; k++) {
    4934             : 
    4935             :                                 /* If no callback, the result will be an array, consisting of current
    4936             :                                  * entries from all arrays. */
    4937          17 :                                 array_init_size(&result, n_arrays);
    4938             : 
    4939          63 :                                 for (i = 0; i < n_arrays; i++) {
    4940             :                                         /* If this array still has elements, add the current one to the
    4941             :                                          * parameter list, otherwise use null value. */
    4942          46 :                                         uint32_t pos = array_pos[i];
    4943             :                                         while (1) {
    4944          46 :                                                 if (pos >= Z_ARRVAL(arrays[i])->nNumUsed) {
    4945           0 :                                                         ZVAL_NULL(&zv);
    4946           0 :                                                         break;
    4947          92 :                                                 } else if (Z_TYPE(Z_ARRVAL(arrays[i])->arData[pos].val) != IS_UNDEF) {
    4948          46 :                                                         ZVAL_COPY(&zv, &Z_ARRVAL(arrays[i])->arData[pos].val);
    4949          46 :                                                         array_pos[i] = pos + 1;
    4950          46 :                                                         break;
    4951             :                                                 }
    4952           0 :                                                 pos++;
    4953           0 :                                         }
    4954             : 
    4955          46 :                                         zend_hash_next_index_insert_new(Z_ARRVAL(result), &zv);
    4956             :                                 }
    4957             : 
    4958          17 :                                 zend_hash_next_index_insert_new(Z_ARRVAL_P(return_value), &result);
    4959             :                         }
    4960             :                 } else {
    4961          17 :                         zval *params = (zval *)safe_emalloc(n_arrays, sizeof(zval), 0);
    4962             : 
    4963             :                         /* We iterate through all the arrays at once. */
    4964          65 :                         for (k = 0; k < maxlen; k++) {
    4965         152 :                                 for (i = 0; i < n_arrays; i++) {
    4966             :                                         /* If this array still has elements, add the current one to the
    4967             :                                          * parameter list, otherwise use null value. */
    4968         103 :                                         uint32_t pos = array_pos[i];
    4969             :                                         while (1) {
    4970         103 :                                                 if (pos >= Z_ARRVAL(arrays[i])->nNumUsed) {
    4971          12 :                                                         ZVAL_NULL(&params[i]);
    4972          12 :                                                         break;
    4973         182 :                                                 } else if (Z_TYPE(Z_ARRVAL(arrays[i])->arData[pos].val) != IS_UNDEF) {
    4974          91 :                                                         ZVAL_COPY(&params[i], &Z_ARRVAL(arrays[i])->arData[pos].val);
    4975          91 :                                                         array_pos[i] = pos + 1;
    4976          91 :                                                         break;
    4977             :                                                 }
    4978           0 :                                                 pos++;
    4979           0 :                                         }
    4980             :                                 }
    4981             : 
    4982          49 :                                 fci.retval = &result;
    4983          49 :                                 fci.param_count = n_arrays;
    4984          49 :                                 fci.params = params;
    4985          49 :                                 fci.no_separation = 0;
    4986             : 
    4987          98 :                                 if (zend_call_function(&fci, &fci_cache) != SUCCESS || Z_TYPE(result) == IS_UNDEF) {
    4988           1 :                                         efree(array_pos);
    4989             :                                         zval_dtor(return_value);
    4990           3 :                                         for (i = 0; i < n_arrays; i++) {
    4991           2 :                                                 zval_ptr_dtor(&params[i]);
    4992             :                                         }
    4993           1 :                                         efree(params);
    4994           1 :                                         RETURN_NULL();
    4995             :                                 } else {
    4996         149 :                                         for (i = 0; i < n_arrays; i++) {
    4997         101 :                                                 zval_ptr_dtor(&params[i]);
    4998             :                                         }
    4999             :                                 }
    5000             : 
    5001          48 :                                 zend_hash_next_index_insert_new(Z_ARRVAL_P(return_value), &result);
    5002             :                         }
    5003             : 
    5004          16 :                         efree(params);
    5005             :                 }
    5006          23 :                 efree(array_pos);
    5007             :         }
    5008             : }
    5009             : /* }}} */
    5010             : 
    5011             : /* {{{ proto bool array_key_exists(mixed key, array search)
    5012             :    Checks if the given key or index exists in the array */
    5013      143799 : PHP_FUNCTION(array_key_exists)
    5014             : {
    5015             :         zval *key;                                      /* key to check for */
    5016             :         HashTable *array;                       /* array to check in */
    5017             : 
    5018             : #ifndef FAST_ZPP
    5019             :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "zH", &key, &array) == FAILURE) {
    5020             :                 return;
    5021             :         }
    5022             : #else
    5023      143799 :         ZEND_PARSE_PARAMETERS_START(2, 2)
    5024      143793 :                 Z_PARAM_ZVAL(key)
    5025      431379 :                 Z_PARAM_ARRAY_OR_OBJECT_HT(array)
    5026      143799 :         ZEND_PARSE_PARAMETERS_END();
    5027             : #endif
    5028             : 
    5029      287528 :         switch (Z_TYPE_P(key)) {
    5030             :                 case IS_STRING:
    5031      286912 :                         if (zend_symtable_exists(array, Z_STR_P(key))) {
    5032       10380 :                                 RETURN_TRUE;
    5033             :                         }
    5034      133076 :                         RETURN_FALSE;
    5035             :                 case IS_LONG:
    5036         235 :                         if (zend_hash_index_exists(array, Z_LVAL_P(key))) {
    5037         101 :                                 RETURN_TRUE;
    5038             :                         }
    5039         134 :                         RETURN_FALSE;
    5040             :                 case IS_NULL:
    5041          55 :                         if (zend_hash_exists(array, STR_EMPTY_ALLOC())) {
    5042          27 :                                 RETURN_TRUE;
    5043             :                         }
    5044          28 :                         RETURN_FALSE;
    5045             : 
    5046             :                 default:
    5047          18 :                         php_error_docref(NULL, E_WARNING, "The first argument should be either a string or an integer");
    5048          18 :                         RETURN_FALSE;
    5049             :         }
    5050             : }
    5051             : /* }}} */
    5052             : 
    5053             : /* {{{ proto array array_chunk(array input, int size [, bool preserve_keys])
    5054             :    Split array into chunks */
    5055         521 : PHP_FUNCTION(array_chunk)
    5056             : {
    5057         521 :         int argc = ZEND_NUM_ARGS(), num_in;
    5058         521 :         zend_long size, current = 0;
    5059             :         zend_string *str_key;
    5060             :         zend_ulong num_key;
    5061         521 :         zend_bool preserve_keys = 0;
    5062         521 :         zval *input = NULL;
    5063             :         zval chunk;
    5064             :         zval *entry;
    5065             : 
    5066         521 :         if (zend_parse_parameters(argc, "al|b", &input, &size, &preserve_keys) == FAILURE) {
    5067         106 :                 return;
    5068             :         }
    5069             :         /* Do bounds checking for size parameter. */
    5070         415 :         if (size < 1) {
    5071         107 :                 php_error_docref(NULL, E_WARNING, "Size parameter expected to be greater than 0");
    5072         107 :                 return;
    5073             :         }
    5074             : 
    5075         308 :         num_in = zend_hash_num_elements(Z_ARRVAL_P(input));
    5076             : 
    5077         308 :         if (size > num_in) {
    5078          34 :                 size = num_in > 0 ? num_in : 1;
    5079             :         }
    5080             : 
    5081         308 :         array_init_size(return_value, (uint32_t)(((num_in - 1) / size) + 1));
    5082             : 
    5083         308 :         ZVAL_UNDEF(&chunk);
    5084             : 
    5085        3340 :         ZEND_HASH_FOREACH_KEY_VAL(Z_ARRVAL_P(input), num_key, str_key, entry) {
    5086             :                 /* If new chunk, create and initialize it. */
    5087        1468 :                 if (Z_TYPE(chunk) == IS_UNDEF) {
    5088         683 :                         array_init_size(&chunk, (uint32_t)size);
    5089             :                 }
    5090             : 
    5091             :                 /* Add entry to the chunk, preserving keys if necessary. */
    5092        1468 :                 if (preserve_keys) {
    5093         507 :                         if (str_key) {
    5094          93 :                                 entry = zend_hash_update(Z_ARRVAL(chunk), str_key, entry);
    5095             :                         } else {
    5096         414 :                                 entry = zend_hash_index_update(Z_ARRVAL(chunk), num_key, entry);
    5097             :                         }
    5098             :                 } else {
    5099         961 :                         entry = zend_hash_next_index_insert(Z_ARRVAL(chunk), entry);
    5100             :                 }
    5101        1468 :                 zval_add_ref(entry);
    5102             : 
    5103             :                 /* If reached the chunk size, add it to the result array, and reset the
    5104             :                  * pointer. */
    5105        1468 :                 if (!(++current % size)) {
    5106         576 :                         add_next_index_zval(return_value, &chunk);
    5107         576 :                         ZVAL_UNDEF(&chunk);
    5108             :                 }
    5109             :         } ZEND_HASH_FOREACH_END();
    5110             : 
    5111             :         /* Add the final chunk if there is one. */
    5112         308 :         if (Z_TYPE(chunk) != IS_UNDEF) {
    5113         107 :                 add_next_index_zval(return_value, &chunk);
    5114             :         }
    5115             : }
    5116             : /* }}} */
    5117             : 
    5118             : /* {{{ proto array array_combine(array keys, array values)
    5119             :    Creates an array by using the elements of the first parameter as keys and the elements of the second as the corresponding values */
    5120         118 : PHP_FUNCTION(array_combine)
    5121             : {
    5122             :         zval *values, *keys;
    5123         118 :         uint32_t pos_values = 0;
    5124             :         zval *entry_keys, *entry_values;
    5125             :         int num_keys, num_values;
    5126             : 
    5127         118 :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "aa", &keys, &values) == FAILURE) {
    5128          51 :                 return;
    5129             :         }
    5130             : 
    5131          67 :         num_keys = zend_hash_num_elements(Z_ARRVAL_P(keys));
    5132          67 :         num_values = zend_hash_num_elements(Z_ARRVAL_P(values));
    5133             : 
    5134          67 :         if (num_keys != num_values) {
    5135           3 :                 php_error_docref(NULL, E_WARNING, "Both parameters should have an equal number of elements");
    5136           3 :                 RETURN_FALSE;
    5137             :         }
    5138             : 
    5139          64 :         array_init_size(return_value, num_keys);
    5140             : 
    5141          64 :         if (!num_keys) {
    5142           4 :                 return;
    5143             :         }
    5144             : 
    5145         440 :         ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(keys), entry_keys) {
    5146             :                 while (1) {
    5147         194 :                         if (pos_values >= Z_ARRVAL_P(values)->nNumUsed) {
    5148           0 :                                 break;
    5149         388 :                         } else if (Z_TYPE(Z_ARRVAL_P(values)->arData[pos_values].val) != IS_UNDEF) {
    5150         181 :                                 entry_values = &Z_ARRVAL_P(values)->arData[pos_values].val;
    5151         181 :                                 if (Z_TYPE_P(entry_keys) == IS_LONG) {
    5152          43 :                                         entry_values = zend_hash_index_update(Z_ARRVAL_P(return_value),
    5153             :                                                 Z_LVAL_P(entry_keys), entry_values);
    5154             :                                 } else {
    5155         138 :                                         zend_string *key = zval_get_string(entry_keys);
    5156         276 :                                         entry_values = zend_symtable_update(Z_ARRVAL_P(return_value),
    5157             :                                                 key, entry_values);
    5158             :                                         zend_string_release(key);
    5159             :                                 }
    5160         181 :                                 zval_add_ref(entry_values);
    5161         181 :                                 pos_values++;
    5162         181 :                                 break;
    5163             :                         }
    5164          13 :                         pos_values++;
    5165          13 :                 }
    5166             :         } ZEND_HASH_FOREACH_END();
    5167             : }
    5168             : /* }}} */
    5169             : 
    5170             : /*
    5171             :  * Local variables:
    5172             :  * tab-width: 4
    5173             :  * c-basic-offset: 4
    5174             :  * End:
    5175             :  * vim600: noet sw=4 ts=4 fdm=marker
    5176             :  * vim<600: noet sw=4 ts=4
    5177             :  */

Generated by: LCOV version 1.10

Generated at Sat, 27 Jun 2015 09:41:19 +0000 (7 days ago)

Copyright © 2005-2015 The PHP Group
All rights reserved.