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