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: 690 745 92.6 %
Date: 2014-10-16 Functions: 44 46 95.7 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :    +----------------------------------------------------------------------+
       3             :    | Zend Engine                                                          |
       4             :    +----------------------------------------------------------------------+
       5             :    | Copyright (c) 1998-2014 Zend Technologies Ltd. (http://www.zend.com) |
       6             :    +----------------------------------------------------------------------+
       7             :    | This source file is subject to version 2.00 of the Zend license,     |
       8             :    | that is bundled with this package in the file LICENSE, and is        | 
       9             :    | available through the world-wide-web at the following url:           |
      10             :    | http://www.zend.com/license/2_00.txt.                                |
      11             :    | If you did not receive a copy of the Zend license and are unable to  |
      12             :    | obtain it through the world-wide-web, please send a note to          |
      13             :    | license@zend.com so we can mail you a copy immediately.              |
      14             :    +----------------------------------------------------------------------+
      15             :    | Authors: Andi Gutmans <andi@zend.com>                                |
      16             :    |          Zeev Suraski <zeev@zend.com>                                |
      17             :    +----------------------------------------------------------------------+
      18             : */
      19             : 
      20             : /* $Id$ */
      21             : 
      22             : #include "zend.h"
      23             : #include "zend_globals.h"
      24             : 
      25             : #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(element, ht)                           \
      33             :         (element)->pListLast = (ht)->pListTail;                                   \
      34             :         (ht)->pListTail = (element);                                                 \
      35             :         (element)->pListNext = NULL;                                                 \
      36             :         if ((element)->pListLast != NULL) {                                          \
      37             :                 (element)->pListLast->pListNext = (element);              \
      38             :         }                                                                                                               \
      39             :         if (!(ht)->pListHead) {                                                                      \
      40             :                 (ht)->pListHead = (element);                                         \
      41             :         }                                                                                                               \
      42             :         if ((ht)->pInternalPointer == NULL) {                                        \
      43             :                 (ht)->pInternalPointer = (element);                                  \
      44             :         }
      45             : 
      46             : #if ZEND_DEBUG
      47             : #define HT_OK                           0
      48             : #define HT_IS_DESTROYING        1
      49             : #define HT_DESTROYED            2
      50             : #define HT_CLEANING                     3
      51             : 
      52             : static void _zend_is_inconsistent(const HashTable *ht, const char *file, int line)
      53             : {
      54             :         if (ht->inconsistent==HT_OK) {
      55             :                 return;
      56             :         }
      57             :         switch (ht->inconsistent) {
      58             :                 case HT_IS_DESTROYING:
      59             :                         zend_output_debug_string(1, "%s(%d) : ht=%p is being destroyed", file, line, ht);
      60             :                         break;
      61             :                 case HT_DESTROYED:
      62             :                         zend_output_debug_string(1, "%s(%d) : ht=%p is already destroyed", file, line, ht);
      63             :                         break;
      64             :                 case HT_CLEANING:
      65             :                         zend_output_debug_string(1, "%s(%d) : ht=%p is being cleaned", file, line, ht);
      66             :                         break;
      67             :                 default:
      68             :                         zend_output_debug_string(1, "%s(%d) : ht=%p is inconsistent", file, line, ht);
      69             :                         break;
      70             :         }
      71             :         zend_bailout();
      72             : }
      73             : #define IS_CONSISTENT(a) _zend_is_inconsistent(a, __FILE__, __LINE__);
      74             : #define SET_INCONSISTENT(n) ht->inconsistent = n;
      75             : #else
      76             : #define IS_CONSISTENT(a)
      77             : #define SET_INCONSISTENT(n)
      78             : #endif
      79             : 
      80             : #define HASH_PROTECT_RECURSION(ht)                                                                                                              \
      81             :         if ((ht)->bApplyProtection) {                                                                                                                \
      82             :                 if ((ht)->nApplyCount++ >= 3) {                                                                                                   \
      83             :                         zend_error(E_ERROR, "Nesting level too deep - recursive dependency?");                \
      84             :                 }                                                                                                                                                               \
      85             :         }
      86             : 
      87             : 
      88             : #define HASH_UNPROTECT_RECURSION(ht)                                                                                                    \
      89             :         if ((ht)->bApplyProtection) {                                                                                                                \
      90             :                 (ht)->nApplyCount--;                                                                                                                 \
      91             :         }
      92             : 
      93             : 
      94             : #define ZEND_HASH_IF_FULL_DO_RESIZE(ht)                         \
      95             :         if ((ht)->nNumOfElements > (ht)->nTableSize) { \
      96             :                 zend_hash_do_resize(ht);                                        \
      97             :         }
      98             : 
      99             : static int zend_hash_do_resize(HashTable *ht);
     100             : 
     101    49303055 : ZEND_API ulong zend_hash_func(const char *arKey, uint nKeyLength)
     102             : {
     103    49303055 :         return zend_inline_hash_func(arKey, nKeyLength);
     104             : }
     105             : 
     106             : 
     107             : #define UPDATE_DATA(ht, p, pData, nDataSize)                                                                                    \
     108             :         if (nDataSize == sizeof(void*)) {                                                                                                       \
     109             :                 if ((p)->pData != &(p)->pDataPtr) {                                                                                           \
     110             :                         pefree_rel((p)->pData, (ht)->persistent);                                                                 \
     111             :                 }                                                                                                                                                               \
     112             :                 memcpy(&(p)->pDataPtr, pData, sizeof(void *));                                                                   \
     113             :                 (p)->pData = &(p)->pDataPtr;                                                                                                  \
     114             :         } else {                                                                                                                                                        \
     115             :                 if ((p)->pData == &(p)->pDataPtr) {                                                                                           \
     116             :                         (p)->pData = (void *) pemalloc_rel(nDataSize, (ht)->persistent);                  \
     117             :                         (p)->pDataPtr=NULL;                                                                                                                  \
     118             :                 } else {                                                                                                                                                \
     119             :                         (p)->pData = (void *) perealloc_rel((p)->pData, nDataSize, (ht)->persistent);  \
     120             :                         /* (p)->pDataPtr is already NULL so no need to initialize it */                              \
     121             :                 }                                                                                                                                                               \
     122             :                 memcpy((p)->pData, pData, nDataSize);                                                                                        \
     123             :         }
     124             : 
     125             : #define INIT_DATA(ht, p, pData, nDataSize);                                                             \
     126             :         if (nDataSize == sizeof(void*)) {                                                                       \
     127             :                 memcpy(&(p)->pDataPtr, pData, sizeof(void *));                                   \
     128             :                 (p)->pData = &(p)->pDataPtr;                                                                  \
     129             :         } else {                                                                                                                        \
     130             :                 (p)->pData = (void *) pemalloc_rel(nDataSize, (ht)->persistent);\
     131             :                 if (!(p)->pData) {                                                                                           \
     132             :                         pefree_rel(p, (ht)->persistent);                                                     \
     133             :                         return FAILURE;                                                                                         \
     134             :                 }                                                                                                                               \
     135             :                 memcpy((p)->pData, pData, nDataSize);                                                        \
     136             :                 (p)->pDataPtr=NULL;                                                                                          \
     137             :         }
     138             : 
     139             : #define CHECK_INIT(ht) do {                                                                                             \
     140             :         if (UNEXPECTED((ht)->nTableMask == 0)) {                                                             \
     141             :                 (ht)->arBuckets = (Bucket **) pecalloc((ht)->nTableSize, sizeof(Bucket *), (ht)->persistent);  \
     142             :                 (ht)->nTableMask = (ht)->nTableSize - 1;                                          \
     143             :         }                                                                                                                                       \
     144             : } while (0)
     145             :  
     146             : static const Bucket *uninitialized_bucket = NULL;
     147             : 
     148    17655326 : ZEND_API int _zend_hash_init(HashTable *ht, uint nSize, hash_func_t pHashFunction, dtor_func_t pDestructor, zend_bool persistent ZEND_FILE_LINE_DC)
     149             : {
     150    17655326 :         uint i = 3;
     151             : 
     152             :         SET_INCONSISTENT(HT_OK);
     153             : 
     154    17655326 :         if (nSize >= 0x80000000) {
     155             :                 /* prevent overflow */
     156           0 :                 ht->nTableSize = 0x80000000;
     157             :         } else {
     158    36196616 :                 while ((1U << i) < nSize) {
     159      885964 :                         i++;
     160             :                 }
     161    17655326 :                 ht->nTableSize = 1 << i;
     162             :         }
     163             : 
     164    17655326 :         ht->nTableMask = 0;  /* 0 means that ht->arBuckets is uninitialized */
     165    17655326 :         ht->pDestructor = pDestructor;
     166    17655326 :         ht->arBuckets = (Bucket**)&uninitialized_bucket;
     167    17655326 :         ht->pListHead = NULL;
     168    17655326 :         ht->pListTail = NULL;
     169    17655326 :         ht->nNumOfElements = 0;
     170    17655326 :         ht->nNextFreeElement = 0;
     171    17655326 :         ht->pInternalPointer = NULL;
     172    17655326 :         ht->persistent = persistent;
     173    17655326 :         ht->nApplyCount = 0;
     174    17655326 :         ht->bApplyProtection = 1;
     175    17655326 :         return SUCCESS;
     176             : }
     177             : 
     178             : 
     179    10154631 : ZEND_API int _zend_hash_init_ex(HashTable *ht, uint nSize, hash_func_t pHashFunction, dtor_func_t pDestructor, zend_bool persistent, zend_bool bApplyProtection ZEND_FILE_LINE_DC)
     180             : {
     181    10154631 :         int retval = _zend_hash_init(ht, nSize, pHashFunction, pDestructor, persistent ZEND_FILE_LINE_CC);
     182             : 
     183    10154631 :         ht->bApplyProtection = bApplyProtection;
     184    10154631 :         return retval;
     185             : }
     186             : 
     187             : 
     188           0 : ZEND_API void zend_hash_set_apply_protection(HashTable *ht, zend_bool bApplyProtection)
     189             : {
     190           0 :         ht->bApplyProtection = bApplyProtection;
     191           0 : }
     192             : 
     193             : 
     194             : 
     195    33217801 : 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)
     196             : {
     197             :         ulong h;
     198             :         uint nIndex;
     199             :         Bucket *p;
     200             : #ifdef ZEND_SIGNALS
     201             :         TSRMLS_FETCH();
     202             : #endif
     203             : 
     204             :         IS_CONSISTENT(ht);
     205             : 
     206    33217801 :         if (nKeyLength <= 0) {
     207             : #if ZEND_DEBUG
     208             :                 ZEND_PUTS("zend_hash_update: Can't put in empty key\n");
     209             : #endif
     210           0 :                 return FAILURE;
     211             :         }
     212             : 
     213    33217801 :         CHECK_INIT(ht);
     214             : 
     215    33217801 :         h = zend_inline_hash_func(arKey, nKeyLength);
     216    33217801 :         nIndex = h & ht->nTableMask;
     217             : 
     218    33217801 :         p = ht->arBuckets[nIndex];
     219    82205389 :         while (p != NULL) {
     220    35072356 :                 if (p->arKey == arKey ||
     221    18420209 :                         ((p->h == h) && (p->nKeyLength == nKeyLength) && !memcmp(p->arKey, arKey, nKeyLength))) {
     222      882360 :                                 if (flag & HASH_ADD) {
     223      271119 :                                         return FAILURE;
     224             :                                 }
     225      611241 :                                 HANDLE_BLOCK_INTERRUPTIONS();
     226             : #if ZEND_DEBUG
     227             :                                 if (p->pData == pData) {
     228             :                                         ZEND_PUTS("Fatal error in zend_hash_update: p->pData == pData\n");
     229             :                                         HANDLE_UNBLOCK_INTERRUPTIONS();
     230             :                                         return FAILURE;
     231             :                                 }
     232             : #endif
     233      611241 :                                 if (ht->pDestructor) {
     234      570398 :                                         ht->pDestructor(p->pData);
     235             :                                 }
     236      611241 :                                 UPDATE_DATA(ht, p, pData, nDataSize);
     237      611241 :                                 if (pDest) {
     238      534791 :                                         *pDest = p->pData;
     239             :                                 }
     240      611241 :                                 HANDLE_UNBLOCK_INTERRUPTIONS();
     241      611241 :                                 return SUCCESS;
     242             :                 }
     243    15769787 :                 p = p->pNext;
     244             :         }
     245             :         
     246    33108022 :         if (IS_INTERNED(arKey)) {
     247      772581 :                 p = (Bucket *) pemalloc(sizeof(Bucket), ht->persistent);
     248      772581 :                 if (!p) {
     249           0 :                         return FAILURE;
     250             :                 }
     251      772581 :                 p->arKey = arKey;
     252             :         } else {
     253    31562860 :                 p = (Bucket *) pemalloc(sizeof(Bucket) + nKeyLength, ht->persistent);
     254    31562860 :                 if (!p) {
     255           0 :                         return FAILURE;
     256             :                 }
     257    31562860 :                 p->arKey = (const char*)(p + 1);
     258    31562860 :                 memcpy((char*)p->arKey, arKey, nKeyLength);
     259             :         }
     260    32335441 :         p->nKeyLength = nKeyLength;
     261    32335441 :         INIT_DATA(ht, p, pData, nDataSize);
     262    32335441 :         p->h = h;
     263    32335441 :         CONNECT_TO_BUCKET_DLLIST(p, ht->arBuckets[nIndex]);
     264    32335441 :         if (pDest) {
     265     8437638 :                 *pDest = p->pData;
     266             :         }
     267             : 
     268    32335441 :         HANDLE_BLOCK_INTERRUPTIONS();
     269    32335441 :         CONNECT_TO_GLOBAL_DLLIST(p, ht);
     270    32335441 :         ht->arBuckets[nIndex] = p;
     271    32335441 :         HANDLE_UNBLOCK_INTERRUPTIONS();
     272             : 
     273    32335441 :         ht->nNumOfElements++;
     274    32335441 :         ZEND_HASH_IF_FULL_DO_RESIZE(ht);                /* If the Hash table is full, resize it */
     275    32335441 :         return SUCCESS;
     276             : }
     277             : 
     278   161692469 : 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)
     279             : {
     280             :         uint nIndex;
     281             :         Bucket *p;
     282             : #ifdef ZEND_SIGNALS
     283             :         TSRMLS_FETCH();
     284             : #endif
     285             : 
     286             :         IS_CONSISTENT(ht);
     287             : 
     288   161692469 :         if (nKeyLength == 0) {
     289           0 :                 return zend_hash_index_update(ht, h, pData, nDataSize, pDest);
     290             :         }
     291             : 
     292   161692469 :         CHECK_INIT(ht);
     293   161692469 :         nIndex = h & ht->nTableMask;
     294             :         
     295   161692469 :         p = ht->arBuckets[nIndex];
     296   429434346 :         while (p != NULL) {
     297   212103463 :                 if (p->arKey == arKey ||
     298   106051308 :                         ((p->h == h) && (p->nKeyLength == nKeyLength) && !memcmp(p->arKey, arKey, nKeyLength))) {
     299        2747 :                                 if (flag & HASH_ADD) {
     300        2095 :                                         return FAILURE;
     301             :                                 }
     302         652 :                                 HANDLE_BLOCK_INTERRUPTIONS();
     303             : #if ZEND_DEBUG
     304             :                                 if (p->pData == pData) {
     305             :                                         ZEND_PUTS("Fatal error in zend_hash_update: p->pData == pData\n");
     306             :                                         HANDLE_UNBLOCK_INTERRUPTIONS();
     307             :                                         return FAILURE;
     308             :                                 }
     309             : #endif
     310         652 :                                 if (ht->pDestructor) {
     311         646 :                                         ht->pDestructor(p->pData);
     312             :                                 }
     313         652 :                                 UPDATE_DATA(ht, p, pData, nDataSize);
     314         652 :                                 if (pDest) {
     315         541 :                                         *pDest = p->pData;
     316             :                                 }
     317         652 :                                 HANDLE_UNBLOCK_INTERRUPTIONS();
     318         652 :                                 return SUCCESS;
     319             :                 }
     320   106049408 :                 p = p->pNext;
     321             :         }
     322             :         
     323   265111738 :         if (IS_INTERNED(arKey)) {
     324   103422016 :                 p = (Bucket *) pemalloc(sizeof(Bucket), ht->persistent);
     325   103422016 :                 if (!p) {
     326           0 :                         return FAILURE;
     327             :                 }
     328   103422016 :                 p->arKey = arKey;
     329             :         } else {
     330    58267706 :                 p = (Bucket *) pemalloc(sizeof(Bucket) + nKeyLength, ht->persistent);
     331    58267706 :                 if (!p) {
     332           0 :                         return FAILURE;
     333             :                 }
     334    58267706 :                 p->arKey = (const char*)(p + 1);
     335    58267706 :                 memcpy((char*)p->arKey, arKey, nKeyLength);
     336             :         }
     337             : 
     338   161689722 :         p->nKeyLength = nKeyLength;
     339   161689722 :         INIT_DATA(ht, p, pData, nDataSize);
     340   161689722 :         p->h = h;
     341             :         
     342   161689722 :         CONNECT_TO_BUCKET_DLLIST(p, ht->arBuckets[nIndex]);
     343             : 
     344   161689722 :         if (pDest) {
     345   108390427 :                 *pDest = p->pData;
     346             :         }
     347             : 
     348   161689722 :         HANDLE_BLOCK_INTERRUPTIONS();
     349   161689722 :         ht->arBuckets[nIndex] = p;
     350   161689722 :         CONNECT_TO_GLOBAL_DLLIST(p, ht);
     351   161689722 :         HANDLE_UNBLOCK_INTERRUPTIONS();
     352             : 
     353   161689722 :         ht->nNumOfElements++;
     354   161689722 :         ZEND_HASH_IF_FULL_DO_RESIZE(ht);                /* If the Hash table is full, resize it */
     355   161689722 :         return SUCCESS;
     356             : }
     357             : 
     358             : 
     359       40855 : ZEND_API int zend_hash_add_empty_element(HashTable *ht, const char *arKey, uint nKeyLength)
     360             : {
     361       40855 :         void *dummy = (void *) 1;
     362             : 
     363       40855 :         return zend_hash_add(ht, arKey, nKeyLength, &dummy, sizeof(void *), NULL);
     364             : }
     365             : 
     366             : 
     367    11208445 : 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)
     368             : {
     369             :         uint nIndex;
     370             :         Bucket *p;
     371             : #ifdef ZEND_SIGNALS
     372             :         TSRMLS_FETCH();
     373             : #endif
     374             : 
     375             :         IS_CONSISTENT(ht);
     376    11208445 :         CHECK_INIT(ht);
     377             : 
     378    11208445 :         if (flag & HASH_NEXT_INSERT) {
     379     4693702 :                 h = ht->nNextFreeElement;
     380             :         }
     381    11208445 :         nIndex = h & ht->nTableMask;
     382             : 
     383    11208445 :         p = ht->arBuckets[nIndex];
     384    23283548 :         while (p != NULL) {
     385      880476 :                 if ((p->nKeyLength == 0) && (p->h == h)) {
     386       13818 :                         if (flag & HASH_NEXT_INSERT || flag & HASH_ADD) {
     387           3 :                                 return FAILURE;
     388             :                         }
     389       13815 :                         HANDLE_BLOCK_INTERRUPTIONS();
     390             : #if ZEND_DEBUG
     391             :                         if (p->pData == pData) {
     392             :                                 ZEND_PUTS("Fatal error in zend_hash_index_update: p->pData == pData\n");
     393             :                                 HANDLE_UNBLOCK_INTERRUPTIONS();
     394             :                                 return FAILURE;
     395             :                         }
     396             : #endif
     397       13815 :                         if (ht->pDestructor) {
     398       13815 :                                 ht->pDestructor(p->pData);
     399             :                         }
     400       13815 :                         UPDATE_DATA(ht, p, pData, nDataSize);
     401       13815 :                         HANDLE_UNBLOCK_INTERRUPTIONS();
     402       13815 :                         if ((long)h >= (long)ht->nNextFreeElement) {
     403           1 :                                 ht->nNextFreeElement = h < LONG_MAX ? h + 1 : LONG_MAX;
     404             :                         }
     405       13815 :                         if (pDest) {
     406           3 :                                 *pDest = p->pData;
     407             :                         }
     408       13815 :                         return SUCCESS;
     409             :                 }
     410      866658 :                 p = p->pNext;
     411             :         }
     412    11194627 :         p = (Bucket *) pemalloc_rel(sizeof(Bucket), ht->persistent);
     413    11194627 :         if (!p) {
     414           0 :                 return FAILURE;
     415             :         }
     416    11194627 :         p->arKey = NULL;
     417    11194627 :         p->nKeyLength = 0; /* Numeric indices are marked by making the nKeyLength == 0 */
     418    11194627 :         p->h = h;
     419    11194627 :         INIT_DATA(ht, p, pData, nDataSize);
     420    11194627 :         if (pDest) {
     421     4680839 :                 *pDest = p->pData;
     422             :         }
     423             : 
     424    11194627 :         CONNECT_TO_BUCKET_DLLIST(p, ht->arBuckets[nIndex]);
     425             : 
     426    11194627 :         HANDLE_BLOCK_INTERRUPTIONS();
     427    11194627 :         ht->arBuckets[nIndex] = p;
     428    11194627 :         CONNECT_TO_GLOBAL_DLLIST(p, ht);
     429    11194627 :         HANDLE_UNBLOCK_INTERRUPTIONS();
     430             : 
     431    11194627 :         if ((long)h >= (long)ht->nNextFreeElement) {
     432     9629520 :                 ht->nNextFreeElement = h < LONG_MAX ? h + 1 : LONG_MAX;
     433             :         }
     434    11194627 :         ht->nNumOfElements++;
     435    11194627 :         ZEND_HASH_IF_FULL_DO_RESIZE(ht);
     436    11194627 :         return SUCCESS;
     437             : }
     438             : 
     439             : 
     440     5647068 : static int zend_hash_do_resize(HashTable *ht)
     441             : {
     442             :         Bucket **t;
     443             : #ifdef ZEND_SIGNALS
     444             :         TSRMLS_FETCH();
     445             : #endif
     446             : 
     447             :         IS_CONSISTENT(ht);
     448             : 
     449     5647068 :         if ((ht->nTableSize << 1) > 0) {    /* Let's double the table size */
     450     5647068 :                 t = (Bucket **) perealloc_recoverable(ht->arBuckets, (ht->nTableSize << 1) * sizeof(Bucket *), ht->persistent);
     451     5647068 :                 if (t) {
     452     5647068 :                         HANDLE_BLOCK_INTERRUPTIONS();
     453     5647068 :                         ht->arBuckets = t;
     454     5647068 :                         ht->nTableSize = (ht->nTableSize << 1);
     455     5647068 :                         ht->nTableMask = ht->nTableSize - 1;
     456     5647068 :                         zend_hash_rehash(ht);
     457     5647068 :                         HANDLE_UNBLOCK_INTERRUPTIONS();
     458     5647068 :                         return SUCCESS;
     459             :                 }
     460           0 :                 return FAILURE;
     461             :         }
     462           0 :         return SUCCESS;
     463             : }
     464             : 
     465     5919593 : ZEND_API int zend_hash_rehash(HashTable *ht)
     466             : {
     467             :         Bucket *p;
     468             :         uint nIndex;
     469             : 
     470             :         IS_CONSISTENT(ht);
     471     5919593 :         if (UNEXPECTED(ht->nNumOfElements == 0)) {
     472           0 :                 return SUCCESS;
     473             :         }
     474             : 
     475     5919593 :         memset(ht->arBuckets, 0, ht->nTableSize * sizeof(Bucket *));
     476     5919593 :         p = ht->pListHead;
     477   347711695 :         while (p != NULL) {
     478   335872509 :                 nIndex = p->h & ht->nTableMask;
     479   335872509 :                 CONNECT_TO_BUCKET_DLLIST(p, ht->arBuckets[nIndex]);
     480   335872509 :                 ht->arBuckets[nIndex] = p;
     481   335872509 :                 p = p->pListNext;
     482             :         }
     483     5919593 :         return SUCCESS;
     484             : }
     485             : 
     486    48045687 : ZEND_API int zend_hash_del_key_or_index(HashTable *ht, const char *arKey, uint nKeyLength, ulong h, int flag)
     487             : {
     488             :         uint nIndex;
     489             :         Bucket *p;
     490             : #ifdef ZEND_SIGNALS
     491             :         TSRMLS_FETCH();
     492             : #endif
     493             : 
     494             :         IS_CONSISTENT(ht);
     495             : 
     496    48045687 :         if (flag == HASH_DEL_KEY) {
     497    46971253 :                 h = zend_inline_hash_func(arKey, nKeyLength);
     498             :         }
     499    48045687 :         nIndex = h & ht->nTableMask;
     500             : 
     501    48045687 :         p = ht->arBuckets[nIndex];
     502    99557996 :         while (p != NULL) {
     503   193779609 :                 if ((p->h == h) 
     504    47813274 :                          && (p->nKeyLength == nKeyLength)
     505    47813274 :                          && ((p->nKeyLength == 0) /* Numeric index (short circuits the memcmp() check) */
     506    46873211 :                                  || !memcmp(p->arKey, arKey, nKeyLength))) { /* String index */
     507    47813228 :                         HANDLE_BLOCK_INTERRUPTIONS();
     508    47813228 :                         if (p == ht->arBuckets[nIndex]) {
     509    44610740 :                                 ht->arBuckets[nIndex] = p->pNext;
     510             :                         } else {
     511     3202488 :                                 p->pLast->pNext = p->pNext;
     512             :                         }
     513    47813228 :                         if (p->pNext) {
     514     8635593 :                                 p->pNext->pLast = p->pLast;
     515             :                         }
     516    47813228 :                         if (p->pListLast != NULL) {
     517    46270523 :                                 p->pListLast->pListNext = p->pListNext;
     518             :                         } else { 
     519             :                                 /* Deleting the head of the list */
     520     1542705 :                                 ht->pListHead = p->pListNext;
     521             :                         }
     522    47813228 :                         if (p->pListNext != NULL) {
     523    47010846 :                                 p->pListNext->pListLast = p->pListLast;
     524             :                         } else {
     525      802382 :                                 ht->pListTail = p->pListLast;
     526             :                         }
     527    47813228 :                         if (ht->pInternalPointer == p) {
     528     1542638 :                                 ht->pInternalPointer = p->pListNext;
     529             :                         }
     530    47813228 :                         if (ht->pDestructor) {
     531    47103626 :                                 ht->pDestructor(p->pData);
     532             :                         }
     533    47813227 :                         if (p->pData != &p->pDataPtr) {
     534    46786268 :                                 pefree(p->pData, ht->persistent);
     535             :                         }
     536    47813227 :                         pefree(p, ht->persistent);
     537    47813227 :                         HANDLE_UNBLOCK_INTERRUPTIONS();
     538    47813227 :                         ht->nNumOfElements--;
     539    47813227 :                         return SUCCESS;
     540             :                 }
     541     3466622 :                 p = p->pNext;
     542             :         }
     543      232459 :         return FAILURE;
     544             : }
     545             : 
     546             : 
     547    17574315 : ZEND_API void zend_hash_destroy(HashTable *ht)
     548             : {
     549             :         Bucket *p, *q;
     550             : 
     551             :         IS_CONSISTENT(ht);
     552             : 
     553             :         SET_INCONSISTENT(HT_IS_DESTROYING);
     554             : 
     555    17574315 :         p = ht->pListHead;
     556   184663230 :         while (p != NULL) {
     557   149514603 :                 q = p;
     558   149514603 :                 p = p->pListNext;
     559   149514603 :                 if (ht->pDestructor) {
     560   130241799 :                         ht->pDestructor(q->pData);
     561             :                 }
     562   149514600 :                 if (q->pData != &q->pDataPtr) {
     563   113935935 :                         pefree(q->pData, ht->persistent);
     564             :                 }
     565   149514600 :                 pefree(q, ht->persistent);
     566             :         }
     567    17574312 :         if (ht->nTableMask) {
     568     9941238 :                 pefree(ht->arBuckets, ht->persistent);
     569             :         }
     570             : 
     571             :         SET_INCONSISTENT(HT_DESTROYED);
     572    17574312 : }
     573             : 
     574             : 
     575       82768 : ZEND_API void zend_hash_clean(HashTable *ht)
     576             : {
     577             :         Bucket *p, *q;
     578             : 
     579             :         IS_CONSISTENT(ht);
     580             : 
     581       82768 :         p = ht->pListHead;
     582             : 
     583       82768 :         if (ht->nTableMask) {
     584       41829 :                 memset(ht->arBuckets, 0, ht->nTableSize*sizeof(Bucket *));
     585             :         }
     586       82768 :         ht->pListHead = NULL;
     587       82768 :         ht->pListTail = NULL;
     588       82768 :         ht->nNumOfElements = 0;
     589       82768 :         ht->nNextFreeElement = 0;
     590       82768 :         ht->pInternalPointer = NULL;
     591             : 
     592     1482897 :         while (p != NULL) {
     593     1317361 :                 q = p;
     594     1317361 :                 p = p->pListNext;
     595     1317361 :                 if (ht->pDestructor) {
     596     1289803 :                         ht->pDestructor(q->pData);
     597             :                 }
     598     1317361 :                 if (q->pData != &q->pDataPtr) {
     599           0 :                         pefree(q->pData, ht->persistent);
     600             :                 }
     601     1317361 :                 pefree(q, ht->persistent);
     602             :         }
     603       82768 : }
     604             : 
     605             : /* This function is used by the various apply() functions.
     606             :  * It deletes the passed bucket, and returns the address of the
     607             :  * next bucket.  The hash *may* be altered during that time, the
     608             :  * returned value will still be valid.
     609             :  */
     610     6913634 : static Bucket *zend_hash_apply_deleter(HashTable *ht, Bucket *p)
     611             : {
     612             :         Bucket *retval;
     613             : #ifdef ZEND_SIGNALS
     614             :         TSRMLS_FETCH();
     615             : #endif
     616             : 
     617     6913634 :         HANDLE_BLOCK_INTERRUPTIONS();
     618     6913634 :         if (p->pLast) {
     619      484742 :                 p->pLast->pNext = p->pNext;
     620             :         } else {
     621             :                 uint nIndex;
     622             : 
     623     6428892 :                 nIndex = p->h & ht->nTableMask;
     624     6428892 :                 ht->arBuckets[nIndex] = p->pNext;
     625             :         }
     626     6913634 :         if (p->pNext) {
     627     1923753 :                 p->pNext->pLast = p->pLast;
     628             :         } else {
     629             :                 /* Nothing to do as this list doesn't have a tail */
     630             :         }
     631             : 
     632     6913634 :         if (p->pListLast != NULL) {
     633     5077371 :                 p->pListLast->pListNext = p->pListNext;
     634             :         } else { 
     635             :                 /* Deleting the head of the list */
     636     1836263 :                 ht->pListHead = p->pListNext;
     637             :         }
     638     6913634 :         if (p->pListNext != NULL) {
     639     4955891 :                 p->pListNext->pListLast = p->pListLast;
     640             :         } else {
     641     1957743 :                 ht->pListTail = p->pListLast;
     642             :         }
     643     6913634 :         if (ht->pInternalPointer == p) {
     644     1836258 :                 ht->pInternalPointer = p->pListNext;
     645             :         }
     646     6913634 :         ht->nNumOfElements--;
     647     6913634 :         HANDLE_UNBLOCK_INTERRUPTIONS();
     648             : 
     649     6913634 :         if (ht->pDestructor) {
     650     1819768 :                 ht->pDestructor(p->pData);
     651             :         }
     652     6913634 :         if (p->pData != &p->pDataPtr) {
     653     6587065 :                 pefree(p->pData, ht->persistent);
     654             :         }
     655     6913634 :         retval = p->pListNext;
     656     6913634 :         pefree(p, ht->persistent);
     657             : 
     658     6913634 :         return retval;
     659             : }
     660             : 
     661             : 
     662           0 : ZEND_API void zend_hash_graceful_destroy(HashTable *ht)
     663             : {
     664             :         Bucket *p;
     665             : 
     666             :         IS_CONSISTENT(ht);
     667             : 
     668           0 :         p = ht->pListHead;
     669           0 :         while (p != NULL) {
     670           0 :                 p = zend_hash_apply_deleter(ht, p);
     671             :         }
     672           0 :         if (ht->nTableMask) {
     673           0 :                 pefree(ht->arBuckets, ht->persistent);
     674             :         }
     675             : 
     676             :         SET_INCONSISTENT(HT_DESTROYED);
     677           0 : }
     678             : 
     679       81084 : ZEND_API void zend_hash_graceful_reverse_destroy(HashTable *ht)
     680             : {
     681             :         Bucket *p;
     682             : 
     683             :         IS_CONSISTENT(ht);
     684             : 
     685       81084 :         p = ht->pListTail;
     686     1872987 :         while (p != NULL) {
     687     1710819 :                 zend_hash_apply_deleter(ht, p);
     688     1710819 :                 p = ht->pListTail;
     689             :         }
     690             : 
     691       81084 :         if (ht->nTableMask) {
     692       62123 :                 pefree(ht->arBuckets, ht->persistent);
     693             :         }
     694             : 
     695             :         SET_INCONSISTENT(HT_DESTROYED);
     696       81084 : }
     697             : 
     698             : /* This is used to recurse elements and selectively delete certain entries 
     699             :  * from a hashtable. apply_func() receives the data and decides if the entry 
     700             :  * should be deleted or recursion should be stopped. The following three 
     701             :  * return codes are possible:
     702             :  * ZEND_HASH_APPLY_KEEP   - continue
     703             :  * ZEND_HASH_APPLY_STOP   - stop iteration
     704             :  * ZEND_HASH_APPLY_REMOVE - delete the element, combineable with the former
     705             :  */
     706             : 
     707      360468 : ZEND_API void zend_hash_apply(HashTable *ht, apply_func_t apply_func TSRMLS_DC)
     708             : {
     709             :         Bucket *p;
     710             : 
     711             :         IS_CONSISTENT(ht);
     712             : 
     713      360468 :         HASH_PROTECT_RECURSION(ht);
     714      360468 :         p = ht->pListHead;
     715     3010783 :         while (p != NULL) {
     716     2289849 :                 int result = apply_func(p->pData TSRMLS_CC);
     717             :                 
     718     2289847 :                 if (result & ZEND_HASH_APPLY_REMOVE) {
     719      106460 :                         p = zend_hash_apply_deleter(ht, p);
     720             :                 } else {
     721     2183387 :                         p = p->pListNext;
     722             :                 }
     723     2289847 :                 if (result & ZEND_HASH_APPLY_STOP) {
     724           0 :                         break;
     725             :                 }
     726             :         }
     727      360466 :         HASH_UNPROTECT_RECURSION(ht);
     728      360466 : }
     729             : 
     730             : 
     731      657033 : ZEND_API void zend_hash_apply_with_argument(HashTable *ht, apply_func_arg_t apply_func, void *argument TSRMLS_DC)
     732             : {
     733             :         Bucket *p;
     734             : 
     735             :         IS_CONSISTENT(ht);
     736             : 
     737      657033 :         HASH_PROTECT_RECURSION(ht);
     738      657033 :         p = ht->pListHead;
     739   104548627 :         while (p != NULL) {
     740   103238869 :                 int result = apply_func(p->pData, argument TSRMLS_CC);
     741             :                 
     742   103238859 :                 if (result & ZEND_HASH_APPLY_REMOVE) {
     743     4991573 :                         p = zend_hash_apply_deleter(ht, p);
     744             :                 } else {
     745    98247286 :                         p = p->pListNext;
     746             :                 }
     747   103238859 :                 if (result & ZEND_HASH_APPLY_STOP) {
     748        4298 :                         break;
     749             :                 }
     750             :         }
     751      657023 :         HASH_UNPROTECT_RECURSION(ht);
     752      657023 : }
     753             : 
     754             : 
     755       26956 : ZEND_API void zend_hash_apply_with_arguments(HashTable *ht TSRMLS_DC, apply_func_args_t apply_func, int num_args, ...)
     756             : {
     757             :         Bucket *p;
     758             :         va_list args;
     759             :         zend_hash_key hash_key;
     760             : 
     761             :         IS_CONSISTENT(ht);
     762             : 
     763       26956 :         HASH_PROTECT_RECURSION(ht);
     764             : 
     765       26956 :         p = ht->pListHead;
     766      284300 :         while (p != NULL) {
     767             :                 int result;
     768      230410 :                 va_start(args, num_args);
     769      230410 :                 hash_key.arKey = p->arKey;
     770      230410 :                 hash_key.nKeyLength = p->nKeyLength;
     771      230410 :                 hash_key.h = p->h;
     772      230410 :                 result = apply_func(p->pData TSRMLS_CC, num_args, args, &hash_key);
     773             : 
     774      230388 :                 if (result & ZEND_HASH_APPLY_REMOVE) {
     775           0 :                         p = zend_hash_apply_deleter(ht, p);
     776             :                 } else {
     777      230388 :                         p = p->pListNext;
     778             :                 }
     779      230388 :                 if (result & ZEND_HASH_APPLY_STOP) {
     780           0 :                         va_end(args);
     781           0 :                         break;
     782             :                 }
     783      230388 :                 va_end(args);
     784             :         }
     785             : 
     786       26934 :         HASH_UNPROTECT_RECURSION(ht);
     787       26934 : }
     788             : 
     789             : 
     790      126005 : ZEND_API void zend_hash_reverse_apply(HashTable *ht, apply_func_t apply_func TSRMLS_DC)
     791             : {
     792             :         Bucket *p, *q;
     793             : 
     794             :         IS_CONSISTENT(ht);
     795             : 
     796      126005 :         HASH_PROTECT_RECURSION(ht);
     797      126005 :         p = ht->pListTail;
     798      648954 :         while (p != NULL) {
     799      498044 :                 int result = apply_func(p->pData TSRMLS_CC);
     800             : 
     801      498043 :                 q = p;
     802      498043 :                 p = p->pListLast;
     803      498043 :                 if (result & ZEND_HASH_APPLY_REMOVE) {
     804      104782 :                         zend_hash_apply_deleter(ht, q);
     805             :                 }
     806      498043 :                 if (result & ZEND_HASH_APPLY_STOP) {
     807      101099 :                         break;
     808             :                 }
     809             :         }
     810      126004 :         HASH_UNPROTECT_RECURSION(ht);
     811      126004 : }
     812             : 
     813             : 
     814     1010408 : ZEND_API void zend_hash_copy(HashTable *target, HashTable *source, copy_ctor_func_t pCopyConstructor, void *tmp, uint size)
     815             : {
     816             :         Bucket *p;
     817             :         void *new_entry;
     818             :         zend_bool setTargetPointer;
     819             : 
     820             :         IS_CONSISTENT(source);
     821             :         IS_CONSISTENT(target);
     822             : 
     823     1010408 :         setTargetPointer = !target->pInternalPointer;
     824     1010408 :         p = source->pListHead;
     825     6386826 :         while (p) {
     826     4366010 :                 if (setTargetPointer && source->pInternalPointer == p) {
     827      921956 :                         target->pInternalPointer = NULL;
     828             :                 }
     829     4366010 :                 if (p->nKeyLength) {
     830     1687058 :                         zend_hash_quick_update(target, p->arKey, p->nKeyLength, p->h, p->pData, size, &new_entry);
     831             :                 } else {
     832     2678952 :                         zend_hash_index_update(target, p->h, p->pData, size, &new_entry);
     833             :                 }
     834     4366010 :                 if (pCopyConstructor) {
     835     4354091 :                         pCopyConstructor(new_entry);
     836             :                 }
     837     4366010 :                 p = p->pListNext;
     838             :         }
     839     1010408 :         if (!target->pInternalPointer) {
     840       88206 :                 target->pInternalPointer = target->pListHead;
     841             :         }
     842     1010408 : }
     843             : 
     844             : 
     845     1519208 : 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)
     846             : {
     847             :         Bucket *p;
     848             :         void *t;
     849     1519208 :         int mode = (overwrite?HASH_UPDATE:HASH_ADD);
     850             : 
     851             :         IS_CONSISTENT(source);
     852             :         IS_CONSISTENT(target);
     853             : 
     854     1519208 :         p = source->pListHead;
     855     7596767 :         while (p) {
     856     4558351 :                 if (p->nKeyLength>0) {
     857     4558335 :                         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) {
     858     1604886 :                                 pCopyConstructor(t);
     859             :                         }
     860             :                 } else {
     861          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) {
     862           6 :                                 pCopyConstructor(t);
     863             :                         }
     864             :                 }
     865     4558351 :                 p = p->pListNext;
     866             :         }
     867     1519208 :         target->pInternalPointer = target->pListHead;
     868     1519208 : }
     869             : 
     870             : 
     871    31797881 : static zend_bool zend_hash_replace_checker_wrapper(HashTable *target, void *source_data, Bucket *p, void *pParam, merge_checker_func_t merge_checker_func)
     872             : {
     873             :         zend_hash_key hash_key;
     874             : 
     875    31797881 :         hash_key.arKey = p->arKey;
     876    31797881 :         hash_key.nKeyLength = p->nKeyLength;
     877    31797881 :         hash_key.h = p->h;
     878    31797881 :         return merge_checker_func(target, source_data, &hash_key, pParam);
     879             : }
     880             : 
     881             : 
     882     5182808 : 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)
     883             : {
     884             :         Bucket *p;
     885             :         void *t;
     886             : 
     887             :         IS_CONSISTENT(source);
     888             :         IS_CONSISTENT(target);
     889             : 
     890     5182808 :         p = source->pListHead;
     891    42163452 :         while (p) {
     892    31797881 :                 if (zend_hash_replace_checker_wrapper(target, p->pData, p, pParam, pMergeSource)) {
     893    24636275 :                         if (zend_hash_quick_update(target, p->arKey, p->nKeyLength, p->h, p->pData, size, &t)==SUCCESS && pCopyConstructor) {
     894    24636275 :                                 pCopyConstructor(t);
     895             :                         }
     896             :                 }
     897    31797836 :                 p = p->pListNext;
     898             :         }
     899     5182763 :         target->pInternalPointer = target->pListHead;
     900     5182763 : }
     901             : 
     902             : 
     903     2090693 : ZEND_API ulong zend_get_hash_value(const char *arKey, uint nKeyLength)
     904             : {
     905     2090693 :         return zend_inline_hash_func(arKey, nKeyLength);
     906             : }
     907             : 
     908             : 
     909             : /* Returns SUCCESS if found and FAILURE if not. The pointer to the
     910             :  * data is returned in pData. The reason is that there's no reason
     911             :  * someone using the hash table might not want to have NULL data
     912             :  */
     913    11295751 : ZEND_API int zend_hash_find(const HashTable *ht, const char *arKey, uint nKeyLength, void **pData)
     914             : {
     915             :         ulong h;
     916             :         uint nIndex;
     917             :         Bucket *p;
     918             : 
     919             :         IS_CONSISTENT(ht);
     920             : 
     921    11295751 :         h = zend_inline_hash_func(arKey, nKeyLength);
     922    11295751 :         nIndex = h & ht->nTableMask;
     923             : 
     924    11295751 :         p = ht->arBuckets[nIndex];
     925    27658085 :         while (p != NULL) {
     926    33384572 :                 if (p->arKey == arKey ||
     927    22496443 :                         ((p->h == h) && (p->nKeyLength == nKeyLength) && !memcmp(p->arKey, arKey, nKeyLength))) {
     928     5821546 :                                 *pData = p->pData;
     929     5821546 :                                 return SUCCESS;
     930             :                 }
     931     5066583 :                 p = p->pNext;
     932             :         }
     933     5474205 :         return FAILURE;
     934             : }
     935             : 
     936             : 
     937    41751957 : ZEND_API int zend_hash_quick_find(const HashTable *ht, const char *arKey, uint nKeyLength, ulong h, void **pData)
     938             : {
     939             :         uint nIndex;
     940             :         Bucket *p;
     941             : 
     942    41751957 :         if (nKeyLength==0) {
     943           0 :                 return zend_hash_index_find(ht, h, pData);
     944             :         }
     945             : 
     946             :         IS_CONSISTENT(ht);
     947             : 
     948    41751957 :         nIndex = h & ht->nTableMask;
     949             : 
     950    41751957 :         p = ht->arBuckets[nIndex];
     951   105170623 :         while (p != NULL) {
     952    59722106 :                 if (p->arKey == arKey ||
     953    27623140 :                         ((p->h == h) && (p->nKeyLength == nKeyLength) && !memcmp(p->arKey, arKey, nKeyLength))) {
     954    10432257 :                                 *pData = p->pData;
     955    10432257 :                                 return SUCCESS;
     956             :                 }
     957    21666709 :                 p = p->pNext;
     958             :         }
     959    31319700 :         return FAILURE;
     960             : }
     961             : 
     962             : 
     963     1081632 : ZEND_API int zend_hash_exists(const HashTable *ht, const char *arKey, uint nKeyLength)
     964             : {
     965             :         ulong h;
     966             :         uint nIndex;
     967             :         Bucket *p;
     968             : 
     969             :         IS_CONSISTENT(ht);
     970             : 
     971     1081632 :         h = zend_inline_hash_func(arKey, nKeyLength);
     972     1081632 :         nIndex = h & ht->nTableMask;
     973             : 
     974     1081632 :         p = ht->arBuckets[nIndex];
     975     2368506 :         while (p != NULL) {
     976     1753669 :                 if (p->arKey == arKey ||
     977     1212444 :                         ((p->h == h) && (p->nKeyLength == nKeyLength) && !memcmp(p->arKey, arKey, nKeyLength))) {
     978      335983 :                                 return 1;
     979             :                 }
     980      205242 :                 p = p->pNext;
     981             :         }
     982      745649 :         return 0;
     983             : }
     984             : 
     985             : 
     986         477 : ZEND_API int zend_hash_quick_exists(const HashTable *ht, const char *arKey, uint nKeyLength, ulong h)
     987             : {
     988             :         uint nIndex;
     989             :         Bucket *p;
     990             : 
     991         477 :         if (nKeyLength==0) {
     992           0 :                 return zend_hash_index_exists(ht, h);
     993             :         }
     994             : 
     995             :         IS_CONSISTENT(ht);
     996             : 
     997         477 :         nIndex = h & ht->nTableMask;
     998             : 
     999         477 :         p = ht->arBuckets[nIndex];
    1000         980 :         while (p != NULL) {
    1001         739 :                 if (p->arKey == arKey ||
    1002         530 :                         ((p->h == h) && (p->nKeyLength == nKeyLength) && !memcmp(p->arKey, arKey, nKeyLength))) {
    1003         183 :                                 return 1;
    1004             :                 }
    1005          26 :                 p = p->pNext;
    1006             :         }
    1007         294 :         return 0;
    1008             : 
    1009             : }
    1010             : 
    1011             : 
    1012    19491363 : ZEND_API int zend_hash_index_find(const HashTable *ht, ulong h, void **pData)
    1013             : {
    1014             :         uint nIndex;
    1015             :         Bucket *p;
    1016             : 
    1017             :         IS_CONSISTENT(ht);
    1018             : 
    1019    19491363 :         nIndex = h & ht->nTableMask;
    1020             : 
    1021    19491363 :         p = ht->arBuckets[nIndex];
    1022    40133295 :         while (p != NULL) {
    1023    19590761 :                 if ((p->h == h) && (p->nKeyLength == 0)) {
    1024    18440192 :                         *pData = p->pData;
    1025    18440192 :                         return SUCCESS;
    1026             :                 }
    1027     1150569 :                 p = p->pNext;
    1028             :         }
    1029     1051171 :         return FAILURE;
    1030             : }
    1031             : 
    1032             : 
    1033     1517243 : ZEND_API int zend_hash_index_exists(const HashTable *ht, ulong h)
    1034             : {
    1035             :         uint nIndex;
    1036             :         Bucket *p;
    1037             : 
    1038             :         IS_CONSISTENT(ht);
    1039             : 
    1040     1517243 :         nIndex = h & ht->nTableMask;
    1041             : 
    1042     1517243 :         p = ht->arBuckets[nIndex];
    1043     3621030 :         while (p != NULL) {
    1044      869918 :                 if ((p->h == h) && (p->nKeyLength == 0)) {
    1045      283374 :                         return 1;
    1046             :                 }
    1047      586544 :                 p = p->pNext;
    1048             :         }
    1049     1233869 :         return 0;
    1050             : }
    1051             : 
    1052             : 
    1053     5384480 : ZEND_API int zend_hash_num_elements(const HashTable *ht)
    1054             : {
    1055             :         IS_CONSISTENT(ht);
    1056             : 
    1057     5384480 :         return ht->nNumOfElements;
    1058             : }
    1059             : 
    1060             : 
    1061     2136014 : ZEND_API int zend_hash_get_pointer(const HashTable *ht, HashPointer *ptr)
    1062             : {
    1063     2136014 :         ptr->pos = ht->pInternalPointer;
    1064     2136014 :         if (ht->pInternalPointer) {
    1065     2071427 :                 ptr->h = ht->pInternalPointer->h;
    1066     2071427 :                 return 1;
    1067             :         } else {
    1068       64587 :                 ptr->h = 0;
    1069       64587 :                 return 0;
    1070             :         }
    1071             : }
    1072             : 
    1073     2130641 : ZEND_API int zend_hash_set_pointer(HashTable *ht, const HashPointer *ptr)
    1074             : {
    1075     2130641 :         if (ptr->pos == NULL) {
    1076       64206 :                 ht->pInternalPointer = NULL;
    1077     2066435 :         } else if (ht->pInternalPointer != ptr->pos) {
    1078             :                 Bucket *p;
    1079             : 
    1080             :                 IS_CONSISTENT(ht);
    1081          69 :                 p = ht->arBuckets[ptr->h & ht->nTableMask];
    1082         186 :                 while (p != NULL) {
    1083          58 :                         if (p == ptr->pos) {
    1084          10 :                                 ht->pInternalPointer = p;
    1085          10 :                                 return 1;
    1086             :                         }
    1087          48 :                         p = p->pNext;
    1088             :                 }
    1089          59 :                 return 0;
    1090             :         }
    1091     2130572 :         return 1;
    1092             : }
    1093             : 
    1094     5207682 : ZEND_API void zend_hash_internal_pointer_reset_ex(HashTable *ht, HashPosition *pos)
    1095             : {
    1096             :         IS_CONSISTENT(ht);
    1097             : 
    1098     5207682 :         if (pos)
    1099      339924 :                 *pos = ht->pListHead;
    1100             :         else
    1101     4867758 :                 ht->pInternalPointer = ht->pListHead;
    1102     5207682 : }
    1103             : 
    1104             : 
    1105             : /* This function will be extremely optimized by remembering 
    1106             :  * the end of the list
    1107             :  */
    1108         274 : ZEND_API void zend_hash_internal_pointer_end_ex(HashTable *ht, HashPosition *pos)
    1109             : {
    1110             :         IS_CONSISTENT(ht);
    1111             : 
    1112         274 :         if (pos)
    1113         157 :                 *pos = ht->pListTail;
    1114             :         else
    1115         117 :                 ht->pInternalPointer = ht->pListTail;
    1116         274 : }
    1117             : 
    1118             : 
    1119    17399029 : ZEND_API int zend_hash_move_forward_ex(HashTable *ht, HashPosition *pos)
    1120             : {
    1121    17399029 :         HashPosition *current = pos ? pos : &ht->pInternalPointer;
    1122             : 
    1123             :         IS_CONSISTENT(ht);
    1124             : 
    1125    17399029 :         if (*current) {
    1126    17399001 :                 *current = (*current)->pListNext;
    1127    17399001 :                 return SUCCESS;
    1128             :         } else
    1129          28 :                 return FAILURE;
    1130             : }
    1131             : 
    1132         531 : ZEND_API int zend_hash_move_backwards_ex(HashTable *ht, HashPosition *pos)
    1133             : {
    1134         531 :         HashPosition *current = pos ? pos : &ht->pInternalPointer;
    1135             : 
    1136             :         IS_CONSISTENT(ht);
    1137             : 
    1138         531 :         if (*current) {
    1139         529 :                 *current = (*current)->pListLast;
    1140         529 :                 return SUCCESS;
    1141             :         } else
    1142           2 :                 return FAILURE;
    1143             : }
    1144             : 
    1145             : 
    1146             : /* This function should be made binary safe  */
    1147     5465403 : 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)
    1148             : {
    1149             :         Bucket *p;
    1150             : 
    1151     5465403 :         p = pos ? (*pos) : ht->pInternalPointer;
    1152             : 
    1153             :         IS_CONSISTENT(ht);
    1154             : 
    1155     5465403 :         if (p) {
    1156     5389074 :                 if (p->nKeyLength) {
    1157     3460387 :                         if (duplicate) {
    1158     1509447 :                                 *str_index = estrndup(p->arKey, p->nKeyLength - 1);
    1159             :                         } else {
    1160     1950940 :                                 *str_index = (char*)p->arKey;
    1161             :                         }
    1162     3460387 :                         if (str_length) {
    1163     3448156 :                                 *str_length = p->nKeyLength;
    1164             :                         }
    1165     3460387 :                         return HASH_KEY_IS_STRING;
    1166             :                 } else {
    1167     1928687 :                         *num_index = p->h;
    1168     1928687 :                         return HASH_KEY_IS_LONG;
    1169             :                 }
    1170             :         }
    1171       76329 :         return HASH_KEY_NON_EXISTANT;
    1172             : }
    1173             : 
    1174             : 
    1175     2672540 : ZEND_API int zend_hash_get_current_key_type_ex(HashTable *ht, HashPosition *pos)
    1176             : {
    1177             :         Bucket *p;
    1178             : 
    1179     2672540 :         p = pos ? (*pos) : ht->pInternalPointer;
    1180             : 
    1181             :         IS_CONSISTENT(ht);
    1182             : 
    1183     2672540 :         if (p) {
    1184     1814109 :                 if (p->nKeyLength) {
    1185       92094 :                         return HASH_KEY_IS_STRING;
    1186             :                 } else {
    1187     1722015 :                         return HASH_KEY_IS_LONG;
    1188             :                 }
    1189             :         }
    1190      858431 :         return HASH_KEY_NON_EXISTANT;
    1191             : }
    1192             : 
    1193             : 
    1194    20780120 : ZEND_API int zend_hash_get_current_data_ex(HashTable *ht, void **pData, HashPosition *pos)
    1195             : {
    1196             :         Bucket *p;
    1197             : 
    1198    20780120 :         p = pos ? (*pos) : ht->pInternalPointer;
    1199             : 
    1200             :         IS_CONSISTENT(ht);
    1201             : 
    1202    20780120 :         if (p) {
    1203    17388693 :                 *pData = p->pData;
    1204    17388693 :                 return SUCCESS;
    1205             :         } else {
    1206     3391427 :                 return FAILURE;
    1207             :         }
    1208             : }
    1209             : 
    1210             : /* This function changes key of current element without changing elements'
    1211             :  * order. If element with target key already exists, it will be deleted first.
    1212             :  */
    1213          93 : 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)
    1214             : {
    1215             :         Bucket *p, *q;
    1216             :         ulong h;
    1217             : #ifdef ZEND_SIGNALS
    1218             :         TSRMLS_FETCH();
    1219             : #endif
    1220             : 
    1221          93 :         p = pos ? (*pos) : ht->pInternalPointer;
    1222             : 
    1223             :         IS_CONSISTENT(ht);
    1224             : 
    1225          93 :         if (p) {
    1226          93 :                 if (key_type == HASH_KEY_IS_LONG) {
    1227          54 :                         str_length = 0;
    1228          54 :                         if (!p->nKeyLength && p->h == num_index) {
    1229           0 :                                 return SUCCESS;
    1230             :                         }
    1231             : 
    1232          54 :                         q = ht->arBuckets[num_index & ht->nTableMask];
    1233         113 :                         while (q != NULL) {
    1234           9 :                                 if (!q->nKeyLength && q->h == num_index) {
    1235           4 :                                         break;
    1236             :                                 }
    1237           5 :                                 q = q->pNext;
    1238             :                         }
    1239          39 :                 } else if (key_type == HASH_KEY_IS_STRING) {
    1240          46 :                         if (IS_INTERNED(str_index)) {
    1241           7 :                                 h = INTERNED_HASH(str_index);
    1242             :                         } else {
    1243          32 :                                 h = zend_inline_hash_func(str_index, str_length);
    1244             :                         }
    1245             : 
    1246          91 :                         if (p->arKey == str_index ||
    1247          39 :                             (p->nKeyLength == str_length &&
    1248          13 :                              p->h == h &&
    1249           0 :                              memcmp(p->arKey, str_index, str_length) == 0)) {
    1250           0 :                                 return SUCCESS;
    1251             :                         }
    1252             : 
    1253          39 :                         q = ht->arBuckets[h & ht->nTableMask];
    1254             : 
    1255          85 :                         while (q != NULL) {
    1256          30 :                                 if (q->arKey == str_index ||
    1257          15 :                                     (q->h == h && q->nKeyLength == str_length &&
    1258           4 :                                      memcmp(q->arKey, str_index, str_length) == 0)) {
    1259             :                                         break;
    1260             :                                 }
    1261           7 :                                 q = q->pNext;
    1262             :                         }
    1263             :                 } else {
    1264           0 :                         return FAILURE;
    1265             :                 }
    1266             : 
    1267          93 :                 HANDLE_BLOCK_INTERRUPTIONS();
    1268             : 
    1269          93 :                 if (q) {
    1270           8 :                         if (mode != HASH_UPDATE_KEY_ANYWAY) {
    1271           8 :                                 Bucket *r = p->pListLast;
    1272           8 :                                 int found = HASH_UPDATE_KEY_IF_BEFORE;
    1273             : 
    1274          16 :                                 while (r) {
    1275           6 :                                         if (r == q) {
    1276           6 :                                                 found = HASH_UPDATE_KEY_IF_AFTER;
    1277           6 :                                                 break;
    1278             :                                         }
    1279           0 :                                         r = r->pListLast;
    1280             :                                 }
    1281           8 :                                 if (mode & found) {
    1282             :                                         /* delete current bucket */
    1283           2 :                                         if (p == ht->arBuckets[p->h & ht->nTableMask]) {
    1284           2 :                                                 ht->arBuckets[p->h & ht->nTableMask] = p->pNext;
    1285             :                                         } else {
    1286           0 :                                                 p->pLast->pNext = p->pNext;
    1287             :                                         }
    1288           2 :                                         if (p->pNext) {
    1289           0 :                                                 p->pNext->pLast = p->pLast;
    1290             :                                         }
    1291           2 :                                         if (p->pListLast != NULL) {
    1292           0 :                                                 p->pListLast->pListNext = p->pListNext;
    1293             :                                         } else {
    1294             :                                                 /* Deleting the head of the list */
    1295           2 :                                                 ht->pListHead = p->pListNext;
    1296             :                                         }
    1297           2 :                                         if (p->pListNext != NULL) {
    1298           2 :                                                 p->pListNext->pListLast = p->pListLast;
    1299             :                                         } else {
    1300           0 :                                                 ht->pListTail = p->pListLast;
    1301             :                                         }
    1302           2 :                                         if (ht->pInternalPointer == p) {
    1303           2 :                                                 ht->pInternalPointer = p->pListNext;
    1304             :                                         }
    1305           2 :                                         if (ht->pDestructor) {
    1306           2 :                                                 ht->pDestructor(p->pData);
    1307             :                                         }
    1308           2 :                                         if (p->pData != &p->pDataPtr) {
    1309           0 :                                                 pefree(p->pData, ht->persistent);
    1310             :                                         }
    1311           2 :                                         pefree(p, ht->persistent);
    1312           2 :                                         ht->nNumOfElements--;
    1313           2 :                                         HANDLE_UNBLOCK_INTERRUPTIONS();
    1314           2 :                                         return FAILURE;
    1315             :                                 }
    1316             :                         }
    1317             :                         /* delete another bucket with the same key */
    1318           6 :                         if (q == ht->arBuckets[q->h & ht->nTableMask]) {
    1319           5 :                                 ht->arBuckets[q->h & ht->nTableMask] = q->pNext;
    1320             :                         } else {
    1321           1 :                                 q->pLast->pNext = q->pNext;
    1322             :                         }
    1323           6 :                         if (q->pNext) {
    1324           0 :                                 q->pNext->pLast = q->pLast;
    1325             :                         }
    1326           6 :                         if (q->pListLast != NULL) {
    1327           1 :                                 q->pListLast->pListNext = q->pListNext;
    1328             :                         } else {
    1329             :                                 /* Deleting the head of the list */
    1330           5 :                                 ht->pListHead = q->pListNext;
    1331             :                         }
    1332           6 :                         if (q->pListNext != NULL) {
    1333           6 :                                 q->pListNext->pListLast = q->pListLast;
    1334             :                         } else {
    1335           0 :                                 ht->pListTail = q->pListLast;
    1336             :                         }
    1337           6 :                         if (ht->pInternalPointer == q) {
    1338           0 :                                 ht->pInternalPointer = q->pListNext;
    1339             :                         }
    1340           6 :                         if (ht->pDestructor) {
    1341           6 :                                 ht->pDestructor(q->pData);
    1342             :                         }
    1343           6 :                         if (q->pData != &q->pDataPtr) {
    1344           0 :                                 pefree(q->pData, ht->persistent);
    1345             :                         }
    1346           6 :                         pefree(q, ht->persistent);
    1347           6 :                         ht->nNumOfElements--;
    1348             :                 }
    1349             : 
    1350          91 :                 if (p->pNext) {
    1351           2 :                         p->pNext->pLast = p->pLast;
    1352             :                 }
    1353          91 :                 if (p->pLast) {
    1354           4 :                         p->pLast->pNext = p->pNext;
    1355             :                 } else {
    1356          87 :                         ht->arBuckets[p->h & ht->nTableMask] = p->pNext;
    1357             :                 }
    1358             : 
    1359         346 :                 if ((IS_INTERNED(p->arKey) != IS_INTERNED(str_index)) ||
    1360         255 :                     (!IS_INTERNED(p->arKey) && p->nKeyLength != str_length)) {
    1361             :                         Bucket *q;
    1362             : 
    1363          84 :                         if (IS_INTERNED(str_index)) {
    1364           6 :                                 q = (Bucket *) pemalloc(sizeof(Bucket), ht->persistent);
    1365             :                         } else {
    1366          72 :                                 q = (Bucket *) pemalloc(sizeof(Bucket) + str_length, ht->persistent);
    1367             :                         }
    1368             : 
    1369          78 :                         q->nKeyLength = str_length;
    1370          78 :                         if (p->pData == &p->pDataPtr) {
    1371          78 :                                 q->pData = &q->pDataPtr;
    1372             :                         } else {
    1373           0 :                                 q->pData = p->pData;
    1374             :                         }
    1375          78 :                         q->pDataPtr = p->pDataPtr;
    1376          78 :                         q->pListNext = p->pListNext;
    1377          78 :                         q->pListLast = p->pListLast;
    1378          78 :                         if (q->pListNext) {
    1379          12 :                                 p->pListNext->pListLast = q;
    1380             :                         } else {
    1381          66 :                                 ht->pListTail = q;
    1382             :                         }
    1383          78 :                         if (q->pListLast) {
    1384           8 :                                 p->pListLast->pListNext = q;
    1385             :                         } else {
    1386          70 :                                 ht->pListHead = q;
    1387             :                         }
    1388          78 :                         if (ht->pInternalPointer == p) {
    1389          78 :                                 ht->pInternalPointer = q;
    1390             :                         }
    1391          78 :                         if (pos) {
    1392           0 :                                 *pos = q;
    1393             :                         }
    1394          78 :                         pefree(p, ht->persistent);
    1395          78 :                         p = q;
    1396             :                 }
    1397             : 
    1398          91 :                 if (key_type == HASH_KEY_IS_LONG) {
    1399          53 :                         p->h = num_index;
    1400             :                 } else {
    1401          38 :                         p->h = h;
    1402          38 :                         p->nKeyLength = str_length;
    1403          44 :                         if (IS_INTERNED(str_index)) {
    1404           6 :                                 p->arKey = str_index;
    1405             :                         } else {
    1406          32 :                                 p->arKey = (const char*)(p+1);
    1407          32 :                                 memcpy((char*)p->arKey, str_index, str_length);
    1408             :                         }
    1409             :                 }
    1410             : 
    1411          91 :                 CONNECT_TO_BUCKET_DLLIST(p, ht->arBuckets[p->h & ht->nTableMask]);
    1412          91 :                 ht->arBuckets[p->h & ht->nTableMask] = p;
    1413          91 :                 HANDLE_UNBLOCK_INTERRUPTIONS();
    1414             : 
    1415          91 :                 return SUCCESS;
    1416             :         } else {
    1417           0 :                 return FAILURE;
    1418             :         }
    1419             : }
    1420             : 
    1421       21914 : ZEND_API int zend_hash_sort(HashTable *ht, sort_func_t sort_func,
    1422             :                                                         compare_func_t compar, int renumber TSRMLS_DC)
    1423             : {
    1424             :         Bucket **arTmp;
    1425             :         Bucket *p;
    1426             :         int i, j;
    1427             : 
    1428             :         IS_CONSISTENT(ht);
    1429             : 
    1430       21914 :         if (!(ht->nNumOfElements>1) && !(renumber && ht->nNumOfElements>0)) { /* Doesn't require sorting */
    1431         284 :                 return SUCCESS;
    1432             :         }
    1433       21630 :         arTmp = (Bucket **) pemalloc(ht->nNumOfElements * sizeof(Bucket *), ht->persistent);
    1434       21630 :         if (!arTmp) {
    1435           0 :                 return FAILURE;
    1436             :         }
    1437       21630 :         p = ht->pListHead;
    1438       21630 :         i = 0;
    1439     1594362 :         while (p) {
    1440     1551102 :                 arTmp[i] = p;
    1441     1551102 :                 p = p->pListNext;
    1442     1551102 :                 i++;
    1443             :         }
    1444             : 
    1445       21630 :         (*sort_func)((void *) arTmp, i, sizeof(Bucket *), compar TSRMLS_CC);
    1446             : 
    1447       21629 :         HANDLE_BLOCK_INTERRUPTIONS();
    1448       21629 :         ht->pListHead = arTmp[0];
    1449       21629 :         ht->pListTail = NULL;
    1450       21629 :         ht->pInternalPointer = ht->pListHead;
    1451             : 
    1452       21629 :         arTmp[0]->pListLast = NULL;
    1453       21629 :         if (i > 1) {
    1454       21620 :                 arTmp[0]->pListNext = arTmp[1];
    1455     1529471 :                 for (j = 1; j < i-1; j++) {
    1456     1507851 :                         arTmp[j]->pListLast = arTmp[j-1];
    1457     1507851 :                         arTmp[j]->pListNext = arTmp[j+1];
    1458             :                 }
    1459       21620 :                 arTmp[j]->pListLast = arTmp[j-1];
    1460       21620 :                 arTmp[j]->pListNext = NULL;
    1461             :         } else {
    1462           9 :                 arTmp[0]->pListNext = NULL;
    1463             :         }
    1464       21629 :         ht->pListTail = arTmp[i-1];
    1465             : 
    1466       21629 :         pefree(arTmp, ht->persistent);
    1467       21629 :         HANDLE_UNBLOCK_INTERRUPTIONS();
    1468             : 
    1469       21629 :         if (renumber) {
    1470         288 :                 p = ht->pListHead;
    1471         288 :                 i=0;
    1472       15208 :                 while (p != NULL) {
    1473       14632 :                         p->nKeyLength = 0;
    1474       14632 :                         p->h = i++;
    1475       14632 :                         p = p->pListNext;
    1476             :                 }
    1477         288 :                 ht->nNextFreeElement = i;
    1478         288 :                 zend_hash_rehash(ht);
    1479             :         }
    1480       21629 :         return SUCCESS;
    1481             : }
    1482             : 
    1483             : 
    1484        1165 : ZEND_API int zend_hash_compare(HashTable *ht1, HashTable *ht2, compare_func_t compar, zend_bool ordered TSRMLS_DC)
    1485             : {
    1486        1165 :         Bucket *p1, *p2 = NULL;
    1487             :         int result;
    1488             :         void *pData2;
    1489             : 
    1490             :         IS_CONSISTENT(ht1);
    1491             :         IS_CONSISTENT(ht2);
    1492             : 
    1493        1165 :         HASH_PROTECT_RECURSION(ht1); 
    1494        1165 :         HASH_PROTECT_RECURSION(ht2); 
    1495             : 
    1496        1165 :         result = ht1->nNumOfElements - ht2->nNumOfElements;
    1497        1165 :         if (result!=0) {
    1498         549 :                 HASH_UNPROTECT_RECURSION(ht1); 
    1499         549 :                 HASH_UNPROTECT_RECURSION(ht2); 
    1500         549 :                 return result;
    1501             :         }
    1502             : 
    1503         616 :         p1 = ht1->pListHead;
    1504         616 :         if (ordered) {
    1505          62 :                 p2 = ht2->pListHead;
    1506             :         }
    1507             : 
    1508        5055 :         while (p1) {
    1509        3995 :                 if (ordered && !p2) {
    1510           0 :                         HASH_UNPROTECT_RECURSION(ht1); 
    1511           0 :                         HASH_UNPROTECT_RECURSION(ht2); 
    1512           0 :                         return 1; /* That's not supposed to happen */
    1513             :                 }
    1514        3995 :                 if (ordered) {
    1515        1492 :                         if (p1->nKeyLength==0 && p2->nKeyLength==0) { /* numeric indices */
    1516         364 :                                 result = p1->h - p2->h;
    1517         364 :                                 if (result!=0) {
    1518           1 :                                         HASH_UNPROTECT_RECURSION(ht1); 
    1519           1 :                                         HASH_UNPROTECT_RECURSION(ht2); 
    1520           1 :                                         return result;
    1521             :                                 }
    1522             :                         } else { /* string indices */
    1523         765 :                                 result = p1->nKeyLength - p2->nKeyLength;
    1524         765 :                                 if (result!=0) {
    1525           0 :                                         HASH_UNPROTECT_RECURSION(ht1); 
    1526           0 :                                         HASH_UNPROTECT_RECURSION(ht2); 
    1527           0 :                                         return result;
    1528             :                                 }
    1529         765 :                                 result = memcmp(p1->arKey, p2->arKey, p1->nKeyLength);
    1530         765 :                                 if (result!=0) {
    1531           0 :                                         HASH_UNPROTECT_RECURSION(ht1); 
    1532           0 :                                         HASH_UNPROTECT_RECURSION(ht2); 
    1533           0 :                                         return result;
    1534             :                                 }
    1535             :                         }
    1536        1128 :                         pData2 = p2->pData;
    1537             :                 } else {
    1538        2866 :                         if (p1->nKeyLength==0) { /* numeric index */
    1539         231 :                                 if (zend_hash_index_find(ht2, p1->h, &pData2)==FAILURE) {
    1540           4 :                                         HASH_UNPROTECT_RECURSION(ht1); 
    1541           4 :                                         HASH_UNPROTECT_RECURSION(ht2); 
    1542           4 :                                         return 1;
    1543             :                                 }
    1544             :                         } else { /* string index */
    1545        2635 :                                 if (zend_hash_quick_find(ht2, p1->arKey, p1->nKeyLength, p1->h, &pData2)==FAILURE) {
    1546          22 :                                         HASH_UNPROTECT_RECURSION(ht1); 
    1547          22 :                                         HASH_UNPROTECT_RECURSION(ht2); 
    1548          22 :                                         return 1;
    1549             :                                 }
    1550             :                         }
    1551             :                 }
    1552        3968 :                 result = compar(p1->pData, pData2 TSRMLS_CC);
    1553        3968 :                 if (result!=0) {
    1554         145 :                         HASH_UNPROTECT_RECURSION(ht1); 
    1555         145 :                         HASH_UNPROTECT_RECURSION(ht2); 
    1556         145 :                         return result;
    1557             :                 }
    1558        3823 :                 p1 = p1->pListNext;
    1559        3823 :                 if (ordered) {
    1560        1124 :                         p2 = p2->pListNext;
    1561             :                 }
    1562             :         }
    1563             :         
    1564         444 :         HASH_UNPROTECT_RECURSION(ht1); 
    1565         444 :         HASH_UNPROTECT_RECURSION(ht2); 
    1566         444 :         return 0;
    1567             : }
    1568             : 
    1569             : 
    1570          82 : ZEND_API int zend_hash_minmax(const HashTable *ht, compare_func_t compar, int flag, void **pData TSRMLS_DC)
    1571             : {
    1572             :         Bucket *p, *res;
    1573             : 
    1574             :         IS_CONSISTENT(ht);
    1575             : 
    1576          82 :         if (ht->nNumOfElements == 0 ) {
    1577           4 :                 *pData=NULL;
    1578           4 :                 return FAILURE;
    1579             :         }
    1580             : 
    1581          78 :         res = p = ht->pListHead;
    1582         376 :         while ((p = p->pListNext)) {
    1583         220 :                 if (flag) {
    1584         168 :                         if (compar(&res, &p TSRMLS_CC) < 0) { /* max */
    1585          20 :                                 res = p;
    1586             :                         }
    1587             :                 } else {
    1588          52 :                         if (compar(&res, &p TSRMLS_CC) > 0) { /* min */
    1589           6 :                                 res = p;
    1590             :                         }
    1591             :                 }
    1592             :         }
    1593          78 :         *pData = res->pData;
    1594          78 :         return SUCCESS;
    1595             : }
    1596             : 
    1597      639127 : ZEND_API ulong zend_hash_next_free_element(const HashTable *ht)
    1598             : {
    1599             :         IS_CONSISTENT(ht);
    1600             : 
    1601      639127 :         return ht->nNextFreeElement;
    1602             : 
    1603             : }
    1604             : 
    1605             : 
    1606             : #if ZEND_DEBUG
    1607             : void zend_hash_display_pListTail(const HashTable *ht)
    1608             : {
    1609             :         Bucket *p;
    1610             : 
    1611             :         p = ht->pListTail;
    1612             :         while (p != NULL) {
    1613             :                 zend_output_debug_string(0, "pListTail has key %s\n", p->arKey);
    1614             :                 p = p->pListLast;
    1615             :         }
    1616             : }
    1617             : 
    1618             : void zend_hash_display(const HashTable *ht)
    1619             : {
    1620             :         Bucket *p;
    1621             :         uint i;
    1622             : 
    1623             :         if (UNEXPECTED(ht->nNumOfElements == 0)) {
    1624             :                 zend_output_debug_string(0, "The hash is empty");
    1625             :                 return;
    1626             :         }
    1627             :         for (i = 0; i < ht->nTableSize; i++) {
    1628             :                 p = ht->arBuckets[i];
    1629             :                 while (p != NULL) {
    1630             :                         zend_output_debug_string(0, "%s <==> 0x%lX\n", p->arKey, p->h);
    1631             :                         p = p->pNext;
    1632             :                 }
    1633             :         }
    1634             : 
    1635             :         p = ht->pListTail;
    1636             :         while (p != NULL) {
    1637             :                 zend_output_debug_string(0, "%s <==> 0x%lX\n", p->arKey, p->h);
    1638             :                 p = p->pListLast;
    1639             :         }
    1640             : }
    1641             : #endif
    1642             : 
    1643             : /*
    1644             :  * Local variables:
    1645             :  * tab-width: 4
    1646             :  * c-basic-offset: 4
    1647             :  * indent-tabs-mode: t
    1648             :  * End:
    1649             :  */

Generated by: LCOV version 1.10

Generated at Thu, 16 Oct 2014 05:26:59 +0000 (6 days ago)

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