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

Generated by: LCOV version 1.10

Generated at Sat, 30 Jul 2016 22:07:33 +0000 (9 hours ago)

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