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

Reply via email to