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

Generated by: LCOV version 1.10

Generated at Wed, 02 Sep 2015 17:19:19 +0000 (2 days ago)

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