- Fixed bug #30096 (gmmktime does not return the corrent time). (Derick)
- Fixed bug #30052 (Crash on shutdown after odbc_pconnect()). (Edin)
- Fixed bug #28377 (debug_backtrace is intermittently passing args). (Dmitry)
+- Fixed bug #28072 (static array with some constant keys will be incorrectly
+ ordered). (Dmitry)
- Fixed bug #27268 (Bad references accentuated by clone). (Dmitry)
22 Jun 2005, PHP 5.1 Beta 2
--- /dev/null
+--TEST--
+Bug #28072 (static array with some constant keys will be incorrectly ordered)
+--FILE--
+<?php
+define("FIRST_KEY", "a");
+define("THIRD_KEY", "c");
+
+
+function test()
+{
+ static $arr = array(
+ FIRST_KEY => "111",
+ "b" => "222",
+ THIRD_KEY => "333",
+ "d" => "444"
+ );
+ print_r($arr);
+}
+
+function test2()
+{
+ static $arr = array(
+ FIRST_KEY => "111",
+ "a" => "222",
+ "c" => "333",
+ THIRD_KEY => "444"
+ );
+ print_r($arr);
+}
+
+test();
+test2();
+?>
+--EXPECT--
+Array
+(
+ [a] => 111
+ [b] => 222
+ [c] => 333
+ [d] => 444
+)
+Array
+(
+ [a] => 111
+ [c] => 444
+)
/* preserve this bit for inheritance */
Z_TYPE_PP(element) |= IS_CONSTANT_INDEX;
+ zval_ptr_dtor(element);
+ *element = new_val;
switch (const_value.type) {
- case IS_STRING:
- zend_symtable_update(p->value.ht, const_value.value.str.val, const_value.value.str.len+1, &new_val, sizeof(zval *), NULL);
+ case IS_STRING: {
+ long lval;
+ double dval;
+
+ if (is_numeric_string(const_value.value.str.val, const_value.value.str.len, &lval, &dval, 0) == IS_LONG) {
+ zend_hash_update_current_key(p->value.ht, HASH_KEY_IS_LONG, NULL, 0, lval);
+ } else {
+ zend_hash_update_current_key(p->value.ht, HASH_KEY_IS_STRING, const_value.value.str.val, const_value.value.str.len+1, 0);
+ }
break;
+ }
case IS_BOOL:
case IS_LONG:
- zend_hash_index_update(p->value.ht, const_value.value.lval, &new_val, sizeof(zval *), NULL);
+ zend_hash_update_current_key(p->value.ht, HASH_KEY_IS_LONG, NULL, 0, const_value.value.lval);
+ break;
+ case IS_DOUBLE:
+ zend_hash_update_current_key(p->value.ht, HASH_KEY_IS_LONG, NULL, 0, (long)const_value.value.dval);
+ break;
+ case IS_NULL:
+ zend_hash_update_current_key(p->value.ht, HASH_KEY_IS_STRING, "", 1, 0);
break;
}
- zend_hash_del(p->value.ht, str_index, str_index_len);
+ zend_hash_move_forward(p->value.ht);
zval_dtor(&const_value);
}
zend_hash_apply_with_argument(p->value.ht, (apply_func_arg_t) zval_update_constant, (void *) 1 TSRMLS_CC);
}
}
+/* This function changes key of currevt element without changing elements'
+ * order. If element with target key already exists, it will be deleted first.
+ */
+ZEND_API int zend_hash_update_current_key_ex(HashTable *ht, int key_type, char *str_index, uint str_length, ulong num_index, HashPosition *pos)
+{
+ Bucket *p;
+
+ p = pos ? (*pos) : ht->pInternalPointer;
+
+ IS_CONSISTENT(ht);
+
+ if (p) {
+ if (key_type == HASH_KEY_IS_LONG) {
+ str_length = 0;
+ if (!p->nKeyLength && p->h == num_index) {
+ return SUCCESS;
+ }
+ 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;
+ }
+ zend_hash_del(ht, str_index, str_length);
+ } else {
+ return FAILURE;
+ }
+
+ HANDLE_BLOCK_INTERRUPTIONS();
+
+ if (p->pNext) {
+ p->pNext->pLast = p->pLast;
+ }
+ if (p->pLast) {
+ p->pLast->pNext = p->pNext;
+ } else{
+ ht->arBuckets[p->h & ht->nTableMask] = p->pNext;
+ }
+
+ if (p->nKeyLength != str_length) {
+ Bucket *q = (Bucket *) pemalloc(sizeof(Bucket) - 1 + str_length, ht->persistent);
+
+ q->nKeyLength = str_length;
+ if (p->pData == &p->pDataPtr) {
+ q->pData = &q->pDataPtr;
+ } else {
+ q->pData = p->pData;
+ }
+ q->pDataPtr = p->pDataPtr;
+ q->pListNext = p->pListNext;
+ q->pListLast = p->pListLast;
+ if (q->pListNext) {
+ p->pListNext->pListLast = q;
+ } else {
+ ht->pListTail = q;
+ }
+ if (q->pListLast) {
+ p->pListLast->pListNext = q;
+ } else {
+ ht->pListHead = q;
+ }
+ if (ht->pInternalPointer == p) {
+ ht->pInternalPointer = q;
+ }
+ if (pos) {
+ *pos = q;
+ }
+ pefree(p, ht->persistent);
+ p = q;
+ }
+
+ if (key_type == HASH_KEY_IS_LONG) {
+ p->h = num_index;
+ } else {
+ memcpy(p->arKey, str_index, str_length);
+ p->h = zend_inline_hash_func(str_index, str_length);
+ }
+
+ CONNECT_TO_BUCKET_DLLIST(p, ht->arBuckets[p->h & ht->nTableMask]);
+ ht->arBuckets[p->h & ht->nTableMask] = p;
+ HANDLE_UNBLOCK_INTERRUPTIONS();
+
+ return SUCCESS;
+ } else {
+ return FAILURE;
+ }
+}
ZEND_API int zend_hash_sort(HashTable *ht, sort_func_t sort_func,
compare_func_t compar, int renumber TSRMLS_DC)
ZEND_API int zend_hash_get_current_data_ex(HashTable *ht, void **pData, HashPosition *pos);
ZEND_API void zend_hash_internal_pointer_reset_ex(HashTable *ht, HashPosition *pos);
ZEND_API void zend_hash_internal_pointer_end_ex(HashTable *ht, HashPosition *pos);
+ZEND_API int zend_hash_update_current_key_ex(HashTable *ht, int key_type, char *str_index, uint str_length, ulong num_index, HashPosition *pos);
#define zend_hash_has_more_elements(ht) \
zend_hash_has_more_elements_ex(ht, NULL)
zend_hash_internal_pointer_reset_ex(ht, NULL)
#define zend_hash_internal_pointer_end(ht) \
zend_hash_internal_pointer_end_ex(ht, NULL)
+#define zend_hash_update_current_key(ht, key_type, str_index, str_length, num_index) \
+ zend_hash_update_current_key_ex(ht, key_type, str_index, str_length, num_index, NULL)
/* Copying, merging and sorting */
ZEND_API void zend_hash_copy(HashTable *target, HashTable *source, copy_ctor_func_t pCopyConstructor, void *tmp, uint size);