version 1.1, 2012/02/21 23:47:52
|
version 1.1.1.3, 2013/07/22 01:32:15
|
Line 2
|
Line 2
|
+----------------------------------------------------------------------+ |
+----------------------------------------------------------------------+ |
| Zend Engine | |
| Zend Engine | |
+----------------------------------------------------------------------+ |
+----------------------------------------------------------------------+ |
| Copyright (c) 1998-2012 Zend Technologies Ltd. (http://www.zend.com) | | | Copyright (c) 1998-2013 Zend Technologies Ltd. (http://www.zend.com) | |
+----------------------------------------------------------------------+ |
+----------------------------------------------------------------------+ |
| This source file is subject to version 2.00 of the Zend license, | |
| This source file is subject to version 2.00 of the Zend license, | |
| that is bundled with this package in the file LICENSE, and is | |
| that is bundled with this package in the file LICENSE, and is | |
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) { |