Diff for /embedaddon/php/Zend/zend_hash.c between versions 1.1.1.1 and 1.1.1.2

version 1.1.1.1, 2012/02/21 23:47:52 version 1.1.1.2, 2012/05/29 12:34:35
Line 20 Line 20
 /* $Id$ */  /* $Id$ */
   
 #include "zend.h"  #include "zend.h"
#include "zend_compile.h"#include "zend_globals.h"
   
 #define CONNECT_TO_BUCKET_DLLIST(element, list_head)            \  #define CONNECT_TO_BUCKET_DLLIST(element, list_head)            \
         (element)->pNext = (list_head);                                                 \          (element)->pNext = (list_head);                                                 \
Line 136  ZEND_API ulong zend_hash_func(const char *arKey, uint  Line 136  ZEND_API ulong zend_hash_func(const char *arKey, uint 
                 (p)->pDataPtr=NULL;                                                                                             \                  (p)->pDataPtr=NULL;                                                                                             \
         }          }
   
   #define CHECK_INIT(ht) do {                                                                                             \
           if (UNEXPECTED((ht)->nTableMask == 0)) {                                                                \
                   (ht)->arBuckets = (Bucket **) pecalloc((ht)->nTableSize, sizeof(Bucket *), (ht)->persistent);   \
                   (ht)->nTableMask = (ht)->nTableSize - 1;                                                \
           }                                                                                                                                       \
   } while (0)
    
   static const Bucket *uninitialized_bucket = NULL;
   
 #if SUHOSIN_PATCH  
 #ifdef ZTS  
 static MUTEX_T zend_hash_dprot_mx_reader;  
 static MUTEX_T zend_hash_dprot_mx_writer;  
 static unsigned int zend_hash_dprot_reader;  
 #endif  
 static unsigned int zend_hash_dprot_counter;  
 static unsigned int zend_hash_dprot_curmax;  
 static dtor_func_t *zend_hash_dprot_table = NULL;  
   
 static void zend_hash_dprot_begin_read()  
 {  
 #ifdef ZTS  
         tsrm_mutex_lock(zend_hash_dprot_mx_reader);  
         if ((++(zend_hash_dprot_reader)) == 1) {  
                 tsrm_mutex_lock(zend_hash_dprot_mx_writer);  
         }  
         tsrm_mutex_unlock(zend_hash_dprot_mx_reader);  
 #endif  
 }  
   
 static void zend_hash_dprot_end_read()  
 {  
 #ifdef ZTS  
         tsrm_mutex_lock(zend_hash_dprot_mx_reader);  
         if ((--(zend_hash_dprot_reader)) == 0) {  
                 tsrm_mutex_unlock(zend_hash_dprot_mx_writer);  
         }  
         tsrm_mutex_unlock(zend_hash_dprot_mx_reader);  
 #endif  
 }  
   
 static void zend_hash_dprot_begin_write()  
 {  
 #ifdef ZTS  
         tsrm_mutex_lock(zend_hash_dprot_mx_writer);  
 #endif  
 }  
   
 static void zend_hash_dprot_end_write()  
 {  
 #ifdef ZTS  
         tsrm_mutex_unlock(zend_hash_dprot_mx_writer);  
 #endif  
 }  
   
 /*ZEND_API void zend_hash_dprot_dtor()  
 {  
 #ifdef ZTS  
         tsrm_mutex_free(zend_hash_dprot_mx_reader);  
         tsrm_mutex_free(zend_hash_dprot_mx_writer);  
 #endif    
         free(zend_hash_dprot_table);  
 }*/  
   
 static void zend_hash_add_destructor(dtor_func_t pDestructor)  
 {  
         int left, right, mid;  
         zend_bool found = 0;  
         unsigned long value;  
           
         if (pDestructor == NULL || pDestructor == ZVAL_PTR_DTOR || pDestructor == ZVAL_INTERNAL_PTR_DTOR  
             || pDestructor == ZEND_FUNCTION_DTOR || pDestructor == ZEND_CLASS_DTOR) {  
                 return;  
         }  
           
         if (zend_hash_dprot_table == NULL) {  
 #ifdef ZTS  
                 zend_hash_dprot_mx_reader = tsrm_mutex_alloc();  
                 zend_hash_dprot_mx_writer = tsrm_mutex_alloc();  
                 zend_hash_dprot_reader = 0;  
 #endif    
                 zend_hash_dprot_counter = 0;  
                 zend_hash_dprot_curmax = 256;  
                 zend_hash_dprot_table = (dtor_func_t *) malloc(256 * sizeof(dtor_func_t));  
         }  
           
         zend_hash_dprot_begin_write();  
   
         if (zend_hash_dprot_counter == 0) {  
                 zend_hash_dprot_counter++;  
                 zend_hash_dprot_table[0] = pDestructor;  
         } else {  
                 value = (unsigned long) pDestructor;  
                 left = 0;  
                 right = zend_hash_dprot_counter-1;  
                 mid = 0;  
                   
                 while (left < right) {  
                         mid = (right - left) >> 1;  
                         mid += left;  
                         if ((unsigned long)zend_hash_dprot_table[mid] == value) {  
                                 found = 1;  
                                 break;  
                         }  
                         if (value < (unsigned long)zend_hash_dprot_table[mid]) {  
                                 right = mid-1;  
                         } else {  
                                 left = mid+1;  
                         }  
                 }  
                 if ((unsigned long)zend_hash_dprot_table[left] == value) {  
                         found = 1;  
                 }  
                   
                 if (!found) {  
                   
                         if (zend_hash_dprot_counter >= zend_hash_dprot_curmax) {  
                                 zend_hash_dprot_curmax += 256;  
                                 zend_hash_dprot_table = (dtor_func_t *) realloc(zend_hash_dprot_table, zend_hash_dprot_curmax * sizeof(dtor_func_t));  
                         }  
                           
                         if ((unsigned long)zend_hash_dprot_table[left] < value) {  
                                 memmove(zend_hash_dprot_table+left+2, zend_hash_dprot_table+left+1, (zend_hash_dprot_counter-left-1)*sizeof(dtor_func_t));  
                                 zend_hash_dprot_table[left+1] = pDestructor;  
                         } else {  
                                 memmove(zend_hash_dprot_table+left+1, zend_hash_dprot_table+left, (zend_hash_dprot_counter-left)*sizeof(dtor_func_t));  
                                 zend_hash_dprot_table[left] = pDestructor;  
                         }  
   
                         zend_hash_dprot_counter++;  
                 }  
         }  
           
         zend_hash_dprot_end_write();  
 }  
   
 static void zend_hash_check_destructor(dtor_func_t pDestructor)  
 {  
         unsigned long value;  
           
         if (pDestructor == NULL || pDestructor == ZVAL_PTR_DTOR || pDestructor == ZVAL_INTERNAL_PTR_DTOR  
 #ifdef ZEND_ENGINE_2  
                 || pDestructor == suhosin_zend_destroy_property_info_internal || pDestructor == suhosin_zend_destroy_property_info  
 #endif  
             || pDestructor == ZEND_FUNCTION_DTOR || pDestructor == ZEND_CLASS_DTOR) {  
                 return;  
         }  
   
         zend_hash_dprot_begin_read();  
           
         if (zend_hash_dprot_counter > 0) {  
                 int left, right, mid;  
                 zend_bool found = 0;  
           
                 value = (unsigned long) pDestructor;  
                 left = 0;  
                 right = zend_hash_dprot_counter-1;  
                   
                 while (left < right) {  
                         mid = (right - left) >> 1;  
                         mid += left;  
                         if ((unsigned long)zend_hash_dprot_table[mid] == value) {  
                                 found = 1;  
                                 break;  
                         }  
                         if (value < (unsigned long)zend_hash_dprot_table[mid]) {  
                                 right = mid-1;  
                         } else {  
                                 left = mid+1;  
                         }  
                 }  
                 if ((unsigned long)zend_hash_dprot_table[left] == value) {  
                         found = 1;  
                 }  
                   
                 if (!found) {  
                         zend_hash_dprot_end_read();  
                   
                         zend_suhosin_log(S_MEMORY, "possible memory corruption detected - unknown Hashtable destructor");  
                         if (SUHOSIN_CONFIG(SUHOSIN_HT_IGNORE_INVALID_DESTRUCTOR) == 0) {  
                                 _exit(1);  
                         }  
                         return;  
                 }  
           
         } else {  
                 zend_hash_dprot_end_read();  
           
                 zend_suhosin_log(S_MEMORY, "possible memory corruption detected - unknown Hashtable destructor");  
                 if (SUHOSIN_CONFIG(SUHOSIN_HT_IGNORE_INVALID_DESTRUCTOR) == 0) {  
                         _exit(1);  
                 }  
                 return;           
         }  
           
         zend_hash_dprot_end_read();  
 }  
   
 #else  
 #define zend_hash_add_destructor(pDestructor) do {} while(0)  
 #define zend_hash_check_destructor(pDestructor) do {} while(0)  
 #endif  
   
 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)  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)
 {  {
         uint i = 3;          uint i = 3;
         Bucket **tmp;  
   
         SET_INCONSISTENT(HT_OK);          SET_INCONSISTENT(HT_OK);
   
Line 348  ZEND_API int _zend_hash_init(HashTable *ht, uint nSize Line 161  ZEND_API int _zend_hash_init(HashTable *ht, uint nSize
                 ht->nTableSize = 1 << i;                  ht->nTableSize = 1 << i;
         }          }
   
        ht->nTableMask = ht->nTableSize - 1;        ht->nTableMask = 0;      /* 0 means that ht->arBuckets is uninitialized */
         ht->pDestructor = pDestructor;          ht->pDestructor = pDestructor;
        zend_hash_add_destructor(pDestructor);        ht->arBuckets = (Bucket**)&uninitialized_bucket;
        ht->arBuckets = NULL; 
         ht->pListHead = NULL;          ht->pListHead = NULL;
         ht->pListTail = NULL;          ht->pListTail = NULL;
         ht->nNumOfElements = 0;          ht->nNumOfElements = 0;
Line 360  ZEND_API int _zend_hash_init(HashTable *ht, uint nSize Line 172  ZEND_API int _zend_hash_init(HashTable *ht, uint nSize
         ht->persistent = persistent;          ht->persistent = persistent;
         ht->nApplyCount = 0;          ht->nApplyCount = 0;
         ht->bApplyProtection = 1;          ht->bApplyProtection = 1;
           
         /* Uses ecalloc() so that Bucket* == NULL */  
         if (persistent) {  
                 tmp = (Bucket **) calloc(ht->nTableSize, sizeof(Bucket *));  
                 if (!tmp) {  
                         return FAILURE;  
                 }  
                 ht->arBuckets = tmp;  
         } else {  
                 tmp = (Bucket **) ecalloc_rel(ht->nTableSize, sizeof(Bucket *));  
                 if (tmp) {  
                         ht->arBuckets = tmp;  
                 }  
         }  
           
         return SUCCESS;          return SUCCESS;
 }  }
   
Line 400  ZEND_API int _zend_hash_add_or_update(HashTable *ht, c Line 197  ZEND_API int _zend_hash_add_or_update(HashTable *ht, c
         ulong h;          ulong h;
         uint nIndex;          uint nIndex;
         Bucket *p;          Bucket *p;
   #ifdef ZEND_SIGNALS
           TSRMLS_FETCH();
   #endif
   
         IS_CONSISTENT(ht);          IS_CONSISTENT(ht);
   
Line 410  ZEND_API int _zend_hash_add_or_update(HashTable *ht, c Line 210  ZEND_API int _zend_hash_add_or_update(HashTable *ht, c
                 return FAILURE;                  return FAILURE;
         }          }
   
           CHECK_INIT(ht);
   
         h = zend_inline_hash_func(arKey, nKeyLength);          h = zend_inline_hash_func(arKey, nKeyLength);
         nIndex = h & ht->nTableMask;          nIndex = h & ht->nTableMask;
   
         p = ht->arBuckets[nIndex];          p = ht->arBuckets[nIndex];
         while (p != NULL) {          while (p != NULL) {
                if ((p->h == h) && (p->nKeyLength == nKeyLength)) {                if (p->arKey == arKey ||
                        if (!memcmp(p->arKey, arKey, nKeyLength)) {                        ((p->h == h) && (p->nKeyLength == nKeyLength) && !memcmp(p->arKey, arKey, nKeyLength))) {
                                 if (flag & HASH_ADD) {                                  if (flag & HASH_ADD) {
                                         return FAILURE;                                          return FAILURE;
                                 }                                  }
Line 428  ZEND_API int _zend_hash_add_or_update(HashTable *ht, c Line 230  ZEND_API int _zend_hash_add_or_update(HashTable *ht, c
                                         return FAILURE;                                          return FAILURE;
                                 }                                  }
 #endif  #endif
                                 zend_hash_check_destructor(ht->pDestructor);  
                                 if (ht->pDestructor) {                                  if (ht->pDestructor) {
                                         ht->pDestructor(p->pData);                                          ht->pDestructor(p->pData);
                                 }                                  }
Line 438  ZEND_API int _zend_hash_add_or_update(HashTable *ht, c Line 239  ZEND_API int _zend_hash_add_or_update(HashTable *ht, c
                                 }                                  }
                                 HANDLE_UNBLOCK_INTERRUPTIONS();                                  HANDLE_UNBLOCK_INTERRUPTIONS();
                                 return SUCCESS;                                  return SUCCESS;
                         }  
                 }                  }
                 p = p->pNext;                  p = p->pNext;
         }          }
                   
        p = (Bucket *) pemalloc(sizeof(Bucket) - 1 + nKeyLength, ht->persistent);        if (IS_INTERNED(arKey)) {
        if (!p) {                p = (Bucket *) pemalloc(sizeof(Bucket), ht->persistent);
                return FAILURE;                if (!p) {
                         return FAILURE;
                 }
                 p->arKey = arKey;
         } else {
                 p = (Bucket *) pemalloc(sizeof(Bucket) + nKeyLength, ht->persistent);
                 if (!p) {
                         return FAILURE;
                 }
                 p->arKey = (const char*)(p + 1);
                 memcpy((char*)p->arKey, arKey, nKeyLength);
         }          }
         memcpy(p->arKey, arKey, nKeyLength);  
         p->nKeyLength = nKeyLength;          p->nKeyLength = nKeyLength;
         INIT_DATA(ht, p, pData, nDataSize);          INIT_DATA(ht, p, pData, nDataSize);
         p->h = h;          p->h = h;
Line 470  ZEND_API int _zend_hash_quick_add_or_update(HashTable  Line 279  ZEND_API int _zend_hash_quick_add_or_update(HashTable 
 {  {
         uint nIndex;          uint nIndex;
         Bucket *p;          Bucket *p;
   #ifdef ZEND_SIGNALS
           TSRMLS_FETCH();
   #endif
   
         IS_CONSISTENT(ht);          IS_CONSISTENT(ht);
   
Line 477  ZEND_API int _zend_hash_quick_add_or_update(HashTable  Line 289  ZEND_API int _zend_hash_quick_add_or_update(HashTable 
                 return zend_hash_index_update(ht, h, pData, nDataSize, pDest);                  return zend_hash_index_update(ht, h, pData, nDataSize, pDest);
         }          }
   
           CHECK_INIT(ht);
         nIndex = h & ht->nTableMask;          nIndex = h & ht->nTableMask;
                   
         p = ht->arBuckets[nIndex];          p = ht->arBuckets[nIndex];
         while (p != NULL) {          while (p != NULL) {
                if ((p->h == h) && (p->nKeyLength == nKeyLength)) {                if (p->arKey == arKey ||
                        if (!memcmp(p->arKey, arKey, nKeyLength)) {                        ((p->h == h) && (p->nKeyLength == nKeyLength) && !memcmp(p->arKey, arKey, nKeyLength))) {
                                 if (flag & HASH_ADD) {                                  if (flag & HASH_ADD) {
                                         return FAILURE;                                          return FAILURE;
                                 }                                  }
Line 494  ZEND_API int _zend_hash_quick_add_or_update(HashTable  Line 307  ZEND_API int _zend_hash_quick_add_or_update(HashTable 
                                         return FAILURE;                                          return FAILURE;
                                 }                                  }
 #endif  #endif
                                 zend_hash_check_destructor(ht->pDestructor);  
                                 if (ht->pDestructor) {                                  if (ht->pDestructor) {
                                         ht->pDestructor(p->pData);                                          ht->pDestructor(p->pData);
                                 }                                  }
Line 504  ZEND_API int _zend_hash_quick_add_or_update(HashTable  Line 316  ZEND_API int _zend_hash_quick_add_or_update(HashTable 
                                 }                                  }
                                 HANDLE_UNBLOCK_INTERRUPTIONS();                                  HANDLE_UNBLOCK_INTERRUPTIONS();
                                 return SUCCESS;                                  return SUCCESS;
                         }  
                 }                  }
                 p = p->pNext;                  p = p->pNext;
         }          }
                   
        p = (Bucket *) pemalloc(sizeof(Bucket) - 1 + nKeyLength, ht->persistent);        if (IS_INTERNED(arKey)) {
        if (!p) {                p = (Bucket *) pemalloc(sizeof(Bucket), ht->persistent);
                return FAILURE;                if (!p) {
                         return FAILURE;
                 }
                 p->arKey = arKey;
         } else {
                 p = (Bucket *) pemalloc(sizeof(Bucket) + nKeyLength, ht->persistent);
                 if (!p) {
                         return FAILURE;
                 }
                 p->arKey = (const char*)(p + 1);
                 memcpy((char*)p->arKey, arKey, nKeyLength);
         }          }
   
         memcpy(p->arKey, arKey, nKeyLength);  
         p->nKeyLength = nKeyLength;          p->nKeyLength = nKeyLength;
         INIT_DATA(ht, p, pData, nDataSize);          INIT_DATA(ht, p, pData, nDataSize);
         p->h = h;          p->h = h;
Line 548  ZEND_API int _zend_hash_index_update_or_next_insert(Ha Line 368  ZEND_API int _zend_hash_index_update_or_next_insert(Ha
 {  {
         uint nIndex;          uint nIndex;
         Bucket *p;          Bucket *p;
   #ifdef ZEND_SIGNALS
           TSRMLS_FETCH();
   #endif
   
         IS_CONSISTENT(ht);          IS_CONSISTENT(ht);
           CHECK_INIT(ht);
   
         if (flag & HASH_NEXT_INSERT) {          if (flag & HASH_NEXT_INSERT) {
                 h = ht->nNextFreeElement;                  h = ht->nNextFreeElement;
Line 570  ZEND_API int _zend_hash_index_update_or_next_insert(Ha Line 394  ZEND_API int _zend_hash_index_update_or_next_insert(Ha
                                 return FAILURE;                                  return FAILURE;
                         }                          }
 #endif  #endif
                         zend_hash_check_destructor(ht->pDestructor);  
                         if (ht->pDestructor) {                          if (ht->pDestructor) {
                                 ht->pDestructor(p->pData);                                  ht->pDestructor(p->pData);
                         }                          }
Line 586  ZEND_API int _zend_hash_index_update_or_next_insert(Ha Line 409  ZEND_API int _zend_hash_index_update_or_next_insert(Ha
                 }                  }
                 p = p->pNext;                  p = p->pNext;
         }          }
        p = (Bucket *) pemalloc_rel(sizeof(Bucket) - 1, ht->persistent);        p = (Bucket *) pemalloc_rel(sizeof(Bucket), ht->persistent);
         if (!p) {          if (!p) {
                 return FAILURE;                  return FAILURE;
         }          }
           p->arKey = NULL;
         p->nKeyLength = 0; /* Numeric indices are marked by making the nKeyLength == 0 */          p->nKeyLength = 0; /* Numeric indices are marked by making the nKeyLength == 0 */
         p->h = h;          p->h = h;
         INIT_DATA(ht, p, pData, nDataSize);          INIT_DATA(ht, p, pData, nDataSize);
Line 616  ZEND_API int _zend_hash_index_update_or_next_insert(Ha Line 440  ZEND_API int _zend_hash_index_update_or_next_insert(Ha
 static int zend_hash_do_resize(HashTable *ht)  static int zend_hash_do_resize(HashTable *ht)
 {  {
         Bucket **t;          Bucket **t;
   #ifdef ZEND_SIGNALS
           TSRMLS_FETCH();
   #endif
   
         IS_CONSISTENT(ht);          IS_CONSISTENT(ht);
   
Line 641  ZEND_API int zend_hash_rehash(HashTable *ht) Line 468  ZEND_API int zend_hash_rehash(HashTable *ht)
         uint nIndex;          uint nIndex;
   
         IS_CONSISTENT(ht);          IS_CONSISTENT(ht);
           if (UNEXPECTED(ht->nNumOfElements == 0)) {
                   return SUCCESS;
           }
   
         memset(ht->arBuckets, 0, ht->nTableSize * sizeof(Bucket *));          memset(ht->arBuckets, 0, ht->nTableSize * sizeof(Bucket *));
         p = ht->pListHead;          p = ht->pListHead;
Line 657  ZEND_API int zend_hash_del_key_or_index(HashTable *ht, Line 487  ZEND_API int zend_hash_del_key_or_index(HashTable *ht,
 {  {
         uint nIndex;          uint nIndex;
         Bucket *p;          Bucket *p;
   #ifdef ZEND_SIGNALS
           TSRMLS_FETCH();
   #endif
   
         IS_CONSISTENT(ht);          IS_CONSISTENT(ht);
   
Line 694  ZEND_API int zend_hash_del_key_or_index(HashTable *ht, Line 527  ZEND_API int zend_hash_del_key_or_index(HashTable *ht,
                         if (ht->pInternalPointer == p) {                          if (ht->pInternalPointer == p) {
                                 ht->pInternalPointer = p->pListNext;                                  ht->pInternalPointer = p->pListNext;
                         }                          }
                         zend_hash_check_destructor(ht->pDestructor);  
                         if (ht->pDestructor) {                          if (ht->pDestructor) {
                                 ht->pDestructor(p->pData);                                  ht->pDestructor(p->pData);
                         }                          }
Line 721  ZEND_API void zend_hash_destroy(HashTable *ht) Line 553  ZEND_API void zend_hash_destroy(HashTable *ht)
         SET_INCONSISTENT(HT_IS_DESTROYING);          SET_INCONSISTENT(HT_IS_DESTROYING);
   
         p = ht->pListHead;          p = ht->pListHead;
         zend_hash_check_destructor(ht->pDestructor);  
         while (p != NULL) {          while (p != NULL) {
                 q = p;                  q = p;
                 p = p->pListNext;                  p = p->pListNext;
Line 733  ZEND_API void zend_hash_destroy(HashTable *ht) Line 564  ZEND_API void zend_hash_destroy(HashTable *ht)
                 }                  }
                 pefree(q, ht->persistent);                  pefree(q, ht->persistent);
         }          }
        pefree(ht->arBuckets, ht->persistent);        if (ht->nTableMask) {
                 pefree(ht->arBuckets, ht->persistent);
         }
   
         SET_INCONSISTENT(HT_DESTROYED);          SET_INCONSISTENT(HT_DESTROYED);
 }  }
Line 747  ZEND_API void zend_hash_clean(HashTable *ht) Line 580  ZEND_API void zend_hash_clean(HashTable *ht)
   
         p = ht->pListHead;          p = ht->pListHead;
   
        memset(ht->arBuckets, 0, ht->nTableSize*sizeof(Bucket *));        if (ht->nTableMask) {
                 memset(ht->arBuckets, 0, ht->nTableSize*sizeof(Bucket *));
         }
         ht->pListHead = NULL;          ht->pListHead = NULL;
         ht->pListTail = NULL;          ht->pListTail = NULL;
         ht->nNumOfElements = 0;          ht->nNumOfElements = 0;
         ht->nNextFreeElement = 0;          ht->nNextFreeElement = 0;
         ht->pInternalPointer = NULL;          ht->pInternalPointer = NULL;
   
         zend_hash_check_destructor(ht->pDestructor);  
         while (p != NULL) {          while (p != NULL) {
                 q = p;                  q = p;
                 p = p->pListNext;                  p = p->pListNext;
Line 776  ZEND_API void zend_hash_clean(HashTable *ht) Line 610  ZEND_API void zend_hash_clean(HashTable *ht)
 static Bucket *zend_hash_apply_deleter(HashTable *ht, Bucket *p)  static Bucket *zend_hash_apply_deleter(HashTable *ht, Bucket *p)
 {  {
         Bucket *retval;          Bucket *retval;
   #ifdef ZEND_SIGNALS
           TSRMLS_FETCH();
   #endif
   
         HANDLE_BLOCK_INTERRUPTIONS();          HANDLE_BLOCK_INTERRUPTIONS();
         if (p->pLast) {          if (p->pLast) {
Line 809  static Bucket *zend_hash_apply_deleter(HashTable *ht,  Line 646  static Bucket *zend_hash_apply_deleter(HashTable *ht, 
         ht->nNumOfElements--;          ht->nNumOfElements--;
         HANDLE_UNBLOCK_INTERRUPTIONS();          HANDLE_UNBLOCK_INTERRUPTIONS();
   
         zend_hash_check_destructor(ht->pDestructor);  
         if (ht->pDestructor) {          if (ht->pDestructor) {
                 ht->pDestructor(p->pData);                  ht->pDestructor(p->pData);
         }          }
Line 830  ZEND_API void zend_hash_graceful_destroy(HashTable *ht Line 666  ZEND_API void zend_hash_graceful_destroy(HashTable *ht
         IS_CONSISTENT(ht);          IS_CONSISTENT(ht);
   
         p = ht->pListHead;          p = ht->pListHead;
         zend_hash_check_destructor(ht->pDestructor);  
         while (p != NULL) {          while (p != NULL) {
                 p = zend_hash_apply_deleter(ht, p);                  p = zend_hash_apply_deleter(ht, p);
         }          }
        pefree(ht->arBuckets, ht->persistent);        if (ht->nTableMask) {
                 pefree(ht->arBuckets, ht->persistent);
         }
   
         SET_INCONSISTENT(HT_DESTROYED);          SET_INCONSISTENT(HT_DESTROYED);
 }  }
Line 851  ZEND_API void zend_hash_graceful_reverse_destroy(HashT Line 688  ZEND_API void zend_hash_graceful_reverse_destroy(HashT
                 p = ht->pListTail;                  p = ht->pListTail;
         }          }
   
        pefree(ht->arBuckets, ht->persistent);        if (ht->nTableMask) {
                 pefree(ht->arBuckets, ht->persistent);
         }
   
         SET_INCONSISTENT(HT_DESTROYED);          SET_INCONSISTENT(HT_DESTROYED);
 }  }
Line 1084  ZEND_API int zend_hash_find(const HashTable *ht, const Line 923  ZEND_API int zend_hash_find(const HashTable *ht, const
   
         p = ht->arBuckets[nIndex];          p = ht->arBuckets[nIndex];
         while (p != NULL) {          while (p != NULL) {
                if ((p->h == h) && (p->nKeyLength == nKeyLength)) {                if (p->arKey == arKey ||
                        if (!memcmp(p->arKey, arKey, nKeyLength)) {                        ((p->h == h) && (p->nKeyLength == nKeyLength) && !memcmp(p->arKey, arKey, nKeyLength))) {
                                 *pData = p->pData;                                  *pData = p->pData;
                                 return SUCCESS;                                  return SUCCESS;
                         }  
                 }                  }
                 p = p->pNext;                  p = p->pNext;
         }          }
Line 1111  ZEND_API int zend_hash_quick_find(const HashTable *ht, Line 949  ZEND_API int zend_hash_quick_find(const HashTable *ht,
   
         p = ht->arBuckets[nIndex];          p = ht->arBuckets[nIndex];
         while (p != NULL) {          while (p != NULL) {
                if ((p->h == h) && (p->nKeyLength == nKeyLength)) {                if (p->arKey == arKey ||
                        if (!memcmp(p->arKey, arKey, nKeyLength)) {                        ((p->h == h) && (p->nKeyLength == nKeyLength) && !memcmp(p->arKey, arKey, nKeyLength))) {
                                 *pData = p->pData;                                  *pData = p->pData;
                                 return SUCCESS;                                  return SUCCESS;
                         }  
                 }                  }
                 p = p->pNext;                  p = p->pNext;
         }          }
Line 1136  ZEND_API int zend_hash_exists(const HashTable *ht, con Line 973  ZEND_API int zend_hash_exists(const HashTable *ht, con
   
         p = ht->arBuckets[nIndex];          p = ht->arBuckets[nIndex];
         while (p != NULL) {          while (p != NULL) {
                if ((p->h == h) && (p->nKeyLength == nKeyLength)) {                if (p->arKey == arKey ||
                        if (!memcmp(p->arKey, arKey, nKeyLength)) {                        ((p->h == h) && (p->nKeyLength == nKeyLength) && !memcmp(p->arKey, arKey, nKeyLength))) {
                                 return 1;                                  return 1;
                         }  
                 }                  }
                 p = p->pNext;                  p = p->pNext;
         }          }
Line 1162  ZEND_API int zend_hash_quick_exists(const HashTable *h Line 998  ZEND_API int zend_hash_quick_exists(const HashTable *h
   
         p = ht->arBuckets[nIndex];          p = ht->arBuckets[nIndex];
         while (p != NULL) {          while (p != NULL) {
                if ((p->h == h) && (p->nKeyLength == nKeyLength)) {                if (p->arKey == arKey ||
                        if (!memcmp(p->arKey, arKey, nKeyLength)) {                        ((p->h == h) && (p->nKeyLength == nKeyLength) && !memcmp(p->arKey, arKey, nKeyLength))) {
                                 return 1;                                  return 1;
                         }  
                 }                  }
                 p = p->pNext;                  p = p->pNext;
         }          }
Line 1322  ZEND_API int zend_hash_get_current_key_ex(const HashTa Line 1157  ZEND_API int zend_hash_get_current_key_ex(const HashTa
                         if (duplicate) {                          if (duplicate) {
                                 *str_index = estrndup(p->arKey, p->nKeyLength - 1);                                  *str_index = estrndup(p->arKey, p->nKeyLength - 1);
                         } else {                          } else {
                                *str_index = p->arKey;                                *str_index = (char*)p->arKey;
                         }                          }
                         if (str_length) {                          if (str_length) {
                                 *str_length = p->nKeyLength;                                  *str_length = p->nKeyLength;
Line 1378  ZEND_API int zend_hash_get_current_data_ex(HashTable * Line 1213  ZEND_API int zend_hash_get_current_data_ex(HashTable *
 ZEND_API int zend_hash_update_current_key_ex(HashTable *ht, int key_type, const char *str_index, uint str_length, ulong num_index, int mode, HashPosition *pos)  ZEND_API int zend_hash_update_current_key_ex(HashTable *ht, int key_type, const char *str_index, uint str_length, ulong num_index, int mode, HashPosition *pos)
 {  {
         Bucket *p, *q;          Bucket *p, *q;
           ulong h;
   #ifdef ZEND_SIGNALS
           TSRMLS_FETCH();
   #endif
   
         p = pos ? (*pos) : ht->pInternalPointer;          p = pos ? (*pos) : ht->pInternalPointer;
   
         IS_CONSISTENT(ht);          IS_CONSISTENT(ht);
   
         zend_hash_check_destructor(ht->pDestructor);  
         if (p) {          if (p) {
                 if (key_type == HASH_KEY_IS_LONG) {                  if (key_type == HASH_KEY_IS_LONG) {
                         str_length = 0;                          str_length = 0;
Line 1399  ZEND_API int zend_hash_update_current_key_ex(HashTable Line 1237  ZEND_API int zend_hash_update_current_key_ex(HashTable
                                 q = q->pNext;                                  q = q->pNext;
                         }                          }
                 } else if (key_type == HASH_KEY_IS_STRING) {                  } else if (key_type == HASH_KEY_IS_STRING) {
                        ulong h;                        if (IS_INTERNED(str_index)) {
                                 h = INTERNED_HASH(str_index);
                         } else {
                                 h = zend_inline_hash_func(str_index, str_length);
                         }
   
                        if (p->nKeyLength == str_length &&                        if (p->arKey == str_index ||
                            memcmp(p->arKey, str_index, str_length) == 0) {                            (p->nKeyLength == str_length &&
                              p->h == h &&
                              memcmp(p->arKey, str_index, str_length) == 0)) {
                                 return SUCCESS;                                  return SUCCESS;
                         }                          }
   
                         h = zend_inline_hash_func(str_index, str_length);  
                         q = ht->arBuckets[h & ht->nTableMask];                          q = ht->arBuckets[h & ht->nTableMask];
   
                         while (q != NULL) {                          while (q != NULL) {
                                if (q->h == h && q->nKeyLength == str_length &&                                 if (q->arKey == str_index ||
                                           memcmp(q->arKey, str_index, str_length) == 0) {                                    (q->h == h && q->nKeyLength == str_length &&
                                      memcmp(q->arKey, str_index, str_length) == 0)) {
                                         break;                                          break;
                                 }                                  }
                                 q = q->pNext;                                  q = q->pNext;
Line 1426  ZEND_API int zend_hash_update_current_key_ex(HashTable Line 1270  ZEND_API int zend_hash_update_current_key_ex(HashTable
                         if (mode != HASH_UPDATE_KEY_ANYWAY) {                          if (mode != HASH_UPDATE_KEY_ANYWAY) {
                                 Bucket *r = p->pListLast;                                  Bucket *r = p->pListLast;
                                 int found = HASH_UPDATE_KEY_IF_BEFORE;                                  int found = HASH_UPDATE_KEY_IF_BEFORE;
                                                
                                 while (r) {                                  while (r) {
                                         if (r == q) {                                          if (r == q) {
                                                 found = HASH_UPDATE_KEY_IF_AFTER;                                                  found = HASH_UPDATE_KEY_IF_AFTER;
Line 1446  ZEND_API int zend_hash_update_current_key_ex(HashTable Line 1290  ZEND_API int zend_hash_update_current_key_ex(HashTable
                                         }                                          }
                                         if (p->pListLast != NULL) {                                          if (p->pListLast != NULL) {
                                                 p->pListLast->pListNext = p->pListNext;                                                  p->pListLast->pListNext = p->pListNext;
                                        } else {                                         } else {
                                                 /* Deleting the head of the list */                                                  /* Deleting the head of the list */
                                                 ht->pListHead = p->pListNext;                                                  ht->pListHead = p->pListNext;
                                         }                                          }
Line 1481  ZEND_API int zend_hash_update_current_key_ex(HashTable Line 1325  ZEND_API int zend_hash_update_current_key_ex(HashTable
                         }                          }
                         if (q->pListLast != NULL) {                          if (q->pListLast != NULL) {
                                 q->pListLast->pListNext = q->pListNext;                                  q->pListLast->pListNext = q->pListNext;
                        } else {                         } else {
                                 /* Deleting the head of the list */                                  /* Deleting the head of the list */
                                 ht->pListHead = q->pListNext;                                  ht->pListHead = q->pListNext;
                         }                          }
Line 1512  ZEND_API int zend_hash_update_current_key_ex(HashTable Line 1356  ZEND_API int zend_hash_update_current_key_ex(HashTable
                         ht->arBuckets[p->h & ht->nTableMask] = p->pNext;                          ht->arBuckets[p->h & ht->nTableMask] = p->pNext;
                 }                  }
   
                if (p->nKeyLength != str_length) {                if ((IS_INTERNED(p->arKey) != IS_INTERNED(str_index)) ||
                        Bucket *q = (Bucket *) pemalloc(sizeof(Bucket) - 1 + str_length, ht->persistent);                    (!IS_INTERNED(p->arKey) && p->nKeyLength != str_length)) {
                         Bucket *q;
   
                           if (IS_INTERNED(str_index)) {
                                   q = (Bucket *) pemalloc(sizeof(Bucket), ht->persistent);
                           } else {
                                   q = (Bucket *) pemalloc(sizeof(Bucket) + str_length, ht->persistent);
                           }
   
                         q->nKeyLength = str_length;                          q->nKeyLength = str_length;
                         if (p->pData == &p->pDataPtr) {                          if (p->pData == &p->pDataPtr) {
                                 q->pData = &q->pDataPtr;                                  q->pData = &q->pDataPtr;
Line 1547  ZEND_API int zend_hash_update_current_key_ex(HashTable Line 1398  ZEND_API int zend_hash_update_current_key_ex(HashTable
                 if (key_type == HASH_KEY_IS_LONG) {                  if (key_type == HASH_KEY_IS_LONG) {
                         p->h = num_index;                          p->h = num_index;
                 } else {                  } else {
                        memcpy(p->arKey, str_index, str_length);                        p->h = h;
                        p->h = zend_inline_hash_func(str_index, str_length);                        p->nKeyLength = str_length;
                         if (IS_INTERNED(str_index)) {
                                 p->arKey = str_index;
                         } else {
                                 p->arKey = (const char*)(p+1);
                                 memcpy((char*)p->arKey, str_index, str_length);
                         }
                 }                  }
   
                 CONNECT_TO_BUCKET_DLLIST(p, ht->arBuckets[p->h & ht->nTableMask]);                  CONNECT_TO_BUCKET_DLLIST(p, ht->arBuckets[p->h & ht->nTableMask]);
Line 1763  void zend_hash_display(const HashTable *ht) Line 1620  void zend_hash_display(const HashTable *ht)
         Bucket *p;          Bucket *p;
         uint i;          uint i;
   
           if (UNEXPECTED(ht->nNumOfElements == 0)) {
                   zend_output_debug_string(0, "The hash is empty");
                   return;
           }
         for (i = 0; i < ht->nTableSize; i++) {          for (i = 0; i < ht->nTableSize; i++) {
                 p = ht->arBuckets[i];                  p = ht->arBuckets[i];
                 while (p != NULL) {                  while (p != NULL) {

Removed from v.1.1.1.1  
changed lines
  Added in v.1.1.1.2


FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>