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 - Zend - zend_hash.c (source / functions) Hit Total Coverage
Test: PHP Code Coverage Lines: 823 929 88.6 %
Date: 2014-10-22 Functions: 57 65 87.7 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :    +----------------------------------------------------------------------+
       3             :    | Zend Engine                                                          |
       4             :    +----------------------------------------------------------------------+
       5             :    | Copyright (c) 1998-2014 Zend Technologies Ltd. (http://www.zend.com) |
       6             :    +----------------------------------------------------------------------+
       7             :    | This source file is subject to version 2.00 of the Zend 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.zend.com/license/2_00.txt.                                |
      11             :    | If you did not receive a copy of the Zend license and are unable to  |
      12             :    | obtain it through the world-wide-web, please send a note to          |
      13             :    | license@zend.com so we can mail you a copy immediately.              |
      14             :    +----------------------------------------------------------------------+
      15             :    | Authors: Andi Gutmans <andi@zend.com>                                |
      16             :    |          Zeev Suraski <zeev@zend.com>                                |
      17             :    +----------------------------------------------------------------------+
      18             : */
      19             : 
      20             : /* $Id$ */
      21             : 
      22             : #include "zend.h"
      23             : #include "zend_globals.h"
      24             : 
      25             : #if ZEND_DEBUG
      26             : /*
      27             : #define HASH_MASK_CONSISTENCY   0x60
      28             : */
      29             : #define HT_OK                                   0x00
      30             : #define HT_IS_DESTROYING                0x20
      31             : #define HT_DESTROYED                    0x40
      32             : #define HT_CLEANING                             0x60
      33             : 
      34             : static void _zend_is_inconsistent(const HashTable *ht, const char *file, int line)
      35             : {
      36             :         if ((ht->u.flags & HASH_MASK_CONSISTENCY) == HT_OK) {
      37             :                 return;
      38             :         }
      39             :         switch ((ht->u.flags & HASH_MASK_CONSISTENCY)) {
      40             :                 case HT_IS_DESTROYING:
      41             :                         zend_output_debug_string(1, "%s(%d) : ht=%p is being destroyed", file, line, ht);
      42             :                         break;
      43             :                 case HT_DESTROYED:
      44             :                         zend_output_debug_string(1, "%s(%d) : ht=%p is already destroyed", file, line, ht);
      45             :                         break;
      46             :                 case HT_CLEANING:
      47             :                         zend_output_debug_string(1, "%s(%d) : ht=%p is being cleaned", file, line, ht);
      48             :                         break;
      49             :                 default:
      50             :                         zend_output_debug_string(1, "%s(%d) : ht=%p is inconsistent", file, line, ht);
      51             :                         break;
      52             :         }
      53             :         zend_bailout();
      54             : }
      55             : #define IS_CONSISTENT(a) _zend_is_inconsistent(a, __FILE__, __LINE__);
      56             : #define SET_INCONSISTENT(n) do { \
      57             :                 (ht)->u.flags |= n; \
      58             :         } while (0)
      59             : #else
      60             : #define IS_CONSISTENT(a)
      61             : #define SET_INCONSISTENT(n)
      62             : #endif
      63             : 
      64             : #define HASH_PROTECT_RECURSION(ht)                                                                                                              \
      65             :         if ((ht)->u.flags & HASH_FLAG_APPLY_PROTECTION) {                                                                        \
      66             :                 if ((ht)->u.flags >= (3 << 8)) {                                                                                            \
      67             :                         zend_error_noreturn(E_ERROR, "Nesting level too deep - recursive dependency?");\
      68             :                 }                                                                                                                                                               \
      69             :                 ZEND_HASH_INC_APPLY_COUNT(ht);                                                                                                  \
      70             :         }
      71             : 
      72             : #define HASH_UNPROTECT_RECURSION(ht)                                                                                                    \
      73             :         if ((ht)->u.flags & HASH_FLAG_APPLY_PROTECTION) {                                                                        \
      74             :                 ZEND_HASH_DEC_APPLY_COUNT(ht);                                                                                                  \
      75             :         }
      76             : 
      77             : #define ZEND_HASH_IF_FULL_DO_RESIZE(ht)                         \
      78             :         if ((ht)->nNumUsed >= (ht)->nTableSize) {              \
      79             :                 zend_hash_do_resize(ht);                                        \
      80             :         }
      81             : 
      82             : static void zend_hash_do_resize(HashTable *ht);
      83             : 
      84             : #define CHECK_INIT(ht, packed) do {                                                                                             \
      85             :         if (UNEXPECTED((ht)->nTableMask == 0)) {                                                     \
      86             :                 if (packed) { \
      87             :                         (ht)->arData = (Bucket *) safe_pemalloc((ht)->nTableSize, sizeof(Bucket), 0, (ht)->u.flags & HASH_FLAG_PERSISTENT);        \
      88             :                         (ht)->u.flags |= HASH_FLAG_PACKED; \
      89             :                 } else { \
      90             :                         (ht)->arData = (Bucket *) safe_pemalloc((ht)->nTableSize, sizeof(Bucket) + sizeof(uint32_t), 0, (ht)->u.flags & HASH_FLAG_PERSISTENT);     \
      91             :                         (ht)->arHash = (uint32_t*)((ht)->arData + (ht)->nTableSize);   \
      92             :                         memset((ht)->arHash, INVALID_IDX, (ht)->nTableSize * sizeof(uint32_t));   \
      93             :                 } \
      94             :                 (ht)->nTableMask = (ht)->nTableSize - 1;                                          \
      95             :         }                                                                                                                                       \
      96             : } while (0)
      97             :  
      98             : static const uint32_t uninitialized_bucket = {INVALID_IDX};
      99             : 
     100    16671690 : ZEND_API void _zend_hash_init(HashTable *ht, uint32_t nSize, dtor_func_t pDestructor, zend_bool persistent ZEND_FILE_LINE_DC)
     101             : {
     102    16671690 :         uint32_t i = 3;
     103             : 
     104             :         SET_INCONSISTENT(HT_OK);
     105             : 
     106    16671690 :         if (nSize >= 0x80000000) {
     107             :                 /* prevent overflow */
     108           0 :                 ht->nTableSize = 0x80000000;
     109             :         } else {
     110    34495616 :                 while ((1U << i) < nSize) {
     111     1152236 :                         i++;
     112             :                 }
     113    16671690 :                 ht->nTableSize = 1 << i;
     114             :         }
     115             : 
     116    16671690 :         ht->nTableMask = 0;  /* 0 means that ht->arBuckets is uninitialized */
     117    16671690 :         ht->nNumUsed = 0;
     118    16671690 :         ht->nNumOfElements = 0;
     119    16671690 :         ht->nNextFreeElement = 0;
     120    16671690 :         ht->arData = NULL;
     121    16671690 :         ht->arHash = (uint32_t*)&uninitialized_bucket;
     122    16671690 :         ht->pDestructor = pDestructor;
     123    16671690 :         ht->nInternalPointer = INVALID_IDX;
     124    16671690 :         if (persistent) {
     125    12236553 :                 ht->u.flags = HASH_FLAG_PERSISTENT | HASH_FLAG_APPLY_PROTECTION;
     126             :         } else {
     127     4435137 :                 ht->u.flags = HASH_FLAG_APPLY_PROTECTION;
     128             :         }
     129    16671690 : }
     130             : 
     131       36938 : static void zend_hash_packed_grow(HashTable *ht)
     132             : {
     133       36938 :         HANDLE_BLOCK_INTERRUPTIONS();
     134       36938 :         ht->arData = (Bucket *) safe_perealloc(ht->arData, (ht->nTableSize << 1), sizeof(Bucket), 0, ht->u.flags & HASH_FLAG_PERSISTENT);
     135       36938 :         ht->nTableSize = (ht->nTableSize << 1);
     136       36938 :         ht->nTableMask = ht->nTableSize - 1;
     137       36938 :         HANDLE_UNBLOCK_INTERRUPTIONS();
     138       36938 : }
     139             : 
     140       69402 : ZEND_API void zend_hash_real_init(HashTable *ht, zend_bool packed)
     141             : {
     142             :         IS_CONSISTENT(ht);
     143             : 
     144       69402 :         CHECK_INIT(ht, packed);
     145       69402 : }
     146             : 
     147       27122 : ZEND_API void zend_hash_packed_to_hash(HashTable *ht)
     148             : {
     149       27122 :         HANDLE_BLOCK_INTERRUPTIONS();
     150       27122 :         ht->u.flags &= ~HASH_FLAG_PACKED;
     151       27122 :         ht->arData = (Bucket *) safe_perealloc(ht->arData, ht->nTableSize, sizeof(Bucket) + sizeof(uint32_t), 0, ht->u.flags & HASH_FLAG_PERSISTENT);
     152       27122 :         ht->arHash = (uint32_t*)(ht->arData + ht->nTableSize);
     153       27122 :         zend_hash_rehash(ht);
     154       27122 :         HANDLE_UNBLOCK_INTERRUPTIONS();
     155       27122 : }
     156             : 
     157          15 : ZEND_API void zend_hash_to_packed(HashTable *ht)
     158             : {
     159          15 :         HANDLE_BLOCK_INTERRUPTIONS();
     160          15 :         ht->u.flags |= HASH_FLAG_PACKED;
     161          15 :         ht->arData = erealloc(ht->arData, ht->nTableSize * sizeof(Bucket));
     162          15 :         ht->arHash = (uint32_t*)&uninitialized_bucket;
     163          15 :         HANDLE_UNBLOCK_INTERRUPTIONS();
     164          15 : }
     165             : 
     166    11111518 : ZEND_API void _zend_hash_init_ex(HashTable *ht, uint32_t nSize, dtor_func_t pDestructor, zend_bool persistent, zend_bool bApplyProtection ZEND_FILE_LINE_DC)
     167             : {
     168    11111518 :         _zend_hash_init(ht, nSize, pDestructor, persistent ZEND_FILE_LINE_CC);
     169    11111518 :         if (!bApplyProtection) {
     170    11111518 :                 ht->u.flags &= ~HASH_FLAG_APPLY_PROTECTION;
     171             :         }
     172    11111518 : }
     173             : 
     174             : 
     175           0 : ZEND_API void zend_hash_set_apply_protection(HashTable *ht, zend_bool bApplyProtection)
     176             : {
     177           0 :         if (bApplyProtection) {
     178           0 :                 ht->u.flags |= HASH_FLAG_APPLY_PROTECTION;
     179             :         } else {
     180           0 :                 ht->u.flags &= ~HASH_FLAG_APPLY_PROTECTION;
     181             :         }
     182           0 : }
     183             : 
     184             : static zend_always_inline Bucket *zend_hash_find_bucket(const HashTable *ht, zend_string *key)
     185             : {
     186             :         zend_ulong h;
     187             :         uint32_t nIndex;
     188             :         uint32_t idx;
     189             :         Bucket *p;
     190             : 
     191   272040173 :         h = zend_string_hash_val(key);
     192   272040173 :         nIndex = h & ht->nTableMask;
     193   272040173 :         idx = ht->arHash[nIndex];
     194   419034815 :         while (idx != INVALID_IDX) {
     195   160849531 :                 p = ht->arData + idx;
     196   328803115 :                 if ((p->key == key) || /* check for the the same interned string */
     197   152232759 :                         (p->h == h &&
     198     5240275 :                          p->key &&
     199     5240275 :                          p->key->len == key->len &&
     200     5240275 :                          memcmp(p->key->val, key->val, key->len) == 0)) {
     201    13854889 :                         return p;
     202             :                 }
     203   146994642 :                 idx = Z_NEXT(p->val);
     204             :         }
     205   258185284 :         return NULL;
     206             : }
     207             : 
     208             : static zend_always_inline Bucket *zend_hash_str_find_bucket(const HashTable *ht, const char *str, size_t len, zend_ulong h)
     209             : {
     210             :         uint32_t nIndex;
     211             :         uint32_t idx;
     212             :         Bucket *p;
     213             : 
     214     3434085 :         nIndex = h & ht->nTableMask;
     215     3434085 :         idx = ht->arHash[nIndex];
     216     4240654 :         while (idx != INVALID_IDX) {
     217             :                 ZEND_ASSERT(idx < ht->nTableSize);
     218     3349831 :                 p = ht->arData + idx;
     219    10979668 :                 if ((p->h == h) 
     220             :                          && p->key
     221     5086558 :                          && (p->key->len == len)
     222     2543279 :                          && !memcmp(p->key->val, str, len)) {
     223     2543262 :                         return p;
     224             :                 }
     225      806569 :                 idx = Z_NEXT(p->val);
     226             :         }
     227      890823 :         return NULL;
     228             : }
     229             : 
     230             : static zend_always_inline Bucket *zend_hash_index_find_bucket(const HashTable *ht, zend_ulong h)
     231             : {
     232             :         uint32_t nIndex;
     233             :         uint32_t idx;
     234             :         Bucket *p;
     235             : 
     236     4087153 :         nIndex = h & ht->nTableMask;
     237     4087153 :         idx = ht->arHash[nIndex];
     238     5410364 :         while (idx != INVALID_IDX) {
     239             :                 ZEND_ASSERT(idx < ht->nTableSize);
     240     2320876 :                 p = ht->arData + idx;
     241     2320876 :                 if (p->h == h && !p->key) {
     242      997665 :                         return p;
     243             :                 }
     244     1323211 :                 idx = Z_NEXT(p->val);
     245             :         }
     246     3089488 :         return NULL;
     247             : }
     248             : 
     249             : static zend_always_inline zval *_zend_hash_add_or_update_i(HashTable *ht, zend_string *key, zval *pData, uint32_t flag ZEND_FILE_LINE_DC)
     250             : {
     251             :         zend_ulong h;
     252             :         uint32_t nIndex;
     253             :         uint32_t idx;
     254             :         Bucket *p;
     255             : #ifdef ZEND_SIGNALS
     256             :         TSRMLS_FETCH();
     257             : #endif
     258             : 
     259             :         IS_CONSISTENT(ht);
     260             : 
     261   249845796 :         CHECK_INIT(ht, 0);
     262   249845796 :         if (ht->u.flags & HASH_FLAG_PACKED) {
     263       26103 :                 zend_hash_packed_to_hash(ht);
     264             :         }
     265             : 
     266   249845796 :         h = zend_string_hash_val(key);
     267             : 
     268   249845796 :         if ((flag & HASH_ADD_NEW) == 0) {
     269   220708993 :                 p = zend_hash_find_bucket(ht, key);
     270             : 
     271   220708993 :                 if (p) {
     272             :                         zval *data;
     273             : 
     274     1017681 :                         if (flag & HASH_ADD) {
     275      255322 :                                 return NULL;
     276             :                         }
     277             :                         ZEND_ASSERT(&p->val != pData);
     278      762359 :                         data = &p->val;
     279      817234 :                         if ((flag & HASH_UPDATE_INDIRECT) && Z_TYPE_P(data) == IS_INDIRECT) {
     280         254 :                                 data = Z_INDIRECT_P(data);
     281             :                         }
     282      762359 :                         HANDLE_BLOCK_INTERRUPTIONS();
     283      762359 :                         if (ht->pDestructor) {
     284      721141 :                                 ht->pDestructor(data);
     285             :                         }
     286      762359 :                         ZVAL_COPY_VALUE(data, pData);
     287      762359 :                         HANDLE_UNBLOCK_INTERRUPTIONS();
     288      762359 :                         return data;
     289             :                 }
     290             :         }
     291             :         
     292   248828115 :         ZEND_HASH_IF_FULL_DO_RESIZE(ht);                /* If the Hash table is full, resize it */
     293             : 
     294   248828115 :         HANDLE_BLOCK_INTERRUPTIONS();
     295   248828115 :         idx = ht->nNumUsed++;
     296   248828115 :         ht->nNumOfElements++;
     297   248828115 :         if (ht->nInternalPointer == INVALID_IDX) {
     298     6811198 :                 ht->nInternalPointer = idx;
     299             :         }
     300   248828115 :         p = ht->arData + idx; 
     301   248828115 :         p->h = h;
     302   248828115 :         p->key = key;
     303             :         zend_string_addref(key);
     304   248828115 :         ZVAL_COPY_VALUE(&p->val, pData);
     305   248828115 :         nIndex = h & ht->nTableMask;
     306   248828115 :         Z_NEXT(p->val) = ht->arHash[nIndex];
     307   248828115 :         ht->arHash[nIndex] = idx;
     308   248828115 :         HANDLE_UNBLOCK_INTERRUPTIONS();
     309             : 
     310   248828115 :         return &p->val;
     311             : }
     312             : 
     313     2983257 : ZEND_API zval *_zend_hash_add_or_update(HashTable *ht, zend_string *key, zval *pData, uint32_t flag ZEND_FILE_LINE_DC)
     314             : {
     315     2983257 :         return _zend_hash_add_or_update_i(ht, key, pData, flag ZEND_FILE_LINE_RELAY_CC);
     316             : }
     317             : 
     318   138365186 : ZEND_API zval *_zend_hash_add(HashTable *ht, zend_string *key, zval *pData ZEND_FILE_LINE_DC)
     319             : {
     320   138365186 :         return _zend_hash_add_or_update_i(ht, key, pData, HASH_ADD ZEND_FILE_LINE_RELAY_CC);
     321             : }
     322             : 
     323    52929764 : ZEND_API zval *_zend_hash_update(HashTable *ht, zend_string *key, zval *pData ZEND_FILE_LINE_DC)
     324             : {
     325    52929764 :         return _zend_hash_add_or_update_i(ht, key, pData, HASH_UPDATE ZEND_FILE_LINE_RELAY_CC);
     326             : }
     327             : 
     328        1133 : ZEND_API zval *_zend_hash_update_ind(HashTable *ht, zend_string *key, zval *pData ZEND_FILE_LINE_DC)
     329             : {
     330        1133 :         return _zend_hash_add_or_update_i(ht, key, pData, HASH_UPDATE | HASH_UPDATE_INDIRECT ZEND_FILE_LINE_RELAY_CC);
     331             : }
     332             : 
     333    29133957 : ZEND_API zval *_zend_hash_add_new(HashTable *ht, zend_string *key, zval *pData ZEND_FILE_LINE_DC)
     334             : {
     335    29133957 :         return _zend_hash_add_or_update_i(ht, key, pData, HASH_ADD_NEW ZEND_FILE_LINE_RELAY_CC);
     336             : }
     337             : 
     338           0 : ZEND_API zval *_zend_hash_str_add_or_update(HashTable *ht, const char *str, size_t len, zval *pData, uint32_t flag ZEND_FILE_LINE_DC)
     339             : {
     340           0 :         zend_string *key = zend_string_init(str, len, ht->u.flags & HASH_FLAG_PERSISTENT);
     341           0 :         zval *ret = _zend_hash_add_or_update_i(ht, key, pData, flag ZEND_FILE_LINE_CC);
     342             :         zend_string_release(key);
     343           0 :         return ret;
     344             : }
     345             : 
     346    12578629 : ZEND_API zval *_zend_hash_str_update(HashTable *ht, const char *str, size_t len, zval *pData ZEND_FILE_LINE_DC)
     347             : {
     348    25157258 :         zend_string *key = zend_string_init(str, len, ht->u.flags & HASH_FLAG_PERSISTENT);
     349    12578629 :         zval *ret = _zend_hash_add_or_update_i(ht, key, pData, HASH_UPDATE ZEND_FILE_LINE_CC);
     350             :         zend_string_release(key);
     351    12578629 :         return ret;
     352             : }
     353             : 
     354     1270689 : ZEND_API zval *_zend_hash_str_update_ind(HashTable *ht, const char *str, size_t len, zval *pData ZEND_FILE_LINE_DC)
     355             : {
     356     2541378 :         zend_string *key = zend_string_init(str, len, ht->u.flags & HASH_FLAG_PERSISTENT);
     357     1270689 :         zval *ret = _zend_hash_add_or_update_i(ht, key, pData, HASH_UPDATE | HASH_UPDATE_INDIRECT ZEND_FILE_LINE_CC);
     358             :         zend_string_release(key);
     359     1270689 :         return ret;
     360             : }
     361             : 
     362    12580335 : ZEND_API zval *_zend_hash_str_add(HashTable *ht, const char *str, size_t len, zval *pData ZEND_FILE_LINE_DC)
     363             : {
     364    25160670 :         zend_string *key = zend_string_init(str, len, ht->u.flags & HASH_FLAG_PERSISTENT);
     365    12580335 :         zval *ret = _zend_hash_add_or_update_i(ht, key, pData, HASH_ADD ZEND_FILE_LINE_CC);
     366             :         zend_string_release(key);
     367    12580335 :         return ret;
     368             : }
     369             : 
     370        2846 : ZEND_API zval *_zend_hash_str_add_new(HashTable *ht, const char *str, size_t len, zval *pData ZEND_FILE_LINE_DC)
     371             : {
     372        5692 :         zend_string *key = zend_string_init(str, len, ht->u.flags & HASH_FLAG_PERSISTENT);
     373        2846 :         zval *ret = _zend_hash_add_or_update_i(ht, key, pData, HASH_ADD_NEW ZEND_FILE_LINE_CC);
     374             :         zend_string_release(key);
     375        2846 :         return ret;
     376             : }
     377             : 
     378           0 : ZEND_API zval *zend_hash_index_add_empty_element(HashTable *ht, zend_ulong h)
     379             : {
     380             :         
     381             :         zval dummy;
     382             : 
     383           0 :         ZVAL_NULL(&dummy);
     384           0 :         return zend_hash_index_add(ht, h, &dummy);
     385             : }
     386             : 
     387         222 : ZEND_API zval *zend_hash_add_empty_element(HashTable *ht, zend_string *key)
     388             : {
     389             :         
     390             :         zval dummy;
     391             : 
     392         222 :         ZVAL_NULL(&dummy);
     393         222 :         return zend_hash_add(ht, key, &dummy);
     394             : }
     395             : 
     396      512338 : ZEND_API zval *zend_hash_str_add_empty_element(HashTable *ht, const char *str, size_t len)
     397             : {
     398             :         
     399             :         zval dummy;
     400             : 
     401      512338 :         ZVAL_NULL(&dummy);
     402      512338 :         return zend_hash_str_add(ht, str, len, &dummy);
     403             : }
     404             : 
     405             : static zend_always_inline zval *_zend_hash_index_add_or_update_i(HashTable *ht, zend_ulong h, zval *pData, uint32_t flag ZEND_FILE_LINE_DC)
     406             : {
     407             :         uint32_t nIndex;
     408             :         uint32_t idx;
     409             :         Bucket *p;
     410             : #ifdef ZEND_SIGNALS
     411             :         TSRMLS_FETCH();
     412             : #endif
     413             : 
     414             :         IS_CONSISTENT(ht);
     415     7537702 :         CHECK_INIT(ht, h < ht->nTableSize);
     416             : 
     417     7537702 :         if (ht->u.flags & HASH_FLAG_PACKED) {
     418     5551877 :                 if (h < ht->nNumUsed) {
     419        3799 :                         p = ht->arData + h;
     420        7598 :                         if (Z_TYPE(p->val) != IS_UNDEF) {
     421        3643 :                                 if (flag & HASH_ADD) {
     422          24 :                                         return NULL;
     423             :                                 }
     424        3619 :                                 if (ht->pDestructor) {
     425        3619 :                                         ht->pDestructor(&p->val);
     426             :                                 }
     427        3619 :                                 ZVAL_COPY_VALUE(&p->val, pData);
     428        3619 :                                 if ((zend_long)h >= (zend_long)ht->nNextFreeElement) {
     429           0 :                                         ht->nNextFreeElement = h < ZEND_LONG_MAX ? h + 1 : ZEND_LONG_MAX;
     430             :                                 }
     431        3619 :                                 return &p->val;
     432             :                         } else { /* we have to keep the order :( */
     433             :                                 goto convert_to_hash;
     434             :                         }
     435     5548078 :                 } else if (EXPECTED(h < ht->nTableSize)) {
     436     5510538 :                         p = ht->arData + h;
     437       75005 :                 } else if (h < ht->nTableSize * 2 &&
     438       37465 :                                    ht->nTableSize - ht->nNumOfElements < ht->nTableSize / 2) {
     439       36938 :                         zend_hash_packed_grow(ht);
     440       36938 :                         p = ht->arData + h;
     441             :                 } else {
     442             :                         goto convert_to_hash;
     443             :                 }
     444             : 
     445     5547476 :                 HANDLE_BLOCK_INTERRUPTIONS();
     446             :                 /* incremental initialization of empty Buckets */
     447     5547476 :                 if ((flag & (HASH_ADD_NEW|HASH_ADD_NEXT)) == (HASH_ADD_NEW|HASH_ADD_NEXT)) {
     448      451994 :                         ht->nNumUsed = h + 1;
     449     5095482 :                 } else if (h >= ht->nNumUsed) {
     450     5095482 :                         if (h > ht->nNumUsed) {
     451      891652 :                                 Bucket *q = ht->arData + ht->nNumUsed;
     452     1787934 :                                 while (q != p) {
     453      896282 :                                         ZVAL_UNDEF(&q->val);
     454      896282 :                                         q++;
     455             :                                 }
     456             :                         }
     457     5095482 :                         ht->nNumUsed = h + 1;
     458             :                 }
     459     5547476 :                 ht->nNumOfElements++;
     460     5547476 :                 if (ht->nInternalPointer == INVALID_IDX) {
     461     1902132 :                         ht->nInternalPointer = h;
     462             :                 }
     463     5547476 :                 if ((zend_long)h >= (zend_long)ht->nNextFreeElement) {
     464     5547464 :                         ht->nNextFreeElement = h < ZEND_LONG_MAX ? h + 1 : ZEND_LONG_MAX;
     465             :                 }
     466     5547476 :                 p->h = h;
     467     5547476 :                 p->key = NULL;
     468     5547476 :                 ZVAL_COPY_VALUE(&p->val, pData);
     469     5547476 :                 Z_NEXT(p->val) = INVALID_IDX;
     470             : 
     471     5547476 :                 HANDLE_UNBLOCK_INTERRUPTIONS();
     472             : 
     473     5547476 :                 return &p->val;
     474             : 
     475             : convert_to_hash:
     476         758 :                 zend_hash_packed_to_hash(ht);
     477             :         }
     478             : 
     479     1986583 :         if ((flag & HASH_ADD_NEW) == 0) {
     480     1429703 :                 p = zend_hash_index_find_bucket(ht, h);
     481     1429703 :                 if (p) {
     482       10251 :                         if (flag & HASH_ADD) {
     483           5 :                                 return NULL;
     484             :                         }
     485             :                         ZEND_ASSERT(&p->val != pData);
     486       10246 :                         HANDLE_BLOCK_INTERRUPTIONS();
     487       10246 :                         if (ht->pDestructor) {
     488       10201 :                                 ht->pDestructor(&p->val);
     489             :                         }
     490       10246 :                         ZVAL_COPY_VALUE(&p->val, pData);
     491       10246 :                         HANDLE_UNBLOCK_INTERRUPTIONS();
     492       10246 :                         if ((zend_long)h >= (zend_long)ht->nNextFreeElement) {
     493           1 :                                 ht->nNextFreeElement = h < ZEND_LONG_MAX ? h + 1 : ZEND_LONG_MAX;
     494             :                         }
     495       10246 :                         return &p->val;
     496             :                 }
     497             :         }
     498             : 
     499     1976332 :         ZEND_HASH_IF_FULL_DO_RESIZE(ht);                /* If the Hash table is full, resize it */
     500             : 
     501     1976332 :         HANDLE_BLOCK_INTERRUPTIONS();
     502     1976332 :         idx = ht->nNumUsed++;
     503     1976332 :         ht->nNumOfElements++;
     504     1976332 :         if (ht->nInternalPointer == INVALID_IDX) {
     505      168436 :                 ht->nInternalPointer = idx;
     506             :         }
     507     1976332 :         if ((zend_long)h >= (zend_long)ht->nNextFreeElement) {
     508      617303 :                 ht->nNextFreeElement = h < ZEND_LONG_MAX ? h + 1 : ZEND_LONG_MAX;
     509             :         }
     510     1976332 :         p = ht->arData + idx;
     511     1976332 :         p->h = h;
     512     1976332 :         p->key = NULL;
     513     1976332 :         nIndex = h & ht->nTableMask;
     514     1976332 :         ZVAL_COPY_VALUE(&p->val, pData);
     515     1976332 :         Z_NEXT(p->val) = ht->arHash[nIndex];
     516     1976332 :         ht->arHash[nIndex] = idx;
     517     1976332 :         HANDLE_UNBLOCK_INTERRUPTIONS();
     518             : 
     519     1976332 :         return &p->val;
     520             : }
     521             : 
     522           0 : ZEND_API zval *_zend_hash_index_add_or_update(HashTable *ht, zend_ulong h, zval *pData, uint32_t flag ZEND_FILE_LINE_DC)
     523             : {
     524           0 :         return _zend_hash_index_add_or_update_i(ht, h, pData, flag ZEND_FILE_LINE_RELAY_CC);
     525             : }
     526             : 
     527         100 : ZEND_API zval *_zend_hash_index_add(HashTable *ht, zend_ulong h, zval *pData ZEND_FILE_LINE_DC)
     528             : {
     529         100 :         return _zend_hash_index_add_or_update_i(ht, h, pData, HASH_ADD ZEND_FILE_LINE_RELAY_CC);
     530             : }
     531             : 
     532      911787 : ZEND_API zval *_zend_hash_index_add_new(HashTable *ht, zend_ulong h, zval *pData ZEND_FILE_LINE_DC)
     533             : {
     534      911787 :         return _zend_hash_index_add_or_update_i(ht, h, pData, HASH_ADD | HASH_ADD_NEW ZEND_FILE_LINE_RELAY_CC);
     535             : }
     536             : 
     537     2361139 : ZEND_API zval *_zend_hash_index_update(HashTable *ht, zend_ulong h, zval *pData ZEND_FILE_LINE_DC)
     538             : {
     539     2361139 :         return _zend_hash_index_add_or_update_i(ht, h, pData, HASH_UPDATE ZEND_FILE_LINE_RELAY_CC);
     540             : }
     541             : 
     542     3812418 : ZEND_API zval *_zend_hash_next_index_insert(HashTable *ht, zval *pData ZEND_FILE_LINE_DC)
     543             : {
     544     7624836 :         return _zend_hash_index_add_or_update_i(ht, ht->nNextFreeElement, pData, HASH_ADD | HASH_ADD_NEXT ZEND_FILE_LINE_RELAY_CC);
     545             : }
     546             : 
     547      452258 : ZEND_API zval *_zend_hash_next_index_insert_new(HashTable *ht, zval *pData ZEND_FILE_LINE_DC)
     548             : {
     549      904516 :         return _zend_hash_index_add_or_update_i(ht, ht->nNextFreeElement, pData, HASH_ADD | HASH_ADD_NEW | HASH_ADD_NEXT ZEND_FILE_LINE_RELAY_CC);
     550             : }
     551             : 
     552     6257041 : static void zend_hash_do_resize(HashTable *ht)
     553             : {
     554             : #ifdef ZEND_SIGNALS
     555             :         TSRMLS_FETCH();
     556             : #endif
     557             : 
     558             :         IS_CONSISTENT(ht);
     559             : 
     560     6257041 :         if (ht->nNumUsed < ht->nNumOfElements) {
     561           0 :                 HANDLE_BLOCK_INTERRUPTIONS();
     562           0 :                 zend_hash_rehash(ht);
     563           0 :                 HANDLE_UNBLOCK_INTERRUPTIONS();
     564     6257041 :         } else if ((ht->nTableSize << 1) > 0) {     /* Let's double the table size */
     565     6257041 :                 HANDLE_BLOCK_INTERRUPTIONS();
     566     6257041 :                 ht->arData = (Bucket *) safe_perealloc(ht->arData, (ht->nTableSize << 1), sizeof(Bucket) + sizeof(uint32_t), 0, ht->u.flags & HASH_FLAG_PERSISTENT);
     567     6257041 :                 ht->arHash = (uint32_t*)(ht->arData + (ht->nTableSize << 1));
     568     6257041 :                 ht->nTableSize = (ht->nTableSize << 1);
     569     6257041 :                 ht->nTableMask = ht->nTableSize - 1;
     570     6257041 :                 zend_hash_rehash(ht);
     571     6257041 :                 HANDLE_UNBLOCK_INTERRUPTIONS();
     572             :         }
     573     6257041 : }
     574             : 
     575     6366768 : ZEND_API int zend_hash_rehash(HashTable *ht)
     576             : {
     577             :         Bucket *p;
     578             :         uint32_t nIndex, i, j;
     579             : 
     580             :         IS_CONSISTENT(ht);
     581             : 
     582     6366768 :         if (UNEXPECTED(ht->nNumOfElements == 0)) {
     583           3 :                 if (ht->nTableMask) {
     584           0 :                         memset(ht->arHash, INVALID_IDX, ht->nTableSize * sizeof(uint32_t));
     585             :                 }
     586           3 :                 return SUCCESS;
     587             :         }
     588             : 
     589     6366765 :         memset(ht->arHash, INVALID_IDX, ht->nTableSize * sizeof(uint32_t));
     590   396182983 :         for (i = 0, j = 0; i < ht->nNumUsed; i++) {
     591   389816218 :                 p = ht->arData + i;
     592   779632436 :                 if (Z_TYPE(p->val) == IS_UNDEF) continue;
     593   389760874 :                 if (i != j) {
     594      126800 :                         ht->arData[j] = ht->arData[i];
     595      126800 :                         if (ht->nInternalPointer == i) {
     596         948 :                                 ht->nInternalPointer = j;
     597             :                         }
     598             :                 }
     599   389760874 :                 nIndex = ht->arData[j].h & ht->nTableMask;
     600   389760874 :                 Z_NEXT(ht->arData[j].val) = ht->arHash[nIndex];
     601   389760874 :                 ht->arHash[nIndex] = j;
     602   389760874 :                 j++;
     603             :         }
     604     6366765 :         ht->nNumUsed = j;
     605     6366765 :         return SUCCESS;
     606             : }
     607             : 
     608             : static zend_always_inline void _zend_hash_del_el_ex(HashTable *ht, uint32_t idx, Bucket *p, Bucket *prev)
     609             : {
     610    53263253 :         if (!(ht->u.flags & HASH_FLAG_PACKED)) {
     611    53158706 :                 if (prev) {
     612     2965216 :                         Z_NEXT(prev->val) = Z_NEXT(p->val);
     613             :                 } else {
     614    50193490 :                         ht->arHash[p->h & ht->nTableMask] = Z_NEXT(p->val);
     615             :                 }
     616             :         }
     617    53263253 :         if (ht->nNumUsed - 1 == idx) {
     618             :                 do {
     619     3669850 :                         ht->nNumUsed--;
     620     7170427 :                 } while (ht->nNumUsed > 0 && (Z_TYPE(ht->arData[ht->nNumUsed-1].val) == IS_UNDEF));
     621             :         }
     622    53263253 :         ht->nNumOfElements--;
     623    53263253 :         if (ht->nInternalPointer == idx) {
     624             :                 while (1) {
     625    47346087 :                         idx++;
     626    47346087 :                         if (idx >= ht->nNumUsed) {
     627      169264 :                                 ht->nInternalPointer = INVALID_IDX;
     628             :                                 break;
     629    94353646 :                         } else if (Z_TYPE(ht->arData[idx].val) != IS_UNDEF) {
     630     2999319 :                                 ht->nInternalPointer = idx;
     631             :                                 break;
     632             :                         }
     633             :                 }
     634             :         }
     635    53263253 :         if (p->key) {
     636    52994493 :                 zend_string_release(p->key);
     637             :         }
     638    53263253 :         if (ht->pDestructor) {
     639             :                 zval tmp;
     640    52477459 :                 ZVAL_COPY_VALUE(&tmp, &p->val);
     641    52477459 :                 ZVAL_UNDEF(&p->val);
     642    52477459 :                 ht->pDestructor(&tmp);
     643             :         } else {
     644      785794 :                 ZVAL_UNDEF(&p->val);
     645             :         }
     646             : }
     647             : 
     648             : static zend_always_inline void _zend_hash_del_el(HashTable *ht, uint32_t idx, Bucket *p)
     649             : {
     650     7360380 :         Bucket *prev = NULL;
     651             : 
     652     7360380 :         if (!(ht->u.flags & HASH_FLAG_PACKED)) {
     653     7348242 :                 uint32_t nIndex = p->h & ht->nTableMask;
     654     7348242 :                 uint32_t i = ht->arHash[nIndex];
     655             : 
     656     7348242 :                 if (i != idx) {
     657      311930 :                         prev = ht->arData + i;
     658      353437 :                         while (Z_NEXT(prev->val) != idx) {
     659       41507 :                                 i = Z_NEXT(prev->val);
     660       41507 :                                 prev = ht->arData + i;
     661             :                         }
     662             :                 }
     663             :         }
     664             : 
     665             :         _zend_hash_del_el_ex(ht, idx, p, prev);
     666             : }
     667             : 
     668    45793352 : ZEND_API int zend_hash_del(HashTable *ht, zend_string *key)
     669             : {
     670             :         zend_ulong h;
     671             :         uint32_t nIndex;
     672             :         uint32_t idx;
     673             :         Bucket *p;
     674    45793352 :         Bucket *prev = NULL;
     675             : #ifdef ZEND_SIGNALS
     676             :         TSRMLS_FETCH();
     677             : #endif
     678             : 
     679             :         IS_CONSISTENT(ht);
     680             : 
     681    45793352 :         if (ht->u.flags & HASH_FLAG_PACKED) {
     682           7 :                 return FAILURE;
     683             :         }
     684             : 
     685    45793345 :         h = zend_string_hash_val(key);
     686    45793345 :         nIndex = h & ht->nTableMask;
     687             : 
     688    45793345 :         idx = ht->arHash[nIndex];
     689    94379782 :         while (idx != INVALID_IDX) {
     690    47763207 :                 p = ht->arData + idx;
     691   230318289 :                 if ((p->key == key) ||
     692    47733555 :                         (p->h == h &&
     693    44940509 :                      p->key &&
     694    44940509 :                      p->key->len == key->len &&
     695    44940509 :                      memcmp(p->key->val, key->val, key->len) == 0)) {
     696    44970115 :                         HANDLE_BLOCK_INTERRUPTIONS();
     697             :                         _zend_hash_del_el_ex(ht, idx, p, prev);
     698    44970115 :                         HANDLE_UNBLOCK_INTERRUPTIONS();
     699    44970115 :                         return SUCCESS;
     700             :                 }
     701     2793092 :                 prev = p;
     702     2793092 :                 idx = Z_NEXT(p->val);
     703             :         }
     704      823230 :         return FAILURE;
     705             : }
     706             : 
     707         383 : ZEND_API int zend_hash_del_ind(HashTable *ht, zend_string *key)
     708             : {
     709             :         zend_ulong h;
     710             :         uint32_t nIndex;
     711             :         uint32_t idx;
     712             :         Bucket *p;
     713         383 :         Bucket *prev = NULL;
     714             : #ifdef ZEND_SIGNALS
     715             :         TSRMLS_FETCH();
     716             : #endif
     717             : 
     718             :         IS_CONSISTENT(ht);
     719             : 
     720         383 :         if (ht->u.flags & HASH_FLAG_PACKED) {
     721           0 :                 return FAILURE;
     722             :         }
     723             : 
     724         383 :         h = zend_string_hash_val(key);
     725         383 :         nIndex = h & ht->nTableMask;
     726             : 
     727         383 :         idx = ht->arHash[nIndex];
     728         775 :         while (idx != INVALID_IDX) {
     729         210 :                 p = ht->arData + idx;
     730         907 :                 if ((p->key == key) ||
     731         181 :                         (p->h == h &&
     732         172 :                      p->key &&
     733         172 :                      p->key->len == key->len &&
     734         172 :                      memcmp(p->key->val, key->val, key->len) == 0)) {
     735         402 :                         if (Z_TYPE(p->val) == IS_INDIRECT) {
     736          14 :                                 zval *data = Z_INDIRECT(p->val);
     737             : 
     738          14 :                                 if (Z_TYPE_P(data) == IS_UNDEF) {
     739           0 :                                         return FAILURE;
     740             :                                 } else {
     741          14 :                                         if (ht->pDestructor) {
     742          14 :                                                 ht->pDestructor(data);
     743             :                                         }
     744          14 :                                         ZVAL_UNDEF(data);
     745             :                                 }
     746             :                         } else {
     747         187 :                                 HANDLE_BLOCK_INTERRUPTIONS();
     748             :                                 _zend_hash_del_el_ex(ht, idx, p, prev);
     749         187 :                                 HANDLE_UNBLOCK_INTERRUPTIONS();
     750             :                         }
     751         201 :                         return SUCCESS;
     752             :                 }
     753           9 :                 prev = p;
     754           9 :                 idx = Z_NEXT(p->val);
     755             :         }
     756         182 :         return FAILURE;
     757             : }
     758             : 
     759      720825 : ZEND_API int zend_hash_str_del(HashTable *ht, const char *str, size_t len)
     760             : {
     761             :         zend_ulong h;
     762             :         uint32_t nIndex;
     763             :         uint32_t idx;
     764             :         Bucket *p;
     765      720825 :         Bucket *prev = NULL;
     766             : #ifdef ZEND_SIGNALS
     767             :         TSRMLS_FETCH();
     768             : #endif
     769             : 
     770             :         IS_CONSISTENT(ht);
     771             : 
     772      720825 :         if (ht->u.flags & HASH_FLAG_PACKED) {
     773           0 :                 return FAILURE;
     774             :         }
     775             : 
     776      720825 :         h = zend_inline_hash_func(str, len);
     777      720825 :         nIndex = h & ht->nTableMask;
     778             : 
     779      720825 :         idx = ht->arHash[nIndex];
     780     1482999 :         while (idx != INVALID_IDX) {
     781      738825 :                 p = ht->arData + idx;
     782     2831253 :                 if ((p->h == h) 
     783             :                          && p->key
     784     1394952 :                          && (p->key->len == len)
     785      697476 :                          && !memcmp(p->key->val, str, len)) {
     786     1394952 :                         if (Z_TYPE(p->val) == IS_INDIRECT) {
     787           0 :                                 zval *data = Z_INDIRECT(p->val);
     788             : 
     789           0 :                                 if (Z_TYPE_P(data) == IS_UNDEF) {
     790           0 :                                         return FAILURE;
     791             :                                 } else {
     792           0 :                                         if (ht->pDestructor) {
     793           0 :                                                 ht->pDestructor(data);
     794             :                                         }
     795           0 :                                         ZVAL_UNDEF(data);
     796             :                                 }
     797             :                         } else {
     798      697476 :                                 HANDLE_BLOCK_INTERRUPTIONS();
     799             :                                 _zend_hash_del_el_ex(ht, idx, p, prev);
     800      697476 :                                 HANDLE_UNBLOCK_INTERRUPTIONS();
     801             :                         }
     802      697476 :                         return SUCCESS;
     803             :                 }
     804       41349 :                 prev = p;
     805       41349 :                 idx = Z_NEXT(p->val);
     806             :         }
     807       23349 :         return FAILURE;
     808             : }
     809             : 
     810           0 : ZEND_API int zend_hash_str_del_ind(HashTable *ht, const char *str, size_t len)
     811             : {
     812             :         zend_ulong h;
     813             :         uint32_t nIndex;
     814             :         uint32_t idx;
     815             :         Bucket *p;
     816           0 :         Bucket *prev = NULL;
     817             : #ifdef ZEND_SIGNALS
     818             :         TSRMLS_FETCH();
     819             : #endif
     820             : 
     821             :         IS_CONSISTENT(ht);
     822             : 
     823           0 :         h = zend_inline_hash_func(str, len);
     824           0 :         nIndex = h & ht->nTableMask;
     825             : 
     826           0 :         idx = ht->arHash[nIndex];
     827           0 :         while (idx != INVALID_IDX) {
     828           0 :                 p = ht->arData + idx;
     829           0 :                 if ((p->h == h) 
     830             :                          && p->key
     831           0 :                          && (p->key->len == len)
     832           0 :                          && !memcmp(p->key->val, str, len)) {
     833           0 :                         HANDLE_BLOCK_INTERRUPTIONS();
     834             :                         _zend_hash_del_el_ex(ht, idx, p, prev);
     835           0 :                         HANDLE_UNBLOCK_INTERRUPTIONS();
     836           0 :                         return SUCCESS;
     837             :                 }
     838           0 :                 prev = p;
     839           0 :                 idx = Z_NEXT(p->val);
     840             :         }
     841           0 :         return FAILURE;
     842             : }
     843             : 
     844      241777 : ZEND_API int zend_hash_index_del(HashTable *ht, zend_ulong h)
     845             : {
     846             :         uint32_t nIndex;
     847             :         uint32_t idx;
     848             :         Bucket *p;
     849      241777 :         Bucket *prev = NULL;
     850             : #ifdef ZEND_SIGNALS
     851             :         TSRMLS_FETCH();
     852             : #endif
     853             : 
     854             :         IS_CONSISTENT(ht);
     855             : 
     856      241777 :         if (ht->u.flags & HASH_FLAG_PACKED) {
     857       97893 :                 if (h < ht->nNumUsed) {
     858       92416 :                         p = ht->arData + h;
     859      184832 :                         if (Z_TYPE(p->val) != IS_UNDEF) {
     860       92409 :                                 HANDLE_BLOCK_INTERRUPTIONS();
     861       92409 :                                 _zend_hash_del_el_ex(ht, h, p, NULL);
     862       92409 :                                 HANDLE_UNBLOCK_INTERRUPTIONS();
     863       92409 :                                 return SUCCESS;
     864             :                         }
     865             :                 }
     866        5484 :                 return FAILURE;
     867             :         }
     868      143884 :         nIndex = h & ht->nTableMask;
     869             : 
     870      143884 :         idx = ht->arHash[nIndex];
     871      287915 :         while (idx != INVALID_IDX) {
     872      142833 :                 p = ht->arData + idx;
     873      142833 :                 if ((p->h == h) && (p->key == NULL)) {
     874      142686 :                         HANDLE_BLOCK_INTERRUPTIONS();
     875             :                         _zend_hash_del_el_ex(ht, idx, p, prev);
     876      142686 :                         HANDLE_UNBLOCK_INTERRUPTIONS();
     877      142686 :                         return SUCCESS;
     878             :                 }
     879         147 :                 prev = p;
     880         147 :                 idx = Z_NEXT(p->val);
     881             :         }
     882        1198 :         return FAILURE;
     883             : }
     884             : 
     885    17888785 : ZEND_API void zend_hash_destroy(HashTable *ht)
     886             : {
     887             :         Bucket *p, *end;
     888             : 
     889             :         IS_CONSISTENT(ht);
     890             : 
     891    17888785 :         if (ht->nNumUsed) {
     892     9759543 :                 p = ht->arData;
     893     9759543 :                 end = p + ht->nNumUsed;
     894     9759543 :                 if (ht->pDestructor) {
     895             :                         SET_INCONSISTENT(HT_IS_DESTROYING);
     896             : 
     897     9467715 :                         if (ht->u.flags & HASH_FLAG_PACKED) {
     898             :                                 do {
     899    19281640 :                                         if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF)) {
     900     7907421 :                                                 ht->pDestructor(&p->val);
     901             :                                         }
     902     9640817 :                                 } while (++p != end);
     903             :                         } else {
     904             :                                 do {
     905   644902866 :                                         if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF)) {
     906   272987584 :                                                 ht->pDestructor(&p->val);
     907   272987584 :                                                 if (EXPECTED(p->key)) {
     908   272388543 :                                                         zend_string_release(p->key);
     909             :                                                 }
     910             :                                         }
     911   322451433 :                                 } while (++p != end);
     912             :                         }
     913             :                 
     914             :                         SET_INCONSISTENT(HT_DESTROYED);
     915             :                 } else {
     916      291828 :                         if (!(ht->u.flags & HASH_FLAG_PACKED)) {
     917             :                                 do {
     918    21115932 :                                         if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF)) {
     919    10476134 :                                                 if (EXPECTED(p->key)) {
     920     9224038 :                                                         zend_string_release(p->key);
     921             :                                                 }
     922             :                                         }
     923    10557966 :                                 } while (++p != end);
     924             :                         }
     925             :                 }
     926     8129242 :         } else if (EXPECTED(!ht->nTableMask)) {
     927     8059805 :                 return;
     928             :         }
     929     9828977 :         pefree(ht->arData, ht->u.flags & HASH_FLAG_PERSISTENT);
     930             : }
     931             : 
     932             : 
     933      137763 : ZEND_API void zend_hash_clean(HashTable *ht)
     934             : {
     935             :         uint32_t idx;
     936             :         Bucket *p;
     937             : 
     938             :         IS_CONSISTENT(ht);
     939             : 
     940     2159060 :         for (idx = 0; idx < ht->nNumUsed; idx++) {
     941     2021297 :                 p = ht->arData + idx;
     942     4042594 :                 if (Z_TYPE(p->val) == IS_UNDEF) continue;
     943     2021293 :                 if (ht->pDestructor) {
     944     1990931 :                         ht->pDestructor(&p->val);
     945             :                 }
     946     2021293 :                 if (p->key) {
     947     2018466 :                         zend_string_release(p->key);
     948             :                 }
     949             :         }
     950      137763 :         ht->nNumUsed = 0;
     951      137763 :         ht->nNumOfElements = 0;
     952      137763 :         ht->nNextFreeElement = 0;
     953      137763 :         ht->nInternalPointer = INVALID_IDX;
     954      137763 :         if (ht->nTableMask) {
     955       96429 :                 if (!(ht->u.flags & HASH_FLAG_PACKED)) {
     956       96419 :                         memset(ht->arHash, INVALID_IDX, ht->nTableSize * sizeof(uint32_t));       
     957             :                 }
     958             :         }
     959      137763 : }
     960             : 
     961             : /* This function is used by the various apply() functions.
     962             :  * It deletes the passed bucket, and returns the address of the
     963             :  * next bucket.  The hash *may* be altered during that time, the
     964             :  * returned value will still be valid.
     965             :  */
     966     7360380 : static void zend_hash_apply_deleter(HashTable *ht, uint32_t idx, Bucket *p)
     967             : {
     968             : #ifdef ZEND_SIGNALS
     969             :         TSRMLS_FETCH();
     970             : #endif
     971             : 
     972     7360380 :         HANDLE_BLOCK_INTERRUPTIONS();
     973             :         _zend_hash_del_el(ht, idx, p);
     974     7360380 :         HANDLE_UNBLOCK_INTERRUPTIONS();
     975     7360380 : }
     976             : 
     977             : 
     978           0 : ZEND_API void zend_hash_graceful_destroy(HashTable *ht)
     979             : {
     980             :         uint32_t idx;
     981             :         Bucket *p;
     982             : 
     983             :         IS_CONSISTENT(ht);
     984             : 
     985           0 :         for (idx = 0; idx < ht->nNumUsed; idx++) {                
     986           0 :                 p = ht->arData + idx;
     987           0 :                 if (Z_TYPE(p->val) == IS_UNDEF) continue;
     988           0 :                 zend_hash_apply_deleter(ht, idx, p);
     989             :         }
     990           0 :         if (ht->nTableMask) {
     991           0 :                 pefree(ht->arData, ht->u.flags & HASH_FLAG_PERSISTENT);
     992             :         }
     993             : 
     994             :         SET_INCONSISTENT(HT_DESTROYED);
     995           0 : }
     996             : 
     997       81868 : ZEND_API void zend_hash_graceful_reverse_destroy(HashTable *ht)
     998             : {
     999             :         uint32_t idx;
    1000             :         Bucket *p;
    1001             : 
    1002             :         IS_CONSISTENT(ht);
    1003             : 
    1004       81868 :         idx = ht->nNumUsed;
    1005     1914746 :         while (idx > 0) {
    1006     1751010 :                 idx--;
    1007     1751010 :                 p = ht->arData + idx;
    1008     3502020 :                 if (Z_TYPE(p->val) == IS_UNDEF) continue;
    1009     1705661 :                 zend_hash_apply_deleter(ht, idx, p);
    1010             :         }
    1011             : 
    1012       81868 :         if (ht->nTableMask) {
    1013       62235 :                 pefree(ht->arData, ht->u.flags & HASH_FLAG_PERSISTENT);
    1014             :         }
    1015             : 
    1016             :         SET_INCONSISTENT(HT_DESTROYED);
    1017       81868 : }
    1018             : 
    1019             : /* This is used to recurse elements and selectively delete certain entries 
    1020             :  * from a hashtable. apply_func() receives the data and decides if the entry 
    1021             :  * should be deleted or recursion should be stopped. The following three 
    1022             :  * return codes are possible:
    1023             :  * ZEND_HASH_APPLY_KEEP   - continue
    1024             :  * ZEND_HASH_APPLY_STOP   - stop iteration
    1025             :  * ZEND_HASH_APPLY_REMOVE - delete the element, combineable with the former
    1026             :  */
    1027             : 
    1028       91413 : ZEND_API void zend_hash_apply(HashTable *ht, apply_func_t apply_func TSRMLS_DC)
    1029             : {
    1030             :         uint32_t idx;
    1031             :         Bucket *p;
    1032             :         int result;
    1033             : 
    1034             :         IS_CONSISTENT(ht);
    1035             : 
    1036       91413 :         HASH_PROTECT_RECURSION(ht);
    1037     1691686 :         for (idx = 0; idx < ht->nNumUsed; idx++) {
    1038     1600275 :                 p = ht->arData + idx;
    1039     3200550 :                 if (Z_TYPE(p->val) == IS_UNDEF) continue;
    1040             :                 
    1041     1600261 :                 result = apply_func(&p->val TSRMLS_CC);
    1042             :                 
    1043     1600259 :                 if (result & ZEND_HASH_APPLY_REMOVE) {
    1044      107232 :                         zend_hash_apply_deleter(ht, idx, p);
    1045             :                 }
    1046     1600259 :                 if (result & ZEND_HASH_APPLY_STOP) {
    1047           0 :                         break;
    1048             :                 }
    1049             :         }
    1050       91411 :         HASH_UNPROTECT_RECURSION(ht);
    1051       91411 : }
    1052             : 
    1053             : 
    1054      644796 : ZEND_API void zend_hash_apply_with_argument(HashTable *ht, apply_func_arg_t apply_func, void *argument TSRMLS_DC)
    1055             : {
    1056             :     uint32_t idx;
    1057             :         Bucket *p;
    1058             :         int result;
    1059             : 
    1060             :         IS_CONSISTENT(ht);
    1061             : 
    1062      644796 :         HASH_PROTECT_RECURSION(ht);
    1063   188847667 :         for (idx = 0; idx < ht->nNumUsed; idx++) {
    1064   188207023 :                 p = ht->arData + idx;
    1065   376414046 :                 if (Z_TYPE(p->val) == IS_UNDEF) continue;
    1066             : 
    1067   148070830 :                 result = apply_func(&p->val, argument TSRMLS_CC);
    1068             :                 
    1069   148070830 :                 if (result & ZEND_HASH_APPLY_REMOVE) {
    1070     5445233 :                         zend_hash_apply_deleter(ht, idx, p);
    1071             :                 }
    1072   148070830 :                 if (result & ZEND_HASH_APPLY_STOP) {
    1073        4152 :                         break;
    1074             :                 }
    1075             :         }
    1076      644796 :         HASH_UNPROTECT_RECURSION(ht);
    1077      644796 : }
    1078             : 
    1079             : 
    1080         715 : ZEND_API void zend_hash_apply_with_arguments(HashTable *ht TSRMLS_DC, apply_func_args_t apply_func, int num_args, ...)
    1081             : {
    1082             :         uint32_t idx;
    1083             :         Bucket *p;
    1084             :         va_list args;
    1085             :         zend_hash_key hash_key;
    1086             :         int result;
    1087             : 
    1088             :         IS_CONSISTENT(ht);
    1089             : 
    1090         715 :         HASH_PROTECT_RECURSION(ht);
    1091             : 
    1092     1100069 :         for (idx = 0; idx < ht->nNumUsed; idx++) {
    1093     1099354 :                 p = ht->arData + idx;
    1094     2198708 :                 if (Z_TYPE(p->val) == IS_UNDEF) continue;
    1095     1099265 :                 va_start(args, num_args);
    1096     1099265 :                 hash_key.h = p->h;
    1097     1099265 :                 hash_key.key = p->key;
    1098             : 
    1099     1099265 :                 result = apply_func(&p->val TSRMLS_CC, num_args, args, &hash_key);
    1100             : 
    1101     1099265 :                 if (result & ZEND_HASH_APPLY_REMOVE) {
    1102          24 :                         zend_hash_apply_deleter(ht, idx, p);
    1103             :                 }
    1104     1099265 :                 if (result & ZEND_HASH_APPLY_STOP) {
    1105           0 :                         va_end(args);
    1106           0 :                         break;
    1107             :                 }
    1108     1099265 :                 va_end(args);
    1109             :         }
    1110             : 
    1111         715 :         HASH_UNPROTECT_RECURSION(ht);
    1112         715 : }
    1113             : 
    1114             : 
    1115      106781 : ZEND_API void zend_hash_reverse_apply(HashTable *ht, apply_func_t apply_func TSRMLS_DC)
    1116             : {
    1117             :         uint32_t idx;
    1118             :         Bucket *p;
    1119             :         int result;
    1120             : 
    1121             :         IS_CONSISTENT(ht);
    1122             : 
    1123      106781 :         HASH_PROTECT_RECURSION(ht);
    1124      106781 :         idx = ht->nNumUsed;
    1125      716142 :         while (idx > 0) {
    1126      563828 :                 idx--;
    1127      563828 :                 p = ht->arData + idx;
    1128     1127656 :                 if (Z_TYPE(p->val) == IS_UNDEF) continue;
    1129             :                 
    1130      510264 :                 result = apply_func(&p->val TSRMLS_CC);
    1131             : 
    1132      510264 :                 if (result & ZEND_HASH_APPLY_REMOVE) {
    1133      102230 :                         zend_hash_apply_deleter(ht, idx, p);
    1134             :                 }
    1135      510264 :                 if (result & ZEND_HASH_APPLY_STOP) {
    1136       61248 :                         break;
    1137             :                 }
    1138             :         }
    1139      106781 :         HASH_UNPROTECT_RECURSION(ht);
    1140      106781 : }
    1141             : 
    1142             : 
    1143         463 : ZEND_API void zend_hash_copy(HashTable *target, HashTable *source, copy_ctor_func_t pCopyConstructor)
    1144             : {
    1145             :     uint32_t idx;
    1146             :         Bucket *p;
    1147             :         zval *new_entry, *data;
    1148             :         zend_bool setTargetPointer;
    1149             : 
    1150             :         IS_CONSISTENT(source);
    1151             :         IS_CONSISTENT(target);
    1152             : 
    1153         463 :         setTargetPointer = (target->nInternalPointer == INVALID_IDX);
    1154       11854 :         for (idx = 0; idx < source->nNumUsed; idx++) {            
    1155       11391 :                 p = source->arData + idx;
    1156       22782 :                 if (Z_TYPE(p->val) == IS_UNDEF) continue;
    1157             : 
    1158       11391 :                 if (setTargetPointer && source->nInternalPointer == idx) {
    1159         312 :                         target->nInternalPointer = INVALID_IDX;
    1160             :                 }
    1161             :                 /* INDIRECT element may point to UNDEF-ined slots */
    1162       11391 :                 data = &p->val;
    1163       11391 :                 if (Z_TYPE_P(data) == IS_INDIRECT) {
    1164          96 :                         data = Z_INDIRECT_P(data);
    1165          96 :                         if (Z_TYPE_P(data) == IS_UNDEF) {
    1166           0 :                                 continue;
    1167             :                         }
    1168             :                 }
    1169       11391 :                 if (p->key) {
    1170       11302 :                         new_entry = zend_hash_update(target, p->key, data);
    1171             :                 } else {
    1172          89 :                         new_entry = zend_hash_index_update(target, p->h, data);
    1173             :                 }
    1174       11391 :                 if (pCopyConstructor) {
    1175         411 :                         pCopyConstructor(new_entry);
    1176             :                 }
    1177             :         }
    1178         463 :         if (target->nInternalPointer == INVALID_IDX && target->nNumOfElements > 0) {
    1179           0 :                 idx = 0;
    1180           0 :                 while (Z_TYPE(target->arData[idx].val) == IS_UNDEF) {
    1181           0 :                         idx++;
    1182             :                 }
    1183           0 :                 target->nInternalPointer = idx;
    1184             :         }
    1185         463 : }
    1186             : 
    1187             : 
    1188     1289934 : ZEND_API void zend_array_dup(HashTable *target, HashTable *source)
    1189             : {
    1190             :     uint32_t idx, target_idx;
    1191             :         uint32_t nIndex;
    1192             :         Bucket *p, *q;
    1193             :         zval *data;
    1194             : 
    1195             :         IS_CONSISTENT(source);
    1196             :         
    1197     1289934 :         target->nTableMask = source->nTableMask;
    1198     1289934 :         target->nTableSize = source->nTableSize;
    1199     1289934 :         target->pDestructor = source->pDestructor;
    1200     1289934 :         target->nInternalPointer = INVALID_IDX;
    1201     1289934 :         target->u.flags = (source->u.flags & ~HASH_FLAG_PERSISTENT) | HASH_FLAG_APPLY_PROTECTION;
    1202             : 
    1203     1289934 :         target_idx = 0;
    1204     1289934 :         if (target->nTableMask) {
    1205     1128691 :                 if (target->u.flags & HASH_FLAG_PACKED) {
    1206     1071656 :                         target->nNumUsed = source->nNumUsed;
    1207     1071656 :                         target->nNumOfElements = source->nNumOfElements;
    1208     1071656 :                         target->nNextFreeElement = source->nNextFreeElement;
    1209     1071656 :                         target->arData = (Bucket *) safe_pemalloc(target->nTableSize, sizeof(Bucket), 0, 0);
    1210     1071656 :                         target->arHash = (uint32_t*)&uninitialized_bucket;
    1211     1071656 :                         target->nInternalPointer = source->nInternalPointer;
    1212             : 
    1213     4433477 :                         for (idx = 0; idx < source->nNumUsed; idx++) {            
    1214     3361821 :                                 p = source->arData + idx;
    1215     3361821 :                                 q = target->arData + idx;
    1216     6723642 :                                 if (Z_TYPE(p->val) == IS_UNDEF) {
    1217      844980 :                                         ZVAL_UNDEF(&q->val);
    1218      844980 :                                         continue;
    1219             :                                 }
    1220             :                                 /* INDIRECT element may point to UNDEF-ined slots */
    1221     2516841 :                                 data = &p->val;
    1222     2516841 :                                 if (Z_TYPE_P(data) == IS_INDIRECT) {
    1223           0 :                                         data = Z_INDIRECT_P(data);
    1224           0 :                                         if (Z_TYPE_P(data) == IS_UNDEF) {
    1225           0 :                                                 ZVAL_UNDEF(&q->val);
    1226           0 :                                                 continue;
    1227             :                                         }
    1228             :                                 }
    1229             : 
    1230     2516841 :                                 q->h = p->h;
    1231     2516841 :                                 q->key = NULL;
    1232     2516841 :                                 if (Z_OPT_REFCOUNTED_P(data)) {
    1233     2385809 :                                         if (Z_ISREF_P(data) && Z_REFCOUNT_P(data) == 1) {
    1234           1 :                                                 ZVAL_COPY(&q->val, Z_REFVAL_P(data));
    1235             :                                         } else {
    1236     2385786 :                                                 ZVAL_COPY(&q->val, data);
    1237             :                                         }
    1238             :                                 } else {
    1239      131054 :                                         ZVAL_COPY_VALUE(&q->val, data);
    1240             :                                 }
    1241             :                         }
    1242     2143312 :                         if (target->nNumOfElements > 0 &&
    1243     1071656 :                             target->nInternalPointer == INVALID_IDX) {
    1244          41 :                                 idx = 0;
    1245         145 :                                 while (Z_TYPE(target->arData[idx].val) == IS_UNDEF) {
    1246          11 :                                         idx++;
    1247             :                                 }
    1248          41 :                                 target->nInternalPointer = idx;
    1249             :                         }
    1250             :                 } else {
    1251       57035 :                         target->nNextFreeElement = source->nNextFreeElement;
    1252       57035 :                         target->arData = (Bucket *) safe_pemalloc(target->nTableSize, sizeof(Bucket) + sizeof(uint32_t), 0, 0);
    1253       57035 :                         target->arHash = (uint32_t*)(target->arData + target->nTableSize);
    1254       57035 :                         memset(target->arHash, INVALID_IDX, target->nTableSize * sizeof(uint32_t));
    1255             : 
    1256      771843 :                         for (idx = 0; idx < source->nNumUsed; idx++) {            
    1257      714808 :                                 p = source->arData + idx;
    1258     1429616 :                                 if (Z_TYPE(p->val) == IS_UNDEF) continue;
    1259             :                                 /* INDIRECT element may point to UNDEF-ined slots */
    1260      714804 :                                 data = &p->val;
    1261      714804 :                                 if (Z_TYPE_P(data) == IS_INDIRECT) {
    1262       29525 :                                         data = Z_INDIRECT_P(data);
    1263       29525 :                                         if (Z_TYPE_P(data) == IS_UNDEF) {
    1264        5178 :                                                 continue;
    1265             :                                         }
    1266             :                                 }
    1267             : 
    1268      709626 :                                 if (source->nInternalPointer == idx) {
    1269       44046 :                                         target->nInternalPointer = target_idx;
    1270             :                                 }
    1271             : 
    1272      709626 :                                 q = target->arData + target_idx;
    1273      709626 :                                 q->h = p->h;
    1274      709626 :                                 q->key = p->key;
    1275      709626 :                                 if (q->key) {
    1276      703987 :                                         zend_string_addref(q->key);
    1277             :                                 }
    1278      709626 :                                 nIndex = q->h & target->nTableMask;
    1279      709626 :                                 Z_NEXT(q->val) = target->arHash[nIndex];
    1280      709626 :                                 target->arHash[nIndex] = target_idx;
    1281      709626 :                                 if (Z_OPT_REFCOUNTED_P(data)) {
    1282      632911 :                                         if (Z_ISREF_P(data) && Z_REFCOUNT_P(data) == 1) {
    1283          97 :                                                 ZVAL_COPY(&q->val, Z_REFVAL_P(data));
    1284             :                                         } else {
    1285      632171 :                                                 ZVAL_COPY(&q->val, data);
    1286             :                                         }
    1287             :                                 } else {
    1288       77358 :                                         ZVAL_COPY_VALUE(&q->val, data);
    1289             :                                 }
    1290      709626 :                                 target_idx++;
    1291             :                         }
    1292       57035 :                         target->nNumUsed = target_idx;
    1293       57035 :                         target->nNumOfElements = target_idx;
    1294      114051 :                         if (target->nNumOfElements > 0 &&
    1295       57016 :                             target->nInternalPointer == INVALID_IDX) {
    1296       12970 :                                 target->nInternalPointer = 0;
    1297             :                         }
    1298             :                 }
    1299             :         } else {
    1300      161243 :                 target->nNumUsed = 0;
    1301      161243 :                 target->nNumOfElements = 0;
    1302      161243 :                 target->nNextFreeElement = 0;
    1303      161243 :                 target->arData = NULL;
    1304      161243 :                 target->arHash = (uint32_t*)&uninitialized_bucket;
    1305             :         }
    1306     1289934 : }
    1307             : 
    1308             : 
    1309      183884 : ZEND_API void _zend_hash_merge(HashTable *target, HashTable *source, copy_ctor_func_t pCopyConstructor, zend_bool overwrite ZEND_FILE_LINE_DC)
    1310             : {
    1311             :     uint32_t idx;
    1312             :         Bucket *p;
    1313             :         zval *t;
    1314      183884 :         uint32_t mode = (overwrite?HASH_UPDATE:HASH_ADD);
    1315             : 
    1316             :         IS_CONSISTENT(source);
    1317             :         IS_CONSISTENT(target);
    1318             : 
    1319     3167157 :         for (idx = 0; idx < source->nNumUsed; idx++) {
    1320     2983273 :                 p = source->arData + idx;
    1321     5966546 :                 if (Z_TYPE(p->val) == IS_UNDEF) continue;
    1322     2983273 :                 if (p->key) {
    1323     2983257 :                         t = _zend_hash_add_or_update(target, p->key, &p->val, mode ZEND_FILE_LINE_RELAY_CC);
    1324     2983257 :                         if (t && pCopyConstructor) {
    1325     2982675 :                                 pCopyConstructor(t);
    1326             :                         }
    1327             :                 } else {
    1328          16 :                         if ((mode==HASH_UPDATE || !zend_hash_index_exists(target, p->h))) {
    1329           6 :                                 t = zend_hash_index_update(target, p->h, &p->val);
    1330           6 :                                 if (t && pCopyConstructor) {
    1331           6 :                                         pCopyConstructor(t);
    1332             :                                 }
    1333             :                         }
    1334             :                 }
    1335             :         }
    1336      183884 :         if (target->nNumOfElements > 0) {
    1337      183882 :                 idx = 0;
    1338      551646 :                 while (Z_TYPE(target->arData[idx].val) == IS_UNDEF) {
    1339           0 :                         idx++;
    1340             :                 }
    1341      183882 :                 target->nInternalPointer = idx;
    1342             :         }
    1343      183884 : }
    1344             : 
    1345             : 
    1346           0 : static zend_bool zend_hash_replace_checker_wrapper(HashTable *target, zval *source_data, Bucket *p, void *pParam, merge_checker_func_t merge_checker_func)
    1347             : {
    1348             :         zend_hash_key hash_key;
    1349             : 
    1350           0 :         hash_key.h = p->h;
    1351           0 :         hash_key.key = p->key;
    1352           0 :         return merge_checker_func(target, source_data, &hash_key, pParam);
    1353             : }
    1354             : 
    1355             : 
    1356           0 : ZEND_API void zend_hash_merge_ex(HashTable *target, HashTable *source, copy_ctor_func_t pCopyConstructor, merge_checker_func_t pMergeSource, void *pParam)
    1357             : {
    1358             :         uint32_t idx;
    1359             :         Bucket *p;
    1360             :         zval *t;
    1361             : 
    1362             :         IS_CONSISTENT(source);
    1363             :         IS_CONSISTENT(target);
    1364             : 
    1365           0 :         for (idx = 0; idx < source->nNumUsed; idx++) {
    1366           0 :                 p = source->arData + idx;
    1367           0 :                 if (Z_TYPE(p->val) == IS_UNDEF) continue;
    1368           0 :                 if (zend_hash_replace_checker_wrapper(target, &p->val, p, pParam, pMergeSource)) {
    1369           0 :                         t = zend_hash_update(target, p->key, &p->val);
    1370           0 :                         if (t && pCopyConstructor) {
    1371           0 :                                 pCopyConstructor(t);
    1372             :                         }
    1373             :                 }
    1374             :         }
    1375           0 :         if (target->nNumOfElements > 0) {
    1376           0 :                 idx = 0;
    1377           0 :                 while (Z_TYPE(target->arData[idx].val) == IS_UNDEF) {
    1378           0 :                         idx++;
    1379             :                 }
    1380           0 :                 target->nInternalPointer = idx;
    1381             :         }
    1382           0 : }
    1383             : 
    1384             : 
    1385             : /* Returns SUCCESS if found and FAILURE if not. The pointer to the
    1386             :  * data is returned in pData. The reason is that there's no reason
    1387             :  * someone using the hash table might not want to have NULL data
    1388             :  */
    1389    50779732 : ZEND_API zval *zend_hash_find(const HashTable *ht, zend_string *key)
    1390             : {
    1391             :         Bucket *p;
    1392             : 
    1393             :         IS_CONSISTENT(ht);
    1394             : 
    1395    50779732 :         if (ht->u.flags & HASH_FLAG_PACKED) {
    1396         747 :                 return NULL;
    1397             :         }
    1398             : 
    1399    50778985 :         p = zend_hash_find_bucket(ht, key);
    1400    50778985 :         return p ? &p->val : NULL;
    1401             : }
    1402             : 
    1403     2585300 : ZEND_API zval *zend_hash_str_find(const HashTable *ht, const char *str, size_t len)
    1404             : {
    1405             :         zend_ulong h;
    1406             :         Bucket *p;
    1407             : 
    1408             :         IS_CONSISTENT(ht);
    1409             : 
    1410     2585300 :         if (ht->u.flags & HASH_FLAG_PACKED) {
    1411         171 :                 return NULL;
    1412             :         }
    1413             : 
    1414     2585129 :         h = zend_inline_hash_func(str, len);
    1415     2585129 :         p = zend_hash_str_find_bucket(ht, str, len, h);
    1416     2585129 :         return p ? &p->val : NULL;
    1417             : }
    1418             : 
    1419      552250 : ZEND_API zend_bool zend_hash_exists(const HashTable *ht, zend_string *key)
    1420             : {
    1421             :         Bucket *p;
    1422             : 
    1423             :         IS_CONSISTENT(ht);
    1424             : 
    1425      552250 :         if (ht->u.flags & HASH_FLAG_PACKED) {
    1426          55 :                 return 0;
    1427             :         }
    1428             : 
    1429      552195 :         p = zend_hash_find_bucket(ht, key);
    1430      552195 :         return p ? 1 : 0;
    1431             : }
    1432             : 
    1433      848956 : ZEND_API zend_bool zend_hash_str_exists(const HashTable *ht, const char *str, size_t len)
    1434             : {
    1435             :         zend_ulong h;
    1436             :         Bucket *p;
    1437             : 
    1438             :         IS_CONSISTENT(ht);
    1439             : 
    1440      848956 :         if (ht->u.flags & HASH_FLAG_PACKED) {
    1441           0 :                 return 0;
    1442             :         }
    1443             : 
    1444      848956 :         h = zend_inline_hash_func(str, len);
    1445      848956 :         p = zend_hash_str_find_bucket(ht, str, len, h);
    1446      848956 :         return p ? 1 : 0;
    1447             : }
    1448             : 
    1449     6102849 : ZEND_API zval *zend_hash_index_find(const HashTable *ht, zend_ulong h)
    1450             : {
    1451             :         Bucket *p;
    1452             : 
    1453             :         IS_CONSISTENT(ht);
    1454             : 
    1455     6102849 :         if (ht->u.flags & HASH_FLAG_PACKED) {
    1456     4957013 :                 if (h < ht->nNumUsed) {
    1457     4705500 :                         p = ht->arData + h;
    1458     9411000 :                         if (Z_TYPE(p->val) != IS_UNDEF) {
    1459     4704965 :                                 return &p->val;
    1460             :                         }
    1461             :                 }
    1462      252048 :                 return NULL;
    1463             :         }
    1464             : 
    1465     1145836 :         p = zend_hash_index_find_bucket(ht, h);
    1466     1145836 :         return p ? &p->val : NULL;
    1467             : }
    1468             : 
    1469             : 
    1470     1511670 : ZEND_API zend_bool zend_hash_index_exists(const HashTable *ht, zend_ulong h)
    1471             : {
    1472             :         Bucket *p;
    1473             : 
    1474             :         IS_CONSISTENT(ht);
    1475             : 
    1476     1511670 :         if (ht->u.flags & HASH_FLAG_PACKED) {
    1477          56 :                 if (h < ht->nNumUsed) {
    1478         102 :                         if (Z_TYPE(ht->arData[h].val) != IS_UNDEF) {
    1479          50 :                                 return 1;
    1480             :                         }
    1481             :                 }
    1482           6 :                 return 0;
    1483             :         }
    1484             : 
    1485     1511614 :         p = zend_hash_index_find_bucket(ht, h);
    1486     1511614 :         return p ? 1 : 0;
    1487             : }
    1488             : 
    1489             : 
    1490       21616 : ZEND_API void zend_hash_internal_pointer_reset_ex(HashTable *ht, HashPosition *pos)
    1491             : {
    1492             :     uint32_t idx;
    1493             :         
    1494             :         IS_CONSISTENT(ht);
    1495       22105 :         for (idx = 0; idx < ht->nNumUsed; idx++) {
    1496       42496 :                 if (Z_TYPE(ht->arData[idx].val) != IS_UNDEF) {
    1497       20759 :                         *pos = idx;
    1498       20759 :                         return;
    1499             :                 }
    1500             :         }
    1501         857 :         *pos = INVALID_IDX;
    1502             : }
    1503             : 
    1504             : 
    1505             : /* This function will be extremely optimized by remembering 
    1506             :  * the end of the list
    1507             :  */
    1508          47 : ZEND_API void zend_hash_internal_pointer_end_ex(HashTable *ht, HashPosition *pos)
    1509             : {
    1510             :         uint32_t idx;
    1511             :         
    1512             :         IS_CONSISTENT(ht);
    1513             : 
    1514          47 :         idx = ht->nNumUsed;
    1515          94 :         while (idx > 0) {
    1516          45 :                 idx--;
    1517          90 :                 if (Z_TYPE(ht->arData[idx].val) != IS_UNDEF) {
    1518          45 :                         *pos = idx;
    1519          45 :                         return;
    1520             :                 }
    1521             :         }
    1522           2 :         *pos = INVALID_IDX;
    1523             : }
    1524             : 
    1525             : 
    1526       81462 : ZEND_API int zend_hash_move_forward_ex(HashTable *ht, HashPosition *pos)
    1527             : {
    1528       81462 :         uint32_t idx = *pos;
    1529             : 
    1530             :         IS_CONSISTENT(ht);
    1531             : 
    1532       81462 :         if (idx != INVALID_IDX) {
    1533             :                 while (1) {
    1534       81514 :                         idx++;
    1535       81514 :                         if (idx >= ht->nNumUsed) {
    1536       17055 :                                 *pos = INVALID_IDX;
    1537       17055 :                                 return SUCCESS;
    1538             :                         }
    1539      128918 :                         if (Z_TYPE(ht->arData[idx].val) != IS_UNDEF) {
    1540       64383 :                                 *pos = idx;
    1541       64383 :                                 return SUCCESS;
    1542             :                         }
    1543          76 :                 }
    1544             :         } else {
    1545          24 :                 return FAILURE;
    1546             :         }
    1547             : }
    1548             : 
    1549          21 : ZEND_API int zend_hash_move_backwards_ex(HashTable *ht, HashPosition *pos)
    1550             : {
    1551          21 :         uint32_t idx = *pos;
    1552             : 
    1553             :         IS_CONSISTENT(ht);
    1554             : 
    1555          21 :         if (idx != INVALID_IDX) {
    1556          38 :                 while (idx > 0) {
    1557          14 :                         idx--;
    1558          28 :                         if (Z_TYPE(ht->arData[idx].val) != IS_UNDEF) {
    1559          14 :                                 *pos = idx;
    1560          14 :                                 return SUCCESS;
    1561             :                         }
    1562             :                 }
    1563           5 :                 *pos = INVALID_IDX;
    1564           5 :                 return SUCCESS;
    1565             :         } else {
    1566           2 :                 return FAILURE;
    1567             :         }
    1568             : }
    1569             : 
    1570             : 
    1571             : /* This function should be made binary safe  */
    1572       23203 : ZEND_API int zend_hash_get_current_key_ex(const HashTable *ht, zend_string **str_index, zend_ulong *num_index, zend_bool duplicate, HashPosition *pos)
    1573             : {
    1574       23203 :         uint32_t idx = *pos;
    1575             :         Bucket *p;
    1576             : 
    1577             :         IS_CONSISTENT(ht);
    1578       23203 :         if (idx != INVALID_IDX) {
    1579       22282 :                 p = ht->arData + idx;
    1580       22282 :                 if (p->key) {
    1581       20786 :                         if (duplicate) {
    1582           0 :                                 *str_index = zend_string_copy(p->key);
    1583             :                         } else {
    1584       20786 :                                 *str_index = p->key;
    1585             :                         }
    1586       20786 :                         return HASH_KEY_IS_STRING;
    1587             :                 } else {
    1588        1496 :                         *num_index = p->h;
    1589        1496 :                         return HASH_KEY_IS_LONG;
    1590             :                 }
    1591             :         }
    1592         921 :         return HASH_KEY_NON_EXISTENT;
    1593             : }
    1594             : 
    1595        3496 : ZEND_API void zend_hash_get_current_key_zval_ex(const HashTable *ht, zval *key, HashPosition *pos)
    1596             : {
    1597        3496 :         uint32_t idx = *pos;
    1598             :         Bucket *p;
    1599             : 
    1600             :         IS_CONSISTENT(ht);
    1601        3496 :         if (idx == INVALID_IDX) {
    1602          54 :                 ZVAL_NULL(key);
    1603             :         } else {
    1604        3442 :                 p = ht->arData + idx;
    1605        3442 :                 if (p->key) {
    1606         669 :                         ZVAL_STR_COPY(key, p->key);
    1607             :                 } else {
    1608        2773 :                         ZVAL_LONG(key, p->h);
    1609             :                 }
    1610             :         }
    1611        3496 : }
    1612             : 
    1613       68692 : ZEND_API int zend_hash_get_current_key_type_ex(HashTable *ht, HashPosition *pos)
    1614             : {
    1615       68692 :     uint32_t idx = *pos;
    1616             :         Bucket *p;
    1617             : 
    1618             :         IS_CONSISTENT(ht);
    1619       68692 :         if (idx != INVALID_IDX) {
    1620       53529 :                 p = ht->arData + idx;
    1621       53529 :                 if (p->key) {
    1622       51003 :                         return HASH_KEY_IS_STRING;
    1623             :                 } else {
    1624        2526 :                         return HASH_KEY_IS_LONG;
    1625             :                 }
    1626             :         }
    1627       15163 :         return HASH_KEY_NON_EXISTENT;
    1628             : }
    1629             : 
    1630             : 
    1631       74770 : ZEND_API zval *zend_hash_get_current_data_ex(HashTable *ht, HashPosition *pos)
    1632             : {
    1633       74770 :         uint32_t idx = *pos;
    1634             :         Bucket *p;
    1635             : 
    1636             :         IS_CONSISTENT(ht);
    1637       74770 :         if (idx != INVALID_IDX) {
    1638       73607 :                 p = ht->arData + idx;
    1639       73607 :                 return &p->val;
    1640             :         } else {
    1641        1163 :                 return NULL;
    1642             :         }
    1643             : }
    1644             : 
    1645       22128 : ZEND_API int zend_hash_sort(HashTable *ht, sort_func_t sort_func,
    1646             :                                                         compare_func_t compar, zend_bool renumber TSRMLS_DC)
    1647             : {
    1648             :         Bucket *p;
    1649             :         uint32_t i, j;
    1650             : 
    1651             :         IS_CONSISTENT(ht);
    1652             : 
    1653       22128 :         if (!(ht->nNumOfElements>1) && !(renumber && ht->nNumOfElements>0)) { /* Doesn't require sorting */
    1654         288 :                 return SUCCESS;
    1655             :         }
    1656             : 
    1657       21840 :         if (ht->nNumUsed == ht->nNumOfElements) {
    1658       21730 :                 i = ht->nNumUsed;
    1659             :         } else {
    1660         787 :                 for (j = 0, i = 0; j < ht->nNumUsed; j++) {
    1661         677 :                         p = ht->arData + j;
    1662        1354 :                         if (Z_TYPE(p->val) == IS_UNDEF) continue;
    1663         520 :                         if (i != j) {
    1664         504 :                                 ht->arData[i] = *p;
    1665             :                         }
    1666         520 :                         i++;
    1667             :                 }
    1668             :         }
    1669             : 
    1670       21840 :         (*sort_func)((void *) ht->arData, i, sizeof(Bucket), compar TSRMLS_CC);
    1671             : 
    1672       21839 :         HANDLE_BLOCK_INTERRUPTIONS();
    1673       21839 :         ht->nNumUsed = i;
    1674       21839 :         ht->nInternalPointer = 0;
    1675             : 
    1676       21839 :         if (renumber) {
    1677       15272 :                 for (j = 0; j < i; j++) {
    1678       14983 :                         p = ht->arData + j;
    1679       14983 :                         p->h = j;
    1680       14983 :                         if (p->key) {
    1681         288 :                                 zend_string_release(p->key);
    1682         288 :                                 p->key = NULL;
    1683             :                         }
    1684             :                 }
    1685             :         }
    1686       21839 :         if (renumber) {
    1687         289 :                 ht->nNextFreeElement = i;
    1688             :         }
    1689       21839 :         if (ht->u.flags & HASH_FLAG_PACKED) {
    1690         502 :                 if (!renumber) {
    1691         261 :                         zend_hash_packed_to_hash(ht);
    1692             :                 }
    1693             :         } else {
    1694       21337 :                 if (renumber) {
    1695          48 :                         ht->u.flags |= HASH_FLAG_PACKED;
    1696          48 :                         ht->arData = erealloc(ht->arData, ht->nTableSize * sizeof(Bucket));
    1697          48 :                         ht->arHash = (uint32_t*)&uninitialized_bucket;
    1698             :                 } else {
    1699       21289 :                         zend_hash_rehash(ht);
    1700             :                 }
    1701             :         }
    1702             : 
    1703       21839 :         HANDLE_UNBLOCK_INTERRUPTIONS();
    1704             : 
    1705       21839 :         return SUCCESS;
    1706             : }
    1707             : 
    1708             : 
    1709        1131 : ZEND_API int zend_hash_compare(HashTable *ht1, HashTable *ht2, compare_func_t compar, zend_bool ordered TSRMLS_DC)
    1710             : {
    1711             :         uint32_t idx1, idx2;
    1712        1131 :         Bucket *p1, *p2 = NULL;
    1713             :         int result;
    1714             :         zval *pData1, *pData2;
    1715             : 
    1716             :         IS_CONSISTENT(ht1);
    1717             :         IS_CONSISTENT(ht2);
    1718             : 
    1719        1131 :         HASH_PROTECT_RECURSION(ht1); 
    1720        1131 :         HASH_PROTECT_RECURSION(ht2); 
    1721             : 
    1722        1131 :         result = ht1->nNumOfElements - ht2->nNumOfElements;
    1723        1131 :         if (result!=0) {
    1724         531 :                 HASH_UNPROTECT_RECURSION(ht1); 
    1725         531 :                 HASH_UNPROTECT_RECURSION(ht2); 
    1726         531 :                 return result;
    1727             :         }
    1728             : 
    1729        4352 :         for (idx1 = 0, idx2 = 0; idx1 < ht1->nNumUsed; idx1++) {
    1730        3926 :                 p1 = ht1->arData + idx1;
    1731        7852 :                 if (Z_TYPE(p1->val) == IS_UNDEF) continue;
    1732             : 
    1733        3913 :                 if (ordered) {
    1734             :                         while (1) {
    1735        1134 :                                 p2 = ht2->arData + idx2;
    1736        1134 :                                 if (idx2 == ht2->nNumUsed) {
    1737           0 :                                         HASH_UNPROTECT_RECURSION(ht1); 
    1738           0 :                                         HASH_UNPROTECT_RECURSION(ht2); 
    1739           0 :                                         return 1; /* That's not supposed to happen */
    1740             :                                 }
    1741        2268 :                                 if (Z_TYPE(p2->val) != IS_UNDEF) break;
    1742           1 :                                 idx2++;
    1743           1 :                         }                                               
    1744        1500 :                         if (p1->key == NULL && p2->key == NULL) { /* numeric indices */
    1745         368 :                                 result = p1->h - p2->h;
    1746         368 :                                 if (result != 0) {
    1747           1 :                                         HASH_UNPROTECT_RECURSION(ht1); 
    1748           1 :                                         HASH_UNPROTECT_RECURSION(ht2); 
    1749           1 :                                         return result;
    1750             :                                 }
    1751             :                         } else { /* string indices */
    1752         765 :                                 result = (p1->key ? p1->key->len : 0) - (p2->key ? p2->key->len : 0);
    1753         765 :                                 if (result != 0) {
    1754           0 :                                         HASH_UNPROTECT_RECURSION(ht1); 
    1755           0 :                                         HASH_UNPROTECT_RECURSION(ht2); 
    1756           0 :                                         return result;
    1757             :                                 }
    1758         765 :                                 result = memcmp(p1->key->val, p2->key->val, p1->key->len);
    1759         765 :                                 if (result != 0) {
    1760           0 :                                         HASH_UNPROTECT_RECURSION(ht1); 
    1761           0 :                                         HASH_UNPROTECT_RECURSION(ht2); 
    1762           0 :                                         return result;
    1763             :                                 }
    1764             :                         }
    1765        1132 :                         pData2 = &p2->val;
    1766             :                 } else {
    1767        2780 :                         if (p1->key == NULL) { /* numeric index */
    1768         219 :                                 pData2 = zend_hash_index_find(ht2, p1->h);
    1769         219 :                                 if (pData2 == NULL) {
    1770           4 :                                         HASH_UNPROTECT_RECURSION(ht1); 
    1771           4 :                                         HASH_UNPROTECT_RECURSION(ht2); 
    1772           4 :                                         return 1;
    1773             :                                 }
    1774             :                         } else { /* string index */
    1775        2561 :                                 pData2 = zend_hash_find(ht2, p1->key);
    1776        2561 :                                 if (pData2 == NULL) {
    1777          24 :                                         HASH_UNPROTECT_RECURSION(ht1); 
    1778          24 :                                         HASH_UNPROTECT_RECURSION(ht2); 
    1779          24 :                                         return 1;
    1780             :                                 }
    1781             :                         }
    1782             :                 }
    1783        3884 :                 pData1 = &p1->val;
    1784        3884 :                 if (Z_TYPE_P(pData1) == IS_INDIRECT) {
    1785         118 :                         pData1 = Z_INDIRECT_P(pData1);
    1786             :                 }
    1787        3884 :                 if (Z_TYPE_P(pData2) == IS_INDIRECT) {
    1788         118 :                         pData2 = Z_INDIRECT_P(pData2);
    1789             :                 }
    1790        3884 :                 if (Z_TYPE_P(pData1) == IS_UNDEF) {
    1791           0 :                         if (Z_TYPE_P(pData2) != IS_UNDEF) {
    1792           0 :                                 return -1;
    1793             :                         }
    1794        3884 :                 } else if (Z_TYPE_P(pData2) == IS_UNDEF) {
    1795           0 :                         return 1;
    1796             :                 } else {
    1797        3884 :                         result = compar(pData1, pData2 TSRMLS_CC);
    1798             :                 }
    1799        3884 :                 if (result != 0) {
    1800         145 :                         HASH_UNPROTECT_RECURSION(ht1); 
    1801         145 :                         HASH_UNPROTECT_RECURSION(ht2); 
    1802         145 :                         return result;
    1803             :                 }
    1804        3739 :                 if (ordered) {
    1805        1128 :                         idx2++;
    1806             :                 }
    1807             :         }
    1808             :         
    1809         426 :         HASH_UNPROTECT_RECURSION(ht1); 
    1810         426 :         HASH_UNPROTECT_RECURSION(ht2); 
    1811         426 :         return 0;
    1812             : }
    1813             : 
    1814             : 
    1815          82 : ZEND_API zval *zend_hash_minmax(const HashTable *ht, compare_func_t compar, uint32_t flag TSRMLS_DC)
    1816             : {
    1817             :         uint32_t idx;
    1818             :         Bucket *p, *res;
    1819             : 
    1820             :         IS_CONSISTENT(ht);
    1821             : 
    1822          82 :         if (ht->nNumOfElements == 0 ) {
    1823           4 :                 return NULL;
    1824             :         }
    1825             : 
    1826          78 :         idx = 0;
    1827             :         while (1) {
    1828          78 :                 if (idx == ht->nNumUsed) {
    1829           0 :                         return NULL;
    1830             :                 }
    1831         156 :                 if (Z_TYPE(ht->arData[idx].val) != IS_UNDEF) break;
    1832           0 :                 idx++;
    1833           0 :         }
    1834          78 :         res = ht->arData + idx;
    1835         376 :         for (; idx < ht->nNumUsed; idx++) {
    1836         298 :                 p = ht->arData + idx;
    1837         596 :                 if (Z_TYPE(p->val) == IS_UNDEF) continue;
    1838             :                 
    1839         298 :                 if (flag) {
    1840         229 :                         if (compar(res, p TSRMLS_CC) < 0) { /* max */
    1841          20 :                                 res = p;
    1842             :                         }
    1843             :                 } else {
    1844          69 :                         if (compar(res, p TSRMLS_CC) > 0) { /* min */
    1845           6 :                                 res = p;
    1846             :                         }
    1847             :                 }
    1848             :         }
    1849          78 :         return &res->val;
    1850             : }
    1851             : 
    1852      382442 : ZEND_API int _zend_handle_numeric_str_ex(const char *key, size_t length, zend_ulong *idx)
    1853             : {
    1854      382442 :         register const char *tmp = key;
    1855             :         const char *end;
    1856             : 
    1857      382442 :         if (*tmp > '9') {
    1858           0 :                 return 0;
    1859      382442 :         } else if (*tmp < '0') {
    1860          59 :                 if (*tmp != '-') {
    1861           0 :                         return 0;
    1862             :                 }
    1863          59 :                 tmp++;
    1864          59 :                 if (*tmp > '9' || *tmp < '0') {
    1865           0 :                         return 0;
    1866             :                 }
    1867             :         }
    1868             : 
    1869             :         /* possibly a numeric index */
    1870      382442 :         end = key + length;
    1871             : 
    1872     1127184 :         if ((*end != '\0') /* not a null terminated string */
    1873      382442 :          || (*tmp == '0' && length > 1) /* numbers with leading zeros */
    1874      362300 :          || (end - tmp > MAX_LENGTH_OF_LONG - 1) /* number too long */
    1875             :          || (SIZEOF_ZEND_LONG == 4 &&
    1876             :              end - tmp == MAX_LENGTH_OF_LONG - 1 &&
    1877             :              *tmp > '2')) { /* overflow */
    1878       20169 :                 return 0;
    1879             :         }
    1880      362273 :         *idx = (*tmp - '0');
    1881             :         while (1) {
    1882     1442833 :                 ++tmp;
    1883     1442833 :                 if (tmp == end) {
    1884      362010 :                         if (*key == '-') {
    1885          28 :                                 if (*idx-1 > ZEND_LONG_MAX) { /* overflow */
    1886           0 :                                         return 0;
    1887             :                                 }
    1888          28 :                                 *idx = 0 - *idx;
    1889      361982 :                         } else if (*idx > ZEND_LONG_MAX) { /* overflow */
    1890           0 :                                 return 0;
    1891             :                         }
    1892      362010 :                         return 1;
    1893             :                 }
    1894     2161383 :                 if (*tmp <= '9' && *tmp >= '0') {
    1895     1080560 :                         *idx = (*idx * 10) + (*tmp - '0');
    1896             :                 } else {
    1897         263 :                         return 0;
    1898             :                 }
    1899     1080560 :         }
    1900             : }
    1901             : 
    1902             : /*
    1903             :  * Local variables:
    1904             :  * tab-width: 4
    1905             :  * c-basic-offset: 4
    1906             :  * indent-tabs-mode: t
    1907             :  * End:
    1908             :  */

Generated by: LCOV version 1.10

Generated at Wed, 22 Oct 2014 07:24:46 +0000 (25 hours ago)

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