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: 2393 2574 93.0 %
Date: 2016-05-26 Functions: 131 136 96.3 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10

Generated at Thu, 26 May 2016 12:48:08 +0000 (11 hours ago)

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