]> granicus.if.org Git - php/commitdiff
Support comparisons of arrays (with arrays) and objects (with objects)
authorZeev Suraski <zeev@php.net>
Sat, 3 Jun 2000 10:34:19 +0000 (10:34 +0000)
committerZeev Suraski <zeev@php.net>
Sat, 3 Jun 2000 10:34:19 +0000 (10:34 +0000)
Zend/zend_hash.c
Zend/zend_hash.h
Zend/zend_operators.c
Zend/zend_operators.h

index 3566c97ce2ffd3617c26c86d69358e9d1f739f94..af532da0a4cc8817aa111af111cd854a3e822e43 100644 (file)
@@ -1068,6 +1068,49 @@ ZEND_API int zend_hash_sort(HashTable *ht, sort_func_t sort_func,
 }
 
 
+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;
index abb82123b8cd0fcfb57f318a206177fd1defa8ac..88741ae71352467ca2f69431be0206415620b79e 100644 (file)
@@ -166,6 +166,7 @@ ZEND_API void zend_hash_internal_pointer_end_ex(HashTable *ht, HashPosition *pos
 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);
index 57a72358f4a2bd8227426512980ec44f32a3e0d8..4ffe2888870a306158856460418a0bda9bfe3ce8 100644 (file)
@@ -1042,6 +1042,7 @@ ZEND_API int numeric_compare_function(zval *result, zval *op1, zval *op2)
        return SUCCESS;
 }
 
+
 ZEND_API int compare_function(zval *result, zval *op1, zval *op2)
 {
        zval op1_copy, op2_copy;
@@ -1075,15 +1076,53 @@ ZEND_API int compare_function(zval *result, zval *op1, zval *op2)
                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;
@@ -1116,8 +1155,22 @@ ZEND_API int is_identical_function(zval *result, zval *op1, zval *op2)
                        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);
@@ -1128,7 +1181,7 @@ ZEND_API int is_identical_function(zval *result, zval *op1, zval *op2)
 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;
@@ -1478,6 +1531,42 @@ ZEND_API void zendi_smart_strcmp(zval *result, zval *s1, zval *s2)
 }
 
 
+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)
index d906660a4617a7d61e127d6e56066ae9f8b6fbd8..0d1fb6cf92a2c9d17e8b4ded8c53eee66d34f427 100644 (file)
@@ -83,6 +83,10 @@ ZEND_API int zend_binary_strncmp(char *s1, uint len1, char *s2, uint len2, uint
 ZEND_API int zend_binary_strcasecmp(char *s1, uint len1, char *s2, uint len2);
 
 ZEND_API void zendi_smart_strcmp(zval *result, zval *s1, zval *s2);
+ZEND_API void zend_compare_symbol_tables(zval *result, HashTable *ht1, HashTable *ht2);
+ZEND_API void zend_compare_arrays(zval *result, zval *a1, zval *a2);
+ZEND_API void zend_compare_objects(zval *result, zval *o1, zval *o2);
+
 
 #define convert_to_ex_master(ppzv, lower_type, upper_type)     \
        if ((*ppzv)->type!=IS_##upper_type) {                                   \