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: 862 954 90.4 %
Date: 2015-01-26 Functions: 61 69 88.4 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :    +----------------------------------------------------------------------+
       3             :    | Zend Engine                                                          |
       4             :    +----------------------------------------------------------------------+
       5             :    | Copyright (c) 1998-2015 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             : #include "zend_variables.h"
      25             : 
      26             : #if ZEND_DEBUG
      27             : /*
      28             : #define HASH_MASK_CONSISTENCY   0x60
      29             : */
      30             : #define HT_OK                                   0x00
      31             : #define HT_IS_DESTROYING                0x20
      32             : #define HT_DESTROYED                    0x40
      33             : #define HT_CLEANING                             0x60
      34             : 
      35             : static void _zend_is_inconsistent(const HashTable *ht, const char *file, int line)
      36             : {
      37             :         if ((ht->u.flags & HASH_MASK_CONSISTENCY) == HT_OK) {
      38             :                 return;
      39             :         }
      40             :         switch ((ht->u.flags & HASH_MASK_CONSISTENCY)) {
      41             :                 case HT_IS_DESTROYING:
      42             :                         zend_output_debug_string(1, "%s(%d) : ht=%p is being destroyed", file, line, ht);
      43             :                         break;
      44             :                 case HT_DESTROYED:
      45             :                         zend_output_debug_string(1, "%s(%d) : ht=%p is already destroyed", file, line, ht);
      46             :                         break;
      47             :                 case HT_CLEANING:
      48             :                         zend_output_debug_string(1, "%s(%d) : ht=%p is being cleaned", file, line, ht);
      49             :                         break;
      50             :                 default:
      51             :                         zend_output_debug_string(1, "%s(%d) : ht=%p is inconsistent", file, line, ht);
      52             :                         break;
      53             :         }
      54             :         zend_bailout();
      55             : }
      56             : #define IS_CONSISTENT(a) _zend_is_inconsistent(a, __FILE__, __LINE__);
      57             : #define SET_INCONSISTENT(n) do { \
      58             :                 (ht)->u.flags |= n; \
      59             :         } while (0)
      60             : #else
      61             : #define IS_CONSISTENT(a)
      62             : #define SET_INCONSISTENT(n)
      63             : #endif
      64             : 
      65             : #define HASH_PROTECT_RECURSION(ht)                                                                                                              \
      66             :         if ((ht)->u.flags & HASH_FLAG_APPLY_PROTECTION) {                                                                        \
      67             :                 if ((ht)->u.flags >= (3 << 8)) {                                                                                            \
      68             :                         zend_error_noreturn(E_ERROR, "Nesting level too deep - recursive dependency?");\
      69             :                 }                                                                                                                                                               \
      70             :                 ZEND_HASH_INC_APPLY_COUNT(ht);                                                                                                  \
      71             :         }
      72             : 
      73             : #define HASH_UNPROTECT_RECURSION(ht)                                                                                                    \
      74             :         if ((ht)->u.flags & HASH_FLAG_APPLY_PROTECTION) {                                                                        \
      75             :                 ZEND_HASH_DEC_APPLY_COUNT(ht);                                                                                                  \
      76             :         }
      77             : 
      78             : #define ZEND_HASH_IF_FULL_DO_RESIZE(ht)                         \
      79             :         if ((ht)->nNumUsed >= (ht)->nTableSize) {              \
      80             :                 zend_hash_do_resize(ht);                                        \
      81             :         }
      82             : 
      83             : static void zend_hash_do_resize(HashTable *ht);
      84             : 
      85             : #define CHECK_INIT(ht, packed) do { \
      86             :         if (UNEXPECTED(!((ht)->u.flags & HASH_FLAG_INITIALIZED))) { \
      87             :                 if (packed) { \
      88             :                         (ht)->u.flags |= HASH_FLAG_INITIALIZED | HASH_FLAG_PACKED; \
      89             :                         (ht)->arData = (Bucket *) safe_pemalloc((ht)->nTableSize, sizeof(Bucket), 0, (ht)->u.flags & HASH_FLAG_PERSISTENT); \
      90             :                 } else { \
      91             :                         (ht)->u.flags |= HASH_FLAG_INITIALIZED; \
      92             :                         (ht)->nTableMask = (ht)->nTableSize - 1; \
      93             :                         (ht)->arData = (Bucket *) safe_pemalloc((ht)->nTableSize, sizeof(Bucket) + sizeof(uint32_t), 0, (ht)->u.flags & HASH_FLAG_PERSISTENT); \
      94             :                         (ht)->arHash = (uint32_t*)((ht)->arData + (ht)->nTableSize); \
      95             :                         memset((ht)->arHash, INVALID_IDX, (ht)->nTableSize * sizeof(uint32_t)); \
      96             :                 } \
      97             :         } \
      98             : } while (0)
      99             : 
     100             : static const uint32_t uninitialized_bucket = {INVALID_IDX};
     101             : 
     102    17000364 : ZEND_API void _zend_hash_init(HashTable *ht, uint32_t nSize, dtor_func_t pDestructor, zend_bool persistent ZEND_FILE_LINE_DC)
     103             : {
     104             : #if defined(ZEND_WIN32)
     105             :         unsigned long index;
     106             : #endif
     107             :         /* Use big enough power of 2 */
     108             :         /* size should be between 8 and 0x80000000 */
     109    17000364 :         nSize = (nSize <= 8 ? 8 : (nSize >= 0x80000000 ? 0x80000000 : nSize));
     110             : 
     111             : #if defined(ZEND_WIN32)
     112             :         if (BitScanReverse(&index, nSize - 1)) {
     113             :                 ht->nTableSize = 0x2 << ((31 - index) ^ 0x1f);
     114             :         } else {
     115             :                 /* nSize is ensured to be in the valid range, fall back to it
     116             :                    rather than using an undefined bis scan result. */
     117             :                 ht->nTableSize = nSize;
     118             :         }
     119             : #elif defined(__GNUC__)
     120    17000364 :         ht->nTableSize =  0x2 << (__builtin_clz(nSize - 1) ^ 0x1f);
     121             : #else
     122             :         nSize -= 1;
     123             :         nSize |= (nSize >> 1);
     124             :         nSize |= (nSize >> 2);
     125             :         nSize |= (nSize >> 4);
     126             :         nSize |= (nSize >> 8);
     127             :         nSize |= (nSize >> 16);
     128             :         ht->nTableSize = nSize + 1;
     129             : #endif
     130             : 
     131    17000364 :         ht->nTableMask = 0;
     132    17000364 :         ht->nNumUsed = 0;
     133    17000364 :         ht->nNumOfElements = 0;
     134    17000364 :         ht->nNextFreeElement = 0;
     135    17000364 :         ht->arData = NULL;
     136    17000364 :         ht->arHash = (uint32_t*)&uninitialized_bucket;
     137    17000364 :         ht->pDestructor = pDestructor;
     138    17000364 :         ht->nInternalPointer = INVALID_IDX;
     139    17000364 :         ht->u.flags = (persistent ? HASH_FLAG_PERSISTENT : 0) | HASH_FLAG_APPLY_PROTECTION;
     140    17000364 : }
     141             : 
     142       37175 : static void zend_hash_packed_grow(HashTable *ht)
     143             : {
     144       37175 :         HANDLE_BLOCK_INTERRUPTIONS();
     145       37175 :         ht->arData = (Bucket *) safe_perealloc(ht->arData, (ht->nTableSize << 1), sizeof(Bucket), 0, ht->u.flags & HASH_FLAG_PERSISTENT);
     146       37175 :         ht->nTableSize = (ht->nTableSize << 1);
     147       37175 :         HANDLE_UNBLOCK_INTERRUPTIONS();
     148       37175 : }
     149             : 
     150      172989 : ZEND_API void zend_hash_real_init(HashTable *ht, zend_bool packed)
     151             : {
     152             :         IS_CONSISTENT(ht);
     153             : 
     154      172989 :         CHECK_INIT(ht, packed);
     155      172989 : }
     156             : 
     157       28677 : ZEND_API void zend_hash_packed_to_hash(HashTable *ht)
     158             : {
     159       28677 :         HANDLE_BLOCK_INTERRUPTIONS();
     160       28677 :         ht->u.flags &= ~HASH_FLAG_PACKED;
     161       28677 :         ht->nTableMask = ht->nTableSize - 1;
     162       28677 :         ht->arData = (Bucket *) safe_perealloc(ht->arData, ht->nTableSize, sizeof(Bucket) + sizeof(uint32_t), 0, ht->u.flags & HASH_FLAG_PERSISTENT);
     163       28677 :         ht->arHash = (uint32_t*)(ht->arData + ht->nTableSize);
     164       28677 :         zend_hash_rehash(ht);
     165       28677 :         HANDLE_UNBLOCK_INTERRUPTIONS();
     166       28677 : }
     167             : 
     168          15 : ZEND_API void zend_hash_to_packed(HashTable *ht)
     169             : {
     170          15 :         HANDLE_BLOCK_INTERRUPTIONS();
     171          15 :         ht->u.flags |= HASH_FLAG_PACKED;
     172          15 :         ht->nTableMask = 0;
     173          30 :         ht->arData = (Bucket *) perealloc(ht->arData, ht->nTableSize * sizeof(Bucket), ht->u.flags & HASH_FLAG_PERSISTENT);
     174          15 :         ht->arHash = (uint32_t*)&uninitialized_bucket;
     175          15 :         HANDLE_UNBLOCK_INTERRUPTIONS();
     176          15 : }
     177             : 
     178    11371039 : 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)
     179             : {
     180    11371039 :         _zend_hash_init(ht, nSize, pDestructor, persistent ZEND_FILE_LINE_CC);
     181    11371039 :         if (!bApplyProtection) {
     182    11371039 :                 ht->u.flags &= ~HASH_FLAG_APPLY_PROTECTION;
     183             :         }
     184    11371039 : }
     185             : 
     186             : 
     187           0 : ZEND_API void zend_hash_set_apply_protection(HashTable *ht, zend_bool bApplyProtection)
     188             : {
     189           0 :         if (bApplyProtection) {
     190           0 :                 ht->u.flags |= HASH_FLAG_APPLY_PROTECTION;
     191             :         } else {
     192           0 :                 ht->u.flags &= ~HASH_FLAG_APPLY_PROTECTION;
     193             :         }
     194           0 : }
     195             : 
     196             : static zend_always_inline Bucket *zend_hash_find_bucket(const HashTable *ht, zend_string *key)
     197             : {
     198             :         zend_ulong h;
     199             :         uint32_t nIndex;
     200             :         uint32_t idx;
     201             :         Bucket *p;
     202             : 
     203   282929499 :         h = zend_string_hash_val(key);
     204   282929499 :         nIndex = h & ht->nTableMask;
     205   282929499 :         idx = ht->arHash[nIndex];
     206   441272092 :         while (idx != INVALID_IDX) {
     207   172405798 :                 p = ht->arData + idx;
     208   352059225 :                 if ((p->key == key) || /* check for the the same interned string */
     209   163668683 :                         (p->h == h &&
     210     5328248 :                          p->key &&
     211     5328248 :                          p->key->len == key->len &&
     212     5328248 :                          memcmp(p->key->val, key->val, key->len) == 0)) {
     213    14063205 :                         return p;
     214             :                 }
     215   158342593 :                 idx = Z_NEXT(p->val);
     216             :         }
     217   268866294 :         return NULL;
     218             : }
     219             : 
     220             : static zend_always_inline Bucket *zend_hash_str_find_bucket(const HashTable *ht, const char *str, size_t len, zend_ulong h)
     221             : {
     222             :         uint32_t nIndex;
     223             :         uint32_t idx;
     224             :         Bucket *p;
     225             : 
     226     3483302 :         nIndex = h & ht->nTableMask;
     227     3483302 :         idx = ht->arHash[nIndex];
     228     4322658 :         while (idx != INVALID_IDX) {
     229             :                 ZEND_ASSERT(idx < ht->nTableSize);
     230     3401524 :                 p = ht->arData + idx;
     231    11088079 :                 if ((p->h == h)
     232             :                          && p->key
     233     5124370 :                          && (p->key->len == len)
     234     2562185 :                          && !memcmp(p->key->val, str, len)) {
     235     2562168 :                         return p;
     236             :                 }
     237      839356 :                 idx = Z_NEXT(p->val);
     238             :         }
     239      921134 :         return NULL;
     240             : }
     241             : 
     242             : static zend_always_inline Bucket *zend_hash_index_find_bucket(const HashTable *ht, zend_ulong h)
     243             : {
     244             :         uint32_t nIndex;
     245             :         uint32_t idx;
     246             :         Bucket *p;
     247             : 
     248     3990435 :         nIndex = h & ht->nTableMask;
     249     3990435 :         idx = ht->arHash[nIndex];
     250     5333849 :         while (idx != INVALID_IDX) {
     251             :                 ZEND_ASSERT(idx < ht->nTableSize);
     252     2350498 :                 p = ht->arData + idx;
     253     2350498 :                 if (p->h == h && !p->key) {
     254     1007084 :                         return p;
     255             :                 }
     256     1343414 :                 idx = Z_NEXT(p->val);
     257             :         }
     258     2983351 :         return NULL;
     259             : }
     260             : 
     261             : 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)
     262             : {
     263             :         zend_ulong h;
     264             :         uint32_t nIndex;
     265             :         uint32_t idx;
     266             :         Bucket *p;
     267             : 
     268             :         IS_CONSISTENT(ht);
     269             : 
     270   266304226 :         if (UNEXPECTED(!(ht->u.flags & HASH_FLAG_INITIALIZED))) {
     271     6829333 :                 CHECK_INIT(ht, 0);
     272             :                 goto add_to_hash;
     273   259474893 :         } else if (ht->u.flags & HASH_FLAG_PACKED) {
     274       27653 :                 zend_hash_packed_to_hash(ht);
     275   259447240 :         } else if ((flag & HASH_ADD_NEW) == 0) {
     276   230783332 :                 p = zend_hash_find_bucket(ht, key);
     277             : 
     278   230783332 :                 if (p) {
     279             :                         zval *data;
     280             : 
     281     1041281 :                         if (flag & HASH_ADD) {
     282      261498 :                                 return NULL;
     283             :                         }
     284             :                         ZEND_ASSERT(&p->val != pData);
     285      779783 :                         data = &p->val;
     286      834834 :                         if ((flag & HASH_UPDATE_INDIRECT) && Z_TYPE_P(data) == IS_INDIRECT) {
     287         258 :                                 data = Z_INDIRECT_P(data);
     288             :                         }
     289      779783 :                         HANDLE_BLOCK_INTERRUPTIONS();
     290      779783 :                         if (ht->pDestructor) {
     291      737839 :                                 ht->pDestructor(data);
     292             :                         }
     293      779783 :                         ZVAL_COPY_VALUE(data, pData);
     294      779783 :                         HANDLE_UNBLOCK_INTERRUPTIONS();
     295      779783 :                         return data;
     296             :                 }
     297             :         }
     298             : 
     299   258433612 :         ZEND_HASH_IF_FULL_DO_RESIZE(ht);                /* If the Hash table is full, resize it */
     300             : 
     301             : add_to_hash:
     302   265262945 :         HANDLE_BLOCK_INTERRUPTIONS();
     303   265262945 :         idx = ht->nNumUsed++;
     304   265262945 :         ht->nNumOfElements++;
     305   265262945 :         if (ht->nInternalPointer == INVALID_IDX) {
     306     6971709 :                 ht->nInternalPointer = idx;
     307             :         }
     308   265262945 :         p = ht->arData + idx;
     309   265262945 :         p->h = h = zend_string_hash_val(key);
     310   265262945 :         p->key = key;
     311             :         zend_string_addref(key);
     312   265262945 :         ZVAL_COPY_VALUE(&p->val, pData);
     313   265262945 :         nIndex = h & ht->nTableMask;
     314   265262945 :         Z_NEXT(p->val) = ht->arHash[nIndex];
     315   265262945 :         ht->arHash[nIndex] = idx;
     316   265262945 :         HANDLE_UNBLOCK_INTERRUPTIONS();
     317             : 
     318   265262945 :         return &p->val;
     319             : }
     320             : 
     321     3036251 : ZEND_API zval *_zend_hash_add_or_update(HashTable *ht, zend_string *key, zval *pData, uint32_t flag ZEND_FILE_LINE_DC)
     322             : {
     323     3036251 :         return _zend_hash_add_or_update_i(ht, key, pData, flag ZEND_FILE_LINE_RELAY_CC);
     324             : }
     325             : 
     326   142115171 : ZEND_API zval *_zend_hash_add(HashTable *ht, zend_string *key, zval *pData ZEND_FILE_LINE_DC)
     327             : {
     328   142115171 :         return _zend_hash_add_or_update_i(ht, key, pData, HASH_ADD ZEND_FILE_LINE_RELAY_CC);
     329             : }
     330             : 
     331    53748778 : ZEND_API zval *_zend_hash_update(HashTable *ht, zend_string *key, zval *pData ZEND_FILE_LINE_DC)
     332             : {
     333    53748778 :         return _zend_hash_add_or_update_i(ht, key, pData, HASH_UPDATE ZEND_FILE_LINE_RELAY_CC);
     334             : }
     335             : 
     336        1095 : ZEND_API zval *_zend_hash_update_ind(HashTable *ht, zend_string *key, zval *pData ZEND_FILE_LINE_DC)
     337             : {
     338        1095 :         return _zend_hash_add_or_update_i(ht, key, pData, HASH_UPDATE | HASH_UPDATE_INDIRECT ZEND_FILE_LINE_RELAY_CC);
     339             : }
     340             : 
     341    29756938 : ZEND_API zval *_zend_hash_add_new(HashTable *ht, zend_string *key, zval *pData ZEND_FILE_LINE_DC)
     342             : {
     343    29756938 :         return _zend_hash_add_or_update_i(ht, key, pData, HASH_ADD_NEW ZEND_FILE_LINE_RELAY_CC);
     344             : }
     345             : 
     346           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)
     347             : {
     348           0 :         zend_string *key = zend_string_init(str, len, ht->u.flags & HASH_FLAG_PERSISTENT);
     349           0 :         zval *ret = _zend_hash_add_or_update_i(ht, key, pData, flag ZEND_FILE_LINE_CC);
     350             :         zend_string_release(key);
     351           0 :         return ret;
     352             : }
     353             : 
     354    23548434 : ZEND_API zval *_zend_hash_str_update(HashTable *ht, const char *str, size_t len, zval *pData ZEND_FILE_LINE_DC)
     355             : {
     356    47096868 :         zend_string *key = zend_string_init(str, len, ht->u.flags & HASH_FLAG_PERSISTENT);
     357    23548434 :         zval *ret = _zend_hash_add_or_update_i(ht, key, pData, HASH_UPDATE ZEND_FILE_LINE_CC);
     358             :         zend_string_release(key);
     359    23548434 :         return ret;
     360             : }
     361             : 
     362     1291543 : ZEND_API zval *_zend_hash_str_update_ind(HashTable *ht, const char *str, size_t len, zval *pData ZEND_FILE_LINE_DC)
     363             : {
     364     2583086 :         zend_string *key = zend_string_init(str, len, ht->u.flags & HASH_FLAG_PERSISTENT);
     365     1291543 :         zval *ret = _zend_hash_add_or_update_i(ht, key, pData, HASH_UPDATE | HASH_UPDATE_INDIRECT ZEND_FILE_LINE_CC);
     366             :         zend_string_release(key);
     367     1291543 :         return ret;
     368             : }
     369             : 
     370    12803186 : ZEND_API zval *_zend_hash_str_add(HashTable *ht, const char *str, size_t len, zval *pData ZEND_FILE_LINE_DC)
     371             : {
     372    25606372 :         zend_string *key = zend_string_init(str, len, ht->u.flags & HASH_FLAG_PERSISTENT);
     373    12803186 :         zval *ret = _zend_hash_add_or_update_i(ht, key, pData, HASH_ADD ZEND_FILE_LINE_CC);
     374             :         zend_string_release(key);
     375    12803186 :         return ret;
     376             : }
     377             : 
     378        2830 : ZEND_API zval *_zend_hash_str_add_new(HashTable *ht, const char *str, size_t len, zval *pData ZEND_FILE_LINE_DC)
     379             : {
     380        5660 :         zend_string *key = zend_string_init(str, len, ht->u.flags & HASH_FLAG_PERSISTENT);
     381        2830 :         zval *ret = _zend_hash_add_or_update_i(ht, key, pData, HASH_ADD_NEW ZEND_FILE_LINE_CC);
     382             :         zend_string_release(key);
     383        2830 :         return ret;
     384             : }
     385             : 
     386           0 : ZEND_API zval *zend_hash_index_add_empty_element(HashTable *ht, zend_ulong h)
     387             : {
     388             : 
     389             :         zval dummy;
     390             : 
     391           0 :         ZVAL_NULL(&dummy);
     392           0 :         return zend_hash_index_add(ht, h, &dummy);
     393             : }
     394             : 
     395         226 : ZEND_API zval *zend_hash_add_empty_element(HashTable *ht, zend_string *key)
     396             : {
     397             : 
     398             :         zval dummy;
     399             : 
     400         226 :         ZVAL_NULL(&dummy);
     401         226 :         return zend_hash_add(ht, key, &dummy);
     402             : }
     403             : 
     404      520919 : ZEND_API zval *zend_hash_str_add_empty_element(HashTable *ht, const char *str, size_t len)
     405             : {
     406             : 
     407             :         zval dummy;
     408             : 
     409      520919 :         ZVAL_NULL(&dummy);
     410      520919 :         return zend_hash_str_add(ht, str, len, &dummy);
     411             : }
     412             : 
     413             : 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)
     414             : {
     415             :         uint32_t nIndex;
     416             :         uint32_t idx;
     417             :         Bucket *p;
     418             : 
     419             :         IS_CONSISTENT(ht);
     420             : 
     421     7248184 :         if (UNEXPECTED(!(ht->u.flags & HASH_FLAG_INITIALIZED))) {
     422     1932645 :                 CHECK_INIT(ht, h < ht->nTableSize);
     423     1932645 :                 if (h < ht->nTableSize) {
     424     1830822 :                         p = ht->arData + h;
     425             :                         goto add_to_packed;
     426             :                 }
     427             :                 goto add_to_hash;
     428     5315539 :         } else if (ht->u.flags & HASH_FLAG_PACKED) {
     429     3400791 :                 if (h < ht->nNumUsed) {
     430        3801 :                         p = ht->arData + h;
     431        7602 :                         if (Z_TYPE(p->val) != IS_UNDEF) {
     432        3644 :                                 if (flag & HASH_ADD) {
     433          24 :                                         return NULL;
     434             :                                 }
     435        3620 :                                 if (ht->pDestructor) {
     436        3620 :                                         ht->pDestructor(&p->val);
     437             :                                 }
     438        3620 :                                 ZVAL_COPY_VALUE(&p->val, pData);
     439        3620 :                                 if ((zend_long)h >= (zend_long)ht->nNextFreeElement) {
     440           0 :                                         ht->nNextFreeElement = h < ZEND_LONG_MAX ? h + 1 : ZEND_LONG_MAX;
     441             :                                 }
     442        3620 :                                 return &p->val;
     443             :                         } else { /* we have to keep the order :( */
     444             :                                 goto convert_to_hash;
     445             :                         }
     446     3396990 :                 } else if (EXPECTED(h < ht->nTableSize)) {
     447     3359209 :                         p = ht->arData + h;
     448       75485 :                 } else if ((h >> 1) < ht->nTableSize &&
     449       37704 :                            (ht->nTableSize >> 1) < ht->nNumOfElements) {
     450       37175 :                         zend_hash_packed_grow(ht);
     451       37175 :                         p = ht->arData + h;
     452             :                 } else {
     453             :                         goto convert_to_hash;
     454             :                 }
     455             : 
     456             : add_to_packed:
     457     5227206 :                 HANDLE_BLOCK_INTERRUPTIONS();
     458             :                 /* incremental initialization of empty Buckets */
     459     5227206 :                 if ((flag & (HASH_ADD_NEW|HASH_ADD_NEXT)) == (HASH_ADD_NEW|HASH_ADD_NEXT)) {
     460       34944 :                         ht->nNumUsed = h + 1;
     461     5192262 :                 } else if (h >= ht->nNumUsed) {
     462     5192262 :                         if (h > ht->nNumUsed) {
     463      896699 :                                 Bucket *q = ht->arData + ht->nNumUsed;
     464     1798119 :                                 while (q != p) {
     465      901420 :                                         ZVAL_UNDEF(&q->val);
     466      901420 :                                         q++;
     467             :                                 }
     468             :                         }
     469     5192262 :                         ht->nNumUsed = h + 1;
     470             :                 }
     471     5227206 :                 ht->nNumOfElements++;
     472     5227206 :                 if (ht->nInternalPointer == INVALID_IDX) {
     473     1830866 :                         ht->nInternalPointer = h;
     474             :                 }
     475     5227206 :                 if ((zend_long)h >= (zend_long)ht->nNextFreeElement) {
     476     5227194 :                         ht->nNextFreeElement = h < ZEND_LONG_MAX ? h + 1 : ZEND_LONG_MAX;
     477             :                 }
     478     5227206 :                 p->h = h;
     479     5227206 :                 p->key = NULL;
     480     5227206 :                 ZVAL_COPY_VALUE(&p->val, pData);
     481             : 
     482     5227206 :                 HANDLE_UNBLOCK_INTERRUPTIONS();
     483             : 
     484     5227206 :                 return &p->val;
     485             : 
     486             : convert_to_hash:
     487         763 :                 zend_hash_packed_to_hash(ht);
     488     1914748 :         } else if ((flag & HASH_ADD_NEW) == 0) {
     489     1298488 :                 p = zend_hash_index_find_bucket(ht, h);
     490     1298488 :                 if (p) {
     491       10252 :                         if (flag & HASH_ADD) {
     492           5 :                                 return NULL;
     493             :                         }
     494             :                         ZEND_ASSERT(&p->val != pData);
     495       10247 :                         HANDLE_BLOCK_INTERRUPTIONS();
     496       10247 :                         if (ht->pDestructor) {
     497       10202 :                                 ht->pDestructor(&p->val);
     498             :                         }
     499       10247 :                         ZVAL_COPY_VALUE(&p->val, pData);
     500       10247 :                         HANDLE_UNBLOCK_INTERRUPTIONS();
     501       10247 :                         if ((zend_long)h >= (zend_long)ht->nNextFreeElement) {
     502           1 :                                 ht->nNextFreeElement = h < ZEND_LONG_MAX ? h + 1 : ZEND_LONG_MAX;
     503             :                         }
     504       10247 :                         return &p->val;
     505             :                 }
     506             :         }
     507             : 
     508     1905259 :         ZEND_HASH_IF_FULL_DO_RESIZE(ht);                /* If the Hash table is full, resize it */
     509             : 
     510             : add_to_hash:
     511     2007082 :         HANDLE_BLOCK_INTERRUPTIONS();
     512     2007082 :         idx = ht->nNumUsed++;
     513     2007082 :         ht->nNumOfElements++;
     514     2007082 :         if (ht->nInternalPointer == INVALID_IDX) {
     515      170302 :                 ht->nInternalPointer = idx;
     516             :         }
     517     2007082 :         if ((zend_long)h >= (zend_long)ht->nNextFreeElement) {
     518      625747 :                 ht->nNextFreeElement = h < ZEND_LONG_MAX ? h + 1 : ZEND_LONG_MAX;
     519             :         }
     520     2007082 :         p = ht->arData + idx;
     521     2007082 :         p->h = h;
     522     2007082 :         p->key = NULL;
     523     2007082 :         nIndex = h & ht->nTableMask;
     524     2007082 :         ZVAL_COPY_VALUE(&p->val, pData);
     525     2007082 :         Z_NEXT(p->val) = ht->arHash[nIndex];
     526     2007082 :         ht->arHash[nIndex] = idx;
     527     2007082 :         HANDLE_UNBLOCK_INTERRUPTIONS();
     528             : 
     529     2007082 :         return &p->val;
     530             : }
     531             : 
     532           0 : ZEND_API zval *_zend_hash_index_add_or_update(HashTable *ht, zend_ulong h, zval *pData, uint32_t flag ZEND_FILE_LINE_DC)
     533             : {
     534           0 :         return _zend_hash_index_add_or_update_i(ht, h, pData, flag ZEND_FILE_LINE_RELAY_CC);
     535             : }
     536             : 
     537          94 : ZEND_API zval *_zend_hash_index_add(HashTable *ht, zend_ulong h, zval *pData ZEND_FILE_LINE_DC)
     538             : {
     539          94 :         return _zend_hash_index_add_or_update_i(ht, h, pData, HASH_ADD ZEND_FILE_LINE_RELAY_CC);
     540             : }
     541             : 
     542     1053214 : ZEND_API zval *_zend_hash_index_add_new(HashTable *ht, zend_ulong h, zval *pData ZEND_FILE_LINE_DC)
     543             : {
     544     1053214 :         return _zend_hash_index_add_or_update_i(ht, h, pData, HASH_ADD | HASH_ADD_NEW ZEND_FILE_LINE_RELAY_CC);
     545             : }
     546             : 
     547     2308778 : ZEND_API zval *_zend_hash_index_update(HashTable *ht, zend_ulong h, zval *pData ZEND_FILE_LINE_DC)
     548             : {
     549     2308778 :         return _zend_hash_index_add_or_update_i(ht, h, pData, HASH_UPDATE ZEND_FILE_LINE_RELAY_CC);
     550             : }
     551             : 
     552     3850625 : ZEND_API zval *_zend_hash_next_index_insert(HashTable *ht, zval *pData ZEND_FILE_LINE_DC)
     553             : {
     554     7701250 :         return _zend_hash_index_add_or_update_i(ht, ht->nNextFreeElement, pData, HASH_ADD | HASH_ADD_NEXT ZEND_FILE_LINE_RELAY_CC);
     555             : }
     556             : 
     557       35473 : ZEND_API zval *_zend_hash_next_index_insert_new(HashTable *ht, zval *pData ZEND_FILE_LINE_DC)
     558             : {
     559       70946 :         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);
     560             : }
     561             : 
     562     6578348 : static void zend_hash_do_resize(HashTable *ht)
     563             : {
     564             : 
     565             :         IS_CONSISTENT(ht);
     566             : 
     567     6578348 :         if (ht->nNumUsed > ht->nNumOfElements) {
     568       23672 :                 HANDLE_BLOCK_INTERRUPTIONS();
     569       23672 :                 zend_hash_rehash(ht);
     570       23672 :                 HANDLE_UNBLOCK_INTERRUPTIONS();
     571     6554676 :         } else if ((ht->nTableSize << 1) > 0) {     /* Let's double the table size */
     572     6554676 :                 HANDLE_BLOCK_INTERRUPTIONS();
     573     6554676 :                 ht->arData = (Bucket *) safe_perealloc(ht->arData, (ht->nTableSize << 1), sizeof(Bucket) + sizeof(uint32_t), 0, ht->u.flags & HASH_FLAG_PERSISTENT);
     574     6554676 :                 ht->arHash = (uint32_t*)(ht->arData + (ht->nTableSize << 1));
     575     6554676 :                 ht->nTableSize = (ht->nTableSize << 1);
     576     6554676 :                 ht->nTableMask = ht->nTableSize - 1;
     577     6554676 :                 zend_hash_rehash(ht);
     578     6554676 :                 HANDLE_UNBLOCK_INTERRUPTIONS();
     579             :         }
     580     6578348 : }
     581             : 
     582     6691062 : ZEND_API int zend_hash_rehash(HashTable *ht)
     583             : {
     584             :         Bucket *p;
     585             :         uint32_t nIndex, i, j;
     586             : 
     587             :         IS_CONSISTENT(ht);
     588             : 
     589     6691062 :         if (UNEXPECTED(ht->nNumOfElements == 0)) {
     590           3 :                 if (ht->u.flags & HASH_FLAG_INITIALIZED) {
     591           0 :                         memset(ht->arHash, INVALID_IDX, ht->nTableSize * sizeof(uint32_t));
     592             :                 }
     593           3 :                 return SUCCESS;
     594             :         }
     595             : 
     596     6691059 :         memset(ht->arHash, INVALID_IDX, ht->nTableSize * sizeof(uint32_t));
     597   426046942 :         for (i = 0, j = 0; i < ht->nNumUsed; i++) {
     598   419355883 :                 p = ht->arData + i;
     599   838711766 :                 if (Z_TYPE(p->val) == IS_UNDEF) continue;
     600   419291851 :                 if (i != j) {
     601      164772 :                         ht->arData[j] = ht->arData[i];
     602      164772 :                         if (ht->nInternalPointer == i) {
     603        1071 :                                 ht->nInternalPointer = j;
     604             :                         }
     605             :                 }
     606   419291851 :                 nIndex = ht->arData[j].h & ht->nTableMask;
     607   419291851 :                 Z_NEXT(ht->arData[j].val) = ht->arHash[nIndex];
     608   419291851 :                 ht->arHash[nIndex] = j;
     609   419291851 :                 j++;
     610             :         }
     611     6691059 :         ht->nNumUsed = j;
     612     6691059 :         return SUCCESS;
     613             : }
     614             : 
     615             : static zend_always_inline void _zend_hash_del_el_ex(HashTable *ht, uint32_t idx, Bucket *p, Bucket *prev)
     616             : {
     617    54180811 :         HANDLE_BLOCK_INTERRUPTIONS();
     618    54180811 :         if (!(ht->u.flags & HASH_FLAG_PACKED)) {
     619    54074879 :                 if (prev) {
     620     3019271 :                         Z_NEXT(prev->val) = Z_NEXT(p->val);
     621             :                 } else {
     622    51055608 :                         ht->arHash[p->h & ht->nTableMask] = Z_NEXT(p->val);
     623             :                 }
     624             :         }
     625    54180811 :         if (ht->nNumUsed - 1 == idx) {
     626             :                 do {
     627     3729615 :                         ht->nNumUsed--;
     628     7287041 :                 } while (ht->nNumUsed > 0 && (Z_TYPE(ht->arData[ht->nNumUsed-1].val) == IS_UNDEF));
     629             :         }
     630    54180811 :         ht->nNumOfElements--;
     631    54180811 :         if (ht->nInternalPointer == idx) {
     632             :                 while (1) {
     633    48158471 :                         idx++;
     634    48158471 :                         if (idx >= ht->nNumUsed) {
     635      172180 :                                 ht->nInternalPointer = INVALID_IDX;
     636             :                                 break;
     637    95972582 :                         } else if (Z_TYPE(ht->arData[idx].val) != IS_UNDEF) {
     638     3052728 :                                 ht->nInternalPointer = idx;
     639             :                                 break;
     640             :                         }
     641             :                 }
     642             :         }
     643    54180811 :         if (p->key) {
     644    53906719 :                 zend_string_release(p->key);
     645             :         }
     646    54180811 :         if (ht->pDestructor) {
     647             :                 zval tmp;
     648    53381194 :                 ZVAL_COPY_VALUE(&tmp, &p->val);
     649    53381194 :                 ZVAL_UNDEF(&p->val);
     650    53381194 :                 ht->pDestructor(&tmp);
     651             :         } else {
     652      799617 :                 ZVAL_UNDEF(&p->val);
     653             :         }
     654    54180811 :         HANDLE_UNBLOCK_INTERRUPTIONS();
     655             : }
     656             : 
     657             : static zend_always_inline void _zend_hash_del_el(HashTable *ht, uint32_t idx, Bucket *p)
     658             : {
     659     7491858 :         Bucket *prev = NULL;
     660             : 
     661     7491858 :         if (!(ht->u.flags & HASH_FLAG_PACKED)) {
     662     7479708 :                 uint32_t nIndex = p->h & ht->nTableMask;
     663     7479708 :                 uint32_t i = ht->arHash[nIndex];
     664             : 
     665     7479708 :                 if (i != idx) {
     666      318292 :                         prev = ht->arData + i;
     667      361371 :                         while (Z_NEXT(prev->val) != idx) {
     668       43079 :                                 i = Z_NEXT(prev->val);
     669       43079 :                                 prev = ht->arData + i;
     670             :                         }
     671             :                 }
     672             :         }
     673             : 
     674             :         _zend_hash_del_el_ex(ht, idx, p, prev);
     675             : }
     676             : 
     677    46561759 : ZEND_API int zend_hash_del(HashTable *ht, zend_string *key)
     678             : {
     679             :         zend_ulong h;
     680             :         uint32_t nIndex;
     681             :         uint32_t idx;
     682             :         Bucket *p;
     683    46561759 :         Bucket *prev = NULL;
     684             : 
     685             :         IS_CONSISTENT(ht);
     686             : 
     687    46561759 :         h = zend_string_hash_val(key);
     688    46561759 :         nIndex = h & ht->nTableMask;
     689             : 
     690    46561759 :         idx = ht->arHash[nIndex];
     691    95966688 :         while (idx != INVALID_IDX) {
     692    48582428 :                 p = ht->arData + idx;
     693   234272104 :                 if ((p->key == key) ||
     694    48554762 :                         (p->h == h &&
     695    45711638 :                      p->key &&
     696    45711638 :                      p->key->len == key->len &&
     697    45711638 :                      memcmp(p->key->val, key->val, key->len) == 0)) {
     698             :                         _zend_hash_del_el_ex(ht, idx, p, prev);
     699    45739258 :                         return SUCCESS;
     700             :                 }
     701     2843170 :                 prev = p;
     702     2843170 :                 idx = Z_NEXT(p->val);
     703             :         }
     704      822501 :         return FAILURE;
     705             : }
     706             : 
     707         389 : 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         389 :         Bucket *prev = NULL;
     714             : 
     715             :         IS_CONSISTENT(ht);
     716             : 
     717         389 :         h = zend_string_hash_val(key);
     718         389 :         nIndex = h & ht->nTableMask;
     719             : 
     720         389 :         idx = ht->arHash[nIndex];
     721         787 :         while (idx != INVALID_IDX) {
     722         217 :                 p = ht->arData + idx;
     723         906 :                 if ((p->key == key) ||
     724         179 :                         (p->h == h &&
     725         170 :                      p->key &&
     726         170 :                      p->key->len == key->len &&
     727         170 :                      memcmp(p->key->val, key->val, key->len) == 0)) {
     728         416 :                         if (Z_TYPE(p->val) == IS_INDIRECT) {
     729          14 :                                 zval *data = Z_INDIRECT(p->val);
     730             : 
     731          14 :                                 if (Z_TYPE_P(data) == IS_UNDEF) {
     732           0 :                                         return FAILURE;
     733             :                                 } else {
     734          14 :                                         if (ht->pDestructor) {
     735          14 :                                                 ht->pDestructor(data);
     736             :                                         }
     737          14 :                                         ZVAL_UNDEF(data);
     738             :                                 }
     739             :                         } else {
     740             :                                 _zend_hash_del_el_ex(ht, idx, p, prev);
     741             :                         }
     742         208 :                         return SUCCESS;
     743             :                 }
     744           9 :                 prev = p;
     745           9 :                 idx = Z_NEXT(p->val);
     746             :         }
     747         181 :         return FAILURE;
     748             : }
     749             : 
     750      733555 : ZEND_API int zend_hash_str_del(HashTable *ht, const char *str, size_t len)
     751             : {
     752             :         zend_ulong h;
     753             :         uint32_t nIndex;
     754             :         uint32_t idx;
     755             :         Bucket *p;
     756      733555 :         Bucket *prev = NULL;
     757             : 
     758             :         IS_CONSISTENT(ht);
     759             : 
     760      733555 :         h = zend_inline_hash_func(str, len);
     761      733555 :         nIndex = h & ht->nTableMask;
     762             : 
     763      733555 :         idx = ht->arHash[nIndex];
     764     1509192 :         while (idx != INVALID_IDX) {
     765      751901 :                 p = ht->arData + idx;
     766     2881358 :                 if ((p->h == h)
     767             :                          && p->key
     768     1419638 :                          && (p->key->len == len)
     769      709819 :                          && !memcmp(p->key->val, str, len)) {
     770     1419638 :                         if (Z_TYPE(p->val) == IS_INDIRECT) {
     771           0 :                                 zval *data = Z_INDIRECT(p->val);
     772             : 
     773           0 :                                 if (Z_TYPE_P(data) == IS_UNDEF) {
     774           0 :                                         return FAILURE;
     775             :                                 } else {
     776           0 :                                         if (ht->pDestructor) {
     777           0 :                                                 ht->pDestructor(data);
     778             :                                         }
     779           0 :                                         ZVAL_UNDEF(data);
     780             :                                 }
     781             :                         } else {
     782             :                                 _zend_hash_del_el_ex(ht, idx, p, prev);
     783             :                         }
     784      709819 :                         return SUCCESS;
     785             :                 }
     786       42082 :                 prev = p;
     787       42082 :                 idx = Z_NEXT(p->val);
     788             :         }
     789       23736 :         return FAILURE;
     790             : }
     791             : 
     792           0 : ZEND_API int zend_hash_str_del_ind(HashTable *ht, const char *str, size_t len)
     793             : {
     794             :         zend_ulong h;
     795             :         uint32_t nIndex;
     796             :         uint32_t idx;
     797             :         Bucket *p;
     798           0 :         Bucket *prev = NULL;
     799             : 
     800             :         IS_CONSISTENT(ht);
     801             : 
     802           0 :         h = zend_inline_hash_func(str, len);
     803           0 :         nIndex = h & ht->nTableMask;
     804             : 
     805           0 :         idx = ht->arHash[nIndex];
     806           0 :         while (idx != INVALID_IDX) {
     807           0 :                 p = ht->arData + idx;
     808           0 :                 if ((p->h == h)
     809             :                          && p->key
     810           0 :                          && (p->key->len == len)
     811           0 :                          && !memcmp(p->key->val, str, len)) {
     812             :                         _zend_hash_del_el_ex(ht, idx, p, prev);
     813           0 :                         return SUCCESS;
     814             :                 }
     815           0 :                 prev = p;
     816           0 :                 idx = Z_NEXT(p->val);
     817             :         }
     818           0 :         return FAILURE;
     819             : }
     820             : 
     821      247050 : ZEND_API int zend_hash_index_del(HashTable *ht, zend_ulong h)
     822             : {
     823             :         uint32_t nIndex;
     824             :         uint32_t idx;
     825             :         Bucket *p;
     826      247050 :         Bucket *prev = NULL;
     827             : 
     828             :         IS_CONSISTENT(ht);
     829             : 
     830      247050 :         if (ht->u.flags & HASH_FLAG_PACKED) {
     831       99947 :                 if (h < ht->nNumUsed) {
     832       93788 :                         p = ht->arData + h;
     833      187576 :                         if (Z_TYPE(p->val) != IS_UNDEF) {
     834       93782 :                                 _zend_hash_del_el_ex(ht, h, p, NULL);
     835       93782 :                                 return SUCCESS;
     836             :                         }
     837             :                 }
     838        6165 :                 return FAILURE;
     839             :         }
     840      147103 :         nIndex = h & ht->nTableMask;
     841             : 
     842      147103 :         idx = ht->arHash[nIndex];
     843      294470 :         while (idx != INVALID_IDX) {
     844      146164 :                 p = ht->arData + idx;
     845      146164 :                 if ((p->h == h) && (p->key == NULL)) {
     846             :                         _zend_hash_del_el_ex(ht, idx, p, prev);
     847      145900 :                         return SUCCESS;
     848             :                 }
     849         264 :                 prev = p;
     850         264 :                 idx = Z_NEXT(p->val);
     851             :         }
     852        1203 :         return FAILURE;
     853             : }
     854             : 
     855    14483371 : ZEND_API void zend_hash_destroy(HashTable *ht)
     856             : {
     857             :         Bucket *p, *end;
     858             : 
     859             :         IS_CONSISTENT(ht);
     860             : 
     861    14483371 :         if (ht->nNumUsed) {
     862     7589467 :                 p = ht->arData;
     863     7589467 :                 end = p + ht->nNumUsed;
     864     7589467 :                 if (ht->pDestructor) {
     865             :                         SET_INCONSISTENT(HT_IS_DESTROYING);
     866             : 
     867     7292165 :                         if (ht->u.flags & HASH_FLAG_PACKED) {
     868             :                                 do {
     869     8190268 :                                         if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF)) {
     870     3225505 :                                                 ht->pDestructor(&p->val);
     871             :                                         }
     872     4095133 :                                 } while (++p != end);
     873             :                         } else {
     874             :                                 do {
     875   675082520 :                                         if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF)) {
     876   287230461 :                                                 ht->pDestructor(&p->val);
     877   287230461 :                                                 if (EXPECTED(p->key)) {
     878   286957778 :                                                         zend_string_release(p->key);
     879             :                                                 }
     880             :                                         }
     881   337541260 :                                 } while (++p != end);
     882             :                         }
     883             : 
     884             :                         SET_INCONSISTENT(HT_DESTROYED);
     885             :                 } else {
     886      297302 :                         if (!(ht->u.flags & HASH_FLAG_PACKED)) {
     887             :                                 do {
     888    21493074 :                                         if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF)) {
     889    10663250 :                                                 if (EXPECTED(p->key)) {
     890     9388757 :                                                         zend_string_release(p->key);
     891             :                                                 }
     892             :                                         }
     893    10746537 :                                 } while (++p != end);
     894             :                         }
     895             :                 }
     896     6893904 :         } else if (EXPECTED(!(ht->u.flags & HASH_FLAG_INITIALIZED))) {
     897     6823560 :                 return;
     898             :         }
     899     7659810 :         pefree(ht->arData, ht->u.flags & HASH_FLAG_PERSISTENT);
     900             : }
     901             : 
     902     3740644 : ZEND_API void zend_array_destroy(HashTable *ht)
     903             : {
     904             :         Bucket *p, *end;
     905             : 
     906             :         IS_CONSISTENT(ht);
     907             : 
     908     3740644 :         if (ht->nNumUsed) {
     909             : 
     910             :                 /* In some rare cases destructors of regular arrays may be changed */
     911     2368255 :                 if (UNEXPECTED(ht->pDestructor != ZVAL_PTR_DTOR)) {
     912          71 :                         zend_hash_destroy(ht);
     913          71 :                         return;
     914             :                 }
     915             : 
     916     2368184 :                 p = ht->arData;
     917     2368184 :                 end = p + ht->nNumUsed;
     918             :                 SET_INCONSISTENT(HT_IS_DESTROYING);
     919             : 
     920     2368184 :                 if (ht->u.flags & HASH_FLAG_PACKED) {
     921             :                         do {
     922    11350684 :                                 if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF)) {
     923     4802293 :                                         i_zval_ptr_dtor(&p->val ZEND_FILE_LINE_CC);
     924             :                                 }
     925     5675340 :                         } while (++p != end);
     926             :                 } else {
     927             :                         do {
     928     9489968 :                                 if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF)) {
     929     4744254 :                                         i_zval_ptr_dtor(&p->val ZEND_FILE_LINE_CC);
     930     4744254 :                                         if (EXPECTED(p->key)) {
     931     4411437 :                                                 zend_string_release(p->key);
     932             :                                         }
     933             :                                 }
     934     4744984 :                         } while (++p != end);
     935             :                 }
     936             : 
     937             :                 SET_INCONSISTENT(HT_DESTROYED);
     938     1372389 :         } else if (EXPECTED(!(ht->u.flags & HASH_FLAG_INITIALIZED))) {
     939     1372149 :                 return;
     940             :         }
     941     2368422 :         pefree(ht->arData, ht->u.flags & HASH_FLAG_PERSISTENT);
     942             : }
     943             : 
     944       50692 : ZEND_API void zend_hash_clean(HashTable *ht)
     945             : {
     946             :         Bucket *p, *end;
     947             : 
     948             :         IS_CONSISTENT(ht);
     949             : 
     950       50692 :         if (ht->nNumUsed) {
     951        8629 :                 p = ht->arData;
     952        8629 :                 end = p + ht->nNumUsed;
     953        8629 :                 if (ht->pDestructor) {
     954        3617 :                         if (ht->u.flags & HASH_FLAG_PACKED) {
     955             :                                 do {
     956         100 :                                         if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF)) {
     957          21 :                                                 ht->pDestructor(&p->val);
     958             :                                         }
     959          50 :                                 } while (++p != end);
     960             :                         } else {
     961             :                                 do {
     962     3628350 :                                         if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF)) {
     963     1814174 :                                                 ht->pDestructor(&p->val);
     964     1814174 :                                                 if (EXPECTED(p->key)) {
     965     1814172 :                                                         zend_string_release(p->key);
     966             :                                                 }
     967             :                                         }
     968     1814175 :                                 } while (++p != end);
     969             :                         }
     970             :                 } else {
     971        5012 :                         if (!(ht->u.flags & HASH_FLAG_PACKED)) {
     972             :                                 do {
     973       60746 :                                         if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF)) {
     974       30373 :                                                 if (EXPECTED(p->key)) {
     975       27553 :                                                         zend_string_release(p->key);
     976             :                                                 }
     977             :                                         }
     978       30373 :                                 } while (++p != end);
     979             :                         }
     980             :                 }
     981        8629 :                 if (!(ht->u.flags & HASH_FLAG_PACKED)) {
     982        8614 :                         memset(ht->arHash, INVALID_IDX, ht->nTableSize * sizeof(uint32_t));
     983             :                 }
     984             :         }
     985       50692 :         ht->nNumUsed = 0;
     986       50692 :         ht->nNumOfElements = 0;
     987       50692 :         ht->nNextFreeElement = 0;
     988       50692 :         ht->nInternalPointer = INVALID_IDX;
     989       50692 : }
     990             : 
     991       87831 : ZEND_API void zend_symtable_clean(HashTable *ht)
     992             : {
     993             :         Bucket *p, *end;
     994             : 
     995             :         IS_CONSISTENT(ht);
     996             : 
     997       87831 :         if (ht->nNumUsed) {
     998       87825 :                 p = ht->arData;
     999       87825 :                 end = p + ht->nNumUsed;
    1000             :                 do {
    1001      354990 :                         if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF)) {
    1002      177494 :                                 i_zval_ptr_dtor(&p->val ZEND_FILE_LINE_CC);
    1003      177494 :                                 if (EXPECTED(p->key)) {
    1004      177494 :                                         zend_string_release(p->key);
    1005             :                                 }
    1006             :                         }
    1007      177495 :                 } while (++p != end);
    1008       87825 :                 if (!(ht->u.flags & HASH_FLAG_PACKED)) {
    1009       87825 :                         memset(ht->arHash, INVALID_IDX, ht->nTableSize * sizeof(uint32_t));
    1010             :                 }
    1011             :         }
    1012       87831 :         ht->nNumUsed = 0;
    1013       87831 :         ht->nNumOfElements = 0;
    1014       87831 :         ht->nNextFreeElement = 0;
    1015       87831 :         ht->nInternalPointer = INVALID_IDX;
    1016       87831 : }
    1017             : 
    1018           0 : ZEND_API void zend_hash_graceful_destroy(HashTable *ht)
    1019             : {
    1020             :         uint32_t idx;
    1021             :         Bucket *p;
    1022             : 
    1023             :         IS_CONSISTENT(ht);
    1024             : 
    1025           0 :         for (idx = 0; idx < ht->nNumUsed; idx++) {
    1026           0 :                 p = ht->arData + idx;
    1027           0 :                 if (Z_TYPE(p->val) == IS_UNDEF) continue;
    1028             :                 _zend_hash_del_el(ht, idx, p);
    1029             :         }
    1030           0 :         if (ht->u.flags & HASH_FLAG_INITIALIZED) {
    1031           0 :                 pefree(ht->arData, ht->u.flags & HASH_FLAG_PERSISTENT);
    1032             :         }
    1033             : 
    1034             :         SET_INCONSISTENT(HT_DESTROYED);
    1035           0 : }
    1036             : 
    1037       83320 : ZEND_API void zend_hash_graceful_reverse_destroy(HashTable *ht)
    1038             : {
    1039             :         uint32_t idx;
    1040             :         Bucket *p;
    1041             : 
    1042             :         IS_CONSISTENT(ht);
    1043             : 
    1044       83320 :         idx = ht->nNumUsed;
    1045     1947073 :         while (idx > 0) {
    1046     1780433 :                 idx--;
    1047     1780433 :                 p = ht->arData + idx;
    1048     3560866 :                 if (Z_TYPE(p->val) == IS_UNDEF) continue;
    1049             :                 _zend_hash_del_el(ht, idx, p);
    1050             :         }
    1051             : 
    1052       83320 :         if (ht->u.flags & HASH_FLAG_INITIALIZED) {
    1053       63326 :                 pefree(ht->arData, ht->u.flags & HASH_FLAG_PERSISTENT);
    1054             :         }
    1055             : 
    1056             :         SET_INCONSISTENT(HT_DESTROYED);
    1057       83320 : }
    1058             : 
    1059             : /* This is used to recurse elements and selectively delete certain entries
    1060             :  * from a hashtable. apply_func() receives the data and decides if the entry
    1061             :  * should be deleted or recursion should be stopped. The following three
    1062             :  * return codes are possible:
    1063             :  * ZEND_HASH_APPLY_KEEP   - continue
    1064             :  * ZEND_HASH_APPLY_STOP   - stop iteration
    1065             :  * ZEND_HASH_APPLY_REMOVE - delete the element, combineable with the former
    1066             :  */
    1067             : 
    1068       92883 : ZEND_API void zend_hash_apply(HashTable *ht, apply_func_t apply_func)
    1069             : {
    1070             :         uint32_t idx;
    1071             :         Bucket *p;
    1072             :         int result;
    1073             : 
    1074             :         IS_CONSISTENT(ht);
    1075             : 
    1076       92883 :         HASH_PROTECT_RECURSION(ht);
    1077     1720907 :         for (idx = 0; idx < ht->nNumUsed; idx++) {
    1078     1628026 :                 p = ht->arData + idx;
    1079     3256052 :                 if (Z_TYPE(p->val) == IS_UNDEF) continue;
    1080             : 
    1081     1628011 :                 result = apply_func(&p->val);
    1082             : 
    1083     1628009 :                 if (result & ZEND_HASH_APPLY_REMOVE) {
    1084             :                         _zend_hash_del_el(ht, idx, p);
    1085             :                 }
    1086     1628009 :                 if (result & ZEND_HASH_APPLY_STOP) {
    1087           0 :                         break;
    1088             :                 }
    1089             :         }
    1090       92881 :         HASH_UNPROTECT_RECURSION(ht);
    1091       92881 : }
    1092             : 
    1093             : 
    1094      656113 : ZEND_API void zend_hash_apply_with_argument(HashTable *ht, apply_func_arg_t apply_func, void *argument)
    1095             : {
    1096             :     uint32_t idx;
    1097             :         Bucket *p;
    1098             :         int result;
    1099             : 
    1100             :         IS_CONSISTENT(ht);
    1101             : 
    1102      656113 :         HASH_PROTECT_RECURSION(ht);
    1103   192135898 :         for (idx = 0; idx < ht->nNumUsed; idx++) {
    1104   191483966 :                 p = ht->arData + idx;
    1105   382967932 :                 if (Z_TYPE(p->val) == IS_UNDEF) continue;
    1106             : 
    1107   150645050 :                 result = apply_func(&p->val, argument);
    1108             : 
    1109   150645050 :                 if (result & ZEND_HASH_APPLY_REMOVE) {
    1110             :                         _zend_hash_del_el(ht, idx, p);
    1111             :                 }
    1112   150645050 :                 if (result & ZEND_HASH_APPLY_STOP) {
    1113        4181 :                         break;
    1114             :                 }
    1115             :         }
    1116      656113 :         HASH_UNPROTECT_RECURSION(ht);
    1117      656113 : }
    1118             : 
    1119             : 
    1120         717 : ZEND_API void zend_hash_apply_with_arguments(HashTable *ht, apply_func_args_t apply_func, int num_args, ...)
    1121             : {
    1122             :         uint32_t idx;
    1123             :         Bucket *p;
    1124             :         va_list args;
    1125             :         zend_hash_key hash_key;
    1126             :         int result;
    1127             : 
    1128             :         IS_CONSISTENT(ht);
    1129             : 
    1130         717 :         HASH_PROTECT_RECURSION(ht);
    1131             : 
    1132     1099538 :         for (idx = 0; idx < ht->nNumUsed; idx++) {
    1133     1098821 :                 p = ht->arData + idx;
    1134     2197642 :                 if (Z_TYPE(p->val) == IS_UNDEF) continue;
    1135     1098732 :                 va_start(args, num_args);
    1136     1098732 :                 hash_key.h = p->h;
    1137     1098732 :                 hash_key.key = p->key;
    1138             : 
    1139     1098732 :                 result = apply_func(&p->val, num_args, args, &hash_key);
    1140             : 
    1141     1098732 :                 if (result & ZEND_HASH_APPLY_REMOVE) {
    1142             :                         _zend_hash_del_el(ht, idx, p);
    1143             :                 }
    1144     1098732 :                 if (result & ZEND_HASH_APPLY_STOP) {
    1145           0 :                         va_end(args);
    1146           0 :                         break;
    1147             :                 }
    1148     1098732 :                 va_end(args);
    1149             :         }
    1150             : 
    1151         717 :         HASH_UNPROTECT_RECURSION(ht);
    1152         717 : }
    1153             : 
    1154             : 
    1155      108690 : ZEND_API void zend_hash_reverse_apply(HashTable *ht, apply_func_t apply_func)
    1156             : {
    1157             :         uint32_t idx;
    1158             :         Bucket *p;
    1159             :         int result;
    1160             : 
    1161             :         IS_CONSISTENT(ht);
    1162             : 
    1163      108690 :         HASH_PROTECT_RECURSION(ht);
    1164      108690 :         idx = ht->nNumUsed;
    1165      727749 :         while (idx > 0) {
    1166      572706 :                 idx--;
    1167      572706 :                 p = ht->arData + idx;
    1168     1145412 :                 if (Z_TYPE(p->val) == IS_UNDEF) continue;
    1169             : 
    1170      520842 :                 result = apply_func(&p->val);
    1171             : 
    1172      520842 :                 if (result & ZEND_HASH_APPLY_REMOVE) {
    1173             :                         _zend_hash_del_el(ht, idx, p);
    1174             :                 }
    1175      520842 :                 if (result & ZEND_HASH_APPLY_STOP) {
    1176       62337 :                         break;
    1177             :                 }
    1178             :         }
    1179      108690 :         HASH_UNPROTECT_RECURSION(ht);
    1180      108690 : }
    1181             : 
    1182             : 
    1183         464 : ZEND_API void zend_hash_copy(HashTable *target, HashTable *source, copy_ctor_func_t pCopyConstructor)
    1184             : {
    1185             :     uint32_t idx;
    1186             :         Bucket *p;
    1187             :         zval *new_entry, *data;
    1188             :         zend_bool setTargetPointer;
    1189             : 
    1190             :         IS_CONSISTENT(source);
    1191             :         IS_CONSISTENT(target);
    1192             : 
    1193         464 :         setTargetPointer = (target->nInternalPointer == INVALID_IDX);
    1194       11928 :         for (idx = 0; idx < source->nNumUsed; idx++) {
    1195       11464 :                 p = source->arData + idx;
    1196       22928 :                 if (Z_TYPE(p->val) == IS_UNDEF) continue;
    1197             : 
    1198       11464 :                 if (setTargetPointer && source->nInternalPointer == idx) {
    1199         313 :                         target->nInternalPointer = INVALID_IDX;
    1200             :                 }
    1201             :                 /* INDIRECT element may point to UNDEF-ined slots */
    1202       11464 :                 data = &p->val;
    1203       11464 :                 if (Z_TYPE_P(data) == IS_INDIRECT) {
    1204          96 :                         data = Z_INDIRECT_P(data);
    1205          96 :                         if (Z_TYPE_P(data) == IS_UNDEF) {
    1206           0 :                                 continue;
    1207             :                         }
    1208             :                 }
    1209       11464 :                 if (p->key) {
    1210       11375 :                         new_entry = zend_hash_update(target, p->key, data);
    1211             :                 } else {
    1212          89 :                         new_entry = zend_hash_index_update(target, p->h, data);
    1213             :                 }
    1214       11464 :                 if (pCopyConstructor) {
    1215         412 :                         pCopyConstructor(new_entry);
    1216             :                 }
    1217             :         }
    1218         464 :         if (target->nInternalPointer == INVALID_IDX && target->nNumOfElements > 0) {
    1219           0 :                 idx = 0;
    1220           0 :                 while (Z_TYPE(target->arData[idx].val) == IS_UNDEF) {
    1221           0 :                         idx++;
    1222             :                 }
    1223           0 :                 target->nInternalPointer = idx;
    1224             :         }
    1225         464 : }
    1226             : 
    1227             : 
    1228     1297705 : ZEND_API void zend_array_dup(HashTable *target, HashTable *source)
    1229             : {
    1230             :     uint32_t idx, target_idx;
    1231             :         uint32_t nIndex;
    1232             :         Bucket *p, *q;
    1233             :         zval *data;
    1234             : 
    1235             :         IS_CONSISTENT(source);
    1236             : 
    1237     1297705 :         target->nTableMask = source->nTableMask;
    1238     1297705 :         target->nTableSize = source->nTableSize;
    1239     1297705 :         target->pDestructor = source->pDestructor;
    1240     1297705 :         target->nInternalPointer = INVALID_IDX;
    1241     1297705 :         target->u.flags = (source->u.flags & ~HASH_FLAG_PERSISTENT) | HASH_FLAG_APPLY_PROTECTION;
    1242             : 
    1243     1297705 :         target_idx = 0;
    1244     1297705 :         if (target->u.flags & HASH_FLAG_INITIALIZED) {
    1245     1135164 :                 if (target->u.flags & HASH_FLAG_PACKED) {
    1246     1077437 :                         target->nNumUsed = source->nNumUsed;
    1247     1077437 :                         target->nNumOfElements = source->nNumOfElements;
    1248     1077437 :                         target->nNextFreeElement = source->nNextFreeElement;
    1249     1077437 :                         target->arData = (Bucket *) safe_pemalloc(target->nTableSize, sizeof(Bucket), 0, 0);
    1250     1077437 :                         target->arHash = (uint32_t*)&uninitialized_bucket;
    1251     1077437 :                         target->nInternalPointer = source->nInternalPointer;
    1252             : 
    1253     4462267 :                         for (idx = 0; idx < source->nNumUsed; idx++) {
    1254     3384830 :                                 p = source->arData + idx;
    1255     3384830 :                                 q = target->arData + idx;
    1256     6769660 :                                 if (Z_TYPE(p->val) == IS_UNDEF) {
    1257      849222 :                                         ZVAL_UNDEF(&q->val);
    1258      849222 :                                         continue;
    1259             :                                 }
    1260             :                                 /* INDIRECT element may point to UNDEF-ined slots */
    1261     2535608 :                                 data = &p->val;
    1262     2535608 :                                 if (Z_TYPE_P(data) == IS_INDIRECT) {
    1263           0 :                                         data = Z_INDIRECT_P(data);
    1264           0 :                                         if (Z_TYPE_P(data) == IS_UNDEF) {
    1265           0 :                                                 ZVAL_UNDEF(&q->val);
    1266           0 :                                                 continue;
    1267             :                                         }
    1268             :                                 }
    1269             : 
    1270     2535608 :                                 q->h = p->h;
    1271     2535608 :                                 q->key = NULL;
    1272     2535608 :                                 if (Z_OPT_REFCOUNTED_P(data)) {
    1273     2404232 :                                         if (Z_ISREF_P(data) && Z_REFCOUNT_P(data) == 1) {
    1274           1 :                                                 ZVAL_COPY(&q->val, Z_REFVAL_P(data));
    1275             :                                         } else {
    1276     2404209 :                                                 ZVAL_COPY(&q->val, data);
    1277             :                                         }
    1278             :                                 } else {
    1279      131398 :                                         ZVAL_COPY_VALUE(&q->val, data);
    1280             :                                 }
    1281             :                         }
    1282     2154874 :                         if (target->nNumOfElements > 0 &&
    1283     1077437 :                             target->nInternalPointer == INVALID_IDX) {
    1284          41 :                                 idx = 0;
    1285         145 :                                 while (Z_TYPE(target->arData[idx].val) == IS_UNDEF) {
    1286          11 :                                         idx++;
    1287             :                                 }
    1288          41 :                                 target->nInternalPointer = idx;
    1289             :                         }
    1290             :                 } else {
    1291       57727 :                         target->nNextFreeElement = source->nNextFreeElement;
    1292       57727 :                         target->arData = (Bucket *) safe_pemalloc(target->nTableSize, sizeof(Bucket) + sizeof(uint32_t), 0, 0);
    1293       57727 :                         target->arHash = (uint32_t*)(target->arData + target->nTableSize);
    1294       57727 :                         memset(target->arHash, INVALID_IDX, target->nTableSize * sizeof(uint32_t));
    1295             : 
    1296      777099 :                         for (idx = 0; idx < source->nNumUsed; idx++) {
    1297      719372 :                                 p = source->arData + idx;
    1298     1438744 :                                 if (Z_TYPE(p->val) == IS_UNDEF) continue;
    1299             :                                 /* INDIRECT element may point to UNDEF-ined slots */
    1300      719368 :                                 data = &p->val;
    1301      719368 :                                 if (Z_TYPE_P(data) == IS_INDIRECT) {
    1302       29408 :                                         data = Z_INDIRECT_P(data);
    1303       29408 :                                         if (Z_TYPE_P(data) == IS_UNDEF) {
    1304        5159 :                                                 continue;
    1305             :                                         }
    1306             :                                 }
    1307             : 
    1308      714209 :                                 if (source->nInternalPointer == idx) {
    1309       44588 :                                         target->nInternalPointer = target_idx;
    1310             :                                 }
    1311             : 
    1312      714209 :                                 q = target->arData + target_idx;
    1313      714209 :                                 q->h = p->h;
    1314      714209 :                                 q->key = p->key;
    1315      714209 :                                 if (q->key) {
    1316      708646 :                                         zend_string_addref(q->key);
    1317             :                                 }
    1318      714209 :                                 nIndex = q->h & target->nTableMask;
    1319      714209 :                                 Z_NEXT(q->val) = target->arHash[nIndex];
    1320      714209 :                                 target->arHash[nIndex] = target_idx;
    1321      714209 :                                 if (Z_OPT_REFCOUNTED_P(data)) {
    1322      639189 :                                         if (Z_ISREF_P(data) && Z_REFCOUNT_P(data) == 1) {
    1323          97 :                                                 ZVAL_COPY(&q->val, Z_REFVAL_P(data));
    1324             :                                         } else {
    1325      638448 :                                                 ZVAL_COPY(&q->val, data);
    1326             :                                         }
    1327             :                                 } else {
    1328       75664 :                                         ZVAL_COPY_VALUE(&q->val, data);
    1329             :                                 }
    1330      714209 :                                 target_idx++;
    1331             :                         }
    1332       57727 :                         target->nNumUsed = target_idx;
    1333       57727 :                         target->nNumOfElements = target_idx;
    1334      115434 :                         if (target->nNumOfElements > 0 &&
    1335       57707 :                             target->nInternalPointer == INVALID_IDX) {
    1336       13119 :                                 target->nInternalPointer = 0;
    1337             :                         }
    1338             :                 }
    1339             :         } else {
    1340      162541 :                 target->nNumUsed = 0;
    1341      162541 :                 target->nNumOfElements = 0;
    1342      162541 :                 target->nNextFreeElement = 0;
    1343      162541 :                 target->arData = NULL;
    1344      162541 :                 target->arHash = (uint32_t*)&uninitialized_bucket;
    1345             :         }
    1346     1297705 : }
    1347             : 
    1348             : 
    1349      187148 : ZEND_API void _zend_hash_merge(HashTable *target, HashTable *source, copy_ctor_func_t pCopyConstructor, zend_bool overwrite ZEND_FILE_LINE_DC)
    1350             : {
    1351             :     uint32_t idx;
    1352             :         Bucket *p;
    1353             :         zval *t;
    1354      187148 :         uint32_t mode = (overwrite?HASH_UPDATE:HASH_ADD);
    1355             : 
    1356             :         IS_CONSISTENT(source);
    1357             :         IS_CONSISTENT(target);
    1358             : 
    1359     3223410 :         for (idx = 0; idx < source->nNumUsed; idx++) {
    1360     3036262 :                 p = source->arData + idx;
    1361     6072524 :                 if (Z_TYPE(p->val) == IS_UNDEF) continue;
    1362     3036262 :                 if (p->key) {
    1363     3036251 :                         t = _zend_hash_add_or_update(target, p->key, &p->val, mode ZEND_FILE_LINE_RELAY_CC);
    1364     3036251 :                         if (t && pCopyConstructor) {
    1365     3035669 :                                 pCopyConstructor(t);
    1366             :                         }
    1367             :                 } else {
    1368          11 :                         if ((mode==HASH_UPDATE || !zend_hash_index_exists(target, p->h))) {
    1369           1 :                                 t = zend_hash_index_update(target, p->h, &p->val);
    1370           1 :                                 if (t && pCopyConstructor) {
    1371           1 :                                         pCopyConstructor(t);
    1372             :                                 }
    1373             :                         }
    1374             :                 }
    1375             :         }
    1376      187148 :         if (target->nNumOfElements > 0) {
    1377      187146 :                 idx = 0;
    1378      561438 :                 while (Z_TYPE(target->arData[idx].val) == IS_UNDEF) {
    1379           0 :                         idx++;
    1380             :                 }
    1381      187146 :                 target->nInternalPointer = idx;
    1382             :         }
    1383      187148 : }
    1384             : 
    1385             : 
    1386           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)
    1387             : {
    1388             :         zend_hash_key hash_key;
    1389             : 
    1390           0 :         hash_key.h = p->h;
    1391           0 :         hash_key.key = p->key;
    1392           0 :         return merge_checker_func(target, source_data, &hash_key, pParam);
    1393             : }
    1394             : 
    1395             : 
    1396           0 : ZEND_API void zend_hash_merge_ex(HashTable *target, HashTable *source, copy_ctor_func_t pCopyConstructor, merge_checker_func_t pMergeSource, void *pParam)
    1397             : {
    1398             :         uint32_t idx;
    1399             :         Bucket *p;
    1400             :         zval *t;
    1401             : 
    1402             :         IS_CONSISTENT(source);
    1403             :         IS_CONSISTENT(target);
    1404             : 
    1405           0 :         for (idx = 0; idx < source->nNumUsed; idx++) {
    1406           0 :                 p = source->arData + idx;
    1407           0 :                 if (Z_TYPE(p->val) == IS_UNDEF) continue;
    1408           0 :                 if (zend_hash_replace_checker_wrapper(target, &p->val, p, pParam, pMergeSource)) {
    1409           0 :                         t = zend_hash_update(target, p->key, &p->val);
    1410           0 :                         if (t && pCopyConstructor) {
    1411           0 :                                 pCopyConstructor(t);
    1412             :                         }
    1413             :                 }
    1414             :         }
    1415           0 :         if (target->nNumOfElements > 0) {
    1416           0 :                 idx = 0;
    1417           0 :                 while (Z_TYPE(target->arData[idx].val) == IS_UNDEF) {
    1418           0 :                         idx++;
    1419             :                 }
    1420           0 :                 target->nInternalPointer = idx;
    1421             :         }
    1422           0 : }
    1423             : 
    1424             : 
    1425             : /* Returns SUCCESS if found and FAILURE if not. The pointer to the
    1426             :  * data is returned in pData. The reason is that there's no reason
    1427             :  * someone using the hash table might not want to have NULL data
    1428             :  */
    1429    51582001 : ZEND_API zval *zend_hash_find(const HashTable *ht, zend_string *key)
    1430             : {
    1431             :         Bucket *p;
    1432             : 
    1433             :         IS_CONSISTENT(ht);
    1434             : 
    1435    51582001 :         p = zend_hash_find_bucket(ht, key);
    1436    51582001 :         return p ? &p->val : NULL;
    1437             : }
    1438             : 
    1439     2623447 : ZEND_API zval *zend_hash_str_find(const HashTable *ht, const char *str, size_t len)
    1440             : {
    1441             :         zend_ulong h;
    1442             :         Bucket *p;
    1443             : 
    1444             :         IS_CONSISTENT(ht);
    1445             : 
    1446     2623447 :         h = zend_inline_hash_func(str, len);
    1447     2623447 :         p = zend_hash_str_find_bucket(ht, str, len, h);
    1448     2623447 :         return p ? &p->val : NULL;
    1449             : }
    1450             : 
    1451      564166 : ZEND_API zend_bool zend_hash_exists(const HashTable *ht, zend_string *key)
    1452             : {
    1453             :         Bucket *p;
    1454             : 
    1455             :         IS_CONSISTENT(ht);
    1456             : 
    1457      564166 :         p = zend_hash_find_bucket(ht, key);
    1458      564166 :         return p ? 1 : 0;
    1459             : }
    1460             : 
    1461      859855 : ZEND_API zend_bool zend_hash_str_exists(const HashTable *ht, const char *str, size_t len)
    1462             : {
    1463             :         zend_ulong h;
    1464             :         Bucket *p;
    1465             : 
    1466             :         IS_CONSISTENT(ht);
    1467             : 
    1468      859855 :         h = zend_inline_hash_func(str, len);
    1469      859855 :         p = zend_hash_str_find_bucket(ht, str, len, h);
    1470      859855 :         return p ? 1 : 0;
    1471             : }
    1472             : 
    1473     6158955 : ZEND_API zval *zend_hash_index_find(const HashTable *ht, zend_ulong h)
    1474             : {
    1475             :         Bucket *p;
    1476             : 
    1477             :         IS_CONSISTENT(ht);
    1478             : 
    1479     6158955 :         if (ht->u.flags & HASH_FLAG_PACKED) {
    1480     5005484 :                 if (h < ht->nNumUsed) {
    1481     4754019 :                         p = ht->arData + h;
    1482     9508038 :                         if (Z_TYPE(p->val) != IS_UNDEF) {
    1483     4753474 :                                 return &p->val;
    1484             :                         }
    1485             :                 }
    1486      252010 :                 return NULL;
    1487             :         }
    1488             : 
    1489     1153471 :         p = zend_hash_index_find_bucket(ht, h);
    1490     1153471 :         return p ? &p->val : NULL;
    1491             : }
    1492             : 
    1493             : 
    1494     1538532 : ZEND_API zend_bool zend_hash_index_exists(const HashTable *ht, zend_ulong h)
    1495             : {
    1496             :         Bucket *p;
    1497             : 
    1498             :         IS_CONSISTENT(ht);
    1499             : 
    1500     1538532 :         if (ht->u.flags & HASH_FLAG_PACKED) {
    1501          56 :                 if (h < ht->nNumUsed) {
    1502         102 :                         if (Z_TYPE(ht->arData[h].val) != IS_UNDEF) {
    1503          50 :                                 return 1;
    1504             :                         }
    1505             :                 }
    1506           6 :                 return 0;
    1507             :         }
    1508             : 
    1509     1538476 :         p = zend_hash_index_find_bucket(ht, h);
    1510     1538476 :         return p ? 1 : 0;
    1511             : }
    1512             : 
    1513             : 
    1514       21242 : ZEND_API void zend_hash_internal_pointer_reset_ex(HashTable *ht, HashPosition *pos)
    1515             : {
    1516             :     uint32_t idx;
    1517             : 
    1518             :         IS_CONSISTENT(ht);
    1519       21736 :         for (idx = 0; idx < ht->nNumUsed; idx++) {
    1520       41754 :                 if (Z_TYPE(ht->arData[idx].val) != IS_UNDEF) {
    1521       20383 :                         *pos = idx;
    1522       20383 :                         return;
    1523             :                 }
    1524             :         }
    1525         859 :         *pos = INVALID_IDX;
    1526             : }
    1527             : 
    1528             : 
    1529             : /* This function will be extremely optimized by remembering
    1530             :  * the end of the list
    1531             :  */
    1532          47 : ZEND_API void zend_hash_internal_pointer_end_ex(HashTable *ht, HashPosition *pos)
    1533             : {
    1534             :         uint32_t idx;
    1535             : 
    1536             :         IS_CONSISTENT(ht);
    1537             : 
    1538          47 :         idx = ht->nNumUsed;
    1539          94 :         while (idx > 0) {
    1540          45 :                 idx--;
    1541          90 :                 if (Z_TYPE(ht->arData[idx].val) != IS_UNDEF) {
    1542          45 :                         *pos = idx;
    1543          45 :                         return;
    1544             :                 }
    1545             :         }
    1546           2 :         *pos = INVALID_IDX;
    1547             : }
    1548             : 
    1549             : 
    1550       81510 : ZEND_API int zend_hash_move_forward_ex(HashTable *ht, HashPosition *pos)
    1551             : {
    1552       81510 :         uint32_t idx = *pos;
    1553             : 
    1554             :         IS_CONSISTENT(ht);
    1555             : 
    1556       81510 :         if (idx != INVALID_IDX) {
    1557             :                 while (1) {
    1558       81554 :                         idx++;
    1559       81554 :                         if (idx >= ht->nNumUsed) {
    1560       17052 :                                 *pos = INVALID_IDX;
    1561       17052 :                                 return SUCCESS;
    1562             :                         }
    1563      129004 :                         if (Z_TYPE(ht->arData[idx].val) != IS_UNDEF) {
    1564       64434 :                                 *pos = idx;
    1565       64434 :                                 return SUCCESS;
    1566             :                         }
    1567          68 :                 }
    1568             :         } else {
    1569          24 :                 return FAILURE;
    1570             :         }
    1571             : }
    1572             : 
    1573          21 : ZEND_API int zend_hash_move_backwards_ex(HashTable *ht, HashPosition *pos)
    1574             : {
    1575          21 :         uint32_t idx = *pos;
    1576             : 
    1577             :         IS_CONSISTENT(ht);
    1578             : 
    1579          21 :         if (idx != INVALID_IDX) {
    1580          38 :                 while (idx > 0) {
    1581          14 :                         idx--;
    1582          28 :                         if (Z_TYPE(ht->arData[idx].val) != IS_UNDEF) {
    1583          14 :                                 *pos = idx;
    1584          14 :                                 return SUCCESS;
    1585             :                         }
    1586             :                 }
    1587           5 :                 *pos = INVALID_IDX;
    1588           5 :                 return SUCCESS;
    1589             :         } else {
    1590           2 :                 return FAILURE;
    1591             :         }
    1592             : }
    1593             : 
    1594             : 
    1595             : /* This function should be made binary safe  */
    1596       23223 : ZEND_API int zend_hash_get_current_key_ex(const HashTable *ht, zend_string **str_index, zend_ulong *num_index, HashPosition *pos)
    1597             : {
    1598       23223 :         uint32_t idx = *pos;
    1599             :         Bucket *p;
    1600             : 
    1601             :         IS_CONSISTENT(ht);
    1602       23223 :         if (idx != INVALID_IDX) {
    1603       22299 :                 p = ht->arData + idx;
    1604       22299 :                 if (p->key) {
    1605       20811 :                         *str_index = p->key;
    1606       20811 :                         return HASH_KEY_IS_STRING;
    1607             :                 } else {
    1608        1488 :                         *num_index = p->h;
    1609        1488 :                         return HASH_KEY_IS_LONG;
    1610             :                 }
    1611             :         }
    1612         924 :         return HASH_KEY_NON_EXISTENT;
    1613             : }
    1614             : 
    1615        3574 : ZEND_API void zend_hash_get_current_key_zval_ex(const HashTable *ht, zval *key, HashPosition *pos)
    1616             : {
    1617        3574 :         uint32_t idx = *pos;
    1618             :         Bucket *p;
    1619             : 
    1620             :         IS_CONSISTENT(ht);
    1621        3574 :         if (idx == INVALID_IDX) {
    1622          56 :                 ZVAL_NULL(key);
    1623             :         } else {
    1624        3518 :                 p = ht->arData + idx;
    1625        3518 :                 if (p->key) {
    1626         669 :                         ZVAL_STR_COPY(key, p->key);
    1627             :                 } else {
    1628        2849 :                         ZVAL_LONG(key, p->h);
    1629             :                 }
    1630             :         }
    1631        3574 : }
    1632             : 
    1633       68694 : ZEND_API int zend_hash_get_current_key_type_ex(HashTable *ht, HashPosition *pos)
    1634             : {
    1635       68694 :     uint32_t idx = *pos;
    1636             :         Bucket *p;
    1637             : 
    1638             :         IS_CONSISTENT(ht);
    1639       68694 :         if (idx != INVALID_IDX) {
    1640       53531 :                 p = ht->arData + idx;
    1641       53531 :                 if (p->key) {
    1642       51005 :                         return HASH_KEY_IS_STRING;
    1643             :                 } else {
    1644        2526 :                         return HASH_KEY_IS_LONG;
    1645             :                 }
    1646             :         }
    1647       15163 :         return HASH_KEY_NON_EXISTENT;
    1648             : }
    1649             : 
    1650             : 
    1651       74816 : ZEND_API zval *zend_hash_get_current_data_ex(HashTable *ht, HashPosition *pos)
    1652             : {
    1653       74816 :         uint32_t idx = *pos;
    1654             :         Bucket *p;
    1655             : 
    1656             :         IS_CONSISTENT(ht);
    1657       74816 :         if (idx != INVALID_IDX) {
    1658       73660 :                 p = ht->arData + idx;
    1659       73660 :                 return &p->val;
    1660             :         } else {
    1661        1156 :                 return NULL;
    1662             :         }
    1663             : }
    1664             : 
    1665       92696 : ZEND_API void zend_hash_bucket_swap(Bucket *p, Bucket *q) {
    1666             :         zval val;
    1667             :         zend_ulong h;
    1668             :         zend_string *key;
    1669             : 
    1670       92696 :         ZVAL_COPY_VALUE(&val, &p->val);
    1671       92696 :         h = p->h;
    1672       92696 :         key = p->key;
    1673             : 
    1674       92696 :         ZVAL_COPY_VALUE(&p->val, &q->val);
    1675       92696 :         p->h = q->h;
    1676       92696 :         p->key = q->key;
    1677             : 
    1678       92696 :         ZVAL_COPY_VALUE(&q->val, &val);
    1679       92696 :         q->h = h;
    1680       92696 :         q->key = key;
    1681       92696 : }
    1682             : 
    1683       68587 : ZEND_API void zend_hash_bucket_renum_swap(Bucket *p, Bucket *q) {
    1684             :         zval val;
    1685             : 
    1686       68587 :         ZVAL_COPY_VALUE(&val, &p->val);
    1687       68587 :         ZVAL_COPY_VALUE(&p->val, &q->val);
    1688       68587 :         ZVAL_COPY_VALUE(&q->val, &val);
    1689       68587 : }
    1690             : 
    1691        1099 : ZEND_API void zend_hash_bucket_packed_swap(Bucket *p, Bucket *q) {
    1692             :         zval val;
    1693             :         zend_ulong h;
    1694             : 
    1695        1099 :         ZVAL_COPY_VALUE(&val, &p->val);
    1696        1099 :         h = p->h;
    1697             : 
    1698        1099 :         ZVAL_COPY_VALUE(&p->val, &q->val);
    1699        1099 :         p->h = q->h;
    1700             : 
    1701        1099 :         ZVAL_COPY_VALUE(&q->val, &val);
    1702        1099 :         q->h = h;
    1703        1099 : }
    1704             : 
    1705       22504 : ZEND_API int zend_hash_sort_ex(HashTable *ht, sort_func_t sort, compare_func_t compar, zend_bool renumber)
    1706             : {
    1707             :         Bucket *p;
    1708             :         uint32_t i, j;
    1709             : 
    1710             :         IS_CONSISTENT(ht);
    1711             : 
    1712       22504 :         if (!(ht->nNumOfElements>1) && !(renumber && ht->nNumOfElements>0)) { /* Doesn't require sorting */
    1713         288 :                 return SUCCESS;
    1714             :         }
    1715             : 
    1716       22216 :         if (ht->nNumUsed == ht->nNumOfElements) {
    1717       22106 :                 i = ht->nNumUsed;
    1718             :         } else {
    1719         787 :                 for (j = 0, i = 0; j < ht->nNumUsed; j++) {
    1720         677 :                         p = ht->arData + j;
    1721        1354 :                         if (Z_TYPE(p->val) == IS_UNDEF) continue;
    1722         520 :                         if (i != j) {
    1723         504 :                                 ht->arData[i] = *p;
    1724             :                         }
    1725         520 :                         i++;
    1726             :                 }
    1727             :         }
    1728             : 
    1729       44134 :         sort((void *)ht->arData, i, sizeof(Bucket), compar,
    1730             :                         (swap_func_t)(renumber? zend_hash_bucket_renum_swap :
    1731       21918 :                                 ((ht->u.flags & HASH_FLAG_PACKED) ? zend_hash_bucket_packed_swap : zend_hash_bucket_swap)));
    1732             : 
    1733       22215 :         HANDLE_BLOCK_INTERRUPTIONS();
    1734       22215 :         ht->nNumUsed = i;
    1735       22215 :         ht->nInternalPointer = 0;
    1736             : 
    1737       22215 :         if (renumber) {
    1738       15695 :                 for (j = 0; j < i; j++) {
    1739       15398 :                         p = ht->arData + j;
    1740       15398 :                         p->h = j;
    1741       15398 :                         if (p->key) {
    1742         288 :                                 zend_string_release(p->key);
    1743         288 :                                 p->key = NULL;
    1744             :                         }
    1745             :                 }
    1746             : 
    1747         297 :                 ht->nNextFreeElement = i;
    1748             :         }
    1749       22215 :         if (ht->u.flags & HASH_FLAG_PACKED) {
    1750         510 :                 if (!renumber) {
    1751         261 :                         zend_hash_packed_to_hash(ht);
    1752             :                 }
    1753             :         } else {
    1754       21705 :                 if (renumber) {
    1755          48 :                         ht->u.flags |= HASH_FLAG_PACKED;
    1756          48 :                         ht->nTableMask = 0;
    1757          96 :                         ht->arData = perealloc(ht->arData, ht->nTableSize * sizeof(Bucket), ht->u.flags & HASH_FLAG_PERSISTENT);
    1758          48 :                         ht->arHash = (uint32_t*)&uninitialized_bucket;
    1759             :                 } else {
    1760       21657 :                         zend_hash_rehash(ht);
    1761             :                 }
    1762             :         }
    1763             : 
    1764       22215 :         HANDLE_UNBLOCK_INTERRUPTIONS();
    1765             : 
    1766       22215 :         return SUCCESS;
    1767             : }
    1768             : 
    1769             : 
    1770        1141 : ZEND_API int zend_hash_compare(HashTable *ht1, HashTable *ht2, compare_func_t compar, zend_bool ordered)
    1771             : {
    1772             :         uint32_t idx1, idx2;
    1773        1141 :         Bucket *p1, *p2 = NULL;
    1774             :         int result;
    1775             :         zval *pData1, *pData2;
    1776             : 
    1777             :         IS_CONSISTENT(ht1);
    1778             :         IS_CONSISTENT(ht2);
    1779             : 
    1780        1141 :         HASH_PROTECT_RECURSION(ht1);
    1781        1141 :         HASH_PROTECT_RECURSION(ht2);
    1782             : 
    1783        1141 :         result = ht1->nNumOfElements - ht2->nNumOfElements;
    1784        1141 :         if (result!=0) {
    1785         527 :                 HASH_UNPROTECT_RECURSION(ht1);
    1786         527 :                 HASH_UNPROTECT_RECURSION(ht2);
    1787         527 :                 return result;
    1788             :         }
    1789             : 
    1790        4477 :         for (idx1 = 0, idx2 = 0; idx1 < ht1->nNumUsed; idx1++) {
    1791        4054 :                 p1 = ht1->arData + idx1;
    1792        8108 :                 if (Z_TYPE(p1->val) == IS_UNDEF) continue;
    1793             : 
    1794        4041 :                 if (ordered) {
    1795             :                         while (1) {
    1796        1140 :                                 p2 = ht2->arData + idx2;
    1797        1140 :                                 if (idx2 == ht2->nNumUsed) {
    1798           0 :                                         HASH_UNPROTECT_RECURSION(ht1);
    1799           0 :                                         HASH_UNPROTECT_RECURSION(ht2);
    1800           0 :                                         return 1; /* That's not supposed to happen */
    1801             :                                 }
    1802        2280 :                                 if (Z_TYPE(p2->val) != IS_UNDEF) break;
    1803           1 :                                 idx2++;
    1804           1 :                         }
    1805        1506 :                         if (p1->key == NULL && p2->key == NULL) { /* numeric indices */
    1806         368 :                                 result = p1->h - p2->h;
    1807         368 :                                 if (result != 0) {
    1808           1 :                                         HASH_UNPROTECT_RECURSION(ht1);
    1809           1 :                                         HASH_UNPROTECT_RECURSION(ht2);
    1810           1 :                                         return result;
    1811             :                                 }
    1812             :                         } else { /* string indices */
    1813         771 :                                 size_t len0 = (p1->key ? p1->key->len : 0);
    1814         771 :                                 size_t len1 = (p2->key ? p2->key->len : 0);
    1815         771 :                                 if (len0 != len1) {
    1816           0 :                                         HASH_UNPROTECT_RECURSION(ht1);
    1817           0 :                                         HASH_UNPROTECT_RECURSION(ht2);
    1818           0 :                                         return len0 > len1 ? 1 : -1;
    1819             :                                 }
    1820         771 :                                 result = memcmp(p1->key->val, p2->key->val, p1->key->len);
    1821         771 :                                 if (result != 0) {
    1822           0 :                                         HASH_UNPROTECT_RECURSION(ht1);
    1823           0 :                                         HASH_UNPROTECT_RECURSION(ht2);
    1824           0 :                                         return result;
    1825             :                                 }
    1826             :                         }
    1827        1138 :                         pData2 = &p2->val;
    1828             :                 } else {
    1829        2902 :                         if (p1->key == NULL) { /* numeric index */
    1830         486 :                                 pData2 = zend_hash_index_find(ht2, p1->h);
    1831         486 :                                 if (pData2 == NULL) {
    1832           2 :                                         HASH_UNPROTECT_RECURSION(ht1);
    1833           2 :                                         HASH_UNPROTECT_RECURSION(ht2);
    1834           2 :                                         return 1;
    1835             :                                 }
    1836             :                         } else { /* string index */
    1837        2416 :                                 pData2 = zend_hash_find(ht2, p1->key);
    1838        2416 :                                 if (pData2 == NULL) {
    1839          24 :                                         HASH_UNPROTECT_RECURSION(ht1);
    1840          24 :                                         HASH_UNPROTECT_RECURSION(ht2);
    1841          24 :                                         return 1;
    1842             :                                 }
    1843             :                         }
    1844             :                 }
    1845        4014 :                 pData1 = &p1->val;
    1846        4014 :                 if (Z_TYPE_P(pData1) == IS_INDIRECT) {
    1847         129 :                         pData1 = Z_INDIRECT_P(pData1);
    1848             :                 }
    1849        4014 :                 if (Z_TYPE_P(pData2) == IS_INDIRECT) {
    1850         129 :                         pData2 = Z_INDIRECT_P(pData2);
    1851             :                 }
    1852        4014 :                 if (Z_TYPE_P(pData1) == IS_UNDEF) {
    1853           0 :                         if (Z_TYPE_P(pData2) != IS_UNDEF) {
    1854           0 :                                 return -1;
    1855             :                         }
    1856        4014 :                 } else if (Z_TYPE_P(pData2) == IS_UNDEF) {
    1857           0 :                         return 1;
    1858             :                 } else {
    1859        4014 :                         result = compar(pData1, pData2);
    1860             :                 }
    1861        4014 :                 if (result != 0) {
    1862         164 :                         HASH_UNPROTECT_RECURSION(ht1);
    1863         164 :                         HASH_UNPROTECT_RECURSION(ht2);
    1864         164 :                         return result;
    1865             :                 }
    1866        3850 :                 if (ordered) {
    1867        1134 :                         idx2++;
    1868             :                 }
    1869             :         }
    1870             : 
    1871         423 :         HASH_UNPROTECT_RECURSION(ht1);
    1872         423 :         HASH_UNPROTECT_RECURSION(ht2);
    1873         423 :         return 0;
    1874             : }
    1875             : 
    1876             : 
    1877          82 : ZEND_API zval *zend_hash_minmax(const HashTable *ht, compare_func_t compar, uint32_t flag)
    1878             : {
    1879             :         uint32_t idx;
    1880             :         Bucket *p, *res;
    1881             : 
    1882             :         IS_CONSISTENT(ht);
    1883             : 
    1884          82 :         if (ht->nNumOfElements == 0 ) {
    1885           4 :                 return NULL;
    1886             :         }
    1887             : 
    1888          78 :         idx = 0;
    1889             :         while (1) {
    1890          78 :                 if (idx == ht->nNumUsed) {
    1891           0 :                         return NULL;
    1892             :                 }
    1893         156 :                 if (Z_TYPE(ht->arData[idx].val) != IS_UNDEF) break;
    1894           0 :                 idx++;
    1895           0 :         }
    1896          78 :         res = ht->arData + idx;
    1897         376 :         for (; idx < ht->nNumUsed; idx++) {
    1898         298 :                 p = ht->arData + idx;
    1899         596 :                 if (Z_TYPE(p->val) == IS_UNDEF) continue;
    1900             : 
    1901         298 :                 if (flag) {
    1902         229 :                         if (compar(res, p) < 0) { /* max */
    1903          20 :                                 res = p;
    1904             :                         }
    1905             :                 } else {
    1906          69 :                         if (compar(res, p) > 0) { /* min */
    1907           6 :                                 res = p;
    1908             :                         }
    1909             :                 }
    1910             :         }
    1911          78 :         return &res->val;
    1912             : }
    1913             : 
    1914      383125 : ZEND_API int _zend_handle_numeric_str_ex(const char *key, size_t length, zend_ulong *idx)
    1915             : {
    1916      383125 :         register const char *tmp = key;
    1917             : 
    1918      383125 :         const char *end = key + length;
    1919             :         ZEND_ASSERT(*end == '\0');
    1920             : 
    1921      383125 :         if (*tmp == '-') {
    1922          59 :                 tmp++;
    1923             :         }
    1924             : 
    1925      746109 :         if ((*tmp == '0' && length > 1) /* numbers with leading zeros */
    1926      362984 :          || (end - tmp > MAX_LENGTH_OF_LONG - 1) /* number too long */
    1927             :          || (SIZEOF_ZEND_LONG == 4 &&
    1928             :              end - tmp == MAX_LENGTH_OF_LONG - 1 &&
    1929             :              *tmp > '2')) { /* overflow */
    1930       20168 :                 return 0;
    1931             :         }
    1932      362957 :         *idx = (*tmp - '0');
    1933             :         while (1) {
    1934     1444658 :                 ++tmp;
    1935     1444658 :                 if (tmp == end) {
    1936      362694 :                         if (*key == '-') {
    1937          28 :                                 if (*idx-1 > ZEND_LONG_MAX) { /* overflow */
    1938           0 :                                         return 0;
    1939             :                                 }
    1940          28 :                                 *idx = 0 - *idx;
    1941      362666 :                         } else if (*idx > ZEND_LONG_MAX) { /* overflow */
    1942           0 :                                 return 0;
    1943             :                         }
    1944      362694 :                         return 1;
    1945             :                 }
    1946     2163665 :                 if (*tmp <= '9' && *tmp >= '0') {
    1947     1081701 :                         *idx = (*idx * 10) + (*tmp - '0');
    1948             :                 } else {
    1949         263 :                         return 0;
    1950             :                 }
    1951     1081701 :         }
    1952             : }
    1953             : 
    1954             : /*
    1955             :  * Local variables:
    1956             :  * tab-width: 4
    1957             :  * c-basic-offset: 4
    1958             :  * indent-tabs-mode: t
    1959             :  * End:
    1960             :  */

Generated by: LCOV version 1.10

Generated at Mon, 26 Jan 2015 14:46:41 +0000 (3 days ago)

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