dmitry Mon, 01 Aug 2011 11:21:23 +0000 Revision: http://svn.php.net/viewvc?view=revision&revision=314013
Log: Fixed bug #50816 (Using class constants in array definition fails). Bug: https://bugs.php.net/50816 (Verified) Using class constants in array definition fails (works in PHP_5_2) Changed paths: U php/php-src/branches/PHP_5_3/NEWS U php/php-src/branches/PHP_5_3/Zend/tests/bug45742.phpt A php/php-src/branches/PHP_5_3/Zend/tests/bug50816.phpt U php/php-src/branches/PHP_5_3/Zend/zend_hash.c U php/php-src/branches/PHP_5_4/Zend/tests/bug45742.phpt A php/php-src/branches/PHP_5_4/Zend/tests/bug50816.phpt U php/php-src/branches/PHP_5_4/Zend/zend_hash.c U php/php-src/trunk/Zend/tests/bug45742.phpt A php/php-src/trunk/Zend/tests/bug50816.phpt U php/php-src/trunk/Zend/zend_hash.c
Modified: php/php-src/branches/PHP_5_3/NEWS =================================================================== --- php/php-src/branches/PHP_5_3/NEWS 2011-08-01 11:04:57 UTC (rev 314012) +++ php/php-src/branches/PHP_5_3/NEWS 2011-08-01 11:21:23 UTC (rev 314013) @@ -15,6 +15,8 @@ - Core . Fix bug #55295 [NEW]: popen_ex on windows, fixed possible heap overflow (Pierre) + . Fixed bug #50816 (Using class constants in array definition fails). + (Pierrick, Dmitry) 14 Jul 2011, PHP 5.3.7 RC3 - Zend Engine: Modified: php/php-src/branches/PHP_5_3/Zend/tests/bug45742.phpt =================================================================== --- php/php-src/branches/PHP_5_3/Zend/tests/bug45742.phpt 2011-08-01 11:04:57 UTC (rev 314012) +++ php/php-src/branches/PHP_5_3/Zend/tests/bug45742.phpt 2011-08-01 11:21:23 UTC (rev 314013) @@ -20,5 +20,5 @@ --EXPECT-- array(1) { [1]=> - int(23) + int(42) } Added: php/php-src/branches/PHP_5_3/Zend/tests/bug50816.phpt =================================================================== --- php/php-src/branches/PHP_5_3/Zend/tests/bug50816.phpt (rev 0) +++ php/php-src/branches/PHP_5_3/Zend/tests/bug50816.phpt 2011-08-01 11:21:23 UTC (rev 314013) @@ -0,0 +1,48 @@ +--TEST-- +Bug #50816 (Using class constants in array definition fails) +--FILE-- +<?php +define("ONE", 1); +define("TWO", 1); + +class Foo { + const ONE = 1; + const TWO = 1; + + public static $mapWithConst = array(self::ONE => 'one', self::TWO => 'two',); + + public static $mapWithConst1 = array(1 => 'one', self::TWO => 'two',); + public static $mapWithConst2 = array(self::ONE => 'one', 1 => 'two',); + + public static $mapWithoutConst = array(1 => 'one', 1 => 'two',); +} + +$mapWithConst = array(1 => 'one', 1 => 'two',); + +$mapWithoutConst = array(Foo::ONE => 'one', Foo::TWO => 'two',); +$mapWithoutConst0 = array(1 => 'one', 1 => 'two',); +$mapWithoutConst1 = array(ONE => 'one', 1 => 'two',); +$mapWithoutConst2 = array(1 => 'one', TWO => 'two',); +$mapWithoutConst3 = array(ONE => 'one', TWO => 'two',); + +var_dump(Foo::$mapWithConst[1]); +var_dump(Foo::$mapWithConst1[1]); +var_dump(Foo::$mapWithConst2[1]); +var_dump(Foo::$mapWithoutConst[1]); +var_dump($mapWithConst[1]); +var_dump($mapWithoutConst[1]); +var_dump($mapWithoutConst0[1]); +var_dump($mapWithoutConst1[1]); +var_dump($mapWithoutConst2[1]); +var_dump($mapWithoutConst3[1]); +--EXPECT-- +string(3) "two" +string(3) "two" +string(3) "two" +string(3) "two" +string(3) "two" +string(3) "two" +string(3) "two" +string(3) "two" +string(3) "two" +string(3) "two" Modified: php/php-src/branches/PHP_5_3/Zend/zend_hash.c =================================================================== --- php/php-src/branches/PHP_5_3/Zend/zend_hash.c 2011-08-01 11:04:57 UTC (rev 314012) +++ php/php-src/branches/PHP_5_3/Zend/zend_hash.c 2011-08-01 11:21:23 UTC (rev 314013) @@ -1173,7 +1173,7 @@ */ 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; + Bucket *p, *q; p = pos ? (*pos) : ht->pInternalPointer; @@ -1186,100 +1186,124 @@ return SUCCESS; } - if (mode != HASH_UPDATE_KEY_ANYWAY) { - Bucket *q = ht->arBuckets[num_index & ht->nTableMask]; - int found = 0; - - while (q != NULL) { - if (q == p) { - found = 1; - } else if (!q->nKeyLength && q->h == num_index) { - if (found) { - if (mode & HASH_UPDATE_KEY_IF_BEFORE) { - break; - } else { - if (p->nKeyLength) { - zend_hash_del(ht, p->arKey, p->nKeyLength); - } else { - zend_hash_index_del(ht, p->h); - } - return FAILURE; - } - } else { - if (mode & HASH_UPDATE_KEY_IF_AFTER) { - break; - } else { - if (p->nKeyLength) { - zend_hash_del(ht, p->arKey, p->nKeyLength); - } else { - zend_hash_index_del(ht, p->h); - } - return FAILURE; - } - } - } - q = q->pNext; + q = ht->arBuckets[num_index & ht->nTableMask]; + while (q != NULL) { + if (!q->nKeyLength && q->h == num_index) { + break; } + q = q->pNext; } + } else if (key_type == HASH_KEY_IS_STRING) { + ulong h; - zend_hash_index_del(ht, num_index); - } else if (key_type == HASH_KEY_IS_STRING) { if (p->nKeyLength == str_length && memcmp(p->arKey, str_index, str_length) == 0) { return SUCCESS; } - if (mode != HASH_UPDATE_KEY_ANYWAY) { - ulong h = zend_inline_hash_func(str_index, str_length); - Bucket *q = ht->arBuckets[h & ht->nTableMask]; - int found = 0; + h = zend_inline_hash_func(str_index, str_length); + q = ht->arBuckets[h & ht->nTableMask]; - while (q != NULL) { - if (q == p) { - found = 1; - } else if (q->h == h && q->nKeyLength == str_length && - memcmp(q->arKey, str_index, str_length) == 0) { - if (found) { - if (mode & HASH_UPDATE_KEY_IF_BEFORE) { - break; - } else { - if (p->nKeyLength) { - zend_hash_del(ht, p->arKey, p->nKeyLength); - } else { - zend_hash_index_del(ht, p->h); - } - return FAILURE; - } - } else { - if (mode & HASH_UPDATE_KEY_IF_AFTER) { - break; - } else { - if (p->nKeyLength) { - zend_hash_del(ht, p->arKey, p->nKeyLength); - } else { - zend_hash_index_del(ht, p->h); - } - return FAILURE; - } - } - } - q = q->pNext; + while (q != NULL) { + if (q->h == h && q->nKeyLength == str_length && + memcmp(q->arKey, str_index, str_length) == 0) { + break; } + q = q->pNext; } - - zend_hash_del(ht, str_index, str_length); } else { return FAILURE; } HANDLE_BLOCK_INTERRUPTIONS(); + if (q) { + if (mode != HASH_UPDATE_KEY_ANYWAY) { + Bucket *r = p->pListLast; + int found = HASH_UPDATE_KEY_IF_BEFORE; + + while (r) { + if (r == q) { + found = HASH_UPDATE_KEY_IF_AFTER; + break; + } + r = r->pListLast; + } + if (mode & found) { + /* delete current bucket */ + if (p == ht->arBuckets[p->h & ht->nTableMask]) { + ht->arBuckets[p->h & ht->nTableMask] = p->pNext; + } else { + p->pLast->pNext = p->pNext; + } + if (p->pNext) { + p->pNext->pLast = p->pLast; + } + if (p->pListLast != NULL) { + p->pListLast->pListNext = p->pListNext; + } else { + /* Deleting the head of the list */ + ht->pListHead = p->pListNext; + } + if (p->pListNext != NULL) { + p->pListNext->pListLast = p->pListLast; + } else { + ht->pListTail = p->pListLast; + } + if (ht->pInternalPointer == p) { + ht->pInternalPointer = p->pListNext; + } + if (ht->pDestructor) { + ht->pDestructor(p->pData); + } + if (p->pData != &p->pDataPtr) { + pefree(p->pData, ht->persistent); + } + pefree(p, ht->persistent); + ht->nNumOfElements--; + HANDLE_UNBLOCK_INTERRUPTIONS(); + return FAILURE; + } + } + /* delete another bucket with the same key */ + if (q == ht->arBuckets[q->h & ht->nTableMask]) { + ht->arBuckets[q->h & ht->nTableMask] = q->pNext; + } else { + q->pLast->pNext = q->pNext; + } + if (q->pNext) { + q->pNext->pLast = q->pLast; + } + if (q->pListLast != NULL) { + q->pListLast->pListNext = q->pListNext; + } else { + /* Deleting the head of the list */ + ht->pListHead = q->pListNext; + } + if (q->pListNext != NULL) { + q->pListNext->pListLast = q->pListLast; + } else { + ht->pListTail = q->pListLast; + } + if (ht->pInternalPointer == q) { + ht->pInternalPointer = q->pListNext; + } + if (ht->pDestructor) { + ht->pDestructor(q->pData); + } + if (q->pData != &q->pDataPtr) { + pefree(q->pData, ht->persistent); + } + pefree(q, ht->persistent); + ht->nNumOfElements--; + } + if (p->pNext) { p->pNext->pLast = p->pLast; } if (p->pLast) { p->pLast->pNext = p->pNext; - } else{ + } else { ht->arBuckets[p->h & ht->nTableMask] = p->pNext; } Modified: php/php-src/branches/PHP_5_4/Zend/tests/bug45742.phpt =================================================================== --- php/php-src/branches/PHP_5_4/Zend/tests/bug45742.phpt 2011-08-01 11:04:57 UTC (rev 314012) +++ php/php-src/branches/PHP_5_4/Zend/tests/bug45742.phpt 2011-08-01 11:21:23 UTC (rev 314013) @@ -20,5 +20,5 @@ --EXPECT-- array(1) { [1]=> - int(23) + int(42) } Added: php/php-src/branches/PHP_5_4/Zend/tests/bug50816.phpt =================================================================== --- php/php-src/branches/PHP_5_4/Zend/tests/bug50816.phpt (rev 0) +++ php/php-src/branches/PHP_5_4/Zend/tests/bug50816.phpt 2011-08-01 11:21:23 UTC (rev 314013) @@ -0,0 +1,48 @@ +--TEST-- +Bug #50816 (Using class constants in array definition fails) +--FILE-- +<?php +define("ONE", 1); +define("TWO", 1); + +class Foo { + const ONE = 1; + const TWO = 1; + + public static $mapWithConst = array(self::ONE => 'one', self::TWO => 'two',); + + public static $mapWithConst1 = array(1 => 'one', self::TWO => 'two',); + public static $mapWithConst2 = array(self::ONE => 'one', 1 => 'two',); + + public static $mapWithoutConst = array(1 => 'one', 1 => 'two',); +} + +$mapWithConst = array(1 => 'one', 1 => 'two',); + +$mapWithoutConst = array(Foo::ONE => 'one', Foo::TWO => 'two',); +$mapWithoutConst0 = array(1 => 'one', 1 => 'two',); +$mapWithoutConst1 = array(ONE => 'one', 1 => 'two',); +$mapWithoutConst2 = array(1 => 'one', TWO => 'two',); +$mapWithoutConst3 = array(ONE => 'one', TWO => 'two',); + +var_dump(Foo::$mapWithConst[1]); +var_dump(Foo::$mapWithConst1[1]); +var_dump(Foo::$mapWithConst2[1]); +var_dump(Foo::$mapWithoutConst[1]); +var_dump($mapWithConst[1]); +var_dump($mapWithoutConst[1]); +var_dump($mapWithoutConst0[1]); +var_dump($mapWithoutConst1[1]); +var_dump($mapWithoutConst2[1]); +var_dump($mapWithoutConst3[1]); +--EXPECT-- +string(3) "two" +string(3) "two" +string(3) "two" +string(3) "two" +string(3) "two" +string(3) "two" +string(3) "two" +string(3) "two" +string(3) "two" +string(3) "two" Modified: php/php-src/branches/PHP_5_4/Zend/zend_hash.c =================================================================== --- php/php-src/branches/PHP_5_4/Zend/zend_hash.c 2011-08-01 11:04:57 UTC (rev 314012) +++ php/php-src/branches/PHP_5_4/Zend/zend_hash.c 2011-08-01 11:21:23 UTC (rev 314013) @@ -1211,7 +1211,8 @@ */ 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; + Bucket *p, *q; + ulong h; #ifdef ZEND_SIGNALS TSRMLS_FETCH(); #endif @@ -1227,106 +1228,143 @@ return SUCCESS; } - if (mode != HASH_UPDATE_KEY_ANYWAY) { - Bucket *q = ht->arBuckets[num_index & ht->nTableMask]; - int found = 0; - - while (q != NULL) { - if (q == p) { - found = 1; - } else if (!q->nKeyLength && q->h == num_index) { - if (found) { - if (mode & HASH_UPDATE_KEY_IF_BEFORE) { - break; - } else { - if (p->nKeyLength) { - zend_hash_del(ht, p->arKey, p->nKeyLength); - } else { - zend_hash_index_del(ht, p->h); - } - return FAILURE; - } - } else { - if (mode & HASH_UPDATE_KEY_IF_AFTER) { - break; - } else { - if (p->nKeyLength) { - zend_hash_del(ht, p->arKey, p->nKeyLength); - } else { - zend_hash_index_del(ht, p->h); - } - return FAILURE; - } - } - } - q = q->pNext; + q = ht->arBuckets[num_index & ht->nTableMask]; + while (q != NULL) { + if (!q->nKeyLength && q->h == num_index) { + break; } + q = q->pNext; } + } else if (key_type == HASH_KEY_IS_STRING) { + if (IS_INTERNED(str_index)) { + h = INTERNED_HASH(str_index); + } else { + h = zend_inline_hash_func(str_index, str_length); + } - zend_hash_index_del(ht, num_index); - } else if (key_type == HASH_KEY_IS_STRING) { - if (p->nKeyLength == str_length && - memcmp(p->arKey, str_index, str_length) == 0) { + if (p->arKey == str_index || + (p->nKeyLength == str_length && + p->h == h && + memcmp(p->arKey, str_index, str_length) == 0)) { return SUCCESS; } - if (mode != HASH_UPDATE_KEY_ANYWAY) { - ulong h = zend_inline_hash_func(str_index, str_length); - Bucket *q = ht->arBuckets[h & ht->nTableMask]; - int found = 0; + q = ht->arBuckets[h & ht->nTableMask]; - while (q != NULL) { - if (q == p) { - found = 1; - } else if (q->h == h && q->nKeyLength == str_length && - memcmp(q->arKey, str_index, str_length) == 0) { - if (found) { - if (mode & HASH_UPDATE_KEY_IF_BEFORE) { - break; - } else { - if (p->nKeyLength) { - zend_hash_del(ht, p->arKey, p->nKeyLength); - } else { - zend_hash_index_del(ht, p->h); - } - return FAILURE; - } - } else { - if (mode & HASH_UPDATE_KEY_IF_AFTER) { - break; - } else { - if (p->nKeyLength) { - zend_hash_del(ht, p->arKey, p->nKeyLength); - } else { - zend_hash_index_del(ht, p->h); - } - return FAILURE; - } - } - } - q = q->pNext; + while (q != NULL) { + if (q->arKey == str_index || + (q->h == h && q->nKeyLength == str_length && + memcmp(q->arKey, str_index, str_length) == 0)) { + break; } + q = q->pNext; } - - zend_hash_del(ht, str_index, str_length); } else { return FAILURE; } HANDLE_BLOCK_INTERRUPTIONS(); + if (q) { + if (mode != HASH_UPDATE_KEY_ANYWAY) { + Bucket *r = p->pListLast; + int found = HASH_UPDATE_KEY_IF_BEFORE; + + while (r) { + if (r == q) { + found = HASH_UPDATE_KEY_IF_AFTER; + break; + } + r = r->pListLast; + } + if (mode & found) { + /* delete current bucket */ + if (p == ht->arBuckets[p->h & ht->nTableMask]) { + ht->arBuckets[p->h & ht->nTableMask] = p->pNext; + } else { + p->pLast->pNext = p->pNext; + } + if (p->pNext) { + p->pNext->pLast = p->pLast; + } + if (p->pListLast != NULL) { + p->pListLast->pListNext = p->pListNext; + } else { + /* Deleting the head of the list */ + ht->pListHead = p->pListNext; + } + if (p->pListNext != NULL) { + p->pListNext->pListLast = p->pListLast; + } else { + ht->pListTail = p->pListLast; + } + if (ht->pInternalPointer == p) { + ht->pInternalPointer = p->pListNext; + } + if (ht->pDestructor) { + ht->pDestructor(p->pData); + } + if (p->pData != &p->pDataPtr) { + pefree(p->pData, ht->persistent); + } + pefree(p, ht->persistent); + ht->nNumOfElements--; + HANDLE_UNBLOCK_INTERRUPTIONS(); + return FAILURE; + } + } + /* delete another bucket with the same key */ + if (q == ht->arBuckets[q->h & ht->nTableMask]) { + ht->arBuckets[q->h & ht->nTableMask] = q->pNext; + } else { + q->pLast->pNext = q->pNext; + } + if (q->pNext) { + q->pNext->pLast = q->pLast; + } + if (q->pListLast != NULL) { + q->pListLast->pListNext = q->pListNext; + } else { + /* Deleting the head of the list */ + ht->pListHead = q->pListNext; + } + if (q->pListNext != NULL) { + q->pListNext->pListLast = q->pListLast; + } else { + ht->pListTail = q->pListLast; + } + if (ht->pInternalPointer == q) { + ht->pInternalPointer = q->pListNext; + } + if (ht->pDestructor) { + ht->pDestructor(q->pData); + } + if (q->pData != &q->pDataPtr) { + pefree(q->pData, ht->persistent); + } + pefree(q, ht->persistent); + ht->nNumOfElements--; + } + if (p->pNext) { p->pNext->pLast = p->pLast; } if (p->pLast) { p->pLast->pNext = p->pNext; - } else{ + } else { ht->arBuckets[p->h & ht->nTableMask] = p->pNext; } - if (p->nKeyLength != str_length) { - Bucket *q = (Bucket *) pemalloc(sizeof(Bucket) + str_length, ht->persistent); + if ((IS_INTERNED(p->arKey) != IS_INTERNED(str_index)) || + (!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; if (p->pData == &p->pDataPtr) { q->pData = &q->pDataPtr; @@ -1359,9 +1397,13 @@ if (key_type == HASH_KEY_IS_LONG) { p->h = num_index; } else { - p->arKey = (char*)(p+1); - memcpy(p->arKey, str_index, str_length); - p->h = zend_inline_hash_func(str_index, str_length); + p->h = h; + if (IS_INTERNED(str_index)) { + p->arKey = str_index; + } else { + p->arKey = (char*)(p+1); + memcpy(p->arKey, str_index, str_length); + } } CONNECT_TO_BUCKET_DLLIST(p, ht->arBuckets[p->h & ht->nTableMask]); Modified: php/php-src/trunk/Zend/tests/bug45742.phpt =================================================================== --- php/php-src/trunk/Zend/tests/bug45742.phpt 2011-08-01 11:04:57 UTC (rev 314012) +++ php/php-src/trunk/Zend/tests/bug45742.phpt 2011-08-01 11:21:23 UTC (rev 314013) @@ -20,5 +20,5 @@ --EXPECT-- array(1) { [1]=> - int(23) + int(42) } Added: php/php-src/trunk/Zend/tests/bug50816.phpt =================================================================== --- php/php-src/trunk/Zend/tests/bug50816.phpt (rev 0) +++ php/php-src/trunk/Zend/tests/bug50816.phpt 2011-08-01 11:21:23 UTC (rev 314013) @@ -0,0 +1,48 @@ +--TEST-- +Bug #50816 (Using class constants in array definition fails) +--FILE-- +<?php +define("ONE", 1); +define("TWO", 1); + +class Foo { + const ONE = 1; + const TWO = 1; + + public static $mapWithConst = array(self::ONE => 'one', self::TWO => 'two',); + + public static $mapWithConst1 = array(1 => 'one', self::TWO => 'two',); + public static $mapWithConst2 = array(self::ONE => 'one', 1 => 'two',); + + public static $mapWithoutConst = array(1 => 'one', 1 => 'two',); +} + +$mapWithConst = array(1 => 'one', 1 => 'two',); + +$mapWithoutConst = array(Foo::ONE => 'one', Foo::TWO => 'two',); +$mapWithoutConst0 = array(1 => 'one', 1 => 'two',); +$mapWithoutConst1 = array(ONE => 'one', 1 => 'two',); +$mapWithoutConst2 = array(1 => 'one', TWO => 'two',); +$mapWithoutConst3 = array(ONE => 'one', TWO => 'two',); + +var_dump(Foo::$mapWithConst[1]); +var_dump(Foo::$mapWithConst1[1]); +var_dump(Foo::$mapWithConst2[1]); +var_dump(Foo::$mapWithoutConst[1]); +var_dump($mapWithConst[1]); +var_dump($mapWithoutConst[1]); +var_dump($mapWithoutConst0[1]); +var_dump($mapWithoutConst1[1]); +var_dump($mapWithoutConst2[1]); +var_dump($mapWithoutConst3[1]); +--EXPECT-- +string(3) "two" +string(3) "two" +string(3) "two" +string(3) "two" +string(3) "two" +string(3) "two" +string(3) "two" +string(3) "two" +string(3) "two" +string(3) "two" Modified: php/php-src/trunk/Zend/zend_hash.c =================================================================== --- php/php-src/trunk/Zend/zend_hash.c 2011-08-01 11:04:57 UTC (rev 314012) +++ php/php-src/trunk/Zend/zend_hash.c 2011-08-01 11:21:23 UTC (rev 314013) @@ -1211,8 +1211,9 @@ */ 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; -#ifdef ZEND_SIGNALS + Bucket *p, *q; + ulong h; +#ifdef ZEND_SIGNALS TSRMLS_FETCH(); #endif @@ -1227,106 +1228,143 @@ return SUCCESS; } - if (mode != HASH_UPDATE_KEY_ANYWAY) { - Bucket *q = ht->arBuckets[num_index & ht->nTableMask]; - int found = 0; - - while (q != NULL) { - if (q == p) { - found = 1; - } else if (!q->nKeyLength && q->h == num_index) { - if (found) { - if (mode & HASH_UPDATE_KEY_IF_BEFORE) { - break; - } else { - if (p->nKeyLength) { - zend_hash_del(ht, p->arKey, p->nKeyLength); - } else { - zend_hash_index_del(ht, p->h); - } - return FAILURE; - } - } else { - if (mode & HASH_UPDATE_KEY_IF_AFTER) { - break; - } else { - if (p->nKeyLength) { - zend_hash_del(ht, p->arKey, p->nKeyLength); - } else { - zend_hash_index_del(ht, p->h); - } - return FAILURE; - } - } - } - q = q->pNext; + q = ht->arBuckets[num_index & ht->nTableMask]; + while (q != NULL) { + if (!q->nKeyLength && q->h == num_index) { + break; } + q = q->pNext; } + } else if (key_type == HASH_KEY_IS_STRING) { + if (IS_INTERNED(str_index)) { + h = INTERNED_HASH(str_index); + } else { + h = zend_inline_hash_func(str_index, str_length); + } - zend_hash_index_del(ht, num_index); - } else if (key_type == HASH_KEY_IS_STRING) { - if (p->nKeyLength == str_length && - memcmp(p->arKey, str_index, str_length) == 0) { + if (p->arKey == str_index || + (p->nKeyLength == str_length && + p->h == h && + memcmp(p->arKey, str_index, str_length) == 0)) { return SUCCESS; } - if (mode != HASH_UPDATE_KEY_ANYWAY) { - ulong h = zend_inline_hash_func(str_index, str_length); - Bucket *q = ht->arBuckets[h & ht->nTableMask]; - int found = 0; + q = ht->arBuckets[h & ht->nTableMask]; - while (q != NULL) { - if (q == p) { - found = 1; - } else if (q->h == h && q->nKeyLength == str_length && - memcmp(q->arKey, str_index, str_length) == 0) { - if (found) { - if (mode & HASH_UPDATE_KEY_IF_BEFORE) { - break; - } else { - if (p->nKeyLength) { - zend_hash_del(ht, p->arKey, p->nKeyLength); - } else { - zend_hash_index_del(ht, p->h); - } - return FAILURE; - } - } else { - if (mode & HASH_UPDATE_KEY_IF_AFTER) { - break; - } else { - if (p->nKeyLength) { - zend_hash_del(ht, p->arKey, p->nKeyLength); - } else { - zend_hash_index_del(ht, p->h); - } - return FAILURE; - } - } - } - q = q->pNext; + while (q != NULL) { + if (q->arKey == str_index || + (q->h == h && q->nKeyLength == str_length && + memcmp(q->arKey, str_index, str_length) == 0)) { + break; } + q = q->pNext; } - - zend_hash_del(ht, str_index, str_length); } else { return FAILURE; } HANDLE_BLOCK_INTERRUPTIONS(); + if (q) { + if (mode != HASH_UPDATE_KEY_ANYWAY) { + Bucket *r = p->pListLast; + int found = HASH_UPDATE_KEY_IF_BEFORE; + + while (r) { + if (r == q) { + found = HASH_UPDATE_KEY_IF_AFTER; + break; + } + r = r->pListLast; + } + if (mode & found) { + /* delete current bucket */ + if (p == ht->arBuckets[p->h & ht->nTableMask]) { + ht->arBuckets[p->h & ht->nTableMask] = p->pNext; + } else { + p->pLast->pNext = p->pNext; + } + if (p->pNext) { + p->pNext->pLast = p->pLast; + } + if (p->pListLast != NULL) { + p->pListLast->pListNext = p->pListNext; + } else { + /* Deleting the head of the list */ + ht->pListHead = p->pListNext; + } + if (p->pListNext != NULL) { + p->pListNext->pListLast = p->pListLast; + } else { + ht->pListTail = p->pListLast; + } + if (ht->pInternalPointer == p) { + ht->pInternalPointer = p->pListNext; + } + if (ht->pDestructor) { + ht->pDestructor(p->pData); + } + if (p->pData != &p->pDataPtr) { + pefree(p->pData, ht->persistent); + } + pefree(p, ht->persistent); + ht->nNumOfElements--; + HANDLE_UNBLOCK_INTERRUPTIONS(); + return FAILURE; + } + } + /* delete another bucket with the same key */ + if (q == ht->arBuckets[q->h & ht->nTableMask]) { + ht->arBuckets[q->h & ht->nTableMask] = q->pNext; + } else { + q->pLast->pNext = q->pNext; + } + if (q->pNext) { + q->pNext->pLast = q->pLast; + } + if (q->pListLast != NULL) { + q->pListLast->pListNext = q->pListNext; + } else { + /* Deleting the head of the list */ + ht->pListHead = q->pListNext; + } + if (q->pListNext != NULL) { + q->pListNext->pListLast = q->pListLast; + } else { + ht->pListTail = q->pListLast; + } + if (ht->pInternalPointer == q) { + ht->pInternalPointer = q->pListNext; + } + if (ht->pDestructor) { + ht->pDestructor(q->pData); + } + if (q->pData != &q->pDataPtr) { + pefree(q->pData, ht->persistent); + } + pefree(q, ht->persistent); + ht->nNumOfElements--; + } + if (p->pNext) { p->pNext->pLast = p->pLast; } if (p->pLast) { p->pLast->pNext = p->pNext; - } else{ + } else { ht->arBuckets[p->h & ht->nTableMask] = p->pNext; } - if (p->nKeyLength != str_length) { - Bucket *q = (Bucket *) pemalloc(sizeof(Bucket) + str_length, ht->persistent); + if ((IS_INTERNED(p->arKey) != IS_INTERNED(str_index)) || + (!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; if (p->pData == &p->pDataPtr) { q->pData = &q->pDataPtr; @@ -1359,9 +1397,13 @@ if (key_type == HASH_KEY_IS_LONG) { p->h = num_index; } else { - p->arKey = (char*)(p+1); - memcpy(p->arKey, str_index, str_length); - p->h = zend_inline_hash_func(str_index, str_length); + p->h = h; + if (IS_INTERNED(str_index)) { + p->arKey = str_index; + } else { + p->arKey = (char*)(p+1); + memcpy(p->arKey, str_index, str_length); + } } CONNECT_TO_BUCKET_DLLIST(p, ht->arBuckets[p->h & ht->nTableMask]);
-- PHP CVS Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php