}
+ZEND_API int zend_hash_compare(HashTable *ht1, HashTable *ht2, compare_func_t compar)
+{
+ Bucket *p1, *p2;
+ int result;
+
+ IS_CONSISTENT(ht1);
+ IS_CONSISTENT(ht2);
+
+ result = ht1->nNumOfElements - ht2->nNumOfElements;
+ if (result!=0) {
+ return result;
+ }
+ p1 = ht1->pListHead;
+ 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;
+ }
+ result = memcmp(p1->arKey, p2->arKey, p1->nKeyLength);
+ if (result!=0) {
+ return result;
+ }
+ }
+ result = compar(p1->pData, p2->pData);
+ if (result!=0) {
+ return result;
+ }
+ p1 = p1->pListNext;
+ p2 = p2->pListNext;
+ }
+
+ return 0;
+}
+
+
ZEND_API int zend_hash_minmax(HashTable *ht, int (*compar) (const void *, const void *), int flag, void **pData)
{
Bucket *p,*res;
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_minmax(HashTable *ht, int (*compar)(const void *, const void *), int flag, void **pData);
ZEND_API int zend_hash_num_elements(HashTable *ht);
return SUCCESS;
}
+
ZEND_API int compare_function(zval *result, zval *op1, zval *op2)
{
zval op1_copy, op2_copy;
result->type = IS_LONG;
return SUCCESS;
}
- if ((op1->type==IS_ARRAY || op1->type==IS_OBJECT)
- && (op2->type==IS_ARRAY || op2->type==IS_OBJECT)) {
- zend_error(E_WARNING,"Cannot compare arrays or objects");
+ if (op1->type==IS_ARRAY && op2->type==IS_ARRAY) {
+ zend_compare_arrays(result, op1, op2);
+ return SUCCESS;
+ }
+
+ if (op1->type==IS_OBJECT && op2->type==IS_OBJECT) {
+ zend_compare_objects(result, op1, op2);
+ return SUCCESS;
+ }
+
+ if (op1->type==IS_ARRAY) {
+ result->value.lval = 1;
+ result->type = IS_LONG;
+ return SUCCESS;
+ }
+ if (op2->type==IS_ARRAY) {
+ result->value.lval = -1;
+ result->type = IS_LONG;
+ return SUCCESS;
+ }
+ if (op1->type==IS_OBJECT) {
+ result->value.lval = 1;
+ result->type = IS_LONG;
+ return SUCCESS;
+ }
+ if (op2->type==IS_OBJECT) {
+ result->value.lval = -1;
+ result->type = IS_LONG;
+ return SUCCESS;
}
+
var_reset(result);
return FAILURE;
}
+static int hash_zval_identical_function(const zval **z1, const zval **z2)
+{
+ zval result;
+
+ if (is_identical_function(&result, (zval *) *z1, (zval *) *z2)==FAILURE) {
+ return 0;
+ }
+ return result.value.lval;
+}
+
+
ZEND_API int is_identical_function(zval *result, zval *op1, zval *op2)
{
result->type = IS_BOOL;
return SUCCESS;
break;
case IS_ARRAY:
+ if (zend_hash_compare(op1->value.ht, op2->value.ht, hash_zval_identical_function)==0) {
+ result->value.lval = 1;
+ } else {
+ result->value.lval = 0;
+ }
+ break;
case IS_OBJECT:
- zend_error(E_WARNING,"Cannot compare arrays or objects");
+ 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) {
+ result->value.lval = 1;
+ } else {
+ result->value.lval = 0;
+ }
+ }
break;
}
var_reset(result);
ZEND_API int is_not_identical_function(zval *result, zval *op1, zval *op2)
{
result->type = IS_BOOL;
- if ( is_identical_function( result, op1, op2 ) == FAILURE ) {
+ if (is_identical_function( result, op1, op2 ) == FAILURE) {
return FAILURE;
}
result->value.lval = !result->value.lval;
}
+static int hash_zval_compare_function(const zval **z1, const zval **z2)
+{
+ zval result;
+
+ if (compare_function(&result, (zval *) *z1, (zval *) *z2)==FAILURE) {
+ return 0;
+ }
+ 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);
+}
+
+
+ZEND_API void zend_compare_arrays(zval *result, zval *a1, zval *a2)
+{
+ zend_compare_symbol_tables(result, a1->value.ht, a2->value.ht);
+}
+
+
+ZEND_API void zend_compare_objects(zval *result, zval *o1, zval *o2)
+{
+ if (o1->value.obj.ce != o2->value.obj.ce) {
+ result->value.lval = 1; /* Comparing objects of different types is pretty much meaningless */
+ result->type = IS_LONG;
+ return;
+ }
+ zend_compare_symbol_tables(result, o1->value.obj.properties, o2->value.obj.properties);
+}
+
+
/* returns 0 for non-numeric string
* returns IS_DOUBLE for floating point string, and assigns the value to *dval (if it's not NULL)
* returns IS_LONG for integer strings, and assigns the value to *lval (if it's not NULL)