- Make == perform an unordered comparison with arrays/objects, and === perform an ordered comparison
}
-ZEND_API int zend_hash_compare(HashTable *ht1, HashTable *ht2, compare_func_t compar)
+ZEND_API int zend_hash_compare(HashTable *ht1, HashTable *ht2, compare_func_t compar, zend_bool ordered)
{
Bucket *p1, *p2;
int result;
+ void *pData2;
IS_CONSISTENT(ht1);
IS_CONSISTENT(ht2);
if (result!=0) {
return result;
}
+
p1 = ht1->pListHead;
- p2 = ht2->pListHead;
+ if (ordered) {
+ p2 = ht2->pListHead;
+ }
- while (p1 && p2) {
- if (p1->nKeyLength==0 && p2->nKeyLength==0) { /* numeric indices */
- result = p1->h - p2->h;
- if (result!=0) {
- return result;
- }
- } else { /* string indices */
- result = p1->nKeyLength - p2->nKeyLength;
- if (result!=0) {
- return result;
+ while (p1) {
+ if (ordered && !p2) {
+ return 1; /* That's not supposed to happen */
+ }
+ if (ordered) {
+ if (p1->nKeyLength==0 && p2->nKeyLength==0) { /* numeric indices */
+ result = p1->h - p2->h;
+ if (result!=0) {
+ return result;
+ }
+ } else { /* string indices */
+ result = p1->nKeyLength - p2->nKeyLength;
+ if (result!=0) {
+ return result;
+ }
+ result = memcmp(p1->arKey, p2->arKey, p1->nKeyLength);
+ if (result!=0) {
+ return result;
+ }
}
- result = memcmp(p1->arKey, p2->arKey, p1->nKeyLength);
- if (result!=0) {
- return result;
+ pData2 = p2->pData;
+ } else {
+ if (p1->nKeyLength==0) { /* numeric index */
+ if (zend_hash_index_find(ht2, p1->h, &pData2)==FAILURE) {
+ return 1;
+ }
+ } else { /* string index */
+ if (zend_hash_find(ht2, p1->arKey, p1->nKeyLength, &pData2)==FAILURE) {
+ return 1;
+ }
}
}
- result = compar(p1->pData, p2->pData);
+ result = compar(p1->pData, pData2);
if (result!=0) {
return result;
}
p1 = p1->pListNext;
- p2 = p2->pListNext;
+ if (ordered) {
+ p2 = p2->pListNext;
+ }
}
return 0;
ZEND_API void zend_hash_copy(HashTable *target, HashTable *source, copy_ctor_func_t pCopyConstructor, void *tmp, uint size);
ZEND_API void zend_hash_merge(HashTable *target, HashTable *source, copy_ctor_func_t pCopyConstructor, void *tmp, uint size, int overwrite);
ZEND_API int zend_hash_sort(HashTable *ht, sort_func_t sort_func, compare_func_t compare_func, int renumber);
-ZEND_API int zend_hash_compare(HashTable *ht1, HashTable *ht2, compare_func_t compar);
+ZEND_API int zend_hash_compare(HashTable *ht1, HashTable *ht2, compare_func_t compar, zend_bool ordered);
ZEND_API int zend_hash_minmax(HashTable *ht, int (*compar)(const void *, const void *), int flag, void **pData);
ZEND_API int zend_hash_num_elements(HashTable *ht);
{
zval result;
+ /* is_identical_function() returns 1 in case of identity and 0 in case
+ * of a difference;
+ * whereas this comparison function is expected to return 0 on identity,
+ * and non zero otherwise.
+ */
if (is_identical_function(&result, (zval *) *z1, (zval *) *z2)==FAILURE) {
- return 0;
+ return 1;
}
- return result.value.lval;
+ return !result.value.lval;
}
switch (op1->type) {
case IS_NULL:
result->value.lval = (op2->type==IS_NULL);
- return SUCCESS;
break;
case IS_BOOL:
case IS_LONG:
case IS_RESOURCE:
result->value.lval = (op1->value.lval == op2->value.lval);
- return SUCCESS;
break;
case IS_DOUBLE:
result->value.lval = (op1->value.dval == op2->value.dval);
- return SUCCESS;
break;
case IS_STRING:
if ((op1->value.str.len == op2->value.str.len)
} else {
result->value.lval = 0;
}
- return SUCCESS;
break;
case IS_ARRAY:
- if (zend_hash_compare(op1->value.ht, op2->value.ht, hash_zval_identical_function)==0) {
+ if (zend_hash_compare(op1->value.ht, op2->value.ht, hash_zval_identical_function, 1)==0) {
result->value.lval = 1;
} else {
result->value.lval = 0;
if (op1->value.obj.ce != op2->value.obj.ce) {
result->value.lval = 0;
} else {
- if (zend_hash_compare(op1->value.obj.properties, op2->value.obj.properties, hash_zval_identical_function)==0) {
+ if (zend_hash_compare(op1->value.obj.properties, op2->value.obj.properties, hash_zval_identical_function, 1)==0) {
result->value.lval = 1;
} else {
result->value.lval = 0;
}
}
break;
+ default:
+ var_reset(result);
+ return FAILURE;
}
- var_reset(result);
- return FAILURE;
+ return SUCCESS;
}
zval result;
if (compare_function(&result, (zval *) *z1, (zval *) *z2)==FAILURE) {
- return 0;
+ return 1;
}
return result.value.lval;
}
ZEND_API void zend_compare_symbol_tables(zval *result, HashTable *ht1, HashTable *ht2)
{
result->type = IS_LONG;
- result->value.lval = zend_hash_compare(ht1, ht2, hash_zval_compare_function);
+ result->value.lval = zend_hash_compare(ht1, ht2, hash_zval_compare_function, 0);
}