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: 631 695 90.8 %
Date: 2014-08-04 Functions: 46 48 95.8 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :    +----------------------------------------------------------------------+
       3             :    | Zend Engine                                                          |
       4             :    +----------------------------------------------------------------------+
       5             :    | Copyright (c) 1998-2014 Zend Technologies Ltd. (http://www.zend.com) |
       6             :    +----------------------------------------------------------------------+
       7             :    | This source file is subject to version 2.00 of the Zend license,     |
       8             :    | that is bundled with this package in the file LICENSE, and is        | 
       9             :    | available through the world-wide-web at the following url:           |
      10             :    | http://www.zend.com/license/2_00.txt.                                |
      11             :    | If you did not receive a copy of the Zend license and are unable to  |
      12             :    | obtain it through the world-wide-web, please send a note to          |
      13             :    | license@zend.com so we can mail you a copy immediately.              |
      14             :    +----------------------------------------------------------------------+
      15             :    | Authors: Andi Gutmans <andi@zend.com>                                |
      16             :    |          Zeev Suraski <zeev@zend.com>                                |
      17             :    +----------------------------------------------------------------------+
      18             : */
      19             : 
      20             : /* $Id$ */
      21             : 
      22             : #include "zend.h"
      23             : #include "zend_globals.h"
      24             : 
      25             : #define CONNECT_TO_BUCKET_DLLIST(element, list_head)            \
      26             :         (element)->pNext = (list_head);                                                      \
      27             :         (element)->pLast = NULL;                                                             \
      28             :         if ((element)->pNext) {                                                                      \
      29             :                 (element)->pNext->pLast = (element);                              \
      30             :         }
      31             : 
      32             : #define CONNECT_TO_GLOBAL_DLLIST_EX(element, ht, last, next)\
      33             :         (element)->pListLast = (last);                                                       \
      34             :         (element)->pListNext = (next);                                                       \
      35             :         if ((last) != NULL) {                                                                   \
      36             :                 (last)->pListNext = (element);                                               \
      37             :         } else {                                                                                                \
      38             :                 (ht)->pListHead = (element);                                         \
      39             :         }                                                                                                               \
      40             :         if ((next) != NULL) {                                                                   \
      41             :                 (next)->pListLast = (element);                                               \
      42             :         } else {                                                                                                \
      43             :                 (ht)->pListTail = (element);                                         \
      44             :         }                                                                                                               \
      45             : 
      46             : #define CONNECT_TO_GLOBAL_DLLIST(element, ht)                                                                   \
      47             :         CONNECT_TO_GLOBAL_DLLIST_EX(element, ht, (ht)->pListTail, (Bucket *) NULL);  \
      48             :         if ((ht)->pInternalPointer == NULL) {                                                                                \
      49             :                 (ht)->pInternalPointer = (element);                                                                          \
      50             :         }
      51             : 
      52             : #if ZEND_DEBUG
      53             : #define HT_OK                           0
      54             : #define HT_IS_DESTROYING        1
      55             : #define HT_DESTROYED            2
      56             : #define HT_CLEANING                     3
      57             : 
      58             : static void _zend_is_inconsistent(const HashTable *ht, const char *file, int line)
      59             : {
      60             :         if (ht->inconsistent==HT_OK) {
      61             :                 return;
      62             :         }
      63             :         switch (ht->inconsistent) {
      64             :                 case HT_IS_DESTROYING:
      65             :                         zend_output_debug_string(1, "%s(%d) : ht=%p is being destroyed", file, line, ht);
      66             :                         break;
      67             :                 case HT_DESTROYED:
      68             :                         zend_output_debug_string(1, "%s(%d) : ht=%p is already destroyed", file, line, ht);
      69             :                         break;
      70             :                 case HT_CLEANING:
      71             :                         zend_output_debug_string(1, "%s(%d) : ht=%p is being cleaned", file, line, ht);
      72             :                         break;
      73             :                 default:
      74             :                         zend_output_debug_string(1, "%s(%d) : ht=%p is inconsistent", file, line, ht);
      75             :                         break;
      76             :         }
      77             :         zend_bailout();
      78             : }
      79             : #define IS_CONSISTENT(a) _zend_is_inconsistent(a, __FILE__, __LINE__);
      80             : #define SET_INCONSISTENT(n) ht->inconsistent = n;
      81             : #else
      82             : #define IS_CONSISTENT(a)
      83             : #define SET_INCONSISTENT(n)
      84             : #endif
      85             : 
      86             : #define HASH_PROTECT_RECURSION(ht)                                                                                                              \
      87             :         if ((ht)->bApplyProtection) {                                                                                                                \
      88             :                 if ((ht)->nApplyCount++ >= 3) {                                                                                                   \
      89             :                         zend_error(E_ERROR, "Nesting level too deep - recursive dependency?");                \
      90             :                 }                                                                                                                                                               \
      91             :         }
      92             : 
      93             : 
      94             : #define HASH_UNPROTECT_RECURSION(ht)                                                                                                    \
      95             :         if ((ht)->bApplyProtection) {                                                                                                                \
      96             :                 (ht)->nApplyCount--;                                                                                                                 \
      97             :         }
      98             : 
      99             : 
     100             : #define ZEND_HASH_IF_FULL_DO_RESIZE(ht)                         \
     101             :         if ((ht)->nNumOfElements > (ht)->nTableSize) { \
     102             :                 zend_hash_do_resize(ht);                                        \
     103             :         }
     104             : 
     105             : static void zend_hash_do_resize(HashTable *ht);
     106             : 
     107    57694565 : ZEND_API ulong zend_hash_func(const char *arKey, uint nKeyLength)
     108             : {
     109    57694565 :         return zend_inline_hash_func(arKey, nKeyLength);
     110             : }
     111             : 
     112             : 
     113             : #define UPDATE_DATA(ht, p, pData, nDataSize)                                                                                    \
     114             :         if (nDataSize == sizeof(void*)) {                                                                                                       \
     115             :                 if ((p)->pData != &(p)->pDataPtr) {                                                                                           \
     116             :                         pefree_rel((p)->pData, (ht)->persistent);                                                                 \
     117             :                 }                                                                                                                                                               \
     118             :                 memcpy(&(p)->pDataPtr, pData, sizeof(void *));                                                                   \
     119             :                 (p)->pData = &(p)->pDataPtr;                                                                                                  \
     120             :         } else {                                                                                                                                                        \
     121             :                 if ((p)->pData == &(p)->pDataPtr) {                                                                                           \
     122             :                         (p)->pData = (void *) pemalloc_rel(nDataSize, (ht)->persistent);                  \
     123             :                         (p)->pDataPtr=NULL;                                                                                                                  \
     124             :                 } else {                                                                                                                                                \
     125             :                         (p)->pData = (void *) perealloc_rel((p)->pData, nDataSize, (ht)->persistent);  \
     126             :                         /* (p)->pDataPtr is already NULL so no need to initialize it */                              \
     127             :                 }                                                                                                                                                               \
     128             :                 memcpy((p)->pData, pData, nDataSize);                                                                                        \
     129             :         }
     130             : 
     131             : #define INIT_DATA(ht, p, _pData, nDataSize);                                                            \
     132             :         if (nDataSize == sizeof(void*)) {                                                                       \
     133             :                 memcpy(&(p)->pDataPtr, (_pData), sizeof(void *));                                        \
     134             :                 (p)->pData = &(p)->pDataPtr;                                                                  \
     135             :         } else {                                                                                                                        \
     136             :                 (p)->pData = (void *) pemalloc_rel(nDataSize, (ht)->persistent);\
     137             :                 memcpy((p)->pData, (_pData), nDataSize);                                                     \
     138             :                 (p)->pDataPtr=NULL;                                                                                          \
     139             :         }
     140             : 
     141             : #define CHECK_INIT(ht) do {                                                                                             \
     142             :         if (UNEXPECTED((ht)->nTableMask == 0)) {                                                             \
     143             :                 (ht)->arBuckets = (Bucket **) pecalloc((ht)->nTableSize, sizeof(Bucket *), (ht)->persistent);  \
     144             :                 (ht)->nTableMask = (ht)->nTableSize - 1;                                          \
     145             :         }                                                                                                                                       \
     146             : } while (0)
     147             :  
     148             : static const Bucket *uninitialized_bucket = NULL;
     149             : 
     150             : static zend_always_inline void i_zend_hash_bucket_delete(HashTable *ht, Bucket *p)
     151             : {
     152             : #ifdef ZEND_SIGNALS
     153             :         TSRMLS_FETCH();
     154             : #endif
     155             : 
     156    59982403 :         HANDLE_BLOCK_INTERRUPTIONS();
     157    59982403 :         if (p->pLast) {
     158     3652759 :                 p->pLast->pNext = p->pNext;
     159             :         } else {
     160    56329644 :                 ht->arBuckets[p->h & ht->nTableMask] = p->pNext;
     161             :         }
     162    59982403 :         if (p->pNext) {
     163    11403329 :                 p->pNext->pLast = p->pLast;
     164             :         }
     165    59982403 :         if (p->pListLast != NULL) {
     166    56401631 :                 p->pListLast->pListNext = p->pListNext;
     167             :         } else { 
     168             :                 /* Deleting the head of the list */
     169     3580772 :                 ht->pListHead = p->pListNext;
     170             :         }
     171    59982403 :         if (p->pListNext != NULL) {
     172    57044726 :                 p->pListNext->pListLast = p->pListLast;
     173             :         } else {
     174             :                 /* Deleting the tail of the list */
     175     2937677 :                 ht->pListTail = p->pListLast;
     176             :         }
     177    59982403 :         if (ht->pInternalPointer == p) {
     178     3580699 :                 ht->pInternalPointer = p->pListNext;
     179             :         }
     180    59982403 :         ht->nNumOfElements--;
     181    59982403 :         if (ht->pDestructor) {
     182    53097889 :                 ht->pDestructor(p->pData);
     183             :         }
     184    59982401 :         if (p->pData != &p->pDataPtr) {
     185    58576856 :                 pefree(p->pData, ht->persistent);
     186             :         }
     187    59982401 :         pefree(p, ht->persistent);
     188    59982401 :         HANDLE_UNBLOCK_INTERRUPTIONS();
     189             : }
     190             : 
     191     8069454 : static void zend_hash_bucket_delete(HashTable *ht, Bucket *p) {
     192             :         i_zend_hash_bucket_delete(ht, p);
     193     8069454 : }
     194             : 
     195    19509497 : ZEND_API int _zend_hash_init(HashTable *ht, uint nSize, dtor_func_t pDestructor, zend_bool persistent ZEND_FILE_LINE_DC)
     196             : {
     197    19509497 :         uint i = 3;
     198             : 
     199             :         SET_INCONSISTENT(HT_OK);
     200             : 
     201    19509497 :         if (nSize >= 0x80000000) {
     202             :                 /* prevent overflow */
     203           0 :                 ht->nTableSize = 0x80000000;
     204             :         } else {
     205    40147642 :                 while ((1U << i) < nSize) {
     206     1128648 :                         i++;
     207             :                 }
     208    19509497 :                 ht->nTableSize = 1 << i;
     209             :         }
     210             : 
     211    19509497 :         ht->nTableMask = 0;  /* 0 means that ht->arBuckets is uninitialized */
     212    19509497 :         ht->pDestructor = pDestructor;
     213    19509497 :         ht->arBuckets = (Bucket**)&uninitialized_bucket;
     214    19509497 :         ht->pListHead = NULL;
     215    19509497 :         ht->pListTail = NULL;
     216    19509497 :         ht->nNumOfElements = 0;
     217    19509497 :         ht->nNextFreeElement = 0;
     218    19509497 :         ht->pInternalPointer = NULL;
     219    19509497 :         ht->persistent = persistent;
     220    19509497 :         ht->nApplyCount = 0;
     221    19509497 :         ht->bApplyProtection = 1;
     222    19509497 :         return SUCCESS;
     223             : }
     224             : 
     225             : 
     226    11696923 : ZEND_API int _zend_hash_init_ex(HashTable *ht, uint nSize, dtor_func_t pDestructor, zend_bool persistent, zend_bool bApplyProtection ZEND_FILE_LINE_DC)
     227             : {
     228    11696923 :         int retval = _zend_hash_init(ht, nSize, pDestructor, persistent ZEND_FILE_LINE_CC);
     229             : 
     230    11696923 :         ht->bApplyProtection = bApplyProtection;
     231    11696923 :         return retval;
     232             : }
     233             : 
     234             : 
     235           0 : ZEND_API void zend_hash_set_apply_protection(HashTable *ht, zend_bool bApplyProtection)
     236             : {
     237           0 :         ht->bApplyProtection = bApplyProtection;
     238           0 : }
     239             : 
     240             : 
     241             : 
     242    89123667 : ZEND_API int _zend_hash_add_or_update(HashTable *ht, const char *arKey, uint nKeyLength, void *pData, uint nDataSize, void **pDest, int flag ZEND_FILE_LINE_DC)
     243             : {
     244             :         ulong h;
     245             :         uint nIndex;
     246             :         Bucket *p;
     247             : #ifdef ZEND_SIGNALS
     248             :         TSRMLS_FETCH();
     249             : #endif
     250             : 
     251             :         IS_CONSISTENT(ht);
     252             : 
     253             :         ZEND_ASSERT(nKeyLength != 0);
     254             : 
     255    89123667 :         CHECK_INIT(ht);
     256             : 
     257    89123667 :         h = zend_inline_hash_func(arKey, nKeyLength);
     258    89123667 :         nIndex = h & ht->nTableMask;
     259             : 
     260    89123667 :         p = ht->arBuckets[nIndex];
     261   212168217 :         while (p != NULL) {
     262    71724553 :                 if (p->arKey == arKey ||
     263    36833790 :                         ((p->h == h) && (p->nKeyLength == nKeyLength) && !memcmp(p->arKey, arKey, nKeyLength))) {
     264      969880 :                                 if (flag & HASH_ADD) {
     265      242086 :                                         return FAILURE;
     266             :                                 }
     267             :                                 ZEND_ASSERT(p->pData != pData);
     268      727794 :                                 HANDLE_BLOCK_INTERRUPTIONS();
     269      727794 :                                 if (ht->pDestructor) {
     270      684874 :                                         ht->pDestructor(p->pData);
     271             :                                 }
     272      727794 :                                 UPDATE_DATA(ht, p, pData, nDataSize);
     273      727794 :                                 if (pDest) {
     274      604887 :                                         *pDest = p->pData;
     275             :                                 }
     276      727794 :                                 HANDLE_UNBLOCK_INTERRUPTIONS();
     277      727794 :                                 return SUCCESS;
     278             :                 }
     279    33920883 :                 p = p->pNext;
     280             :         }
     281             :         
     282    88964679 :         if (IS_INTERNED(arKey)) {
     283      810892 :                 p = (Bucket *) pemalloc(sizeof(Bucket), ht->persistent);
     284      810892 :                 p->arKey = arKey;
     285             :         } else {
     286    87342895 :                 p = (Bucket *) pemalloc(sizeof(Bucket) + nKeyLength, ht->persistent);
     287    87342895 :                 p->arKey = (const char*)(p + 1);
     288    87342895 :                 memcpy((char*)p->arKey, arKey, nKeyLength);
     289             :         }
     290    88153787 :         p->nKeyLength = nKeyLength;
     291    88153787 :         INIT_DATA(ht, p, pData, nDataSize);
     292    88153787 :         p->h = h;
     293    88153787 :         CONNECT_TO_BUCKET_DLLIST(p, ht->arBuckets[nIndex]);
     294    88153787 :         if (pDest) {
     295     9733026 :                 *pDest = p->pData;
     296             :         }
     297             : 
     298    88153787 :         HANDLE_BLOCK_INTERRUPTIONS();
     299    88153787 :         CONNECT_TO_GLOBAL_DLLIST(p, ht);
     300    88153787 :         ht->arBuckets[nIndex] = p;
     301    88153787 :         HANDLE_UNBLOCK_INTERRUPTIONS();
     302             : 
     303    88153787 :         ht->nNumOfElements++;
     304    88153787 :         ZEND_HASH_IF_FULL_DO_RESIZE(ht);                /* If the Hash table is full, resize it */
     305    88153787 :         return SUCCESS;
     306             : }
     307             : 
     308   183862354 : ZEND_API int _zend_hash_quick_add_or_update(HashTable *ht, const char *arKey, uint nKeyLength, ulong h, void *pData, uint nDataSize, void **pDest, int flag ZEND_FILE_LINE_DC)
     309             : {
     310             :         uint nIndex;
     311             :         Bucket *p;
     312             : #ifdef ZEND_SIGNALS
     313             :         TSRMLS_FETCH();
     314             : #endif
     315             : 
     316             :         IS_CONSISTENT(ht);
     317             : 
     318             :         ZEND_ASSERT(nKeyLength != 0);
     319             : 
     320   183862354 :         CHECK_INIT(ht);
     321   183862354 :         nIndex = h & ht->nTableMask;
     322             :         
     323   183862354 :         p = ht->arBuckets[nIndex];
     324   487621558 :         while (p != NULL) {
     325   239798379 :                 if (p->arKey == arKey ||
     326   119898756 :                         ((p->h == h) && (p->nKeyLength == nKeyLength) && !memcmp(p->arKey, arKey, nKeyLength))) {
     327        2773 :                                 if (flag & HASH_ADD) {
     328        2106 :                                         return FAILURE;
     329             :                                 }
     330             :                                 ZEND_ASSERT(p->pData != pData);
     331         667 :                                 HANDLE_BLOCK_INTERRUPTIONS();
     332         667 :                                 if (ht->pDestructor) {
     333         661 :                                         ht->pDestructor(p->pData);
     334             :                                 }
     335         667 :                                 UPDATE_DATA(ht, p, pData, nDataSize);
     336         667 :                                 if (pDest) {
     337         554 :                                         *pDest = p->pData;
     338             :                                 }
     339         667 :                                 HANDLE_UNBLOCK_INTERRUPTIONS();
     340         667 :                                 return SUCCESS;
     341             :                 }
     342   119896850 :                 p = p->pNext;
     343             :         }
     344             :         
     345   301691381 :         if (IS_INTERNED(arKey)) {
     346   117831800 :                 p = (Bucket *) pemalloc(sizeof(Bucket), ht->persistent);
     347   117831800 :                 p->arKey = arKey;
     348             :         } else {
     349    66027781 :                 p = (Bucket *) pemalloc(sizeof(Bucket) + nKeyLength, ht->persistent);
     350    66027781 :                 p->arKey = (const char*)(p + 1);
     351    66027781 :                 memcpy((char*)p->arKey, arKey, nKeyLength);
     352             :         }
     353             : 
     354   183859581 :         p->nKeyLength = nKeyLength;
     355   183859581 :         INIT_DATA(ht, p, pData, nDataSize);
     356   183859581 :         p->h = h;
     357             :         
     358   183859581 :         CONNECT_TO_BUCKET_DLLIST(p, ht->arBuckets[nIndex]);
     359             : 
     360   183859581 :         if (pDest) {
     361   123509624 :                 *pDest = p->pData;
     362             :         }
     363             : 
     364   183859581 :         HANDLE_BLOCK_INTERRUPTIONS();
     365   183859581 :         ht->arBuckets[nIndex] = p;
     366   183859581 :         CONNECT_TO_GLOBAL_DLLIST(p, ht);
     367   183859581 :         HANDLE_UNBLOCK_INTERRUPTIONS();
     368             : 
     369   183859581 :         ht->nNumOfElements++;
     370   183859581 :         ZEND_HASH_IF_FULL_DO_RESIZE(ht);                /* If the Hash table is full, resize it */
     371   183859581 :         return SUCCESS;
     372             : }
     373             : 
     374             : 
     375      487429 : ZEND_API int zend_hash_add_empty_element(HashTable *ht, const char *arKey, uint nKeyLength)
     376             : {
     377      487429 :         void *dummy = (void *) 1;
     378             : 
     379      487429 :         return zend_hash_add(ht, arKey, nKeyLength, &dummy, sizeof(void *), NULL);
     380             : }
     381             : 
     382             : 
     383    11791909 : ZEND_API int _zend_hash_index_update_or_next_insert(HashTable *ht, ulong h, void *pData, uint nDataSize, void **pDest, int flag ZEND_FILE_LINE_DC)
     384             : {
     385             :         uint nIndex;
     386             :         Bucket *p;
     387             : #ifdef ZEND_SIGNALS
     388             :         TSRMLS_FETCH();
     389             : #endif
     390             : 
     391             :         IS_CONSISTENT(ht);
     392    11791909 :         CHECK_INIT(ht);
     393             : 
     394    11791909 :         if (flag & HASH_NEXT_INSERT) {
     395     5008462 :                 h = ht->nNextFreeElement;
     396             :         }
     397    11791909 :         nIndex = h & ht->nTableMask;
     398             : 
     399    11791909 :         p = ht->arBuckets[nIndex];
     400    24441686 :         while (p != NULL) {
     401      871691 :                 if ((p->nKeyLength == 0) && (p->h == h)) {
     402       13823 :                         if (flag & HASH_NEXT_INSERT || flag & HASH_ADD) {
     403           3 :                                 return FAILURE;
     404             :                         }
     405             :                         ZEND_ASSERT(p->pData != pData);
     406       13820 :                         HANDLE_BLOCK_INTERRUPTIONS();
     407       13820 :                         if (ht->pDestructor) {
     408       13820 :                                 ht->pDestructor(p->pData);
     409             :                         }
     410       13820 :                         UPDATE_DATA(ht, p, pData, nDataSize);
     411       13820 :                         HANDLE_UNBLOCK_INTERRUPTIONS();
     412       13820 :                         if (pDest) {
     413           3 :                                 *pDest = p->pData;
     414             :                         }
     415       13820 :                         return SUCCESS;
     416             :                 }
     417      857868 :                 p = p->pNext;
     418             :         }
     419    11778086 :         p = (Bucket *) pemalloc_rel(sizeof(Bucket), ht->persistent);
     420    11778086 :         p->arKey = NULL;
     421    11778086 :         p->nKeyLength = 0; /* Numeric indices are marked by making the nKeyLength == 0 */
     422    11778086 :         p->h = h;
     423    11778086 :         INIT_DATA(ht, p, pData, nDataSize);
     424    11778086 :         if (pDest) {
     425     4870409 :                 *pDest = p->pData;
     426             :         }
     427             : 
     428    11778086 :         CONNECT_TO_BUCKET_DLLIST(p, ht->arBuckets[nIndex]);
     429             : 
     430    11778086 :         HANDLE_BLOCK_INTERRUPTIONS();
     431    11778086 :         ht->arBuckets[nIndex] = p;
     432    11778086 :         CONNECT_TO_GLOBAL_DLLIST(p, ht);
     433    11778086 :         HANDLE_UNBLOCK_INTERRUPTIONS();
     434             : 
     435    11778086 :         if ((long)h >= (long)ht->nNextFreeElement) {
     436    10168636 :                 ht->nNextFreeElement = h < LONG_MAX ? h + 1 : LONG_MAX;
     437             :         }
     438    11778086 :         ht->nNumOfElements++;
     439    11778086 :         ZEND_HASH_IF_FULL_DO_RESIZE(ht);
     440    11778086 :         return SUCCESS;
     441             : }
     442             : 
     443             : 
     444     6703497 : static void zend_hash_do_resize(HashTable *ht)
     445             : {
     446             :         Bucket **t;
     447             : #ifdef ZEND_SIGNALS
     448             :         TSRMLS_FETCH();
     449             : #endif
     450             : 
     451             :         IS_CONSISTENT(ht);
     452             : 
     453     6703497 :         if ((ht->nTableSize << 1) > 0) {    /* Let's double the table size */
     454     6703497 :                 t = (Bucket **) perealloc(ht->arBuckets, (ht->nTableSize << 1) * sizeof(Bucket *), ht->persistent);
     455     6703497 :                 HANDLE_BLOCK_INTERRUPTIONS();
     456     6703497 :                 ht->arBuckets = t;
     457     6703497 :                 ht->nTableSize = (ht->nTableSize << 1);
     458     6703497 :                 ht->nTableMask = ht->nTableSize - 1;
     459     6703497 :                 zend_hash_rehash(ht);
     460     6703497 :                 HANDLE_UNBLOCK_INTERRUPTIONS();
     461             :         }
     462     6703497 : }
     463             : 
     464     6894914 : ZEND_API int zend_hash_rehash(HashTable *ht)
     465             : {
     466             :         Bucket *p;
     467             :         uint nIndex;
     468             : 
     469             :         IS_CONSISTENT(ht);
     470     6894914 :         if (UNEXPECTED(ht->nNumOfElements == 0)) {
     471           0 :                 return SUCCESS;
     472             :         }
     473             : 
     474     6894914 :         memset(ht->arBuckets, 0, ht->nTableSize * sizeof(Bucket *));
     475   377145672 :         for (p = ht->pListHead; p != NULL; p = p->pListNext) {
     476   370250758 :                 nIndex = p->h & ht->nTableMask;
     477   370250758 :                 CONNECT_TO_BUCKET_DLLIST(p, ht->arBuckets[nIndex]);
     478   370250758 :                 ht->arBuckets[nIndex] = p;
     479             :         }
     480     6894914 :         return SUCCESS;
     481             : }
     482             : 
     483       90995 : ZEND_API void zend_hash_reindex(HashTable *ht, zend_bool only_integer_keys) {
     484             :         Bucket *p;
     485             :         uint nIndex;
     486       90995 :         ulong offset = 0;
     487             : 
     488             :         IS_CONSISTENT(ht);
     489       90995 :         if (UNEXPECTED(ht->nNumOfElements == 0)) {
     490          43 :                 ht->nNextFreeElement = 0;
     491          43 :                 return;
     492             :         }
     493             : 
     494       90952 :         memset(ht->arBuckets, 0, ht->nTableSize * sizeof(Bucket *));
     495      470654 :         for (p = ht->pListHead; p != NULL; p = p->pListNext) {
     496      379702 :                 if (!only_integer_keys || p->nKeyLength == 0) {
     497      378892 :                         p->h = offset++;
     498      378892 :                         p->nKeyLength = 0;
     499             :                 }
     500             : 
     501      379702 :                 nIndex = p->h & ht->nTableMask;
     502      379702 :                 CONNECT_TO_BUCKET_DLLIST(p, ht->arBuckets[nIndex]);
     503      379702 :                 ht->arBuckets[nIndex] = p;
     504             :         }
     505       90952 :         ht->nNextFreeElement = offset;
     506             : }
     507             : 
     508    52826286 : ZEND_API int zend_hash_del_key_or_index(HashTable *ht, const char *arKey, uint nKeyLength, ulong h, int flag)
     509             : {
     510             :         uint nIndex;
     511             :         Bucket *p;
     512             : 
     513             :         IS_CONSISTENT(ht);
     514             : 
     515    52826286 :         if (flag == HASH_DEL_KEY) {
     516    51738691 :                 h = zend_inline_hash_func(arKey, nKeyLength);
     517             :         }
     518    52826286 :         nIndex = h & ht->nTableMask;
     519             : 
     520    52826286 :         p = ht->arBuckets[nIndex];
     521   109171759 :         while (p != NULL) {
     522   210222722 :                 if ((p->h == h) 
     523    51912995 :                          && (p->nKeyLength == nKeyLength)
     524    51912995 :                          && ((p->nKeyLength == 0) /* Numeric index (short circuits the memcmp() check) */
     525    50964596 :                                  || !memcmp(p->arKey, arKey, nKeyLength))) { /* String index */
     526             :                         i_zend_hash_bucket_delete(ht, p);
     527    51912947 :                         return SUCCESS;
     528             :                 }
     529     3519187 :                 p = p->pNext;
     530             :         }
     531      913337 :         return FAILURE;
     532             : }
     533             : 
     534             : 
     535    19421951 : ZEND_API void zend_hash_destroy(HashTable *ht)
     536             : {
     537             :         Bucket *p, *q;
     538             : 
     539             :         IS_CONSISTENT(ht);
     540             : 
     541             :         SET_INCONSISTENT(HT_IS_DESTROYING);
     542             : 
     543    19421951 :         p = ht->pListHead;
     544   259774667 :         while (p != NULL) {
     545   220930768 :                 q = p;
     546   220930768 :                 p = p->pListNext;
     547   220930768 :                 if (ht->pDestructor) {
     548   149882416 :                         ht->pDestructor(q->pData);
     549             :                 }
     550   220930765 :                 if (q->pData != &q->pDataPtr) {
     551   179395159 :                         pefree(q->pData, ht->persistent);
     552             :                 }
     553   220930765 :                 pefree(q, ht->persistent);
     554             :         }
     555    19421948 :         if (ht->nTableMask) {
     556    10926818 :                 pefree(ht->arBuckets, ht->persistent);
     557             :         }
     558             : 
     559             :         SET_INCONSISTENT(HT_DESTROYED);
     560    19421948 : }
     561             : 
     562             : 
     563       88508 : ZEND_API void zend_hash_clean(HashTable *ht)
     564             : {
     565             :         Bucket *p, *q;
     566             : 
     567             :         IS_CONSISTENT(ht);
     568             : 
     569       88508 :         p = ht->pListHead;
     570             : 
     571       88508 :         if (ht->nTableMask) {
     572       45485 :                 memset(ht->arBuckets, 0, ht->nTableSize*sizeof(Bucket *));
     573             :         }
     574       88508 :         ht->pListHead = NULL;
     575       88508 :         ht->pListTail = NULL;
     576       88508 :         ht->nNumOfElements = 0;
     577       88508 :         ht->nNextFreeElement = 0;
     578       88508 :         ht->pInternalPointer = NULL;
     579             : 
     580     3480217 :         while (p != NULL) {
     581     3303201 :                 q = p;
     582     3303201 :                 p = p->pListNext;
     583     3303201 :                 if (ht->pDestructor) {
     584     3272714 :                         ht->pDestructor(q->pData);
     585             :                 }
     586     3303201 :                 if (q->pData != &q->pDataPtr) {
     587     1821015 :                         pefree(q->pData, ht->persistent);
     588             :                 }
     589     3303201 :                 pefree(q, ht->persistent);
     590             :         }
     591       88508 : }
     592             : 
     593           0 : ZEND_API void zend_hash_graceful_destroy(HashTable *ht)
     594             : {
     595             :         IS_CONSISTENT(ht);
     596             : 
     597           0 :         while (ht->pListHead != NULL) {
     598           0 :                 zend_hash_bucket_delete(ht, ht->pListHead);
     599             :         }
     600             : 
     601           0 :         if (ht->nTableMask) {
     602           0 :                 pefree(ht->arBuckets, ht->persistent);
     603             :         }
     604             : 
     605             :         SET_INCONSISTENT(HT_DESTROYED);
     606           0 : }
     607             : 
     608       85232 : ZEND_API void zend_hash_graceful_reverse_destroy(HashTable *ht)
     609             : {
     610             :         IS_CONSISTENT(ht);
     611             : 
     612     1989235 :         while (ht->pListTail != NULL) {
     613     1818771 :                 zend_hash_bucket_delete(ht, ht->pListTail);
     614             :         }
     615             : 
     616       85232 :         if (ht->nTableMask) {
     617       65283 :                 pefree(ht->arBuckets, ht->persistent);
     618             :         }
     619             : 
     620             :         SET_INCONSISTENT(HT_DESTROYED);
     621       85232 : }
     622             : 
     623             : /* This is used to recurse elements and selectively delete certain entries 
     624             :  * from a hashtable. apply_func() receives the data and decides if the entry 
     625             :  * should be deleted or recursion should be stopped. The following three 
     626             :  * return codes are possible:
     627             :  * ZEND_HASH_APPLY_KEEP   - continue
     628             :  * ZEND_HASH_APPLY_STOP   - stop iteration
     629             :  * ZEND_HASH_APPLY_REMOVE - delete the element, combineable with the former
     630             :  */
     631             : 
     632      367500 : ZEND_API void zend_hash_apply(HashTable *ht, apply_func_t apply_func TSRMLS_DC)
     633             : {
     634             :         Bucket *p;
     635             : 
     636             :         IS_CONSISTENT(ht);
     637             : 
     638      367500 :         HASH_PROTECT_RECURSION(ht);
     639      367500 :         p = ht->pListHead;
     640     3120019 :         while (p != NULL) {
     641     2385021 :                 int result = apply_func(p->pData TSRMLS_CC);
     642             : 
     643     2385019 :                 Bucket *p_next = p->pListNext;
     644     2385019 :                 if (result & ZEND_HASH_APPLY_REMOVE) {
     645      112058 :                         zend_hash_bucket_delete(ht, p);
     646             :                 }
     647     2385019 :                 p = p_next;
     648             : 
     649     2385019 :                 if (result & ZEND_HASH_APPLY_STOP) {
     650           0 :                         break;
     651             :                 }
     652             :         }
     653      367498 :         HASH_UNPROTECT_RECURSION(ht);
     654      367498 : }
     655             : 
     656             : 
     657      731739 : ZEND_API void zend_hash_apply_with_argument(HashTable *ht, apply_func_arg_t apply_func, void *argument TSRMLS_DC)
     658             : {
     659             :         Bucket *p;
     660             : 
     661             :         IS_CONSISTENT(ht);
     662             : 
     663      731739 :         HASH_PROTECT_RECURSION(ht);
     664      731739 :         p = ht->pListHead;
     665   171812901 :         while (p != NULL) {
     666   170354079 :                 int result = apply_func(p->pData, argument TSRMLS_CC);
     667             :                 
     668   170354078 :                 Bucket *p_next = p->pListNext;
     669   170354078 :                 if (result & ZEND_HASH_APPLY_REMOVE) {
     670     6031117 :                         zend_hash_bucket_delete(ht, p);
     671             :                 }
     672   170354078 :                 p = p_next;
     673             : 
     674   170354078 :                 if (result & ZEND_HASH_APPLY_STOP) {
     675        4655 :                         break;
     676             :                 }
     677             :         }
     678      731738 :         HASH_UNPROTECT_RECURSION(ht);
     679      731738 : }
     680             : 
     681             : 
     682       27856 : ZEND_API void zend_hash_apply_with_arguments(HashTable *ht TSRMLS_DC, apply_func_args_t apply_func, int num_args, ...)
     683             : {
     684             :         Bucket *p;
     685             :         va_list args;
     686             :         zend_hash_key hash_key;
     687             : 
     688             :         IS_CONSISTENT(ht);
     689             : 
     690       27856 :         HASH_PROTECT_RECURSION(ht);
     691             : 
     692       27856 :         p = ht->pListHead;
     693     1298850 :         while (p != NULL) {
     694             :                 int result;
     695             :                 Bucket *p_next;
     696             : 
     697     1243162 :                 va_start(args, num_args);
     698     1243162 :                 hash_key.arKey = p->arKey;
     699     1243162 :                 hash_key.nKeyLength = p->nKeyLength;
     700     1243162 :                 hash_key.h = p->h;
     701     1243162 :                 result = apply_func(p->pData TSRMLS_CC, num_args, args, &hash_key);
     702             : 
     703     1243140 :                 p_next = p->pListNext;
     704     1243140 :                 if (result & ZEND_HASH_APPLY_REMOVE) {
     705          26 :                         zend_hash_bucket_delete(ht, p);
     706             :                 }
     707     1243140 :                 p = p_next;
     708             : 
     709     1243140 :                 if (result & ZEND_HASH_APPLY_STOP) {
     710           2 :                         va_end(args);
     711           2 :                         break;
     712             :                 }
     713     1243138 :                 va_end(args);
     714             :         }
     715             : 
     716       27834 :         HASH_UNPROTECT_RECURSION(ht);
     717       27834 : }
     718             : 
     719             : 
     720      132532 : ZEND_API void zend_hash_reverse_apply(HashTable *ht, apply_func_t apply_func TSRMLS_DC)
     721             : {
     722             :         Bucket *p;
     723             : 
     724             :         IS_CONSISTENT(ht);
     725             : 
     726      132532 :         HASH_PROTECT_RECURSION(ht);
     727      132532 :         p = ht->pListTail;
     728      674870 :         while (p != NULL) {
     729      516091 :                 int result = apply_func(p->pData TSRMLS_CC);
     730             : 
     731      516090 :                 Bucket *p_last = p->pListLast;
     732      516090 :                 if (result & ZEND_HASH_APPLY_REMOVE) {
     733      107371 :                         zend_hash_bucket_delete(ht, p);
     734             :                 }
     735      516090 :                 p = p_last;
     736             : 
     737      516090 :                 if (result & ZEND_HASH_APPLY_STOP) {
     738      106284 :                         break;
     739             :                 }
     740             :         }
     741      132531 :         HASH_UNPROTECT_RECURSION(ht);
     742      132531 : }
     743             : 
     744             : 
     745     1033338 : ZEND_API void zend_hash_copy(HashTable *target, HashTable *source, copy_ctor_func_t pCopyConstructor, void *tmp, uint size)
     746             : {
     747             :         Bucket *p;
     748             :         void *new_entry;
     749             :         zend_bool setTargetPointer;
     750             : 
     751             :         IS_CONSISTENT(source);
     752             :         IS_CONSISTENT(target);
     753             : 
     754     1033338 :         setTargetPointer = !target->pInternalPointer;
     755     1033338 :         p = source->pListHead;
     756     6685230 :         while (p) {
     757     4618554 :                 if (setTargetPointer && source->pInternalPointer == p) {
     758      944798 :                         target->pInternalPointer = NULL;
     759             :                 }
     760     4618554 :                 if (p->nKeyLength) {
     761     1771602 :                         zend_hash_quick_update(target, p->arKey, p->nKeyLength, p->h, p->pData, size, &new_entry);
     762             :                 } else {
     763     2846952 :                         zend_hash_index_update(target, p->h, p->pData, size, &new_entry);
     764             :                 }
     765     4618554 :                 if (pCopyConstructor) {
     766     4606625 :                         pCopyConstructor(new_entry);
     767             :                 }
     768     4618554 :                 p = p->pListNext;
     769             :         }
     770     1033338 :         if (!target->pInternalPointer) {
     771       88294 :                 target->pInternalPointer = target->pListHead;
     772             :         }
     773     1033338 : }
     774             : 
     775             : 
     776     1703575 : ZEND_API void _zend_hash_merge(HashTable *target, HashTable *source, copy_ctor_func_t pCopyConstructor, void *tmp, uint size, int overwrite ZEND_FILE_LINE_DC)
     777             : {
     778             :         Bucket *p;
     779             :         void *t;
     780     1703575 :         int mode = (overwrite?HASH_UPDATE:HASH_ADD);
     781             : 
     782             :         IS_CONSISTENT(source);
     783             :         IS_CONSISTENT(target);
     784             : 
     785     1703575 :         p = source->pListHead;
     786     9029230 :         while (p) {
     787     5622080 :                 if (p->nKeyLength>0) {
     788     5622064 :                         if (_zend_hash_quick_add_or_update(target, p->arKey, p->nKeyLength, p->h, p->pData, size, &t, mode ZEND_FILE_LINE_RELAY_CC)==SUCCESS && pCopyConstructor) {
     789     2516773 :                                 pCopyConstructor(t);
     790             :                         }
     791             :                 } else {
     792          16 :                         if ((mode==HASH_UPDATE || !zend_hash_index_exists(target, p->h)) && zend_hash_index_update(target, p->h, p->pData, size, &t)==SUCCESS && pCopyConstructor) {
     793           6 :                                 pCopyConstructor(t);
     794             :                         }
     795             :                 }
     796     5622080 :                 p = p->pListNext;
     797             :         }
     798     1703575 :         target->pInternalPointer = target->pListHead;
     799     1703575 : }
     800             : 
     801             : 
     802    36261291 : static zend_bool zend_hash_replace_checker_wrapper(HashTable *target, void *source_data, Bucket *p, void *pParam, merge_checker_func_t merge_checker_func)
     803             : {
     804             :         zend_hash_key hash_key;
     805             : 
     806    36261291 :         hash_key.arKey = p->arKey;
     807    36261291 :         hash_key.nKeyLength = p->nKeyLength;
     808    36261291 :         hash_key.h = p->h;
     809    36261291 :         return merge_checker_func(target, source_data, &hash_key, pParam);
     810             : }
     811             : 
     812             : 
     813     5916982 : ZEND_API void zend_hash_merge_ex(HashTable *target, HashTable *source, copy_ctor_func_t pCopyConstructor, uint size, merge_checker_func_t pMergeSource, void *pParam)
     814             : {
     815             :         Bucket *p;
     816             :         void *t;
     817             : 
     818             :         IS_CONSISTENT(source);
     819             :         IS_CONSISTENT(target);
     820             : 
     821     5916982 :         p = source->pListHead;
     822    48095205 :         while (p) {
     823    36261291 :                 if (zend_hash_replace_checker_wrapper(target, p->pData, p, pParam, pMergeSource)) {
     824    28136039 :                         if (zend_hash_quick_update(target, p->arKey, p->nKeyLength, p->h, p->pData, size, &t)==SUCCESS && pCopyConstructor) {
     825    28136039 :                                 pCopyConstructor(t);
     826             :                         }
     827             :                 }
     828    36261241 :                 p = p->pListNext;
     829             :         }
     830     5916932 :         target->pInternalPointer = target->pListHead;
     831     5916932 : }
     832             : 
     833             : 
     834             : /* Returns SUCCESS if found and FAILURE if not. The pointer to the
     835             :  * data is returned in pData. The reason is that there's no reason
     836             :  * someone using the hash table might not want to have NULL data
     837             :  */
     838    12574043 : ZEND_API int zend_hash_find(const HashTable *ht, const char *arKey, uint nKeyLength, void **pData)
     839             : {
     840             :         ulong h;
     841             :         uint nIndex;
     842             :         Bucket *p;
     843             : 
     844             :         IS_CONSISTENT(ht);
     845             : 
     846    12574043 :         h = zend_inline_hash_func(arKey, nKeyLength);
     847    12574043 :         nIndex = h & ht->nTableMask;
     848             : 
     849    12574043 :         p = ht->arBuckets[nIndex];
     850    30908905 :         while (p != NULL) {
     851    35577213 :                 if (p->arKey == arKey ||
     852    23793463 :                         ((p->h == h) && (p->nKeyLength == nKeyLength) && !memcmp(p->arKey, arKey, nKeyLength))) {
     853     6022931 :                                 *pData = p->pData;
     854     6022931 :                                 return SUCCESS;
     855             :                 }
     856     5760819 :                 p = p->pNext;
     857             :         }
     858     6551112 :         return FAILURE;
     859             : }
     860             : 
     861             : 
     862    46699145 : ZEND_API int zend_hash_quick_find(const HashTable *ht, const char *arKey, uint nKeyLength, ulong h, void **pData)
     863             : {
     864             :         uint nIndex;
     865             :         Bucket *p;
     866             : 
     867             :         ZEND_ASSERT(nKeyLength != 0);
     868             : 
     869             :         IS_CONSISTENT(ht);
     870             : 
     871    46699145 :         nIndex = h & ht->nTableMask;
     872             : 
     873    46699145 :         p = ht->arBuckets[nIndex];
     874   118196172 :         while (p != NULL) {
     875    67167881 :                 if (p->arKey == arKey ||
     876    30886694 :                         ((p->h == h) && (p->nKeyLength == nKeyLength) && !memcmp(p->arKey, arKey, nKeyLength))) {
     877    11483305 :                                 *pData = p->pData;
     878    11483305 :                                 return SUCCESS;
     879             :                 }
     880    24797882 :                 p = p->pNext;
     881             :         }
     882    35215840 :         return FAILURE;
     883             : }
     884             : 
     885             : 
     886     1486480 : ZEND_API int zend_hash_exists(const HashTable *ht, const char *arKey, uint nKeyLength)
     887             : {
     888             :         ulong h;
     889             :         uint nIndex;
     890             :         Bucket *p;
     891             : 
     892             :         IS_CONSISTENT(ht);
     893             : 
     894     1486480 :         h = zend_inline_hash_func(arKey, nKeyLength);
     895     1486480 :         nIndex = h & ht->nTableMask;
     896             : 
     897     1486480 :         p = ht->arBuckets[nIndex];
     898     3465113 :         while (p != NULL) {
     899     3674949 :                 if (p->arKey == arKey ||
     900     2509911 :                         ((p->h == h) && (p->nKeyLength == nKeyLength) && !memcmp(p->arKey, arKey, nKeyLength))) {
     901      672885 :                                 return 1;
     902             :                 }
     903      492153 :                 p = p->pNext;
     904             :         }
     905      813595 :         return 0;
     906             : }
     907             : 
     908             : 
     909         498 : ZEND_API int zend_hash_quick_exists(const HashTable *ht, const char *arKey, uint nKeyLength, ulong h)
     910             : {
     911             :         uint nIndex;
     912             :         Bucket *p;
     913             : 
     914             :         ZEND_ASSERT(nKeyLength != 0);
     915             : 
     916             :         IS_CONSISTENT(ht);
     917             : 
     918         498 :         nIndex = h & ht->nTableMask;
     919             : 
     920         498 :         p = ht->arBuckets[nIndex];
     921        1023 :         while (p != NULL) {
     922         789 :                 if (p->arKey == arKey ||
     923         567 :                         ((p->h == h) && (p->nKeyLength == nKeyLength) && !memcmp(p->arKey, arKey, nKeyLength))) {
     924         195 :                                 return 1;
     925             :                 }
     926          27 :                 p = p->pNext;
     927             :         }
     928         303 :         return 0;
     929             : 
     930             : }
     931             : 
     932             : 
     933    19810239 : ZEND_API int zend_hash_index_find(const HashTable *ht, ulong h, void **pData)
     934             : {
     935             :         uint nIndex;
     936             :         Bucket *p;
     937             : 
     938             :         IS_CONSISTENT(ht);
     939             : 
     940    19810239 :         nIndex = h & ht->nTableMask;
     941             : 
     942    19810239 :         p = ht->arBuckets[nIndex];
     943    40778338 :         while (p != NULL) {
     944    19898888 :                 if ((p->h == h) && (p->nKeyLength == 0)) {
     945    18741028 :                         *pData = p->pData;
     946    18741028 :                         return SUCCESS;
     947             :                 }
     948     1157860 :                 p = p->pNext;
     949             :         }
     950     1069211 :         return FAILURE;
     951             : }
     952             : 
     953             : 
     954     1552713 : ZEND_API int zend_hash_index_exists(const HashTable *ht, ulong h)
     955             : {
     956             :         uint nIndex;
     957             :         Bucket *p;
     958             : 
     959             :         IS_CONSISTENT(ht);
     960             : 
     961     1552713 :         nIndex = h & ht->nTableMask;
     962             : 
     963     1552713 :         p = ht->arBuckets[nIndex];
     964     3679600 :         while (p != NULL) {
     965      850843 :                 if ((p->h == h) && (p->nKeyLength == 0)) {
     966      276669 :                         return 1;
     967             :                 }
     968      574174 :                 p = p->pNext;
     969             :         }
     970     1276044 :         return 0;
     971             : }
     972             : 
     973             : 
     974     5595707 : ZEND_API int zend_hash_num_elements(const HashTable *ht)
     975             : {
     976             :         IS_CONSISTENT(ht);
     977             : 
     978     5595707 :         return ht->nNumOfElements;
     979             : }
     980             : 
     981             : 
     982     2392959 : ZEND_API int zend_hash_get_pointer(const HashTable *ht, HashPointer *ptr)
     983             : {
     984     2392959 :         ptr->pos = ht->pInternalPointer;
     985     2392959 :         if (ht->pInternalPointer) {
     986     2312003 :                 ptr->h = ht->pInternalPointer->h;
     987     2312003 :                 return 1;
     988             :         } else {
     989       80956 :                 ptr->h = 0;
     990       80956 :                 return 0;
     991             :         }
     992             : }
     993             : 
     994     2387564 : ZEND_API int zend_hash_set_pointer(HashTable *ht, const HashPointer *ptr)
     995             : {
     996     2387564 :         if (ptr->pos == NULL) {
     997       80558 :                 ht->pInternalPointer = NULL;
     998     2307006 :         } else if (ht->pInternalPointer != ptr->pos) {
     999             :                 Bucket *p;
    1000             : 
    1001             :                 IS_CONSISTENT(ht);
    1002          69 :                 p = ht->arBuckets[ptr->h & ht->nTableMask];
    1003         186 :                 while (p != NULL) {
    1004          58 :                         if (p == ptr->pos) {
    1005          10 :                                 ht->pInternalPointer = p;
    1006          10 :                                 return 1;
    1007             :                         }
    1008          48 :                         p = p->pNext;
    1009             :                 }
    1010          59 :                 return 0;
    1011             :         }
    1012     2387495 :         return 1;
    1013             : }
    1014             : 
    1015     5489194 : ZEND_API void zend_hash_internal_pointer_reset_ex(HashTable *ht, HashPosition *pos)
    1016             : {
    1017             :         IS_CONSISTENT(ht);
    1018             : 
    1019     5489194 :         if (pos)
    1020      350392 :                 *pos = ht->pListHead;
    1021             :         else
    1022     5138802 :                 ht->pInternalPointer = ht->pListHead;
    1023     5489194 : }
    1024             : 
    1025             : 
    1026             : /* This function will be extremely optimized by remembering 
    1027             :  * the end of the list
    1028             :  */
    1029         275 : ZEND_API void zend_hash_internal_pointer_end_ex(HashTable *ht, HashPosition *pos)
    1030             : {
    1031             :         IS_CONSISTENT(ht);
    1032             : 
    1033         275 :         if (pos)
    1034         157 :                 *pos = ht->pListTail;
    1035             :         else
    1036         118 :                 ht->pInternalPointer = ht->pListTail;
    1037         275 : }
    1038             : 
    1039             : 
    1040    18663757 : ZEND_API int zend_hash_move_forward_ex(HashTable *ht, HashPosition *pos)
    1041             : {
    1042    18663757 :         HashPosition *current = pos ? pos : &ht->pInternalPointer;
    1043             : 
    1044             :         IS_CONSISTENT(ht);
    1045             : 
    1046    18663757 :         if (*current) {
    1047    18663729 :                 *current = (*current)->pListNext;
    1048    18663729 :                 return SUCCESS;
    1049             :         } else
    1050          28 :                 return FAILURE;
    1051             : }
    1052             : 
    1053         533 : ZEND_API int zend_hash_move_backwards_ex(HashTable *ht, HashPosition *pos)
    1054             : {
    1055         533 :         HashPosition *current = pos ? pos : &ht->pInternalPointer;
    1056             : 
    1057             :         IS_CONSISTENT(ht);
    1058             : 
    1059         533 :         if (*current) {
    1060         531 :                 *current = (*current)->pListLast;
    1061         531 :                 return SUCCESS;
    1062             :         } else
    1063           2 :                 return FAILURE;
    1064             : }
    1065             : 
    1066             : 
    1067             : /* This function should be made binary safe  */
    1068     4106031 : ZEND_API int zend_hash_get_current_key_ex(const HashTable *ht, char **str_index, uint *str_length, ulong *num_index, zend_bool duplicate, HashPosition *pos)
    1069             : {
    1070             :         Bucket *p;
    1071             : 
    1072     4106031 :         p = pos ? (*pos) : ht->pInternalPointer;
    1073             : 
    1074             :         IS_CONSISTENT(ht);
    1075             : 
    1076     4106031 :         if (p) {
    1077     4027055 :                 if (p->nKeyLength) {
    1078     2043184 :                         if (duplicate) {
    1079          19 :                                 *str_index = estrndup(p->arKey, p->nKeyLength - 1);
    1080             :                         } else {
    1081     2043165 :                                 *str_index = (char*)p->arKey;
    1082             :                         }
    1083     2043184 :                         if (str_length) {
    1084     2030115 :                                 *str_length = p->nKeyLength;
    1085             :                         }
    1086     2043184 :                         return HASH_KEY_IS_STRING;
    1087             :                 } else {
    1088     1983871 :                         *num_index = p->h;
    1089     1983871 :                         return HASH_KEY_IS_LONG;
    1090             :                 }
    1091             :         }
    1092       78976 :         return HASH_KEY_NON_EXISTENT;
    1093             : }
    1094             : 
    1095     1639907 : ZEND_API void zend_hash_get_current_key_zval_ex(const HashTable *ht, zval *key, HashPosition *pos) {
    1096             :         Bucket *p;
    1097             : 
    1098             :         IS_CONSISTENT(ht);
    1099             : 
    1100     1639907 :         p = pos ? (*pos) : ht->pInternalPointer;
    1101             : 
    1102     1639907 :         if (!p) {
    1103          58 :                 Z_TYPE_P(key) = IS_NULL;
    1104     1639849 :         } else if (p->nKeyLength) {
    1105     1629486 :                 Z_TYPE_P(key) = IS_STRING;
    1106     1629486 :                 Z_STRVAL_P(key) = IS_INTERNED(p->arKey) ? (char*)p->arKey : estrndup(p->arKey, p->nKeyLength - 1);
    1107     1629486 :                 Z_STRLEN_P(key) = p->nKeyLength - 1;
    1108             :         } else {
    1109       10363 :                 Z_TYPE_P(key) = IS_LONG;
    1110       10363 :                 Z_LVAL_P(key) = p->h;
    1111             :         }
    1112     1639907 : }
    1113             : 
    1114     2745669 : ZEND_API int zend_hash_get_current_key_type_ex(HashTable *ht, HashPosition *pos)
    1115             : {
    1116             :         Bucket *p;
    1117             : 
    1118     2745669 :         p = pos ? (*pos) : ht->pInternalPointer;
    1119             : 
    1120             :         IS_CONSISTENT(ht);
    1121             : 
    1122     2745669 :         if (p) {
    1123     1867564 :                 if (p->nKeyLength) {
    1124       90998 :                         return HASH_KEY_IS_STRING;
    1125             :                 } else {
    1126     1776566 :                         return HASH_KEY_IS_LONG;
    1127             :                 }
    1128             :         }
    1129      878105 :         return HASH_KEY_NON_EXISTENT;
    1130             : }
    1131             : 
    1132             : 
    1133    22282459 : ZEND_API int zend_hash_get_current_data_ex(HashTable *ht, void **pData, HashPosition *pos)
    1134             : {
    1135             :         Bucket *p;
    1136             : 
    1137    22282459 :         p = pos ? (*pos) : ht->pInternalPointer;
    1138             : 
    1139             :         IS_CONSISTENT(ht);
    1140             : 
    1141    22282459 :         if (p) {
    1142    18652100 :                 *pData = p->pData;
    1143    18652100 :                 return SUCCESS;
    1144             :         } else {
    1145     3630359 :                 return FAILURE;
    1146             :         }
    1147             : }
    1148             : 
    1149             : /* This function changes key of current element without changing elements'
    1150             :  * order. If element with target key already exists, it will be deleted first.
    1151             :  */
    1152          13 : ZEND_API int zend_hash_update_current_key_ex(HashTable *ht, int key_type, const char *str_index, uint str_length, ulong num_index, int mode, HashPosition *pos)
    1153             : {
    1154             :         Bucket *p, *q;
    1155             :         ulong h;
    1156             : #ifdef ZEND_SIGNALS
    1157             :         TSRMLS_FETCH();
    1158             : #endif
    1159             : 
    1160          13 :         p = pos ? (*pos) : ht->pInternalPointer;
    1161             : 
    1162             :         IS_CONSISTENT(ht);
    1163             : 
    1164          13 :         if (p) {
    1165          13 :                 if (key_type == HASH_KEY_IS_LONG) {
    1166           0 :                         str_length = 0;
    1167           0 :                         if (!p->nKeyLength && p->h == num_index) {
    1168           0 :                                 return SUCCESS;
    1169             :                         }
    1170             : 
    1171           0 :                         q = ht->arBuckets[num_index & ht->nTableMask];
    1172           0 :                         while (q != NULL) {
    1173           0 :                                 if (!q->nKeyLength && q->h == num_index) {
    1174           0 :                                         break;
    1175             :                                 }
    1176           0 :                                 q = q->pNext;
    1177             :                         }
    1178          13 :                 } else if (key_type == HASH_KEY_IS_STRING) {
    1179          13 :                         if (IS_INTERNED(str_index)) {
    1180           0 :                                 h = INTERNED_HASH(str_index);
    1181             :                         } else {
    1182          13 :                                 h = zend_inline_hash_func(str_index, str_length);
    1183             :                         }
    1184             : 
    1185          39 :                         if (p->arKey == str_index ||
    1186          13 :                             (p->nKeyLength == str_length &&
    1187          13 :                              p->h == h &&
    1188           0 :                              memcmp(p->arKey, str_index, str_length) == 0)) {
    1189           0 :                                 return SUCCESS;
    1190             :                         }
    1191             : 
    1192          13 :                         q = ht->arBuckets[h & ht->nTableMask];
    1193             : 
    1194          29 :                         while (q != NULL) {
    1195           6 :                                 if (q->arKey == str_index ||
    1196           3 :                                     (q->h == h && q->nKeyLength == str_length &&
    1197           0 :                                      memcmp(q->arKey, str_index, str_length) == 0)) {
    1198             :                                         break;
    1199             :                                 }
    1200           3 :                                 q = q->pNext;
    1201             :                         }
    1202             :                 } else {
    1203           0 :                         return FAILURE;
    1204             :                 }
    1205             : 
    1206          13 :                 if (q) {
    1207           0 :                         if (mode != HASH_UPDATE_KEY_ANYWAY) {
    1208           0 :                                 Bucket *r = p->pListLast;
    1209           0 :                                 int found = HASH_UPDATE_KEY_IF_BEFORE;
    1210             : 
    1211           0 :                                 while (r) {
    1212           0 :                                         if (r == q) {
    1213           0 :                                                 found = HASH_UPDATE_KEY_IF_AFTER;
    1214           0 :                                                 break;
    1215             :                                         }
    1216           0 :                                         r = r->pListLast;
    1217             :                                 }
    1218           0 :                                 if (mode & found) {
    1219             :                                         /* delete current bucket */
    1220           0 :                                         zend_hash_bucket_delete(ht, p);
    1221           0 :                                         return FAILURE;
    1222             :                                 }
    1223             :                         }
    1224             : 
    1225             :                         /* delete another bucket with the same key */
    1226           0 :                         zend_hash_bucket_delete(ht, q);
    1227             :                 }
    1228             : 
    1229          13 :                 HANDLE_BLOCK_INTERRUPTIONS();
    1230             : 
    1231          13 :                 if (p->pNext) {
    1232           2 :                         p->pNext->pLast = p->pLast;
    1233             :                 }
    1234          13 :                 if (p->pLast) {
    1235           3 :                         p->pLast->pNext = p->pNext;
    1236             :                 } else {
    1237          10 :                         ht->arBuckets[p->h & ht->nTableMask] = p->pNext;
    1238             :                 }
    1239             : 
    1240          52 :                 if ((IS_INTERNED(p->arKey) != IS_INTERNED(str_index)) ||
    1241          39 :                     (!IS_INTERNED(p->arKey) && p->nKeyLength != str_length)) {
    1242             :                         Bucket *q;
    1243             : 
    1244           0 :                         if (IS_INTERNED(str_index)) {
    1245           0 :                                 q = (Bucket *) pemalloc(sizeof(Bucket), ht->persistent);
    1246             :                         } else {
    1247           0 :                                 q = (Bucket *) pemalloc(sizeof(Bucket) + str_length, ht->persistent);
    1248             :                         }
    1249             : 
    1250           0 :                         q->nKeyLength = str_length;
    1251           0 :                         if (p->pData == &p->pDataPtr) {
    1252           0 :                                 q->pData = &q->pDataPtr;
    1253             :                         } else {
    1254           0 :                                 q->pData = p->pData;
    1255             :                         }
    1256           0 :                         q->pDataPtr = p->pDataPtr;
    1257             : 
    1258           0 :                         CONNECT_TO_GLOBAL_DLLIST_EX(q, ht, p->pListLast, p->pListNext);
    1259           0 :                         if (ht->pInternalPointer == p) {
    1260           0 :                                 ht->pInternalPointer = q;
    1261             :                         }
    1262             : 
    1263           0 :                         if (pos) {
    1264           0 :                                 *pos = q;
    1265             :                         }
    1266           0 :                         pefree(p, ht->persistent);
    1267           0 :                         p = q;
    1268             :                 }
    1269             : 
    1270          13 :                 if (key_type == HASH_KEY_IS_LONG) {
    1271           0 :                         p->h = num_index;
    1272             :                 } else {
    1273          13 :                         p->h = h;
    1274          13 :                         p->nKeyLength = str_length;
    1275          13 :                         if (IS_INTERNED(str_index)) {
    1276           0 :                                 p->arKey = str_index;
    1277             :                         } else {
    1278          13 :                                 p->arKey = (const char*)(p+1);
    1279          13 :                                 memcpy((char*)p->arKey, str_index, str_length);
    1280             :                         }
    1281             :                 }
    1282             : 
    1283          13 :                 CONNECT_TO_BUCKET_DLLIST(p, ht->arBuckets[p->h & ht->nTableMask]);
    1284          13 :                 ht->arBuckets[p->h & ht->nTableMask] = p;
    1285          13 :                 HANDLE_UNBLOCK_INTERRUPTIONS();
    1286             : 
    1287          13 :                 return SUCCESS;
    1288             :         } else {
    1289           0 :                 return FAILURE;
    1290             :         }
    1291             : }
    1292             : 
    1293             : /* Performs an in-place splice operation on a hashtable:
    1294             :  * The elements between offset and offset+length are removed and the elements in list[list_count]
    1295             :  * are inserted in their place. The removed elements can be optionally collected into a hashtable.
    1296             :  * This operation reindexes the hashtable, i.e. integer keys will be zero-based and sequential,
    1297             :  * while string keys stay intact. The same applies to the elements inserted into the removed HT. */
    1298         431 : ZEND_API void _zend_hash_splice(HashTable *ht, uint nDataSize, copy_ctor_func_t pCopyConstructor, uint offset, uint length, void **list, uint list_count, HashTable *removed ZEND_FILE_LINE_DC) /* {{{ */
    1299             : {
    1300             :         int pos;
    1301             :         Bucket *p;
    1302             : 
    1303             :         IS_CONSISTENT(ht);
    1304         431 :         CHECK_INIT(ht);
    1305             : 
    1306             :         /* Skip all elements until offset */
    1307         431 :         for (pos = 0, p = ht->pListHead; pos < offset && p; pos++, p = p->pListNext);
    1308             : 
    1309         973 :         while (pos < offset + length && p) {
    1310             :                 /* Copy removed element into HT, if it was specified */
    1311         111 :                 if (removed != NULL) {
    1312             :                         void *new_entry;
    1313             : 
    1314          93 :                         if (p->nKeyLength == 0) {
    1315          92 :                                 zend_hash_next_index_insert(removed, p->pData, sizeof(zval *), &new_entry);
    1316             :                         } else {
    1317           1 :                                 zend_hash_quick_update(removed, p->arKey, p->nKeyLength, p->h, p->pData, sizeof(zval *), &new_entry);
    1318             :                         }
    1319             : 
    1320          93 :                         if (pCopyConstructor) {
    1321          93 :                                 pCopyConstructor(new_entry);
    1322             :                         }
    1323             :                 }
    1324             : 
    1325             :                 /* Remove element */
    1326             :                 {
    1327         111 :                         Bucket *p_next = p->pListNext;       
    1328         111 :                         zend_hash_bucket_delete(ht, p);
    1329         111 :                         p = p_next;
    1330             :                 }
    1331             : 
    1332         111 :                 pos++;
    1333             :         }
    1334             : 
    1335         431 :         if (list != NULL) {
    1336             :                 int i;
    1337        1202 :                 for (i = 0; i < list_count; i++) {
    1338             :                         /* Add new element only to the global linked list, not the bucket list.
    1339             :                          * Also use key 0 for everything, as we'll reindex the hashtable anyways. */
    1340         800 :                         Bucket *q = pemalloc_rel(sizeof(Bucket), ht->persistent);
    1341         800 :                         q->arKey = NULL;
    1342         800 :                         q->nKeyLength = 0;
    1343         800 :                         q->h = 0;
    1344         800 :                         INIT_DATA(ht, q, list[i], nDataSize);
    1345             : 
    1346         800 :                         CONNECT_TO_GLOBAL_DLLIST_EX(q, ht, p ? p->pListLast : ht->pListTail, p);
    1347             : 
    1348         800 :                         ht->nNumOfElements++;
    1349             : 
    1350         800 :                         if (pCopyConstructor) {
    1351         800 :                                 pCopyConstructor(q->pData);
    1352             :                         }
    1353             :                 }
    1354             : 
    1355         402 :                 ZEND_HASH_IF_FULL_DO_RESIZE(ht);
    1356             :         }
    1357             : 
    1358         431 :         zend_hash_reindex(ht, 1);
    1359         431 : }
    1360             : /* }}} */
    1361             : 
    1362       22963 : ZEND_API int zend_hash_sort(HashTable *ht, sort_func_t sort_func,
    1363             :                                                         compare_func_t compar, int renumber TSRMLS_DC)
    1364             : {
    1365             :         Bucket **arTmp;
    1366             :         Bucket *p;
    1367             :         int i, j;
    1368             : 
    1369             :         IS_CONSISTENT(ht);
    1370             : 
    1371       22963 :         if (!(ht->nNumOfElements>1) && !(renumber && ht->nNumOfElements>0)) { /* Doesn't require sorting */
    1372         286 :                 return SUCCESS;
    1373             :         }
    1374       22677 :         arTmp = (Bucket **) pemalloc(ht->nNumOfElements * sizeof(Bucket *), ht->persistent);
    1375       22677 :         p = ht->pListHead;
    1376       22677 :         i = 0;
    1377     1680381 :         while (p) {
    1378     1635027 :                 arTmp[i] = p;
    1379     1635027 :                 p = p->pListNext;
    1380     1635027 :                 i++;
    1381             :         }
    1382             : 
    1383       22677 :         (*sort_func)((void *) arTmp, i, sizeof(Bucket *), compar TSRMLS_CC);
    1384             : 
    1385       22676 :         HANDLE_BLOCK_INTERRUPTIONS();
    1386       22676 :         ht->pListHead = arTmp[0];
    1387       22676 :         ht->pListTail = NULL;
    1388       22676 :         ht->pInternalPointer = ht->pListHead;
    1389             : 
    1390       22676 :         arTmp[0]->pListLast = NULL;
    1391       22676 :         if (i > 1) {
    1392       22667 :                 arTmp[0]->pListNext = arTmp[1];
    1393     1612349 :                 for (j = 1; j < i-1; j++) {
    1394     1589682 :                         arTmp[j]->pListLast = arTmp[j-1];
    1395     1589682 :                         arTmp[j]->pListNext = arTmp[j+1];
    1396             :                 }
    1397       22667 :                 arTmp[j]->pListLast = arTmp[j-1];
    1398       22667 :                 arTmp[j]->pListNext = NULL;
    1399             :         } else {
    1400           9 :                 arTmp[0]->pListNext = NULL;
    1401             :         }
    1402       22676 :         ht->pListTail = arTmp[i-1];
    1403             : 
    1404       22676 :         pefree(arTmp, ht->persistent);
    1405       22676 :         HANDLE_UNBLOCK_INTERRUPTIONS();
    1406             : 
    1407       22676 :         if (renumber) {
    1408         289 :                 zend_hash_reindex(ht, 0);
    1409             :         }
    1410       22676 :         return SUCCESS;
    1411             : }
    1412             : 
    1413             : 
    1414        1161 : ZEND_API int zend_hash_compare(HashTable *ht1, HashTable *ht2, compare_func_t compar, zend_bool ordered TSRMLS_DC)
    1415             : {
    1416        1161 :         Bucket *p1, *p2 = NULL;
    1417             :         int result;
    1418             :         void *pData2;
    1419             : 
    1420             :         IS_CONSISTENT(ht1);
    1421             :         IS_CONSISTENT(ht2);
    1422             : 
    1423        1161 :         HASH_PROTECT_RECURSION(ht1); 
    1424        1161 :         HASH_PROTECT_RECURSION(ht2); 
    1425             : 
    1426        1161 :         result = ht1->nNumOfElements - ht2->nNumOfElements;
    1427        1161 :         if (result!=0) {
    1428         553 :                 HASH_UNPROTECT_RECURSION(ht1); 
    1429         553 :                 HASH_UNPROTECT_RECURSION(ht2); 
    1430         553 :                 return result;
    1431             :         }
    1432             : 
    1433         608 :         p1 = ht1->pListHead;
    1434         608 :         if (ordered) {
    1435          62 :                 p2 = ht2->pListHead;
    1436             :         }
    1437             : 
    1438        4885 :         while (p1) {
    1439        3845 :                 if (ordered && !p2) {
    1440           0 :                         HASH_UNPROTECT_RECURSION(ht1); 
    1441           0 :                         HASH_UNPROTECT_RECURSION(ht2); 
    1442           0 :                         return 1; /* That's not supposed to happen */
    1443             :                 }
    1444        3845 :                 if (ordered) {
    1445        1492 :                         if (p1->nKeyLength==0 && p2->nKeyLength==0) { /* numeric indices */
    1446         364 :                                 result = p1->h - p2->h;
    1447         364 :                                 if (result!=0) {
    1448           1 :                                         HASH_UNPROTECT_RECURSION(ht1); 
    1449           1 :                                         HASH_UNPROTECT_RECURSION(ht2); 
    1450           1 :                                         return result;
    1451             :                                 }
    1452             :                         } else { /* string indices */
    1453         765 :                                 result = p1->nKeyLength - p2->nKeyLength;
    1454         765 :                                 if (result!=0) {
    1455           0 :                                         HASH_UNPROTECT_RECURSION(ht1); 
    1456           0 :                                         HASH_UNPROTECT_RECURSION(ht2); 
    1457           0 :                                         return result;
    1458             :                                 }
    1459         765 :                                 result = memcmp(p1->arKey, p2->arKey, p1->nKeyLength);
    1460         765 :                                 if (result!=0) {
    1461           0 :                                         HASH_UNPROTECT_RECURSION(ht1); 
    1462           0 :                                         HASH_UNPROTECT_RECURSION(ht2); 
    1463           0 :                                         return result;
    1464             :                                 }
    1465             :                         }
    1466        1128 :                         pData2 = p2->pData;
    1467             :                 } else {
    1468        2716 :                         if (p1->nKeyLength==0) { /* numeric index */
    1469         231 :                                 if (zend_hash_index_find(ht2, p1->h, &pData2)==FAILURE) {
    1470           4 :                                         HASH_UNPROTECT_RECURSION(ht1); 
    1471           4 :                                         HASH_UNPROTECT_RECURSION(ht2); 
    1472           4 :                                         return 1;
    1473             :                                 }
    1474             :                         } else { /* string index */
    1475        2485 :                                 if (zend_hash_quick_find(ht2, p1->arKey, p1->nKeyLength, p1->h, &pData2)==FAILURE) {
    1476          26 :                                         HASH_UNPROTECT_RECURSION(ht1); 
    1477          26 :                                         HASH_UNPROTECT_RECURSION(ht2); 
    1478          26 :                                         return 1;
    1479             :                                 }
    1480             :                         }
    1481             :                 }
    1482        3814 :                 result = compar(p1->pData, pData2 TSRMLS_CC);
    1483        3814 :                 if (result!=0) {
    1484         145 :                         HASH_UNPROTECT_RECURSION(ht1); 
    1485         145 :                         HASH_UNPROTECT_RECURSION(ht2); 
    1486         145 :                         return result;
    1487             :                 }
    1488        3669 :                 p1 = p1->pListNext;
    1489        3669 :                 if (ordered) {
    1490        1124 :                         p2 = p2->pListNext;
    1491             :                 }
    1492             :         }
    1493             :         
    1494         432 :         HASH_UNPROTECT_RECURSION(ht1); 
    1495         432 :         HASH_UNPROTECT_RECURSION(ht2); 
    1496         432 :         return 0;
    1497             : }
    1498             : 
    1499             : 
    1500          82 : ZEND_API int zend_hash_minmax(const HashTable *ht, compare_func_t compar, int flag, void **pData TSRMLS_DC)
    1501             : {
    1502             :         Bucket *p, *res;
    1503             : 
    1504             :         IS_CONSISTENT(ht);
    1505             : 
    1506          82 :         if (ht->nNumOfElements == 0 ) {
    1507           4 :                 *pData=NULL;
    1508           4 :                 return FAILURE;
    1509             :         }
    1510             : 
    1511          78 :         res = p = ht->pListHead;
    1512         376 :         while ((p = p->pListNext)) {
    1513         220 :                 if (flag) {
    1514         168 :                         if (compar(&res, &p TSRMLS_CC) < 0) { /* max */
    1515          20 :                                 res = p;
    1516             :                         }
    1517             :                 } else {
    1518          52 :                         if (compar(&res, &p TSRMLS_CC) > 0) { /* min */
    1519           6 :                                 res = p;
    1520             :                         }
    1521             :                 }
    1522             :         }
    1523          78 :         *pData = res->pData;
    1524          78 :         return SUCCESS;
    1525             : }
    1526             : 
    1527      646616 : ZEND_API ulong zend_hash_next_free_element(const HashTable *ht)
    1528             : {
    1529             :         IS_CONSISTENT(ht);
    1530             : 
    1531      646616 :         return ht->nNextFreeElement;
    1532             : 
    1533             : }
    1534             : 
    1535             : 
    1536             : #if ZEND_DEBUG
    1537             : void zend_hash_display_pListTail(const HashTable *ht)
    1538             : {
    1539             :         Bucket *p;
    1540             : 
    1541             :         p = ht->pListTail;
    1542             :         while (p != NULL) {
    1543             :                 zend_output_debug_string(0, "pListTail has key %s\n", p->arKey);
    1544             :                 p = p->pListLast;
    1545             :         }
    1546             : }
    1547             : 
    1548             : void zend_hash_display(const HashTable *ht)
    1549             : {
    1550             :         Bucket *p;
    1551             :         uint i;
    1552             : 
    1553             :         if (UNEXPECTED(ht->nNumOfElements == 0)) {
    1554             :                 zend_output_debug_string(0, "The hash is empty");
    1555             :                 return;
    1556             :         }
    1557             :         for (i = 0; i < ht->nTableSize; i++) {
    1558             :                 p = ht->arBuckets[i];
    1559             :                 while (p != NULL) {
    1560             :                         zend_output_debug_string(0, "%s <==> 0x%lX\n", p->arKey, p->h);
    1561             :                         p = p->pNext;
    1562             :                 }
    1563             :         }
    1564             : 
    1565             :         p = ht->pListTail;
    1566             :         while (p != NULL) {
    1567             :                 zend_output_debug_string(0, "%s <==> 0x%lX\n", p->arKey, p->h);
    1568             :                 p = p->pListLast;
    1569             :         }
    1570             : }
    1571             : #endif
    1572             : 
    1573             : /*
    1574             :  * Local variables:
    1575             :  * tab-width: 4
    1576             :  * c-basic-offset: 4
    1577             :  * indent-tabs-mode: t
    1578             :  * End:
    1579             :  */

Generated by: LCOV version 1.10

Generated at Mon, 04 Aug 2014 15:49:01 +0000 (45 days ago)

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