PHP  
 PHP: Test and Code Coverage Analysis
downloads | QA | documentation | faq | getting help | mailing lists | reporting bugs | php.net sites | links | my php.net 
 

LTP GCOV extension - code coverage report
Current view: directory - var/php_gcov/PHP_HEAD/Zend - zend_hash.c
Test: PHP Code Coverage
Date: 2009-11-23 Instrumented lines: 989
Code covered: 85.6 % Executed lines: 847
Legend: not executed executed

       1                 : /*
       2                 :    +----------------------------------------------------------------------+
       3                 :    | Zend Engine                                                          |
       4                 :    +----------------------------------------------------------------------+
       5                 :    | Copyright (c) 1998-2009 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: zend_hash.c 281777 2009-06-07 19:28:02Z mattwil $ */
      21                 : 
      22                 : #include "zend.h"
      23                 : #include "zend_operators.h"
      24                 : #include "zend_globals.h"
      25                 : 
      26                 : #include <unicode/utypes.h>
      27                 : #include <unicode/uchar.h>
      28                 : 
      29                 : #define CONNECT_TO_BUCKET_DLLIST(element, list_head)            \
      30                 :         (element)->pNext = (list_head);                                                      \
      31                 :         (element)->pLast = NULL;                                                             \
      32                 :         if ((element)->pNext) {                                                                      \
      33                 :                 (element)->pNext->pLast = (element);                              \
      34                 :         }
      35                 : 
      36                 : #define CONNECT_TO_GLOBAL_DLLIST(element, ht)                           \
      37                 :         (element)->pListLast = (ht)->pListTail;                                   \
      38                 :         (ht)->pListTail = (element);                                                 \
      39                 :         (element)->pListNext = NULL;                                                 \
      40                 :         if ((element)->pListLast != NULL) {                                          \
      41                 :                 (element)->pListLast->pListNext = (element);              \
      42                 :         }                                                                                                               \
      43                 :         if (!(ht)->pListHead) {                                                                      \
      44                 :                 (ht)->pListHead = (element);                                         \
      45                 :         }                                                                                                               \
      46                 :         if ((ht)->pInternalPointer == NULL) {                                        \
      47                 :                 (ht)->pInternalPointer = (element);                                  \
      48                 :         }
      49                 : 
      50                 : #define ZEND_HASH_CVT_ERROR() zend_error(E_WARNING, "Could not convert String to Unicode")
      51                 : 
      52                 : #define UNICODE_KEY(ht, type, arKey, nKeyLength, tmp) \
      53                 :         if (ht->unicode && type == IS_STRING) { \
      54                 :                 UErrorCode status = U_ZERO_ERROR; \
      55                 :                 UChar *u = NULL; \
      56                 :                 int u_len; \
      57                 :                 TSRMLS_FETCH(); \
      58                 :                 zend_string_to_unicode_ex(ZEND_U_CONVERTER(UG(runtime_encoding_conv)), &u, &u_len, arKey.s, nKeyLength-1, &status); \
      59                 :                 if (U_FAILURE(status)) { \
      60                 :                         ZEND_HASH_CVT_ERROR(); \
      61                 :                 } else { \
      62                 :                         type = IS_UNICODE; \
      63                 :                         tmp = arKey.u = u; \
      64                 :                         nKeyLength = u_len + 1; \
      65                 :                 } \
      66                 :         }
      67                 : 
      68                 : 
      69                 : #if ZEND_DEBUG
      70                 : #define HT_OK                           0
      71                 : #define HT_IS_DESTROYING        1
      72                 : #define HT_DESTROYED            2
      73                 : #define HT_CLEANING                     3
      74                 : 
      75                 : static void _zend_is_inconsistent(const HashTable *ht, const char *file, int line) /* {{{ */
      76                 : {
      77                 :         if (ht->inconsistent==HT_OK) {
      78                 :                 return;
      79                 :         }
      80                 :         switch (ht->inconsistent) {
      81                 :                 case HT_IS_DESTROYING:
      82                 :                         zend_output_debug_string(1, "%s(%d) : ht=%p is being destroyed", file, line, ht);
      83                 :                         break;
      84                 :                 case HT_DESTROYED:
      85                 :                         zend_output_debug_string(1, "%s(%d) : ht=%p is already destroyed", file, line, ht);
      86                 :                         break;
      87                 :                 case HT_CLEANING:
      88                 :                         zend_output_debug_string(1, "%s(%d) : ht=%p is being cleaned", file, line, ht);
      89                 :                         break;
      90                 :         }
      91                 :         zend_bailout();
      92                 : }
      93                 : /* }}} */
      94                 : 
      95                 : #define IS_CONSISTENT(a) _zend_is_inconsistent(a, __FILE__, __LINE__);
      96                 : #define SET_INCONSISTENT(n) ht->inconsistent = n;
      97                 : #else
      98                 : #define IS_CONSISTENT(a)
      99                 : #define SET_INCONSISTENT(n)
     100                 : #endif
     101                 : 
     102                 : #define HASH_PROTECT_RECURSION(ht)                                                                                                              \
     103                 :         if ((ht)->bApplyProtection) {                                                                                                                \
     104                 :                 if ((ht)->nApplyCount++ >= 3) {                                                                                                   \
     105                 :                         zend_error(E_ERROR, "Nesting level too deep - recursive dependency?");                \
     106                 :                 }                                                                                                                                                               \
     107                 :         }
     108                 : 
     109                 : 
     110                 : #define HASH_UNPROTECT_RECURSION(ht)                                                                                                    \
     111                 :         if ((ht)->bApplyProtection) {                                                                                                                \
     112                 :                 (ht)->nApplyCount--;                                                                                                                 \
     113                 :         }
     114                 : 
     115                 : 
     116                 : #define ZEND_HASH_IF_FULL_DO_RESIZE(ht)                         \
     117                 :         if ((ht)->nNumOfElements > (ht)->nTableSize) { \
     118                 :                 zend_hash_do_resize(ht);                                        \
     119                 :         }
     120                 : 
     121                 : static int zend_hash_do_resize(HashTable *ht);
     122                 : 
     123                 : #define UPDATE_DATA(ht, p, pData, nDataSize)                                                                                    \
     124                 :         if (nDataSize == sizeof(void*)) {                                                                                                       \
     125                 :                 if ((p)->pData != &(p)->pDataPtr) {                                                                                           \
     126                 :                         pefree_rel(p->pData, ht->persistent);                                                                             \
     127                 :                 }                                                                                                                                                               \
     128                 :                 memcpy(&(p)->pDataPtr, pData, sizeof(void *));                                                                   \
     129                 :                 (p)->pData = &(p)->pDataPtr;                                                                                                  \
     130                 :         } else {                                                                                                                                                        \
     131                 :                 if ((p)->pData == &(p)->pDataPtr) {                                                                                           \
     132                 :                         (p)->pData = (void *) pemalloc_rel(nDataSize, (ht)->persistent);                  \
     133                 :                 } else {                                                                                                                                                \
     134                 :                         (p)->pData = (void *) perealloc_rel((p)->pData, nDataSize, (ht)->persistent);  \
     135                 :                 }                                                                                                                                                               \
     136                 :                 memcpy((p)->pData, pData, nDataSize);                                                                                        \
     137                 :         }
     138                 : 
     139                 : #define INIT_DATA(ht, p, pData, nDataSize);                                                             \
     140                 :         if (nDataSize == sizeof(void*)) {                                                                       \
     141                 :                 memcpy(&(p)->pDataPtr, pData, sizeof(void *));                                   \
     142                 :                 (p)->pData = &(p)->pDataPtr;                                                                  \
     143                 :         } else {                                                                                                                        \
     144                 :                 (p)->pData = (void *) pemalloc_rel(nDataSize, (ht)->persistent);  \
     145                 :                 if (!(p)->pData) {                                                                                           \
     146                 :                         pefree_rel(p, (ht)->persistent);                                                             \
     147                 :                         return FAILURE;                                                                                         \
     148                 :                 }                                                                                                                               \
     149                 :                 memcpy((p)->pData, pData, nDataSize);                                                        \
     150                 :         }
     151                 : /* }}} */
     152                 : 
     153                 : ZEND_API int _zend_u_hash_init(HashTable *ht, uint nSize, hash_func_t pHashFunction, dtor_func_t pDestructor, zend_bool persistent, zend_bool unicode ZEND_FILE_LINE_DC) /* {{{ */
     154        20465145 : {
     155        20465145 :         uint i = 3;
     156                 :         Bucket **tmp;
     157                 : 
     158                 :         SET_INCONSISTENT(HT_OK);
     159                 : 
     160        20465145 :         if (nSize >= 0x80000000) {
     161                 :                 /* prevent overflow */
     162               0 :                 ht->nTableSize = 0x80000000;
     163                 :         } else {
     164        41664384 :                 while ((1U << i) < nSize) {
     165          734094 :                         i++;
     166                 :                 }
     167        20465145 :                 ht->nTableSize = 1 << i;
     168                 :         }
     169                 : 
     170        20465145 :         ht->nTableMask = ht->nTableSize - 1;
     171        20465145 :         ht->pDestructor = pDestructor;
     172        20465145 :         ht->arBuckets = NULL;
     173        20465145 :         ht->pListHead = NULL;
     174        20465145 :         ht->pListTail = NULL;
     175        20465145 :         ht->nNumOfElements = 0;
     176        20465145 :         ht->nNextFreeElement = 0;
     177        20465145 :         ht->pInternalPointer = NULL;
     178        20465145 :         ht->persistent = persistent;
     179        20465145 :         ht->unicode = unicode;
     180        20465145 :         ht->nApplyCount = 0;
     181        20465145 :         ht->bApplyProtection = 1;
     182                 : 
     183                 :         /* Uses ecalloc() so that Bucket* == NULL */
     184        20465145 :         if (persistent) {
     185        14408374 :                 tmp = (Bucket **) calloc(ht->nTableSize, sizeof(Bucket *));
     186        14408374 :                 if (!tmp) {
     187               0 :                         return FAILURE;
     188                 :                 }
     189        14408374 :                 ht->arBuckets = tmp;
     190                 :         } else {
     191         6056771 :                 tmp = (Bucket **) ecalloc_rel(ht->nTableSize, sizeof(Bucket *));
     192         6056771 :                 if (tmp) {
     193         6056771 :                         ht->arBuckets = tmp;
     194                 :                 }
     195                 :         }
     196                 : 
     197        20465145 :         return SUCCESS;
     198                 : }
     199                 : /* }}} */
     200                 : 
     201                 : 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) /* {{{ */
     202         2809764 : {
     203         2809764 :         return _zend_u_hash_init(ht, nSize, pHashFunction, pDestructor, persistent, 0 ZEND_FILE_LINE_CC);
     204                 : }
     205                 : /* }}} */
     206                 : 
     207                 : 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) /* {{{ */
     208          170079 : {
     209          170079 :         int retval = _zend_hash_init(ht, nSize, pHashFunction, pDestructor, persistent ZEND_FILE_LINE_CC);
     210                 : 
     211          170079 :         ht->bApplyProtection = bApplyProtection;
     212          170079 :         return retval;
     213                 : }
     214                 : /* }}} */
     215                 : 
     216                 : ZEND_API int _zend_u_hash_init_ex(HashTable *ht, uint nSize, hash_func_t pHashFunction, dtor_func_t pDestructor, zend_bool persistent, zend_bool unicode, zend_bool bApplyProtection ZEND_FILE_LINE_DC) /* {{{ */
     217        13295740 : {
     218        13295740 :         int retval = _zend_u_hash_init(ht, nSize, pHashFunction, pDestructor, persistent, unicode ZEND_FILE_LINE_CC);
     219                 : 
     220        13295740 :         ht->bApplyProtection = bApplyProtection;
     221        13295740 :         return retval;
     222                 : }
     223                 : /* }}} */
     224                 : 
     225                 : ZEND_API void zend_hash_set_apply_protection(HashTable *ht, zend_bool bApplyProtection) /* {{{ */
     226               0 : {
     227               0 :         ht->bApplyProtection = bApplyProtection;
     228               0 : }
     229                 : /* }}} */
     230                 : 
     231                 : ZEND_API int _zend_u_hash_add_or_update(HashTable *ht, zend_uchar type, zstr arKey, uint nKeyLength, void *pData, uint nDataSize, void **pDest, int flag ZEND_FILE_LINE_DC) /* {{{ */
     232       128143295 : {
     233                 :         ulong h;
     234                 :         uint nIndex;
     235                 :         Bucket *p;
     236       128143295 :         void *tmp = NULL;
     237                 :         uint realKeyLength;
     238                 : 
     239                 :         IS_CONSISTENT(ht);
     240                 : 
     241       128143295 :         if (nKeyLength <= 0) {
     242                 : #if ZEND_DEBUG
     243                 :                 ZEND_PUTS("zend_hash_update: Can't put in empty key\n");
     244                 : #endif
     245               0 :                 return FAILURE;
     246                 :         }
     247                 : 
     248       128143295 :         UNICODE_KEY(ht, type, arKey, nKeyLength, tmp);
     249       128143295 :         realKeyLength = USTR_BYTES(type, nKeyLength);
     250                 : 
     251       128143295 :         h = zend_u_inline_hash_func(type, arKey, nKeyLength);
     252       128143295 :         nIndex = h & ht->nTableMask;
     253                 : 
     254       128143295 :         p = ht->arBuckets[nIndex];
     255       336516561 :         while (p != NULL) {
     256        80762971 :                 if ((p->h == h) &&
     257                 :                     (p->key.type == type) &&
     258                 :                     (p->nKeyLength == nKeyLength) &&
     259                 :                     !memcmp(p->key.arKey.s, arKey.s, realKeyLength)) {
     260          533000 :                         if (flag & HASH_ADD) {
     261          240090 :                                 if (tmp) efree(tmp);
     262          240090 :                                 return FAILURE;
     263                 :                         }
     264          292910 :                         HANDLE_BLOCK_INTERRUPTIONS();
     265                 : #if ZEND_DEBUG
     266                 :                         if (p->pData == pData) {
     267                 :                                 ZEND_PUTS("Fatal error in zend_hash_update: p->pData == pData\n");
     268                 :                                 HANDLE_UNBLOCK_INTERRUPTIONS();
     269                 :                                 if (tmp) efree(tmp);
     270                 :                                 return FAILURE;
     271                 :                         }
     272                 : #endif
     273          292910 :                         if (ht->pDestructor) {
     274          258618 :                                 ht->pDestructor(p->pData);
     275                 :                         }
     276          292910 :                         UPDATE_DATA(ht, p, pData, nDataSize);
     277          292910 :                         if (pDest) {
     278           86906 :                                 *pDest = p->pData;
     279                 :                         }
     280          292910 :                         HANDLE_UNBLOCK_INTERRUPTIONS();
     281          292910 :                         if (tmp) efree(tmp);
     282          292910 :                         return SUCCESS;
     283                 :                 }
     284        80229971 :                 p = p->pNext;
     285                 :         }
     286                 : 
     287       127610295 :         p = (Bucket *) pemalloc(sizeof(Bucket)-sizeof(p->key.arKey)+realKeyLength, ht->persistent);
     288       127610295 :         if (!p) {
     289               0 :                 if (tmp) efree(tmp);
     290               0 :                 return FAILURE;
     291                 :         }
     292       127610295 :         p->key.type = type;
     293       127610295 :         memcpy(p->key.arKey.s, arKey.s, realKeyLength);
     294       127610295 :         p->nKeyLength = nKeyLength;
     295       127610295 :         INIT_DATA(ht, p, pData, nDataSize);
     296       127610295 :         p->h = h;
     297       127610295 :         CONNECT_TO_BUCKET_DLLIST(p, ht->arBuckets[nIndex]);
     298       127610295 :         if (pDest) {
     299        63707588 :                 *pDest = p->pData;
     300                 :         }
     301                 : 
     302       127610295 :         HANDLE_BLOCK_INTERRUPTIONS();
     303       127610295 :         CONNECT_TO_GLOBAL_DLLIST(p, ht);
     304       127610295 :         ht->arBuckets[nIndex] = p;
     305       127610295 :         HANDLE_UNBLOCK_INTERRUPTIONS();
     306                 : 
     307       127610295 :         ht->nNumOfElements++;
     308       127610295 :         ZEND_HASH_IF_FULL_DO_RESIZE(ht);                /* If the Hash table is full, resize it */
     309       127610295 :         if (tmp) efree(tmp);
     310       127610295 :         return SUCCESS;
     311                 : }
     312                 : /* }}} */
     313                 : 
     314                 : 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) /* {{{ */
     315        15660807 : {
     316        15660807 :         return _zend_u_hash_add_or_update(ht, IS_STRING, ZSTR(arKey), nKeyLength, pData, nDataSize, pDest, flag ZEND_FILE_LINE_CC);
     317                 : }
     318                 : /* }}} */
     319                 : 
     320                 : ZEND_API int _zend_ascii_hash_add_or_update(HashTable *ht, const char *arKey, uint nKeyLength, void *pData, uint nDataSize, void **pDest, int flag ZEND_FILE_LINE_DC) /* {{{ */
     321        71111320 : {
     322                 :         zstr key;
     323                 :         int ret;
     324                 : 
     325        71111320 :         key.u = zend_ascii_to_unicode(arKey, nKeyLength ZEND_FILE_LINE_CC);
     326        71111320 :         ret = _zend_u_hash_add_or_update(ht, IS_UNICODE, key, nKeyLength, pData, nDataSize, pDest, flag ZEND_FILE_LINE_CC);
     327        71111320 :         efree(key.u);
     328        71111320 :         return ret;
     329                 : }
     330                 : /* }}} */
     331                 : 
     332                 : ZEND_API int _zend_rt_hash_add_or_update(HashTable *ht, const char *arKey, uint nKeyLength, void *pData, uint nDataSize, void **pDest, int flag ZEND_FILE_LINE_DC) /* {{{ */
     333            1281 : {
     334                 :         zstr key;
     335                 :         int ret;
     336            1281 :         UErrorCode status = U_ZERO_ERROR;
     337                 :         int u_len;
     338                 :         TSRMLS_FETCH();
     339                 : 
     340            1281 :         zend_string_to_unicode_ex(ZEND_U_CONVERTER(UG(runtime_encoding_conv)), &key.u, &u_len, arKey, nKeyLength-1, &status);
     341            1281 :         if (U_FAILURE(status)) {
     342               0 :                 ZEND_HASH_CVT_ERROR();
     343               0 :                 return _zend_u_hash_add_or_update(ht, IS_STRING, ZSTR(arKey), nKeyLength, pData, nDataSize, pDest, flag ZEND_FILE_LINE_CC);
     344                 :         }
     345                 : 
     346            1281 :         ret = _zend_u_hash_add_or_update(ht, IS_UNICODE, key, u_len+1, pData, nDataSize, pDest, flag ZEND_FILE_LINE_CC);
     347            1281 :         efree(key.u);
     348            1281 :         return ret;     
     349                 : }
     350                 : /* }}} */
     351                 : 
     352                 : ZEND_API int _zend_utf8_hash_add_or_update(HashTable *ht, const char *arKey, uint nKeyLength, void *pData, uint nDataSize, void **pDest, int flag ZEND_FILE_LINE_DC) /* {{{ */
     353             308 : {
     354                 :         zstr key;
     355                 :         int ret;
     356             308 :         UErrorCode status = U_ZERO_ERROR;
     357                 :         int u_len;
     358                 :         TSRMLS_FETCH();
     359                 : 
     360             308 :         zend_string_to_unicode_ex(ZEND_U_CONVERTER(UG(utf8_conv)), &key.u, &u_len, arKey, nKeyLength-1, &status);
     361             308 :         if (U_FAILURE(status)) {
     362               0 :                 ZEND_HASH_CVT_ERROR();
     363               0 :                 return _zend_u_hash_add_or_update(ht, IS_STRING, ZSTR(arKey), nKeyLength, pData, nDataSize, pDest, flag ZEND_FILE_LINE_CC);
     364                 :         }
     365                 : 
     366             308 :         ret = _zend_u_hash_add_or_update(ht, IS_UNICODE, key, u_len+1, pData, nDataSize, pDest, flag ZEND_FILE_LINE_CC);
     367             308 :         efree(key.u);
     368             308 :         return ret;
     369                 : }
     370                 : /* }}} */
     371                 : 
     372                 : ZEND_API int _zend_u_hash_quick_add_or_update(HashTable *ht, zend_uchar type, zstr arKey, uint nKeyLength, ulong h, void *pData, uint nDataSize, void **pDest, int flag ZEND_FILE_LINE_DC) /* {{{ */
     373        31369592 : {
     374                 :         uint nIndex;
     375                 :         Bucket *p;
     376        31369592 :         void *tmp = NULL;
     377                 :         uint realKeyLength;
     378                 : 
     379                 :         IS_CONSISTENT(ht);
     380                 : 
     381        31369592 :         if (nKeyLength == 0) {
     382               0 :                 return zend_hash_index_update(ht, h, pData, nDataSize, pDest);
     383                 :         }
     384                 : 
     385        31369592 :         if (ht->unicode && type == IS_STRING) {
     386           18207 :                 UNICODE_KEY(ht, type, arKey, nKeyLength, tmp);
     387           18207 :                 h = zend_u_inline_hash_func(IS_UNICODE, arKey, nKeyLength);
     388                 :         }
     389        31369592 :         realKeyLength = USTR_BYTES(type, nKeyLength);
     390                 : 
     391        31369592 :         nIndex = h & ht->nTableMask;
     392                 : 
     393        31369592 :         p = ht->arBuckets[nIndex];
     394        79871985 :         while (p != NULL) {
     395        17135935 :                 if ((p->h == h) &&
     396                 :                     (p->key.type == type) &&
     397                 :                     (p->nKeyLength == nKeyLength) &&
     398                 :                     !memcmp(p->key.arKey.s, arKey.s, realKeyLength)) {
     399            3134 :                         if (flag & HASH_ADD) {
     400             641 :                                 if (tmp) efree(tmp);
     401             641 :                                 return FAILURE;
     402                 :                         }
     403            2493 :                         HANDLE_BLOCK_INTERRUPTIONS();
     404                 : #if ZEND_DEBUG
     405                 :                         if (p->pData == pData) {
     406                 :                                 ZEND_PUTS("Fatal error in zend_hash_update: p->pData == pData\n");
     407                 :                                 HANDLE_UNBLOCK_INTERRUPTIONS();
     408                 :                                 if (tmp) efree(tmp);
     409                 :                                 return FAILURE;
     410                 :                         }
     411                 : #endif
     412            2493 :                         if (ht->pDestructor) {
     413            2493 :                                 ht->pDestructor(p->pData);
     414                 :                         }
     415            2493 :                         UPDATE_DATA(ht, p, pData, nDataSize);
     416            2493 :                         if (pDest) {
     417             478 :                                 *pDest = p->pData;
     418                 :                         }
     419            2493 :                         HANDLE_UNBLOCK_INTERRUPTIONS();
     420            2493 :                         if (tmp) efree(tmp);
     421            2493 :                         return SUCCESS;
     422                 :                 }
     423        17132801 :                 p = p->pNext;
     424                 :         }
     425                 : 
     426        31366458 :         p = (Bucket *) pemalloc(sizeof(Bucket)-sizeof(p->key.arKey)+realKeyLength, ht->persistent);
     427        31366458 :         if (!p) {
     428               0 :                 if (tmp) efree(tmp);
     429               0 :                 return FAILURE;
     430                 :         }
     431                 : 
     432        31366458 :         p->key.type = type;
     433        31366458 :         memcpy(p->key.arKey.s, arKey.s, realKeyLength);
     434        31366458 :         p->nKeyLength = nKeyLength;
     435        31366458 :         INIT_DATA(ht, p, pData, nDataSize);
     436        31366458 :         p->h = h;
     437                 : 
     438        31366458 :         CONNECT_TO_BUCKET_DLLIST(p, ht->arBuckets[nIndex]);
     439                 : 
     440        31366458 :         if (pDest) {
     441        31316754 :                 *pDest = p->pData;
     442                 :         }
     443                 : 
     444        31366458 :         HANDLE_BLOCK_INTERRUPTIONS();
     445        31366458 :         ht->arBuckets[nIndex] = p;
     446        31366458 :         CONNECT_TO_GLOBAL_DLLIST(p, ht);
     447        31366458 :         HANDLE_UNBLOCK_INTERRUPTIONS();
     448                 : 
     449        31366458 :         ht->nNumOfElements++;
     450        31366458 :         ZEND_HASH_IF_FULL_DO_RESIZE(ht);                /* If the Hash table is full, resize it */
     451        31366458 :         if (tmp) efree(tmp);
     452        31366458 :         return SUCCESS;
     453                 : }
     454                 : /* }}} */
     455                 : 
     456                 : 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) /* {{{ */
     457           18246 : {
     458           18246 :         return _zend_u_hash_quick_add_or_update(ht, IS_STRING, ZSTR(arKey), nKeyLength, h, pData, nDataSize, pDest, flag ZEND_FILE_LINE_CC);
     459                 : }
     460                 : /* }}} */
     461                 : 
     462                 : ZEND_API int zend_u_hash_add_empty_element(HashTable *ht, zend_uchar type, zstr arKey, uint nKeyLength) /* {{{ */
     463               0 : {
     464               0 :         void *dummy = (void *) 1;
     465                 : 
     466               0 :         return zend_u_hash_add(ht, type, arKey, nKeyLength, &dummy, sizeof(void *), NULL);
     467                 : }
     468                 : /* }}} */
     469                 : 
     470                 : ZEND_API int zend_hash_add_empty_element(HashTable *ht, const char *arKey, uint nKeyLength) /* {{{ */
     471           26968 : {
     472           26968 :         void *dummy = (void *) 1;
     473                 : 
     474           26968 :         return zend_u_hash_add(ht, IS_STRING, ZSTR(arKey), nKeyLength, &dummy, sizeof(void *), NULL);
     475                 : }
     476                 : /* }}} */
     477                 : 
     478                 : 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) /* {{{ */
     479        10242172 : {
     480                 :         uint nIndex;
     481                 :         Bucket *p;
     482                 : 
     483                 :         IS_CONSISTENT(ht);
     484                 : 
     485        10242172 :         if (flag & HASH_NEXT_INSERT) {
     486         4432034 :                 h = ht->nNextFreeElement;
     487                 :         }
     488        10242172 :         nIndex = h & ht->nTableMask;
     489                 : 
     490        10242172 :         p = ht->arBuckets[nIndex];
     491        21160607 :         while (p != NULL) {
     492          685957 :                 if ((p->nKeyLength == 0) && (p->h == h)) {
     493            9694 :                         if (flag & HASH_NEXT_INSERT || flag & HASH_ADD) {
     494               2 :                                 return FAILURE;
     495                 :                         }
     496            9692 :                         HANDLE_BLOCK_INTERRUPTIONS();
     497                 : #if ZEND_DEBUG
     498                 :                         if (p->pData == pData) {
     499                 :                                 ZEND_PUTS("Fatal error in zend_hash_index_update: p->pData == pData\n");
     500                 :                                 HANDLE_UNBLOCK_INTERRUPTIONS();
     501                 :                                 return FAILURE;
     502                 :                         }
     503                 : #endif
     504            9692 :                         if (ht->pDestructor) {
     505            9692 :                                 ht->pDestructor(p->pData);
     506                 :                         }
     507            9692 :                         UPDATE_DATA(ht, p, pData, nDataSize);
     508            9692 :                         HANDLE_UNBLOCK_INTERRUPTIONS();
     509            9692 :                         if ((long)h >= (long)ht->nNextFreeElement) {
     510               2 :                                 ht->nNextFreeElement = h < LONG_MAX ? h + 1 : LONG_MAX;
     511                 :                         }
     512            9692 :                         if (pDest) {
     513            4931 :                                 *pDest = p->pData;
     514                 :                         }
     515            9692 :                         return SUCCESS;
     516                 :                 }
     517          676263 :                 p = p->pNext;
     518                 :         }
     519        10232478 :         p = (Bucket *) pemalloc_rel(sizeof(Bucket) - sizeof(p->key.arKey), ht->persistent);
     520        10232478 :         if (!p) {
     521               0 :                 return FAILURE;
     522                 :         }
     523        10232478 :         p->nKeyLength = 0; /* Numeric indices are marked by making the nKeyLength == 0 */
     524        10232478 :         p->h = h;
     525        10232478 :         INIT_DATA(ht, p, pData, nDataSize);
     526        10232478 :         if (pDest) {
     527         5238622 :                 *pDest = p->pData;
     528                 :         }
     529                 : 
     530        10232478 :         p->key.type = IS_LONG;
     531                 : 
     532        10232478 :         CONNECT_TO_BUCKET_DLLIST(p, ht->arBuckets[nIndex]);
     533                 : 
     534        10232478 :         HANDLE_BLOCK_INTERRUPTIONS();
     535        10232478 :         ht->arBuckets[nIndex] = p;
     536        10232478 :         CONNECT_TO_GLOBAL_DLLIST(p, ht);
     537        10232478 :         HANDLE_UNBLOCK_INTERRUPTIONS();
     538                 : 
     539        10232478 :         if ((long)h >= (long)ht->nNextFreeElement) {
     540         9191105 :                 ht->nNextFreeElement = h < LONG_MAX ? h + 1 : LONG_MAX;
     541                 :         }
     542        10232478 :         ht->nNumOfElements++;
     543        10232478 :         ZEND_HASH_IF_FULL_DO_RESIZE(ht);
     544        10232478 :         return SUCCESS;
     545                 : }
     546                 : /* }}} */
     547                 : 
     548                 : static int zend_hash_do_resize(HashTable *ht) /* {{{ */
     549         4716207 : {
     550                 :         Bucket **t;
     551                 : 
     552                 :         IS_CONSISTENT(ht);
     553                 : 
     554         4716207 :         if ((ht->nTableSize << 1) > 0) {    /* Let's double the table size */
     555         4716207 :                 t = (Bucket **) perealloc_recoverable(ht->arBuckets, (ht->nTableSize << 1) * sizeof(Bucket *), ht->persistent);
     556         4716207 :                 if (t) {
     557         4716207 :                         HANDLE_BLOCK_INTERRUPTIONS();
     558         4716207 :                         ht->arBuckets = t;
     559         4716207 :                         ht->nTableSize = (ht->nTableSize << 1);
     560         4716207 :                         ht->nTableMask = ht->nTableSize - 1;
     561         4716207 :                         zend_hash_rehash(ht);
     562         4716207 :                         HANDLE_UNBLOCK_INTERRUPTIONS();
     563         4716207 :                         return SUCCESS;
     564                 :                 }
     565               0 :                 return FAILURE;
     566                 :         }
     567               0 :         return SUCCESS;
     568                 : }
     569                 : /* }}} */
     570                 : 
     571                 : ZEND_API int zend_hash_rehash(HashTable *ht) /* {{{ */
     572         4806601 : {
     573                 :         Bucket *p;
     574                 :         uint nIndex;
     575                 : 
     576                 :         IS_CONSISTENT(ht);
     577                 : 
     578         4806601 :         memset(ht->arBuckets, 0, ht->nTableSize * sizeof(Bucket *));
     579         4806601 :         p = ht->pListHead;
     580       157553625 :         while (p != NULL) {
     581       147940423 :                 nIndex = p->h & ht->nTableMask;
     582       147940423 :                 CONNECT_TO_BUCKET_DLLIST(p, ht->arBuckets[nIndex]);
     583       147940423 :                 ht->arBuckets[nIndex] = p;
     584       147940423 :                 p = p->pListNext;
     585                 :         }
     586         4806601 :         return SUCCESS;
     587                 : }
     588                 : /* }}} */
     589                 : 
     590                 : ZEND_API int zend_u_hash_del_key_or_index(HashTable *ht, zend_uchar type, zstr arKey, uint nKeyLength, ulong h, int flag) /* {{{ */
     591        35753281 : {
     592                 :         uint nIndex;
     593                 :         Bucket *p;
     594        35753281 :         void *tmp = NULL;
     595                 : 
     596                 :         IS_CONSISTENT(ht);
     597                 : 
     598        35753281 :         if (flag == HASH_DEL_KEY) {
     599        35241538 :                 UNICODE_KEY(ht, type, arKey, nKeyLength, tmp);
     600        35241538 :                 h = zend_u_inline_hash_func(type, arKey, nKeyLength);
     601                 :         }
     602        35753281 :         nIndex = h & ht->nTableMask;
     603                 : 
     604        35753281 :         p = ht->arBuckets[nIndex];
     605        77080123 :         while (p != NULL) {
     606        41097372 :                 if ((p->h == h)
     607                 :                         && (p->nKeyLength == nKeyLength)
     608                 :                     && ((p->nKeyLength == 0) /* Numeric index (short circuits the memcmp()) */
     609                 :                                 || ((p->key.type == type)
     610                 :                                 && !memcmp(p->key.arKey.s, arKey.s, USTR_BYTES(type, nKeyLength))))) {
     611        35523811 :                         HANDLE_BLOCK_INTERRUPTIONS();
     612        35523811 :                         if (p == ht->arBuckets[nIndex]) {
     613        30581664 :                                 ht->arBuckets[nIndex] = p->pNext;
     614                 :                         } else {
     615         4942147 :                                 p->pLast->pNext = p->pNext;
     616                 :                         }
     617        35523811 :                         if (p->pNext) {
     618         9139657 :                                 p->pNext->pLast = p->pLast;
     619                 :                         }
     620        35523811 :                         if (p->pListLast != NULL) {
     621        34567468 :                                 p->pListLast->pListNext = p->pListNext;
     622                 :                         } else {
     623                 :                                 /* Deleting the head of the list */
     624          956343 :                                 ht->pListHead = p->pListNext;
     625                 :                         }
     626        35523811 :                         if (p->pListNext != NULL) {
     627        35045569 :                                 p->pListNext->pListLast = p->pListLast;
     628                 :                         } else {
     629          478242 :                                 ht->pListTail = p->pListLast;
     630                 :                         }
     631        35523811 :                         if (ht->pInternalPointer == p) {
     632          956296 :                                 ht->pInternalPointer = p->pListNext;
     633                 :                         }
     634        35523811 :                         if (ht->pDestructor) {
     635        34995211 :                                 ht->pDestructor(p->pData);
     636                 :                         }
     637        35523809 :                         if (p->pData != &p->pDataPtr) {
     638        34970245 :                                 pefree(p->pData, ht->persistent);
     639                 :                         }
     640        35523809 :                         pefree(p, ht->persistent);
     641        35523809 :                         HANDLE_UNBLOCK_INTERRUPTIONS();
     642        35523809 :                         ht->nNumOfElements--;
     643        35523809 :                         if (tmp) efree(tmp);
     644        35523809 :                         return SUCCESS;
     645                 :                 }
     646         5573561 :                 p = p->pNext;
     647                 :         }
     648          229470 :         if (tmp) efree(tmp);
     649          229470 :         return FAILURE;
     650                 : }
     651                 : /* }}} */
     652                 : 
     653                 : ZEND_API int zend_hash_del_key_or_index(HashTable *ht, const char *arKey, uint nKeyLength, ulong h, int flag) /* {{{ */
     654         1173662 : {
     655         1173662 :         return zend_u_hash_del_key_or_index(ht, IS_STRING, ZSTR(arKey), nKeyLength, h, flag);
     656                 : }
     657                 : /* }}} */
     658                 : 
     659                 : ZEND_API int zend_ascii_hash_del(HashTable *ht, const char *arKey, uint nKeyLength) /* {{{ */
     660        34384943 : {
     661                 :         zstr key;
     662                 :         int ret;
     663                 : 
     664        34384943 :         key.u = zend_ascii_to_unicode(arKey, nKeyLength ZEND_FILE_LINE_CC);
     665        34384943 :         ret = zend_u_hash_del_key_or_index(ht, IS_UNICODE, key, nKeyLength, 0, HASH_DEL_KEY);
     666        34384943 :         efree(key.u);
     667        34384943 :         return ret;
     668                 : }
     669                 : /* }}} */
     670                 : 
     671                 : ZEND_API int zend_rt_hash_del(HashTable *ht, const char *arKey, uint nKeyLength) /* {{{ */
     672               0 : {
     673                 :         zstr key;
     674                 :         int ret;
     675               0 :         UErrorCode status = U_ZERO_ERROR;
     676                 :         int u_len;
     677                 :         TSRMLS_FETCH();
     678                 : 
     679               0 :         zend_string_to_unicode_ex(ZEND_U_CONVERTER(UG(runtime_encoding_conv)), &key.u, &u_len, arKey, nKeyLength-1, &status);
     680               0 :         if (U_FAILURE(status)) {
     681               0 :                 ZEND_HASH_CVT_ERROR();
     682               0 :                 return zend_u_hash_del_key_or_index(ht, IS_STRING, ZSTR(arKey), nKeyLength, 0, HASH_DEL_KEY);
     683                 :         }
     684               0 :         ret = zend_u_hash_del_key_or_index(ht, IS_UNICODE, key, u_len+1, 0, HASH_DEL_KEY);
     685               0 :         efree(key.u);
     686               0 :         return ret;
     687                 :         
     688                 : }
     689                 : /* }}} */
     690                 : 
     691                 : ZEND_API int zend_utf8_hash_del(HashTable *ht, const char *arKey, uint nKeyLength) /* {{{ */
     692               0 : {
     693                 :         zstr key;
     694                 :         int ret;
     695               0 :         UErrorCode status = U_ZERO_ERROR;
     696                 :         int u_len;
     697                 :         TSRMLS_FETCH();
     698                 : 
     699               0 :         zend_string_to_unicode_ex(ZEND_U_CONVERTER(UG(utf8_conv)), &key.u, &u_len, arKey, nKeyLength-1, &status);
     700               0 :         if (U_FAILURE(status)) {
     701               0 :                 ZEND_HASH_CVT_ERROR();
     702               0 :                 return zend_u_hash_del_key_or_index(ht, IS_STRING, ZSTR(arKey), nKeyLength, 0, HASH_DEL_KEY);
     703                 :         }
     704               0 :         ret = zend_u_hash_del_key_or_index(ht, IS_UNICODE, key, u_len+1, 0, HASH_DEL_KEY);
     705               0 :         efree(key.u);
     706               0 :         return ret;
     707                 : }
     708                 : /* }}} */
     709                 : 
     710                 : ZEND_API void zend_hash_destroy(HashTable *ht) /* {{{ */
     711        20423819 : {
     712                 :         Bucket *p, *q;
     713                 : 
     714                 :         IS_CONSISTENT(ht);
     715                 : 
     716                 :         SET_INCONSISTENT(HT_IS_DESTROYING);
     717                 : 
     718        20423819 :         p = ht->pListHead;
     719       168486867 :         while (p != NULL) {
     720       127639229 :                 q = p;
     721       127639229 :                 p = p->pListNext;
     722       127639229 :                 if (ht->pDestructor) {
     723       111768642 :                         ht->pDestructor(q->pData);
     724                 :                 }
     725       127639229 :                 if (q->pData != &q->pDataPtr) {
     726        87557040 :                         pefree(q->pData, ht->persistent);
     727                 :                 }
     728       127639229 :                 pefree(q, ht->persistent);
     729                 :         }
     730        20423819 :         pefree(ht->arBuckets, ht->persistent);
     731                 : 
     732                 :         SET_INCONSISTENT(HT_DESTROYED);
     733        20423819 : }
     734                 : /* }}} */
     735                 : 
     736                 : ZEND_API void zend_hash_clean(HashTable *ht) /* {{{ */
     737           57100 : {
     738                 :         Bucket *p, *q;
     739                 : 
     740                 :         IS_CONSISTENT(ht);
     741                 : 
     742                 :         SET_INCONSISTENT(HT_CLEANING);
     743                 : 
     744           57100 :         p = ht->pListHead;
     745         1222406 :         while (p != NULL) {
     746         1108206 :                 q = p;
     747         1108206 :                 p = p->pListNext;
     748         1108206 :                 if (ht->pDestructor) {
     749         1087193 :                         ht->pDestructor(q->pData);
     750                 :                 }
     751         1108206 :                 if (q->pData != &q->pDataPtr) {
     752               0 :                         pefree(q->pData, ht->persistent);
     753                 :                 }
     754         1108206 :                 pefree(q, ht->persistent);
     755                 :         }
     756           57100 :         memset(ht->arBuckets, 0, ht->nTableSize*sizeof(Bucket *));
     757           57100 :         ht->pListHead = NULL;
     758           57100 :         ht->pListTail = NULL;
     759           57100 :         ht->nNumOfElements = 0;
     760           57100 :         ht->nNextFreeElement = 0;
     761           57100 :         ht->pInternalPointer = NULL;
     762                 : 
     763                 :         SET_INCONSISTENT(HT_OK);
     764           57100 : }
     765                 : /* }}} */
     766                 : 
     767                 : /* This function is used by the various apply() functions.
     768                 :  * It deletes the passed bucket, and returns the address of the
     769                 :  * next bucket.  The hash *may* be altered during that time, the
     770                 :  * returned value will still be valid.
     771                 :  */
     772                 : static Bucket *zend_hash_apply_deleter(HashTable *ht, Bucket *p) /* {{{ */
     773         5230582 : {
     774                 :         Bucket *retval;
     775                 : 
     776         5230582 :         HANDLE_BLOCK_INTERRUPTIONS();
     777         5230582 :         if (p->pLast) {
     778          361147 :                 p->pLast->pNext = p->pNext;
     779                 :         } else {
     780                 :                 uint nIndex;
     781                 : 
     782         4869435 :                 nIndex = p->h & ht->nTableMask;
     783         4869435 :                 ht->arBuckets[nIndex] = p->pNext;
     784                 :         }
     785         5230582 :         if (p->pNext) {
     786         1257494 :                 p->pNext->pLast = p->pLast;
     787                 :         } else {
     788                 :                 /* Nothing to do as this list doesn't have a tail */
     789                 :         }
     790                 : 
     791         5230582 :         if (p->pListLast != NULL) {
     792         3555191 :                 p->pListLast->pListNext = p->pListNext;
     793                 :         } else {
     794                 :                 /* Deleting the head of the list */
     795         1675391 :                 ht->pListHead = p->pListNext;
     796                 :         }
     797         5230582 :         if (p->pListNext != NULL) {
     798         3754199 :                 p->pListNext->pListLast = p->pListLast;
     799                 :         } else {
     800         1476383 :                 ht->pListTail = p->pListLast;
     801                 :         }
     802         5230582 :         if (ht->pInternalPointer == p) {
     803         1675386 :                 ht->pInternalPointer = p->pListNext;
     804                 :         }
     805         5230582 :         ht->nNumOfElements--;
     806         5230582 :         HANDLE_UNBLOCK_INTERRUPTIONS();
     807                 : 
     808         5230582 :         if (ht->pDestructor) {
     809         1561156 :                 ht->pDestructor(p->pData);
     810                 :         }
     811         5230582 :         if (p->pData != &p->pDataPtr) {
     812         4855458 :                 pefree(p->pData, ht->persistent);
     813                 :         }
     814         5230582 :         retval = p->pListNext;
     815         5230582 :         pefree(p, ht->persistent);
     816                 : 
     817         5230582 :         return retval;
     818                 : }
     819                 : /* }}} */
     820                 : 
     821                 : ZEND_API void zend_hash_graceful_destroy(HashTable *ht) /* {{{ */
     822               0 : {
     823                 :         Bucket *p;
     824                 : 
     825                 :         IS_CONSISTENT(ht);
     826                 : 
     827               0 :         p = ht->pListHead;
     828               0 :         while (p != NULL) {
     829               0 :                 p = zend_hash_apply_deleter(ht, p);
     830                 :         }
     831               0 :         pefree(ht->arBuckets, ht->persistent);
     832                 : 
     833                 :         SET_INCONSISTENT(HT_DESTROYED);
     834               0 : }
     835                 : /* }}} */
     836                 : 
     837                 : ZEND_API void zend_hash_graceful_reverse_destroy(HashTable *ht) /* {{{ */
     838           68250 : {
     839                 :         Bucket *p;
     840                 : 
     841                 :         IS_CONSISTENT(ht);
     842                 : 
     843           68250 :         p = ht->pListTail;
     844         1508895 :         while (p != NULL) {
     845         1372395 :                 zend_hash_apply_deleter(ht, p);
     846         1372395 :                 p = ht->pListTail;
     847                 :         }
     848                 : 
     849           68250 :         pefree(ht->arBuckets, ht->persistent);
     850                 : 
     851                 :         SET_INCONSISTENT(HT_DESTROYED);
     852           68250 : }
     853                 : /* }}} */
     854                 : 
     855                 : /* This is used to recurse elements and selectively delete certain entries 
     856                 :  * from a hashtable. apply_func() receives the data and decides if the entry 
     857                 :  * should be deleted or recursion should be stopped. The following three 
     858                 :  * return codes are possible:
     859                 :  * ZEND_HASH_APPLY_KEEP   - continue
     860                 :  * ZEND_HASH_APPLY_STOP   - stop iteration
     861                 :  * ZEND_HASH_APPLY_REMOVE - delete the element, combineable with the former
     862                 :  */
     863                 : 
     864                 : ZEND_API void zend_hash_apply(HashTable *ht, apply_func_t apply_func TSRMLS_DC) /* {{{ */
     865          202855 : {
     866                 :         Bucket *p;
     867                 : 
     868                 :         IS_CONSISTENT(ht);
     869                 : 
     870          202855 :         HASH_PROTECT_RECURSION(ht);
     871          202855 :         p = ht->pListHead;
     872         6860154 :         while (p != NULL) {
     873         6454445 :                 int result = apply_func(p->pData TSRMLS_CC);
     874                 :                 
     875         6454444 :                 if (result & ZEND_HASH_APPLY_REMOVE) {
     876            3465 :                         p = zend_hash_apply_deleter(ht, p);
     877                 :                 } else {
     878         6450979 :                         p = p->pListNext;
     879                 :                 }
     880         6454444 :                 if (result & ZEND_HASH_APPLY_STOP) {
     881               0 :                         break;
     882                 :                 }
     883                 :         }
     884          202854 :         HASH_UNPROTECT_RECURSION(ht);
     885          202854 : }
     886                 : /* }}} */
     887                 : 
     888                 : ZEND_API void zend_hash_apply_with_argument(HashTable *ht, apply_func_arg_t apply_func, void *argument TSRMLS_DC) /* {{{ */
     889          672600 : {
     890                 :         Bucket *p;
     891                 : 
     892                 :         IS_CONSISTENT(ht);
     893                 : 
     894          672600 :         HASH_PROTECT_RECURSION(ht);
     895          672600 :         p = ht->pListHead;
     896        70202477 :         while (p != NULL) {
     897        68858368 :                 int result = apply_func(p->pData, argument TSRMLS_CC);
     898                 :                 
     899        68858358 :                 if (result & ZEND_HASH_APPLY_REMOVE) {
     900         3854722 :                         p = zend_hash_apply_deleter(ht, p);
     901                 :                 } else {
     902        65003636 :                         p = p->pListNext;
     903                 :                 }
     904        68858358 :                 if (result & ZEND_HASH_APPLY_STOP) {
     905            1081 :                         break;
     906                 :                 }
     907                 :         }
     908          672590 :         HASH_UNPROTECT_RECURSION(ht);
     909          672590 : }
     910                 : /* }}} */
     911                 : 
     912                 : ZEND_API void zend_hash_apply_with_arguments(HashTable *ht TSRMLS_DC, apply_func_args_t apply_func, int num_args, ...) /* {{{ */
     913         1117419 : {
     914                 :         Bucket *p;
     915                 :         va_list args;
     916                 :         zend_hash_key hash_key;
     917                 : 
     918                 :         IS_CONSISTENT(ht);
     919                 : 
     920         1117419 :         HASH_PROTECT_RECURSION(ht);
     921                 : 
     922         1117417 :         p = ht->pListHead;
     923         2455041 :         while (p != NULL) {
     924                 :                 int result;
     925          220214 :                 va_start(args, num_args);
     926          220214 :                 hash_key.nKeyLength = p->nKeyLength;
     927          220214 :                 hash_key.h = p->h;
     928          220214 :                 hash_key.type = p->key.type;
     929          220214 :                 hash_key.arKey.s = p->key.arKey.s;
     930          220214 :                 result = apply_func(p->pData TSRMLS_CC, num_args, args, &hash_key);
     931                 : 
     932          220207 :                 if (result & ZEND_HASH_APPLY_REMOVE) {
     933               0 :                         p = zend_hash_apply_deleter(ht, p);
     934                 :                 } else {
     935          220207 :                         p = p->pListNext;
     936                 :                 }
     937          220207 :                 if (result & ZEND_HASH_APPLY_STOP) {
     938               0 :                         break;
     939                 :                 }
     940          220207 :                 va_end(args);
     941                 :         }
     942                 : 
     943         1117410 :         HASH_UNPROTECT_RECURSION(ht);
     944         1117410 : }
     945                 : /* }}} */
     946                 : 
     947                 : ZEND_API void zend_hash_reverse_apply(HashTable *ht, apply_func_t apply_func TSRMLS_DC) /* {{{ */
     948          123114 : {
     949                 :         Bucket *p, *q;
     950                 : 
     951                 :         IS_CONSISTENT(ht);
     952                 : 
     953          123114 :         HASH_PROTECT_RECURSION(ht);
     954          123114 :         p = ht->pListTail;
     955         1748894 :         while (p != NULL) {
     956         1587791 :                 int result = apply_func(p->pData TSRMLS_CC);
     957                 : 
     958         1587791 :                 q = p;
     959         1587791 :                 p = p->pListLast;
     960         1587791 :                 if (result & ZEND_HASH_APPLY_REMOVE) {
     961           77354 :                         if (q->nKeyLength==0) {
     962               0 :                                 zend_hash_index_del(ht, q->h);
     963                 :                         } else {
     964           77354 :                                 zend_u_hash_del(ht, q->key.type, ZSTR(q->key.arKey.s), q->nKeyLength);
     965                 :                         }
     966                 :                 }
     967         1587791 :                 if (result & ZEND_HASH_APPLY_STOP) {
     968           85125 :                         break;
     969                 :                 }
     970                 :         }
     971          123114 :         HASH_UNPROTECT_RECURSION(ht);
     972          123114 : }
     973                 : /* }}} */
     974                 : 
     975                 : ZEND_API void zend_hash_copy(HashTable *target, HashTable *source, copy_ctor_func_t pCopyConstructor, void *tmp, uint size) /* {{{ */
     976         1521376 : {
     977                 :         Bucket *p;
     978                 :         void *new_entry;
     979                 :         zend_bool setTargetPointer;
     980                 : 
     981                 :         IS_CONSISTENT(source);
     982                 :         IS_CONSISTENT(target);
     983                 : 
     984         1521376 :         setTargetPointer = !target->pInternalPointer;
     985         1521376 :         p = source->pListHead;
     986         9462541 :         while (p) {
     987         6419789 :                 if (setTargetPointer && source->pInternalPointer == p) {
     988         1060556 :                         target->pInternalPointer = NULL;
     989                 :                 }
     990         6419789 :                 if (p->nKeyLength == 0) {
     991         3743275 :                         zend_hash_index_update(target, p->h, p->pData, size, &new_entry);
     992                 :                 } else {
     993         2676514 :                         zend_u_hash_quick_update(target, p->key.type, ZSTR(p->key.arKey.s), p->nKeyLength, p->h, p->pData, size, &new_entry);
     994                 :                 }
     995         6419789 :                 if (pCopyConstructor) {
     996         5242768 :                         pCopyConstructor(new_entry);
     997                 :                 }
     998         6419789 :                 p = p->pListNext;
     999                 :         }
    1000         1521376 :         if (!target->pInternalPointer) {
    1001          460616 :                 target->pInternalPointer = target->pListHead;
    1002                 :         }
    1003         1521376 : }
    1004                 : /* }}} */
    1005                 : 
    1006                 : 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) /* {{{ */
    1007         2316893 : {
    1008                 :         Bucket *p;
    1009                 :         void *t;
    1010         2316893 :         int mode = (overwrite?HASH_UPDATE:HASH_ADD);
    1011                 : 
    1012                 :         IS_CONSISTENT(source);
    1013                 :         IS_CONSISTENT(target);
    1014                 : 
    1015         2316893 :         p = source->pListHead;
    1016        10827660 :         while (p) {
    1017         6193874 :                 if (p->nKeyLength==0) {
    1018              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) {
    1019               6 :                                 pCopyConstructor(t);
    1020                 :                         }
    1021                 :                 } else {
    1022         6193858 :                         if (_zend_u_hash_quick_add_or_update(target, p->key.type, ZSTR(p->key.arKey.s), p->nKeyLength, p->h, p->pData, size, &t, mode ZEND_FILE_LINE_RELAY_CC)==SUCCESS && pCopyConstructor) {
    1023         3982311 :                                 pCopyConstructor(t);
    1024                 :                         }
    1025                 :                 }
    1026         6193874 :                 p = p->pListNext;
    1027                 :         }
    1028         2316893 :         target->pInternalPointer = target->pListHead;
    1029         2316893 : }
    1030                 : /* }}} */
    1031                 : 
    1032                 : static zend_bool zend_hash_replace_checker_wrapper(HashTable *target, void *source_data, Bucket *p, void *pParam, merge_checker_func_t merge_checker_func) /* {{{ */
    1033        25855404 : {
    1034                 :         zend_hash_key hash_key;
    1035                 : 
    1036        25855404 :         hash_key.nKeyLength = p->nKeyLength;
    1037        25855404 :         hash_key.h = p->h;
    1038        25855404 :         hash_key.type = p->key.type;
    1039        25855404 :         hash_key.arKey.s = p->key.arKey.s;
    1040        25855404 :         return merge_checker_func(target, source_data, &hash_key, pParam);
    1041                 : }
    1042                 : /* }}} */
    1043                 : 
    1044                 : 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) /* {{{ */
    1045         4188166 : {
    1046                 :         Bucket *p;
    1047                 :         void *t;
    1048                 : 
    1049                 :         IS_CONSISTENT(source);
    1050                 :         IS_CONSISTENT(target);
    1051                 : 
    1052         4188166 :         p = source->pListHead;
    1053        34231693 :         while (p) {
    1054        25855404 :                 if (zend_hash_replace_checker_wrapper(target, p->pData, p, pParam, pMergeSource)) {
    1055        19815978 :                         if (zend_u_hash_quick_update(target, p->key.type, ZSTR(p->key.arKey.s), p->nKeyLength, p->h, p->pData, size, &t)==SUCCESS && pCopyConstructor) {
    1056        19815978 :                                 pCopyConstructor(t);
    1057                 :                         }
    1058                 :                 }
    1059        25855361 :                 p = p->pListNext;
    1060                 :         }
    1061         4188123 :         target->pInternalPointer = target->pListHead;
    1062         4188123 : }
    1063                 : /* }}} */
    1064                 : 
    1065                 : ZEND_API ulong zend_u_get_hash_value(zend_uchar type, zstr arKey, uint nKeyLength) /* {{{ */
    1066         1806717 : {
    1067         1806717 :         return zend_u_inline_hash_func(type, arKey, nKeyLength);
    1068                 : }
    1069                 : /* }}} */
    1070                 : 
    1071                 : ZEND_API ulong zend_get_hash_value(const char *arKey, uint nKeyLength) /* {{{ */
    1072           29598 : {
    1073           29598 :         return zend_u_get_hash_value(IS_STRING, ZSTR(arKey), nKeyLength);
    1074                 : }
    1075                 : /* }}} */
    1076                 : 
    1077                 : /* Returns SUCCESS if found and FAILURE if not. The pointer to the
    1078                 :  * data is returned in pData. The reason is that there's no reason
    1079                 :  * someone using the hash table might not want to have NULL data
    1080                 :  */
    1081                 : ZEND_API int zend_u_hash_find(const HashTable *ht, zend_uchar type, zstr arKey, uint nKeyLength, void **pData) /* {{{ */
    1082        18539285 : {
    1083                 :         ulong h;
    1084                 :         uint nIndex;
    1085                 :         Bucket *p;
    1086        18539285 :         void *tmp = NULL;
    1087                 :         uint realKeyLength;
    1088                 : 
    1089                 :         IS_CONSISTENT(ht);
    1090                 : 
    1091        18539285 :         UNICODE_KEY(ht, type, arKey, nKeyLength, tmp);
    1092        18539285 :         realKeyLength = USTR_BYTES(type, nKeyLength);
    1093                 : 
    1094        18539285 :         h = zend_u_inline_hash_func(type, arKey, nKeyLength);
    1095        18539285 :         nIndex = h & ht->nTableMask;
    1096                 : 
    1097        18539285 :         p = ht->arBuckets[nIndex];
    1098        48080152 :         while (p != NULL) {
    1099        23754926 :                 if ((p->h == h) &&
    1100                 :                     (p->key.type == type) &&
    1101                 :                     (p->nKeyLength == nKeyLength) &&
    1102                 :                     !memcmp(p->key.arKey.s, arKey.s, realKeyLength)) {
    1103        12753344 :                         *pData = p->pData;
    1104        12753344 :                         if (tmp) efree(tmp);
    1105        12753344 :                         return SUCCESS;
    1106                 :                 }
    1107        11001582 :                 p = p->pNext;
    1108                 :         }
    1109         5785941 :         if (tmp) efree(tmp);
    1110         5785941 :         return FAILURE;
    1111                 : }
    1112                 : /* }}} */
    1113                 : 
    1114                 : ZEND_API int zend_hash_find(const HashTable *ht, const char *arKey, uint nKeyLength, void **pData) /* {{{ */
    1115        11918164 : {
    1116        11918164 :         return zend_u_hash_find(ht, IS_STRING, ZSTR(arKey), nKeyLength, pData);
    1117                 : }
    1118                 : /* }}} */
    1119                 : 
    1120                 : ZEND_API int zend_ascii_hash_find(const HashTable *ht, const char *arKey, uint nKeyLength, void **pData) /* {{{ */
    1121          125593 : {
    1122                 :         zstr key;
    1123                 :         int ret;
    1124                 : 
    1125          125593 :         key.u = zend_ascii_to_unicode(arKey, nKeyLength ZEND_FILE_LINE_CC);
    1126          125593 :         ret = zend_u_hash_find(ht, IS_UNICODE, key, nKeyLength, pData);
    1127          125593 :         efree(key.u);
    1128          125593 :         return ret;
    1129                 : }
    1130                 : /* }}} */
    1131                 : 
    1132                 : ZEND_API int zend_rt_hash_find(const HashTable *ht, const char *arKey, uint nKeyLength, void **pData) /* {{{ */
    1133            2118 : {
    1134                 :         zstr key;
    1135                 :         int ret;
    1136            2118 :         UErrorCode status = U_ZERO_ERROR;
    1137                 :         int u_len;
    1138                 :         TSRMLS_FETCH();
    1139                 : 
    1140            2118 :         zend_string_to_unicode_ex(ZEND_U_CONVERTER(UG(runtime_encoding_conv)), &key.u, &u_len, arKey, nKeyLength-1, &status);
    1141            2118 :         if (U_FAILURE(status)) {
    1142               0 :                 ZEND_HASH_CVT_ERROR();
    1143               0 :                 return zend_u_hash_find(ht, IS_STRING, ZSTR(arKey), nKeyLength, pData);
    1144                 :         }
    1145            2118 :         ret = zend_u_hash_find(ht, IS_UNICODE, key, u_len+1, pData);
    1146            2118 :         efree(key.u);
    1147            2118 :         return ret;
    1148                 : }
    1149                 : /* }}} */
    1150                 : 
    1151                 : ZEND_API int zend_utf8_hash_find(const HashTable *ht, const char *arKey, uint nKeyLength, void **pData) /* {{{ */
    1152              43 : {
    1153                 :         zstr key;
    1154                 :         int ret;
    1155              43 :         UErrorCode status = U_ZERO_ERROR;
    1156                 :         int u_len;
    1157                 :         TSRMLS_FETCH();
    1158                 : 
    1159              43 :         zend_string_to_unicode_ex(ZEND_U_CONVERTER(UG(utf8_conv)), &key.u, &u_len, arKey, nKeyLength-1, &status);
    1160              43 :         if (U_FAILURE(status)) {
    1161               0 :                 ZEND_HASH_CVT_ERROR();
    1162               0 :                 return zend_u_hash_find(ht, IS_STRING, ZSTR(arKey), nKeyLength, pData);
    1163                 :         }
    1164              43 :         ret = zend_u_hash_find(ht, IS_UNICODE, key, u_len+1, pData);
    1165              43 :         efree(key.u);
    1166              43 :         return ret;
    1167                 : }
    1168                 : /* }}} */
    1169                 : 
    1170                 : ZEND_API int zend_u_hash_quick_find(const HashTable *ht, zend_uchar type, zstr arKey, uint nKeyLength, ulong h, void **pData) /* {{{ */
    1171        62827461 : {
    1172                 :         uint nIndex;
    1173                 :         Bucket *p;
    1174        62827461 :         void *tmp = NULL;
    1175                 :         uint realKeyLength;
    1176                 : 
    1177        62827461 :         if (nKeyLength==0) {
    1178               0 :                 return zend_hash_index_find(ht, h, pData);
    1179                 :         }
    1180                 : 
    1181                 :         IS_CONSISTENT(ht);
    1182                 : 
    1183        62827461 :         if (ht->unicode && type == IS_STRING) {
    1184           28790 :                 UNICODE_KEY(ht, type, arKey, nKeyLength, tmp);
    1185           28790 :                 h = zend_u_inline_hash_func(IS_UNICODE, arKey, nKeyLength);
    1186                 :         }
    1187        62827461 :         realKeyLength = USTR_BYTES(type, nKeyLength);
    1188                 : 
    1189        62827461 :         nIndex = h & ht->nTableMask;
    1190                 : 
    1191        62827461 :         p = ht->arBuckets[nIndex];
    1192       143464427 :         while (p != NULL) {
    1193        58380351 :                 if ((p->h == h) &&
    1194                 :                     (p->key.type == type) &&
    1195                 :                     (p->nKeyLength == nKeyLength) &&
    1196                 :                     !memcmp(p->key.arKey.s, arKey.s, realKeyLength)) {
    1197        40570846 :                         *pData = p->pData;
    1198        40570846 :                         if (tmp) efree(tmp);
    1199        40570846 :                         return SUCCESS;
    1200                 :                 }
    1201        17809505 :                 p = p->pNext;
    1202                 :         }
    1203        22256615 :         if (tmp) efree(tmp);
    1204        22256615 :         return FAILURE;
    1205                 : }
    1206                 : /* }}} */
    1207                 : 
    1208                 : ZEND_API int zend_hash_quick_find(const HashTable *ht, char *arKey, uint nKeyLength, ulong h, void **pData) /* {{{ */
    1209           32005 : {
    1210           32005 :         return zend_u_hash_quick_find(ht, IS_STRING, ZSTR(arKey), nKeyLength, h, pData);
    1211                 : }
    1212                 : /* }}} */
    1213                 : 
    1214                 : ZEND_API int zend_u_hash_exists(const HashTable *ht, zend_uchar type, zstr arKey, uint nKeyLength) /* {{{ */
    1215          685290 : {
    1216                 :         ulong h;
    1217                 :         uint nIndex;
    1218                 :         Bucket *p;
    1219          685290 :         void *tmp = NULL;
    1220                 :         uint realKeyLength;
    1221                 : 
    1222                 :         IS_CONSISTENT(ht);
    1223                 : 
    1224          685290 :         UNICODE_KEY(ht, type, arKey, nKeyLength, tmp);
    1225          685290 :         realKeyLength = USTR_BYTES(type, nKeyLength);
    1226                 : 
    1227          685290 :         h = zend_u_inline_hash_func(type, arKey, nKeyLength);
    1228          685290 :         nIndex = h & ht->nTableMask;
    1229                 : 
    1230          685290 :         p = ht->arBuckets[nIndex];
    1231         1463528 :         while (p != NULL) {
    1232          688540 :                 if ((p->h == h) &&
    1233                 :                     (p->key.type == type) &&
    1234                 :                     (p->nKeyLength == nKeyLength) &&
    1235                 :                     !memcmp(p->key.arKey.s, arKey.s, realKeyLength)) {
    1236          595592 :                         if (tmp) efree(tmp);
    1237          595592 :                         return 1;
    1238                 :                 }
    1239           92948 :                 p = p->pNext;
    1240                 :         }
    1241           89698 :         if (tmp) efree(tmp);
    1242           89698 :         return 0;
    1243                 : }
    1244                 : /* }}} */
    1245                 : 
    1246                 : ZEND_API int zend_hash_exists(const HashTable *ht, const char *arKey, uint nKeyLength) /* {{{ */
    1247          236700 : {
    1248          236700 :         return zend_u_hash_exists(ht, IS_STRING, ZSTR(arKey), nKeyLength);
    1249                 : }
    1250                 : /* }}} */
    1251                 : 
    1252                 : ZEND_API int zend_ascii_hash_exists(HashTable *ht, const char *arKey, uint nKeyLength) /* {{{ */
    1253          374401 : {
    1254                 :         zstr key;
    1255                 :         int ret;
    1256                 : 
    1257          374401 :         key.u = zend_ascii_to_unicode(arKey, nKeyLength ZEND_FILE_LINE_CC);
    1258          374401 :         ret = zend_u_hash_exists(ht, IS_UNICODE, key, nKeyLength);
    1259          374401 :         efree(key.u);
    1260          374401 :         return ret;
    1261                 : }
    1262                 : /* }}} */
    1263                 : 
    1264                 : ZEND_API int zend_rt_hash_exists(HashTable *ht, const char *arKey, uint nKeyLength) /* {{{ */
    1265               0 : {
    1266                 :         zstr key;
    1267                 :         int ret;
    1268               0 :         UErrorCode status = U_ZERO_ERROR;
    1269                 :         int u_len;
    1270                 :         TSRMLS_FETCH();
    1271                 : 
    1272               0 :         zend_string_to_unicode_ex(ZEND_U_CONVERTER(UG(runtime_encoding_conv)), &key.u, &u_len, arKey, nKeyLength-1, &status);
    1273               0 :         if (U_FAILURE(status)) {
    1274               0 :                 ZEND_HASH_CVT_ERROR();
    1275               0 :                 return zend_u_hash_exists(ht, IS_STRING, ZSTR(arKey), nKeyLength);
    1276                 :         }
    1277               0 :         ret = zend_u_hash_exists(ht, IS_UNICODE, key, u_len+1);
    1278               0 :         efree(key.u);
    1279               0 :         return ret;
    1280                 : }
    1281                 : /* }}} */
    1282                 : 
    1283                 : ZEND_API int zend_utf8_hash_exists(HashTable *ht, const char *arKey, uint nKeyLength) /* {{{ */
    1284               0 : {
    1285                 :         zstr key;
    1286                 :         int ret;
    1287               0 :         UErrorCode status = U_ZERO_ERROR;
    1288                 :         int u_len;
    1289                 :         TSRMLS_FETCH();
    1290                 : 
    1291               0 :         zend_string_to_unicode_ex(ZEND_U_CONVERTER(UG(utf8_conv)), &key.u, &u_len, arKey, nKeyLength-1, &status);
    1292               0 :         if (U_FAILURE(status)) {
    1293               0 :                 ZEND_HASH_CVT_ERROR();
    1294               0 :                 return zend_u_hash_exists(ht, IS_STRING, ZSTR(arKey), nKeyLength);
    1295                 :         }
    1296               0 :         ret = zend_u_hash_exists(ht, IS_UNICODE, key, u_len+1);
    1297               0 :         efree(key.u);
    1298               0 :         return ret;
    1299                 : }
    1300                 : /* }}} */
    1301                 : 
    1302                 : ZEND_API int zend_u_hash_quick_exists(const HashTable *ht, zend_uchar type, zstr arKey, uint nKeyLength, ulong h) /* {{{ */
    1303             501 : {
    1304                 :         uint nIndex;
    1305                 :         Bucket *p;
    1306             501 :         void *tmp = NULL;
    1307                 :         uint realKeyLength;
    1308                 : 
    1309             501 :         if (nKeyLength==0) {
    1310               0 :                 return zend_hash_index_exists(ht, h);
    1311                 :         }
    1312                 : 
    1313                 :         IS_CONSISTENT(ht);
    1314                 : 
    1315             501 :         if (ht->unicode && type == IS_STRING) {
    1316             352 :                 UNICODE_KEY(ht, type, arKey, nKeyLength, tmp);
    1317             352 :                 h = zend_u_inline_hash_func(type, arKey, nKeyLength);
    1318                 :         }
    1319             501 :         realKeyLength = USTR_BYTES(type, nKeyLength);
    1320                 : 
    1321             501 :         nIndex = h & ht->nTableMask;
    1322                 : 
    1323             501 :         p = ht->arBuckets[nIndex];
    1324            1042 :         while (p != NULL) {
    1325             180 :                 if ((p->h == h) &&
    1326                 :                     (p->key.type == type) &&
    1327                 :                     (p->nKeyLength == nKeyLength) &&
    1328                 :                     !memcmp(p->key.arKey.s, arKey.s, realKeyLength)) {
    1329             140 :                   if (tmp) efree(tmp);
    1330             140 :                         return 1;
    1331                 :                 }
    1332              40 :                 p = p->pNext;
    1333                 :         }
    1334             361 :   if (tmp) efree(tmp);
    1335             361 :         return 0;
    1336                 : }
    1337                 : /* }}} */
    1338                 : 
    1339                 : ZEND_API int zend_hash_quick_exists(const HashTable *ht, const char *arKey, uint nKeyLength, ulong h) /* {{{ */
    1340             119 : {
    1341             119 :         return zend_u_hash_quick_exists(ht, IS_STRING, ZSTR(arKey), nKeyLength, h);
    1342                 : }
    1343                 : /* }}} */
    1344                 : 
    1345                 : ZEND_API int zend_hash_index_find(const HashTable *ht, ulong h, void **pData) /* {{{ */
    1346        30758717 : {
    1347                 :         uint nIndex;
    1348                 :         Bucket *p;
    1349                 : 
    1350                 :         IS_CONSISTENT(ht);
    1351                 : 
    1352        30758717 :         nIndex = h & ht->nTableMask;
    1353                 : 
    1354        30758717 :         p = ht->arBuckets[nIndex];
    1355        62313128 :         while (p != NULL) {
    1356        28618901 :                 if ((p->h == h) && (p->nKeyLength == 0)) {
    1357        27823207 :                         *pData = p->pData;
    1358        27823207 :                         return SUCCESS;
    1359                 :                 }
    1360          795694 :                 p = p->pNext;
    1361                 :         }
    1362         2935510 :         return FAILURE;
    1363                 : }
    1364                 : /* }}} */
    1365                 : 
    1366                 : ZEND_API int zend_hash_index_exists(const HashTable *ht, ulong h) /* {{{ */
    1367         1292904 : {
    1368                 :         uint nIndex;
    1369                 :         Bucket *p;
    1370                 : 
    1371                 :         IS_CONSISTENT(ht);
    1372                 : 
    1373         1292904 :         nIndex = h & ht->nTableMask;
    1374                 : 
    1375         1292904 :         p = ht->arBuckets[nIndex];
    1376         3096037 :         while (p != NULL) {
    1377          748548 :                 if ((p->h == h) && (p->nKeyLength == 0)) {
    1378          238319 :                         return 1;
    1379                 :                 }
    1380          510229 :                 p = p->pNext;
    1381                 :         }
    1382         1054585 :         return 0;
    1383                 : }
    1384                 : /* }}} */
    1385                 : 
    1386                 : ZEND_API int zend_hash_num_elements(const HashTable *ht) /* {{{ */
    1387         3714160 : {
    1388                 :         IS_CONSISTENT(ht);
    1389                 : 
    1390         3714160 :         return ht->nNumOfElements;
    1391                 : }
    1392                 : /* }}} */
    1393                 : 
    1394                 : ZEND_API int zend_hash_get_pointer(const HashTable *ht, HashPointer *ptr) /* {{{ */
    1395         1839038 : {
    1396         1839038 :         ptr->pos = ht->pInternalPointer;
    1397         1839038 :         if (ht->pInternalPointer) {
    1398         1786660 :                 ptr->h = ht->pInternalPointer->h;
    1399         1786660 :                 return 1;
    1400                 :         } else {
    1401           52378 :                 ptr->h = 0;
    1402           52378 :                 return 0;
    1403                 :         }
    1404                 : }
    1405                 : /* }}} */
    1406                 : 
    1407                 : ZEND_API int zend_hash_set_pointer(HashTable *ht, const HashPointer *ptr) /* {{{ */
    1408         1838709 : {
    1409         1838709 :         if (ptr->pos == NULL) {
    1410           52317 :                 ht->pInternalPointer = NULL;
    1411         1786392 :         } else if (ht->pInternalPointer != ptr->pos) {
    1412                 :                 Bucket *p;
    1413                 : 
    1414                 :                 IS_CONSISTENT(ht);
    1415              69 :                 p = ht->arBuckets[ptr->h & ht->nTableMask];
    1416             186 :                 while (p != NULL) {
    1417              58 :                         if (p == ptr->pos) {
    1418              10 :                                 ht->pInternalPointer = p;
    1419              10 :                                 return 1;
    1420                 :                         }
    1421              48 :                         p = p->pNext;
    1422                 :                 }
    1423              59 :                 return 0;
    1424                 :         }
    1425         1838640 :         return 1;
    1426                 : }
    1427                 : /* }}} */
    1428                 : 
    1429                 : ZEND_API void zend_hash_internal_pointer_reset_ex(HashTable *ht, HashPosition *pos) /* {{{ */
    1430         3588187 : {
    1431                 :         IS_CONSISTENT(ht);
    1432                 : 
    1433         3588187 :         if (pos)
    1434          203691 :                 *pos = ht->pListHead;
    1435                 :         else
    1436         3384496 :                 ht->pInternalPointer = ht->pListHead;
    1437         3588187 : }
    1438                 : /* }}} */
    1439                 : 
    1440                 : /* This function will be extremely optimized by remembering
    1441                 :  * the end of the list
    1442                 :  */
    1443                 : ZEND_API void zend_hash_internal_pointer_end_ex(HashTable *ht, HashPosition *pos) /* {{{ */
    1444             270 : {
    1445                 :         IS_CONSISTENT(ht);
    1446                 : 
    1447             270 :         if (pos)
    1448             155 :                 *pos = ht->pListTail;
    1449                 :         else
    1450             115 :                 ht->pInternalPointer = ht->pListTail;
    1451             270 : }
    1452                 : /* }}} */
    1453                 : 
    1454                 : ZEND_API int zend_hash_move_forward_ex(HashTable *ht, HashPosition *pos) /* {{{ */
    1455        12195991 : {
    1456        12195991 :         HashPosition *current = pos ? pos : &ht->pInternalPointer;
    1457                 : 
    1458                 :         IS_CONSISTENT(ht);
    1459                 : 
    1460        12195991 :         if (*current) {
    1461        12195968 :                 *current = (*current)->pListNext;
    1462        12195968 :                 return SUCCESS;
    1463                 :         } else
    1464              23 :                 return FAILURE;
    1465                 : }
    1466                 : /* }}} */
    1467                 : 
    1468                 : ZEND_API int zend_hash_move_backwards_ex(HashTable *ht, HashPosition *pos) /* {{{ */
    1469             530 : {
    1470             530 :         HashPosition *current = pos ? pos : &ht->pInternalPointer;
    1471                 : 
    1472                 :         IS_CONSISTENT(ht);
    1473                 : 
    1474             530 :         if (*current) {
    1475             528 :                 *current = (*current)->pListLast;
    1476             528 :                 return SUCCESS;
    1477                 :         } else
    1478               2 :                 return FAILURE;
    1479                 : }
    1480                 : /* }}} */
    1481                 : 
    1482                 : /* This function should be made binary safe  */
    1483                 : ZEND_API int zend_hash_get_current_key_ex(const HashTable *ht, zstr *str_index, uint *str_length, ulong *num_index, zend_bool duplicate, HashPosition *pos) /* {{{ */
    1484         3013319 : {
    1485                 :         Bucket *p;
    1486                 : 
    1487         3013319 :         p = pos ? (*pos) : ht->pInternalPointer;
    1488                 : 
    1489                 :         IS_CONSISTENT(ht);
    1490                 : 
    1491         3013319 :         if (p) {
    1492         3003865 :                 if (p->nKeyLength) {
    1493         2881035 :                         if (p->key.type == IS_STRING) {
    1494         2257102 :                                 if (duplicate) {
    1495          731033 :                                         str_index->s = estrndup(p->key.arKey.s, p->nKeyLength-1);
    1496                 :                                 } else {
    1497         1526069 :                                         str_index->s = p->key.arKey.s;
    1498                 :                                 }
    1499         2257102 :                                 if (str_length) {
    1500         2255294 :                                         *str_length = p->nKeyLength;
    1501                 :                                 }
    1502         2257102 :                                 return HASH_KEY_IS_STRING;
    1503          623933 :                         } else if (p->key.type == IS_UNICODE) {
    1504          623933 :                                 if (duplicate) {
    1505          573321 :                                         str_index->u = eustrndup(p->key.arKey.u, p->nKeyLength-1);
    1506                 :                                 } else {
    1507           50612 :                                         str_index->u = p->key.arKey.u;
    1508                 :                                 }
    1509          623933 :                                 if (str_length) {
    1510          619623 :                                         *str_length = p->nKeyLength;
    1511                 :                                 }
    1512          623933 :                                 return HASH_KEY_IS_UNICODE;
    1513                 :                         }
    1514                 :                 } else {
    1515          122830 :                         *num_index = p->h;
    1516          122830 :                         return HASH_KEY_IS_LONG;
    1517                 :                 }
    1518                 :         }
    1519            9454 :         return HASH_KEY_NON_EXISTANT;
    1520                 : }
    1521                 : /* }}} */
    1522                 : 
    1523                 : ZEND_API int zend_hash_get_current_key_type_ex(HashTable *ht, HashPosition *pos) /* {{{ */
    1524          105723 : {
    1525                 :         Bucket *p;
    1526                 : 
    1527          105723 :         p = pos ? (*pos) : ht->pInternalPointer;
    1528                 : 
    1529                 :         IS_CONSISTENT(ht);
    1530                 : 
    1531          105723 :         if (p) {
    1532           90569 :                 if (p->nKeyLength) {
    1533           65973 :                         if (p->key.type == IS_UNICODE) {
    1534           17885 :                                 return HASH_KEY_IS_UNICODE;
    1535                 :                         } else {
    1536           48088 :                                 return HASH_KEY_IS_STRING;
    1537                 :                         }
    1538                 :                 } else {
    1539           24596 :                         return HASH_KEY_IS_LONG;
    1540                 :                 }
    1541                 :         }
    1542           15154 :         return HASH_KEY_NON_EXISTANT;
    1543                 : }
    1544                 : /* }}} */
    1545                 : 
    1546                 : ZEND_API int zend_hash_get_current_data_ex(HashTable *ht, void **pData, HashPosition *pos) /* {{{ */
    1547        14957477 : {
    1548                 :         Bucket *p;
    1549                 : 
    1550        14957477 :         p = pos ? (*pos) : ht->pInternalPointer;
    1551                 : 
    1552                 :         IS_CONSISTENT(ht);
    1553                 : 
    1554        14957477 :         if (p) {
    1555        12224863 :                 *pData = p->pData;
    1556        12224863 :                 return SUCCESS;
    1557                 :         } else {
    1558         2732614 :                 return FAILURE;
    1559                 :         }
    1560                 : }
    1561                 : /* }}} */
    1562                 : 
    1563                 : /* This function changes key of currevt element without changing elements'
    1564                 :  * order. If element with target key already exists, it will be deleted first.
    1565                 :  */
    1566                 : ZEND_API int zend_hash_update_current_key_ex(HashTable *ht, int key_type, zstr str_index, uint str_length, ulong num_index, int mode, HashPosition *pos) /* {{{ */
    1567              88 : {
    1568                 :         Bucket *p;
    1569                 :         uint real_length;
    1570                 : 
    1571              88 :         p = pos ? (*pos) : ht->pInternalPointer;
    1572                 : 
    1573                 :         IS_CONSISTENT(ht);
    1574                 : 
    1575              88 :         if (p) {
    1576              88 :                 if (key_type == HASH_KEY_IS_LONG) {
    1577              49 :                         real_length = str_length = 0;
    1578              49 :                         if (!p->nKeyLength && p->h == num_index) {
    1579               0 :                                 return SUCCESS;
    1580                 :                         }
    1581                 : 
    1582              49 :                         if (mode != HASH_UPDATE_KEY_ANYWAY) {
    1583              49 :                                 Bucket *q = ht->arBuckets[num_index & ht->nTableMask];
    1584              49 :                                 int found = 0;
    1585                 : 
    1586             103 :                                 while (q != NULL) {
    1587               6 :                                         if (q == p) {
    1588               5 :                                                 found = 1;
    1589               1 :                                         } else if (!q->nKeyLength && q->h == num_index) {
    1590               1 :                                                 if (found) {
    1591               0 :                                                         if (mode & HASH_UPDATE_KEY_IF_BEFORE) {
    1592               0 :                                                                 break;
    1593                 :                                                         } else {
    1594               0 :                                                                 if (p->nKeyLength) {
    1595               0 :                                                                         zend_u_hash_del(ht, p->key.type, ZSTR(p->key.arKey.s), p->nKeyLength);
    1596                 :                                                                 } else {
    1597               0 :                                                                         zend_hash_index_del(ht, p->h);
    1598                 :                                                                 }
    1599               0 :                                                                 return FAILURE;
    1600                 :                                                         }
    1601                 :                                                 } else {
    1602               1 :                                                         if (mode & HASH_UPDATE_KEY_IF_AFTER) {
    1603               0 :                                                                 break;
    1604                 :                                                         } else {
    1605               1 :                                                                 if (p->nKeyLength) {
    1606               1 :                                                                         zend_u_hash_del(ht, p->key.type, ZSTR(p->key.arKey.s), p->nKeyLength);
    1607                 :                                                                 } else {
    1608               0 :                                                                         zend_hash_index_del(ht, p->h);
    1609                 :                                                                 }
    1610               1 :                                                                 return FAILURE;
    1611                 :                                                         }
    1612                 :                                                 }
    1613                 :                                         }
    1614               5 :                                         q = q->pNext;
    1615                 :                                 }
    1616                 :                         }
    1617                 : 
    1618              48 :                         zend_hash_index_del(ht, num_index);
    1619              75 :                 } else if (key_type == HASH_KEY_IS_STRING ||
    1620                 :                            key_type == HASH_KEY_IS_UNICODE) {
    1621              39 :                         real_length = key_type == HASH_KEY_IS_STRING ? str_length : str_length * sizeof(UChar);
    1622              39 :                         if (p->nKeyLength == str_length &&
    1623                 :                             p->key.type == key_type &&
    1624                 :                             memcmp(p->key.arKey.s, str_index.v, real_length) == 0) {
    1625               0 :                                 return SUCCESS;
    1626                 :                         }
    1627                 : 
    1628              39 :                         if (mode != HASH_UPDATE_KEY_ANYWAY) {
    1629              26 :                                 ulong h = zend_u_inline_hash_func(key_type, str_index, str_length);
    1630              26 :                                 Bucket *q = ht->arBuckets[h & ht->nTableMask];
    1631              26 :                                 int found = 0;
    1632                 : 
    1633              56 :                                 while (q != NULL) {
    1634               8 :                                         if (q == p) {
    1635               4 :                                                 found = 1;
    1636               4 :                                         } else if (q->h == h && q->nKeyLength == str_length && 
    1637                 :                                                    q->key.type == key_type &&
    1638                 :                                                            memcmp(q->key.arKey.s, str_index.v, real_length) == 0) {
    1639               4 :                                                 if (found) {
    1640               1 :                                                         if (mode & HASH_UPDATE_KEY_IF_BEFORE) {
    1641               1 :                                                                 break;
    1642                 :                                                         } else {
    1643               0 :                                                                 if (p->nKeyLength) {
    1644               0 :                                                                         zend_u_hash_del(ht, p->key.type, ZSTR(p->key.arKey.s), p->nKeyLength);
    1645                 :                                                                 } else {
    1646               0 :                                                                         zend_hash_index_del(ht, p->h);
    1647                 :                                                                 }
    1648               0 :                                                                 return FAILURE;
    1649                 :                                                         }
    1650                 :                                                 } else {
    1651               3 :                                                         if (mode & HASH_UPDATE_KEY_IF_AFTER) {
    1652               0 :                                                                 break;
    1653                 :                                                         } else {
    1654               3 :                                                                 if (p->nKeyLength) {
    1655               3 :                                                                         zend_u_hash_del(ht, p->key.type, ZSTR(p->key.arKey.s), p->nKeyLength);
    1656                 :                                                                 } else {
    1657               0 :                                                                         zend_hash_index_del(ht, p->h);
    1658                 :                                                                 }
    1659               3 :                                                                 return FAILURE;
    1660                 :                                                         }
    1661                 :                                                 }
    1662                 :                                         }
    1663               4 :                                         q = q->pNext;
    1664                 :                                 }
    1665                 :                         }
    1666                 : 
    1667              36 :                         zend_u_hash_del(ht, key_type, str_index, str_length);
    1668                 :                 } else {
    1669               0 :                         return FAILURE;
    1670                 :                 }
    1671                 : 
    1672              84 :                 HANDLE_BLOCK_INTERRUPTIONS();
    1673                 : 
    1674              84 :                 if (p->pNext) {
    1675               2 :                         p->pNext->pLast = p->pLast;
    1676                 :                 }
    1677              84 :                 if (p->pLast) {
    1678               3 :                         p->pLast->pNext = p->pNext;
    1679                 :                 } else{
    1680              81 :                         ht->arBuckets[p->h & ht->nTableMask] = p->pNext;
    1681                 :                 }
    1682                 : 
    1683              84 :                 if (p->nKeyLength != str_length) {
    1684              71 :                         Bucket *q = (Bucket *) pemalloc(sizeof(Bucket) - 1 + real_length, ht->persistent);
    1685                 : 
    1686              71 :                         q->nKeyLength = str_length;
    1687              71 :                         if (p->pData == &p->pDataPtr) {
    1688              71 :                                 q->pData = &q->pDataPtr;
    1689                 :                         } else {
    1690               0 :                                 q->pData = p->pData;
    1691                 :                         }
    1692              71 :                         q->pDataPtr = p->pDataPtr;
    1693              71 :                         q->pListNext = p->pListNext;
    1694              71 :                         q->pListLast = p->pListLast;
    1695              71 :                         if (q->pListNext) {
    1696               9 :                                 p->pListNext->pListLast = q;
    1697                 :                         } else {
    1698              62 :                                 ht->pListTail = q;
    1699                 :                         }
    1700              71 :                         if (q->pListLast) {
    1701               8 :                                 p->pListLast->pListNext = q;
    1702                 :                         } else {
    1703              63 :                                 ht->pListHead = q;
    1704                 :                         }
    1705              71 :                         if (ht->pInternalPointer == p) {
    1706              71 :                                 ht->pInternalPointer = q;
    1707                 :                         }
    1708              71 :                         if (pos) {
    1709               0 :                                 *pos = q;
    1710                 :                         }
    1711              71 :                         pefree(p, ht->persistent);
    1712              71 :                         p = q;
    1713                 :                 }
    1714                 : 
    1715              84 :                 if (key_type == HASH_KEY_IS_LONG) {
    1716              48 :                         p->h = num_index;
    1717              36 :                 } else if (key_type == HASH_KEY_IS_UNICODE) {
    1718              23 :                         memcpy(p->key.arKey.u, str_index.u, real_length);
    1719              23 :                         p->key.type = IS_UNICODE;
    1720              23 :                         p->h = zend_u_inline_hash_func(IS_UNICODE, str_index, str_length);
    1721                 :                 } else {
    1722              13 :                         memcpy(p->key.arKey.s, str_index.s, real_length);
    1723              13 :                         p->key.type = IS_STRING;
    1724              13 :                         p->h = zend_u_inline_hash_func(p->key.type, str_index, str_length);
    1725                 :                 }
    1726                 : 
    1727              84 :                 CONNECT_TO_BUCKET_DLLIST(p, ht->arBuckets[p->h & ht->nTableMask]);
    1728              84 :                 ht->arBuckets[p->h & ht->nTableMask] = p;
    1729              84 :                 HANDLE_UNBLOCK_INTERRUPTIONS();
    1730                 : 
    1731              84 :                 return SUCCESS;
    1732                 :         } else {
    1733               0 :                 return FAILURE;
    1734                 :         }
    1735                 : }
    1736                 : /* }}} */
    1737                 : 
    1738                 : ZEND_API int zend_hash_sort(HashTable *ht, sort_func_t sort_func, compare_func_t compar, int renumber TSRMLS_DC) /* {{{ */
    1739           18292 : {
    1740                 :         Bucket **arTmp;
    1741                 :         Bucket *p;
    1742                 :         int i, j;
    1743                 : 
    1744                 :         IS_CONSISTENT(ht);
    1745                 : 
    1746           18292 :         if (!(ht->nNumOfElements>1) && !(renumber && ht->nNumOfElements>0)) { /* Doesn't require sorting */
    1747             268 :                 return SUCCESS;
    1748                 :         }
    1749           18024 :         arTmp = (Bucket **) pemalloc(ht->nNumOfElements * sizeof(Bucket *), ht->persistent);
    1750           18024 :         if (!arTmp) {
    1751               0 :                 return FAILURE;
    1752                 :         }
    1753           18024 :         p = ht->pListHead;
    1754           18024 :         i = 0;
    1755         1224082 :         while (p) {
    1756         1188034 :                 arTmp[i] = p;
    1757         1188034 :                 p = p->pListNext;
    1758         1188034 :                 i++;
    1759                 :         }
    1760                 : 
    1761           18024 :         (*sort_func)((void *) arTmp, i, sizeof(Bucket *), compar TSRMLS_CC);
    1762                 : 
    1763           18024 :         HANDLE_BLOCK_INTERRUPTIONS();
    1764           18024 :         ht->pListHead = arTmp[0];
    1765           18024 :         ht->pListTail = NULL;
    1766           18024 :         ht->pInternalPointer = ht->pListHead;
    1767                 : 
    1768           18024 :         arTmp[0]->pListLast = NULL;
    1769           18024 :         if (i > 1) {
    1770           18015 :                 arTmp[0]->pListNext = arTmp[1];
    1771         1170010 :                 for (j = 1; j < i-1; j++) {
    1772         1151995 :                         arTmp[j]->pListLast = arTmp[j-1];
    1773         1151995 :                         arTmp[j]->pListNext = arTmp[j+1];
    1774                 :                 }
    1775           18015 :                 arTmp[j]->pListLast = arTmp[j-1];
    1776           18015 :                 arTmp[j]->pListNext = NULL;
    1777                 :         } else {
    1778               9 :                 arTmp[0]->pListNext = NULL;
    1779                 :         }
    1780           18024 :         ht->pListTail = arTmp[i-1];
    1781                 : 
    1782           18024 :         pefree(arTmp, ht->persistent);
    1783           18024 :         HANDLE_UNBLOCK_INTERRUPTIONS();
    1784                 : 
    1785           18024 :         if (renumber) {
    1786             236 :                 p = ht->pListHead;
    1787             236 :                 i=0;
    1788           13043 :                 while (p != NULL) {
    1789           12571 :                         p->nKeyLength = 0;
    1790           12571 :                         p->h = i++;
    1791           12571 :                         p = p->pListNext;
    1792                 :                 }
    1793             236 :                 ht->nNextFreeElement = i;
    1794             236 :                 zend_hash_rehash(ht);
    1795                 :         }
    1796           18024 :         return SUCCESS;
    1797                 : }
    1798                 : /* }}} */
    1799                 : 
    1800                 : ZEND_API int zend_hash_compare(HashTable *ht1, HashTable *ht2, compare_func_t compar, zend_bool ordered TSRMLS_DC) /* {{{ */
    1801            1218 : {
    1802            1218 :         Bucket *p1, *p2 = NULL;
    1803                 :         int result;
    1804                 :         void *pData2;
    1805                 : 
    1806                 :         IS_CONSISTENT(ht1);
    1807                 :         IS_CONSISTENT(ht2);
    1808                 : 
    1809            1218 :         HASH_PROTECT_RECURSION(ht1);
    1810            1218 :         HASH_PROTECT_RECURSION(ht2);
    1811                 : 
    1812            1218 :         result = ht1->nNumOfElements - ht2->nNumOfElements;
    1813            1218 :         if (result!=0) {
    1814             463 :                 HASH_UNPROTECT_RECURSION(ht1);
    1815             463 :                 HASH_UNPROTECT_RECURSION(ht2);
    1816             463 :                 return result;
    1817                 :         }
    1818                 : 
    1819             755 :         p1 = ht1->pListHead;
    1820             755 :         if (ordered) {
    1821              59 :                 p2 = ht2->pListHead;
    1822                 :         }
    1823                 : 
    1824            4556 :         while (p1) {
    1825            3382 :                 if (ordered && !p2) {
    1826               0 :                         HASH_UNPROTECT_RECURSION(ht1);
    1827               0 :                         HASH_UNPROTECT_RECURSION(ht2);
    1828               0 :                         return 1; /* That's not supposed to happen */
    1829                 :                 }
    1830            3382 :                 if (ordered) {
    1831            1445 :                         if (p1->nKeyLength==0 && p2->nKeyLength==0) { /* numeric indices */
    1832             363 :                                 result = p1->h - p2->h;
    1833             363 :                                 if (result!=0) {
    1834               1 :                                         HASH_UNPROTECT_RECURSION(ht1);
    1835               1 :                                         HASH_UNPROTECT_RECURSION(ht2);
    1836               1 :                                         return result;
    1837                 :                                 }
    1838                 :                         } else { /* string indices */
    1839             720 :                           result = p1->key.type - p2->key.type;
    1840             720 :                                 if (result==0) {
    1841             714 :                                         result = p1->nKeyLength - p2->nKeyLength;
    1842                 :                                 }
    1843             720 :                                 if (result==0) {
    1844             714 :                                         result = memcmp(p1->key.arKey.s, p2->key.arKey.s, USTR_BYTES(p1->key.type, p1->nKeyLength));
    1845                 :                                 }
    1846             720 :                                 if (result!=0) {
    1847               6 :                                         HASH_UNPROTECT_RECURSION(ht1);
    1848               6 :                                         HASH_UNPROTECT_RECURSION(ht2);
    1849               6 :                                         return result;
    1850                 :                                 }
    1851                 :                         }
    1852            1076 :                         pData2 = p2->pData;
    1853                 :                 } else {
    1854            2299 :                         if (p1->nKeyLength==0) { /* numeric index */
    1855             212 :                                 if (zend_hash_index_find(ht2, p1->h, &pData2)==FAILURE) {
    1856               4 :                                         HASH_UNPROTECT_RECURSION(ht1);
    1857               4 :                                         HASH_UNPROTECT_RECURSION(ht2);
    1858               4 :                                         return 1;
    1859                 :                                 }
    1860                 :                         } else { /* string, binary or unicode index */
    1861            2087 :                                 if (zend_u_hash_find(ht2, p1->key.type, ZSTR(p1->key.arKey.s), p1->nKeyLength, &pData2)==FAILURE) {
    1862              18 :                                         HASH_UNPROTECT_RECURSION(ht1);
    1863              18 :                                         HASH_UNPROTECT_RECURSION(ht2);
    1864              18 :                                         return 1;
    1865                 :                                 }
    1866                 :                         }
    1867                 :                 }
    1868            3353 :                 result = compar(p1->pData, pData2 TSRMLS_CC);
    1869            3353 :                 if (result!=0) {
    1870             307 :                         HASH_UNPROTECT_RECURSION(ht1);
    1871             307 :                         HASH_UNPROTECT_RECURSION(ht2);
    1872             307 :                         return result;
    1873                 :                 }
    1874            3046 :                 p1 = p1->pListNext;
    1875            3046 :                 if (ordered) {
    1876            1070 :                         p2 = p2->pListNext;
    1877                 :                 }
    1878                 :         }
    1879                 : 
    1880             419 :         HASH_UNPROTECT_RECURSION(ht1);
    1881             419 :         HASH_UNPROTECT_RECURSION(ht2);
    1882             419 :         return 0;
    1883                 : }
    1884                 : /* }}} */
    1885                 : 
    1886                 : ZEND_API int zend_hash_minmax(const HashTable *ht, compare_func_t compar, int flag, void **pData TSRMLS_DC) /* {{{ */
    1887              34 : {
    1888                 :         Bucket *p, *res;
    1889                 : 
    1890                 :         IS_CONSISTENT(ht);
    1891                 : 
    1892              34 :         if (ht->nNumOfElements == 0 ) {
    1893               4 :                 *pData=NULL;
    1894               4 :                 return FAILURE;
    1895                 :         }
    1896                 : 
    1897              30 :         res = p = ht->pListHead;
    1898             112 :         while ((p = p->pListNext)) {
    1899              52 :                 if (flag) {
    1900              26 :                         if (compar(&res, &p TSRMLS_CC) < 0) { /* max */
    1901              14 :                                 res = p;
    1902                 :                         }
    1903                 :                 } else {
    1904              26 :                         if (compar(&res, &p TSRMLS_CC) > 0) { /* min */
    1905               4 :                                 res = p;
    1906                 :                         }
    1907                 :                 }
    1908                 :         }
    1909              30 :         *pData = res->pData;
    1910              30 :         return SUCCESS;
    1911                 : }
    1912                 : /* }}} */
    1913                 : 
    1914                 : ZEND_API ulong zend_hash_next_free_element(const HashTable *ht) /* {{{ */
    1915          505658 : {
    1916                 :         IS_CONSISTENT(ht);
    1917                 : 
    1918          505658 :         return ht->nNextFreeElement;
    1919                 : 
    1920                 : }
    1921                 : /* }}} */
    1922                 : 
    1923                 : ZEND_API int zend_u_symtable_update(HashTable *ht, zend_uchar type, zstr arKey, uint nKeyLength, void *pData, uint nDataSize, void **pDest) /* {{{ */
    1924         1731252 : {
    1925         1731252 :         if (type == IS_STRING) {
    1926          892925 :                 ZEND_HANDLE_NUMERIC(arKey.s, nKeyLength, zend_hash_index_update(ht, idx, pData, nDataSize, pDest));
    1927          838327 :         } else if (type == IS_UNICODE) {
    1928          838327 :                 ZEND_HANDLE_U_NUMERIC(arKey.u, nKeyLength, zend_hash_index_update(ht, idx, pData, nDataSize, pDest));
    1929                 :         }
    1930         1729944 :         return zend_u_hash_update(ht, type, arKey, nKeyLength, pData, nDataSize, pDest);
    1931                 : }
    1932                 : /* }}} */
    1933                 : 
    1934                 : ZEND_API int zend_u_symtable_del(HashTable *ht, zend_uchar type, zstr arKey, uint nKeyLength) /* {{{ */
    1935             527 : {
    1936             527 :         if (type == IS_STRING) {
    1937               0 :                 ZEND_HANDLE_NUMERIC(arKey.s, nKeyLength, zend_hash_index_del(ht, idx));
    1938             527 :         } else if (type == IS_UNICODE) {
    1939             527 :                 ZEND_HANDLE_U_NUMERIC(arKey.u, nKeyLength, zend_hash_index_del(ht, idx));
    1940                 :         }
    1941             520 :         return zend_u_hash_del(ht, type, arKey, nKeyLength);
    1942                 : }
    1943                 : /* }}} */
    1944                 : 
    1945                 : ZEND_API int zend_u_symtable_find(HashTable *ht, zend_uchar type, zstr arKey, uint nKeyLength, void **pData) /* {{{ */
    1946         3589240 : {
    1947         3589240 :         if (type == IS_STRING) {
    1948          919397 :                 ZEND_HANDLE_NUMERIC(arKey.s, nKeyLength, zend_hash_index_find(ht, idx, pData));
    1949         2669843 :         } else if (type == IS_UNICODE) {
    1950         2669843 :                 ZEND_HANDLE_U_NUMERIC(arKey.u, nKeyLength, zend_hash_index_find(ht, idx, pData));
    1951                 :         }
    1952         3229120 :         return zend_u_hash_find(ht, type, arKey, nKeyLength, pData);
    1953                 : }
    1954                 : /* }}} */
    1955                 : 
    1956                 : ZEND_API int zend_u_symtable_exists(HashTable *ht, zend_uchar type, zstr arKey, uint nKeyLength) /* {{{ */
    1957           73626 : {
    1958           73626 :         if (type == IS_STRING) {
    1959               0 :                 ZEND_HANDLE_NUMERIC(arKey.s, nKeyLength, zend_hash_index_exists(ht, idx));
    1960           73626 :         } else if (type == IS_UNICODE) {
    1961           73626 :                 ZEND_HANDLE_U_NUMERIC(arKey.u, nKeyLength, zend_hash_index_exists(ht, idx));
    1962                 :         }
    1963           73595 :         return zend_u_hash_exists(ht, type, arKey, nKeyLength);
    1964                 : }
    1965                 : /* }}} */
    1966                 : 
    1967                 : ZEND_API int zend_u_symtable_update_current_key_ex(HashTable *ht, zend_uchar type, zstr arKey, uint nKeyLength, int mode, HashPosition *pos) /* {{{ */
    1968              27 : {
    1969                 :         zend_uchar key_type;
    1970                 : 
    1971              27 :         if (type == IS_STRING) {
    1972               0 :                 key_type = HASH_KEY_IS_STRING;
    1973               0 :                 ZEND_HANDLE_NUMERIC(arKey.s, nKeyLength, zend_hash_update_current_key_ex(ht, HASH_KEY_IS_LONG, NULL_ZSTR, 0, idx, mode, pos));
    1974                 :         } else {
    1975              27 :                 key_type = HASH_KEY_IS_UNICODE;
    1976              27 :                 ZEND_HANDLE_U_NUMERIC(arKey.u, nKeyLength, zend_hash_update_current_key_ex(ht, HASH_KEY_IS_LONG, NULL_ZSTR, 0, idx, mode, pos));
    1977                 :         }
    1978              26 :         return zend_hash_update_current_key_ex(ht, key_type, arKey, nKeyLength, 0, mode, pos);
    1979                 : }
    1980                 : /* }}} */
    1981                 : 
    1982                 : ZEND_API int zend_symtable_update(HashTable *ht, const char *arKey, uint nKeyLength, void *pData, uint nDataSize, void **pDest) /* {{{ */
    1983         1005943 : {
    1984         1005943 :         ZEND_HANDLE_NUMERIC(arKey, nKeyLength, zend_hash_index_update(ht, idx, pData, nDataSize, pDest));
    1985         1005805 :         return zend_hash_update(ht, arKey, nKeyLength, pData, nDataSize, pDest);
    1986                 : }
    1987                 : /* }}} */
    1988                 : 
    1989                 : ZEND_API int zend_symtable_del(HashTable *ht, const char *arKey, uint nKeyLength) /* {{{ */
    1990               0 : {
    1991               0 :         ZEND_HANDLE_NUMERIC(arKey, nKeyLength, zend_hash_index_del(ht, idx));
    1992               0 :         return zend_hash_del(ht, arKey, nKeyLength);
    1993                 : }
    1994                 : /* }}} */
    1995                 : 
    1996                 : ZEND_API int zend_symtable_find(HashTable *ht, const char *arKey, uint nKeyLength, void **pData) /* {{{ */
    1997              93 : {
    1998              93 :         ZEND_HANDLE_NUMERIC(arKey, nKeyLength, zend_hash_index_find(ht, idx, pData));
    1999              79 :         return zend_hash_find(ht, arKey, nKeyLength, pData);
    2000                 : }
    2001                 : /* }}} */
    2002                 : 
    2003                 : ZEND_API int zend_symtable_exists(HashTable *ht, const char *arKey, uint nKeyLength) /* {{{ */
    2004               0 : {
    2005               0 :         ZEND_HANDLE_NUMERIC(arKey, nKeyLength, zend_hash_index_exists(ht, idx));
    2006               0 :         return zend_hash_exists(ht, arKey, nKeyLength);
    2007                 : }
    2008                 : /* }}} */
    2009                 : 
    2010                 : ZEND_API int zend_symtable_update_current_key_ex(HashTable *ht, const char *arKey, uint nKeyLength, int mode, HashPosition *pos) /* {{{ */
    2011               0 : {
    2012               0 :         ZEND_HANDLE_NUMERIC(arKey, nKeyLength, zend_hash_update_current_key_ex(ht, HASH_KEY_IS_LONG, NULL_ZSTR, 0, idx, mode, pos));
    2013               0 :         return zend_hash_update_current_key_ex(ht, HASH_KEY_IS_STRING, ZSTR(arKey), nKeyLength, 0, mode, pos);
    2014                 : }
    2015                 : /* }}} */
    2016                 : 
    2017                 : ZEND_API int zend_ascii_symtable_update(HashTable *ht, const char *arKey, uint nKeyLength, void *pData, uint nDataSize, void **pDest) /* {{{ */
    2018          212212 : {
    2019          212212 :         ZEND_HANDLE_NUMERIC(arKey, nKeyLength, zend_hash_index_update(ht, idx, pData, nDataSize, pDest));
    2020          212212 :         return zend_ascii_hash_update(ht, arKey, nKeyLength, pData, nDataSize, pDest);
    2021                 : }
    2022                 : /* }}} */
    2023                 : 
    2024                 : ZEND_API int zend_ascii_symtable_del(HashTable *ht, const char *arKey, uint nKeyLength) /* {{{ */
    2025               0 : {
    2026               0 :         ZEND_HANDLE_NUMERIC(arKey, nKeyLength, zend_hash_index_del(ht, idx));
    2027               0 :         return zend_ascii_hash_del(ht, arKey, nKeyLength);
    2028                 : }
    2029                 : /* }}} */
    2030                 : 
    2031                 : ZEND_API int zend_ascii_symtable_find(HashTable *ht, const char *arKey, uint nKeyLength, void **pData) /* {{{ */
    2032               0 : {
    2033               0 :         ZEND_HANDLE_NUMERIC(arKey, nKeyLength, zend_hash_index_find(ht, idx, pData));
    2034               0 :         return zend_ascii_hash_find(ht, arKey, nKeyLength, pData);
    2035                 : }
    2036                 : /* }}} */
    2037                 : 
    2038                 : ZEND_API int zend_ascii_symtable_exists(HashTable *ht, const char *arKey, uint nKeyLength) /* {{{ */
    2039               0 : {
    2040               0 :         ZEND_HANDLE_NUMERIC(arKey, nKeyLength, zend_hash_index_exists(ht, idx));
    2041               0 :         return zend_ascii_hash_exists(ht, arKey, nKeyLength);
    2042                 : }
    2043                 : /* }}} */
    2044                 : 
    2045                 : ZEND_API int zend_rt_symtable_update(HashTable *ht, const char *arKey, uint nKeyLength, void *pData, uint nDataSize, void **pDest) /* {{{ */
    2046              99 : {
    2047              99 :         ZEND_HANDLE_NUMERIC(arKey, nKeyLength, zend_hash_index_update(ht, idx, pData, nDataSize, pDest));
    2048              19 :         return zend_rt_hash_update(ht, arKey, nKeyLength, pData, nDataSize, pDest);
    2049                 : }
    2050                 : /* }}} */
    2051                 : 
    2052                 : ZEND_API int zend_rt_symtable_del(HashTable *ht, const char *arKey, uint nKeyLength) /* {{{ */
    2053               0 : {
    2054               0 :         ZEND_HANDLE_NUMERIC(arKey, nKeyLength, zend_hash_index_del(ht, idx));
    2055               0 :         return zend_rt_hash_del(ht, arKey, nKeyLength);
    2056                 : }
    2057                 : /* }}} */
    2058                 : 
    2059                 : ZEND_API int zend_rt_symtable_find(HashTable *ht, const char *arKey, uint nKeyLength, void **pData) /* {{{ */
    2060               0 : {
    2061               0 :         ZEND_HANDLE_NUMERIC(arKey, nKeyLength, zend_hash_index_find(ht, idx, pData));
    2062               0 :         return zend_rt_hash_find(ht, arKey, nKeyLength, pData);
    2063                 : }
    2064                 : /* }}} */
    2065                 : 
    2066                 : ZEND_API int zend_rt_symtable_exists(HashTable *ht, const char *arKey, uint nKeyLength) /* {{{ */
    2067               0 : {
    2068               0 :         ZEND_HANDLE_NUMERIC(arKey, nKeyLength, zend_hash_index_exists(ht, idx));
    2069               0 :         return zend_rt_hash_exists(ht, arKey, nKeyLength);
    2070                 : }
    2071                 : /* }}} */
    2072                 : 
    2073                 : ZEND_API int zend_utf8_symtable_update(HashTable *ht, const char *arKey, uint nKeyLength, void *pData, uint nDataSize, void **pDest) /* {{{ */
    2074             203 : {
    2075             203 :         ZEND_HANDLE_NUMERIC(arKey, nKeyLength, zend_hash_index_update(ht, idx, pData, nDataSize, pDest));
    2076             197 :         return zend_utf8_hash_update(ht, arKey, nKeyLength, pData, nDataSize, pDest);
    2077                 : }
    2078                 : /* }}} */
    2079                 : 
    2080                 : ZEND_API int zend_utf8_symtable_del(HashTable *ht, const char *arKey, uint nKeyLength) /* {{{ */
    2081               0 : {
    2082               0 :         ZEND_HANDLE_NUMERIC(arKey, nKeyLength, zend_hash_index_del(ht, idx));
    2083               0 :         return zend_utf8_hash_del(ht, arKey, nKeyLength);
    2084                 : }
    2085                 : /* }}} */
    2086                 : 
    2087                 : ZEND_API int zend_utf8_symtable_find(HashTable *ht, const char *arKey, uint nKeyLength, void **pData) /* {{{ */
    2088               0 : {
    2089               0 :         ZEND_HANDLE_NUMERIC(arKey, nKeyLength, zend_hash_index_find(ht, idx, pData));
    2090               0 :         return zend_utf8_hash_find(ht, arKey, nKeyLength, pData);
    2091                 : }
    2092                 : /* }}} */
    2093                 : 
    2094                 : ZEND_API int zend_utf8_symtable_exists(HashTable *ht, const char *arKey, uint nKeyLength) /* {{{ */
    2095               0 : {
    2096               0 :         ZEND_HANDLE_NUMERIC(arKey, nKeyLength, zend_hash_index_exists(ht, idx));
    2097               0 :         return zend_utf8_hash_exists(ht, arKey, nKeyLength);
    2098                 : }
    2099                 : /* }}} */
    2100                 : 
    2101                 : ZEND_API void zend_hash_to_unicode(HashTable *ht, apply_func_t apply_func TSRMLS_DC) /* {{{ */
    2102           68028 : {
    2103                 :         Bucket **p;
    2104                 :         uint nIndex;
    2105                 : 
    2106                 :         IS_CONSISTENT(ht);
    2107           68028 :         if (ht->unicode) {
    2108               0 :                 return;
    2109                 :         }
    2110                 : 
    2111           68028 :         ht->unicode = 1;
    2112           68028 :         memset(ht->arBuckets, 0, ht->nTableSize * sizeof(Bucket *));
    2113           68028 :         p = &ht->pListHead;
    2114         1462602 :         while ((*p) != NULL) {
    2115         1326546 :                 if ((*p)->key.type == IS_STRING) {
    2116           17007 :                         UErrorCode status = U_ZERO_ERROR;
    2117           17007 :                         UChar *u = NULL;
    2118                 :                         int u_len;
    2119                 :                         Bucket *q;
    2120                 : 
    2121           17007 :                         zend_string_to_unicode_ex(ZEND_U_CONVERTER(UG(runtime_encoding_conv)), &u, &u_len, (*p)->key.arKey.s, (*p)->nKeyLength-1, &status);
    2122           17007 :                         if (U_FAILURE(status)) {
    2123               0 :                                 zend_error(E_ERROR, "Cannot convert HashTable to Unicode");
    2124                 :                         }
    2125                 : 
    2126           17007 :                         q = (Bucket *) pemalloc(sizeof(Bucket)-sizeof(q->key.arKey)+((u_len+1)*2), ht->persistent);
    2127           17007 :                         memcpy(q, *p, sizeof(Bucket)-sizeof(q->key.arKey));
    2128           17007 :                         memcpy(q->key.arKey.u, u, (u_len+1)*2);
    2129           17007 :                         q->key.type = IS_UNICODE;
    2130           17007 :                         q->nKeyLength = u_len+1;
    2131           17007 :                         q->h = zend_u_inline_hash_func(IS_UNICODE, q->key.arKey, q->nKeyLength);
    2132           17007 :                         if ((*p)->pData == &(*p)->pDataPtr) {
    2133               0 :                                 q->pData = &q->pDataPtr;
    2134                 :                         }
    2135           17007 :                         efree(u);
    2136           17007 :                         pefree(*p, ht->persistent);
    2137           17007 :                         *p = q;
    2138           17007 :                         if (q->pListNext) {
    2139               0 :                                 q->pListNext->pListLast = q;
    2140                 :                         } else {
    2141           17007 :                                 ht->pListTail = q;
    2142                 :                         }
    2143                 :                 }
    2144         1326546 :                 nIndex = (*p)->h & ht->nTableMask;
    2145         1326546 :                 CONNECT_TO_BUCKET_DLLIST(*p, ht->arBuckets[nIndex]);
    2146         1326546 :                 ht->arBuckets[nIndex] = *p;
    2147         1326546 :                 if (apply_func) {
    2148         1309539 :                         apply_func((*p)->pData TSRMLS_CC);
    2149                 :                 }
    2150         1326546 :                 p = &(*p)->pListNext;
    2151                 :         }
    2152                 : }
    2153                 : /* }}} */
    2154                 : 
    2155                 : #if ZEND_DEBUG
    2156                 : void zend_hash_display_pListTail(const HashTable *ht) /* {{{ */
    2157                 : {
    2158                 :         Bucket *p;
    2159                 : 
    2160                 :         p = ht->pListTail;
    2161                 :         while (p != NULL) {
    2162                 :                 if (p->key.type == IS_UNICODE) {
    2163                 :                         /* FIXME: Unicode support??? */
    2164                 :                 } else {
    2165                 :                         zend_output_debug_string(0, "pListTail has key %s\n", p->key.arKey.s);
    2166                 :                 }
    2167                 :                 p = p->pListLast;
    2168                 :         }
    2169                 : }
    2170                 : /* }}} */
    2171                 : 
    2172                 : void zend_hash_display(const HashTable *ht) /* {{{ */
    2173                 : {
    2174                 :         Bucket *p;
    2175                 :         uint i;
    2176                 : 
    2177                 :         for (i = 0; i < ht->nTableSize; i++) {
    2178                 :                 p = ht->arBuckets[i];
    2179                 :                 while (p != NULL) {
    2180                 :                         if (p->key.type == IS_UNICODE) {
    2181                 :                                 /* FIXME: Unicode support??? */
    2182                 :                         } else {
    2183                 :                                 zend_output_debug_string(0, "%s <==> 0x%lX\n", p->key.arKey.s, p->h);
    2184                 :                         }
    2185                 :                         p = p->pNext;
    2186                 :                 }
    2187                 :         }
    2188                 : 
    2189                 :         p = ht->pListTail;
    2190                 :         while (p != NULL) {
    2191                 :                 if (p->key.type == IS_UNICODE) {
    2192                 :                         /* FIXME: Unicode support??? */
    2193                 :                 } else {
    2194                 :                         zend_output_debug_string(0, "%s <==> 0x%lX\n", p->key.arKey.s, p->h);
    2195                 :                 }
    2196                 :                 p = p->pListLast;
    2197                 :         }
    2198                 : }
    2199                 : /* }}} */
    2200                 : 
    2201                 : #endif
    2202                 : 
    2203                 : /*
    2204                 :  * Local variables:
    2205                 :  * tab-width: 4
    2206                 :  * c-basic-offset: 4
    2207                 :  * indent-tabs-mode: t
    2208                 :  * End:
    2209                 :  */

Generated by: LTP GCOV extension version 1.5

Generated at Mon, 23 Nov 2009 17:39:27 +0000 (35 hours ago)

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