Author: dcreager
Date: Sat Oct 15 13:38:44 2011
New Revision: 1183638

URL: http://svn.apache.org/viewvc?rev=1183638&view=rev
Log:
AVRO-922. C: Value comparison function

This patch adds the avro_value_cmp and avro_value_cmp_fast functions,
which compare two avro_value_t instances using the sort order from the
Avro specification.  Like the avro_value_equal and avro_value_copy
methods, we don't require the two values to have the same value
implementation, but they do need to be instances of the same schema.

Modified:
    avro/trunk/CHANGES.txt
    avro/trunk/lang/c/src/avro/value.h
    avro/trunk/lang/c/src/value.c
    avro/trunk/lang/c/tests/test_avro_values.c

Modified: avro/trunk/CHANGES.txt
URL: 
http://svn.apache.org/viewvc/avro/trunk/CHANGES.txt?rev=1183638&r1=1183637&r2=1183638&view=diff
==============================================================================
--- avro/trunk/CHANGES.txt (original)
+++ avro/trunk/CHANGES.txt Sat Oct 15 13:38:44 2011
@@ -33,6 +33,8 @@ Avro 1.6.0 (unreleased)
     AVRO-921. C: Default wrapped buffer implementation is zero-copy.
     (dcreager)
 
+    AVRO-922. C: Comparison function for new value interface. (dcreager)
+
     AVRO-890: Java: Add Maven archetype for creating Avro service
     projects.  (Stephen Gargan via cutting)
 

Modified: avro/trunk/lang/c/src/avro/value.h
URL: 
http://svn.apache.org/viewvc/avro/trunk/lang/c/src/avro/value.h?rev=1183638&r1=1183637&r2=1183638&view=diff
==============================================================================
--- avro/trunk/lang/c/src/avro/value.h (original)
+++ avro/trunk/lang/c/src/avro/value.h Sat Oct 15 13:38:44 2011
@@ -325,6 +325,33 @@ int
 avro_value_equal_fast(avro_value_t *val1, avro_value_t *val2);
 
 /**
+ * Compares two values using the sort order defined in the Avro
+ * specification.  The two values don't need to have the same
+ * implementation of the value interface, but they do need to represent
+ * Avro values of the same schema.  This function ensures that the
+ * schemas match; if you want to skip this check, use
+ * avro_value_cmp_fast.
+ */
+
+int
+avro_value_cmp(avro_value_t *val1, avro_value_t *val2);
+
+/**
+ * Compares two values using the sort order defined in the Avro
+ * specification.  The two values don't need to have the same
+ * implementation of the value interface, but they do need to represent
+ * Avro values of the same schema.  This function assumes that the
+ * schemas match; if you can't guarantee this, you should use
+ * avro_value_cmp, which compares the schemas before comparing the
+ * values.
+ */
+
+int
+avro_value_cmp_fast(avro_value_t *val1, avro_value_t *val2);
+
+
+
+/**
  * Copies the contents of src into dest.  The two values don't need to
  * have the same implementation of the value interface, but they do need
  * to represent Avro values of the same schema.  This function ensures

Modified: avro/trunk/lang/c/src/value.c
URL: 
http://svn.apache.org/viewvc/avro/trunk/lang/c/src/value.c?rev=1183638&r1=1183637&r2=1183638&view=diff
==============================================================================
--- avro/trunk/lang/c/src/value.c (original)
+++ avro/trunk/lang/c/src/value.c Sat Oct 15 13:38:44 2011
@@ -289,6 +289,225 @@ avro_value_equal(avro_value_t *val1, avr
 }
 
 
+#define cmp(v1, v2) \
+       (((v1) == (v2))? 0: \
+        ((v1) <  (v2))? -1: 1)
+int
+avro_value_cmp_fast(avro_value_t *val1, avro_value_t *val2)
+{
+       avro_type_t  type1 = avro_value_get_type(val1);
+       avro_type_t  type2 = avro_value_get_type(val2);
+       if (type1 != type2) {
+               return -1;
+       }
+
+       switch (type1) {
+               case AVRO_BOOLEAN:
+               {
+                       int  v1;
+                       int  v2;
+                       check_return(0, avro_value_get_boolean(val1, &v1));
+                       check_return(0, avro_value_get_boolean(val2, &v2));
+                       return cmp(!!v1, !!v2);
+               }
+
+               case AVRO_BYTES:
+               {
+                       const void  *buf1;
+                       const void  *buf2;
+                       size_t  size1;
+                       size_t  size2;
+                       size_t  min_size;
+                       int  result;
+
+                       check_return(0, avro_value_get_bytes(val1, &buf1, 
&size1));
+                       check_return(0, avro_value_get_bytes(val2, &buf2, 
&size2));
+
+                       min_size = (size1 < size2)? size1: size2;
+                       result = memcmp(buf1, buf2, min_size);
+                       if (result != 0) {
+                               return result;
+                       } else {
+                               return cmp(size1, size2);
+                       }
+               }
+
+               case AVRO_DOUBLE:
+               {
+                       double  v1;
+                       double  v2;
+                       check_return(0, avro_value_get_double(val1, &v1));
+                       check_return(0, avro_value_get_double(val2, &v2));
+                       return cmp(v1, v2);
+               }
+
+               case AVRO_FLOAT:
+               {
+                       float  v1;
+                       float  v2;
+                       check_return(0, avro_value_get_float(val1, &v1));
+                       check_return(0, avro_value_get_float(val2, &v2));
+                       return cmp(v1, v2);
+               }
+
+               case AVRO_INT32:
+               {
+                       int32_t  v1;
+                       int32_t  v2;
+                       check_return(0, avro_value_get_int(val1, &v1));
+                       check_return(0, avro_value_get_int(val2, &v2));
+                       return cmp(v1, v2);
+               }
+
+               case AVRO_INT64:
+               {
+                       int64_t  v1;
+                       int64_t  v2;
+                       check_return(0, avro_value_get_long(val1, &v1));
+                       check_return(0, avro_value_get_long(val2, &v2));
+                       return cmp(v1, v2);
+               }
+
+               case AVRO_NULL:
+               {
+                       check_return(0, avro_value_get_null(val1));
+                       check_return(0, avro_value_get_null(val2));
+                       return 0;
+               }
+
+               case AVRO_STRING:
+               {
+                       const char  *buf1;
+                       const char  *buf2;
+                       size_t  size1;
+                       size_t  size2;
+                       size_t  min_size;
+                       int  result;
+
+                       min_size = (size1 < size2)? size1: size2;
+                       result = memcmp(buf1, buf2, min_size);
+                       if (result != 0) {
+                               return result;
+                       } else {
+                               return cmp(size1, size2);
+                       }
+               }
+
+               case AVRO_ARRAY:
+               {
+                       size_t  count1;
+                       size_t  count2;
+                       size_t  min_count;
+                       size_t  i;
+                       check_return(0, avro_value_get_size(val1, &count1));
+                       check_return(0, avro_value_get_size(val2, &count2));
+
+                       min_count = (count1 < count2)? count1: count2;
+                       for (i = 0; i < min_count; i++) {
+                               avro_value_t  child1;
+                               avro_value_t  child2;
+                               int  result;
+                               check_return(0, avro_value_get_by_index
+                                            (val1, i, &child1, NULL));
+                               check_return(0, avro_value_get_by_index
+                                            (val2, i, &child2, NULL));
+                               result = avro_value_cmp_fast(&child1, &child2);
+                               if (result != 0) {
+                                       return result;
+                               }
+                       }
+
+                       return cmp(count1, count2);
+               }
+
+               case AVRO_ENUM:
+               {
+                       int  v1;
+                       int  v2;
+                       check_return(0, avro_value_get_enum(val1, &v1));
+                       check_return(0, avro_value_get_enum(val2, &v2));
+                       return cmp(v1, v2);
+               }
+
+               case AVRO_FIXED:
+               {
+                       const void  *buf1;
+                       const void  *buf2;
+                       size_t  size1;
+                       size_t  size2;
+                       check_return(0, avro_value_get_fixed(val1, &buf1, 
&size1));
+                       check_return(0, avro_value_get_fixed(val2, &buf2, 
&size2));
+                       if (size1 != size2) {
+                               return -1;
+                       }
+                       return memcmp(buf1, buf2, size1);
+               }
+
+               case AVRO_MAP:
+               {
+                       return -1;
+               }
+
+               case AVRO_RECORD:
+               {
+                       size_t  count1;
+                       check_return(0, avro_value_get_size(val1, &count1));
+
+                       size_t  i;
+                       for (i = 0; i < count1; i++) {
+                               avro_value_t  child1;
+                               avro_value_t  child2;
+                               int  result;
+
+                               check_return(0, avro_value_get_by_index
+                                            (val1, i, &child1, NULL));
+                               check_return(0, avro_value_get_by_index
+                                            (val2, i, &child2, NULL));
+                               result = avro_value_cmp_fast(&child1, &child2);
+                               if (result != 0) {
+                                       return result;
+                               }
+                       }
+
+                       return 0;
+               }
+
+               case AVRO_UNION:
+               {
+                       int  disc1;
+                       int  disc2;
+                       check_return(0, avro_value_get_discriminant(val1, 
&disc1));
+                       check_return(0, avro_value_get_discriminant(val2, 
&disc2));
+
+                       if (disc1 == disc2) {
+                               avro_value_t  branch1;
+                               avro_value_t  branch2;
+                               check_return(0, 
avro_value_get_current_branch(val1, &branch1));
+                               check_return(0, 
avro_value_get_current_branch(val2, &branch2));
+                               return avro_value_cmp_fast(&branch1, &branch2);
+                       } else {
+                               return cmp(disc1, disc2);
+                       }
+               }
+
+               default:
+                       return 0;
+       }
+}
+
+int
+avro_value_cmp(avro_value_t *val1, avro_value_t *val2)
+{
+       avro_schema_t  schema1 = avro_value_get_schema(val1);
+       avro_schema_t  schema2 = avro_value_get_schema(val2);
+       if (!avro_schema_equal(schema1, schema2)) {
+               return 0;
+       }
+
+       return avro_value_cmp_fast(val1, val2);
+}
+
+
 int
 avro_value_copy_fast(avro_value_t *dest, const avro_value_t *src)
 {

Modified: avro/trunk/lang/c/tests/test_avro_values.c
URL: 
http://svn.apache.org/viewvc/avro/trunk/lang/c/tests/test_avro_values.c?rev=1183638&r1=1183637&r2=1183638&view=diff
==============================================================================
--- avro/trunk/lang/c/tests/test_avro_values.c (original)
+++ avro/trunk/lang/c/tests/test_avro_values.c Sat Oct 15 13:38:44 2011
@@ -422,6 +422,28 @@ test_boolean(void)
                check_copy(&val);
                avro_value_decref(&val);
        }
+
+       avro_value_t  val1;
+       avro_value_t  val2;
+       try(avro_generic_boolean_new(&val1, 0),
+           "Cannot create boolean");
+       try(avro_generic_boolean_new(&val2, 1),
+           "Cannot create boolean");
+       if (avro_value_cmp_fast(&val1, &val2) != -1) {
+               fprintf(stderr, "Incorrect sort order\n");
+               return EXIT_FAILURE;
+       }
+       if (avro_value_cmp_fast(&val2, &val1) != 1) {
+               fprintf(stderr, "Incorrect sort order\n");
+               return EXIT_FAILURE;
+       }
+       if (avro_value_cmp_fast(&val1, &val1) != 0) {
+               fprintf(stderr, "Incorrect sort order\n");
+               return EXIT_FAILURE;
+       }
+       avro_value_decref(&val1);
+       avro_value_decref(&val2);
+
        return 0;
 }
 
@@ -478,6 +500,36 @@ test_bytes(void)
        check_write_read(&val);
        check_copy(&val);
        avro_value_decref(&val);
+
+       avro_value_t  val1;
+       avro_value_t  val2;
+       avro_value_t  val3;
+       try(avro_generic_bytes_new(&val1, "abcd", 4),
+           "Cannot create bytes");
+       try(avro_generic_bytes_new(&val2, "abcde", 5),
+           "Cannot create bytes");
+       try(avro_generic_bytes_new(&val3, "abce", 4),
+           "Cannot create bytes");
+       if (avro_value_cmp_fast(&val1, &val2) != -1) {
+               fprintf(stderr, "Incorrect sort order\n");
+               return EXIT_FAILURE;
+       }
+       if (avro_value_cmp_fast(&val2, &val1) != 1) {
+               fprintf(stderr, "Incorrect sort order\n");
+               return EXIT_FAILURE;
+       }
+       if (avro_value_cmp_fast(&val1, &val3) != -1) {
+               fprintf(stderr, "Incorrect sort order\n");
+               return EXIT_FAILURE;
+       }
+       if (avro_value_cmp_fast(&val1, &val1) != 0) {
+               fprintf(stderr, "Incorrect sort order\n");
+               return EXIT_FAILURE;
+       }
+       avro_value_decref(&val1);
+       avro_value_decref(&val2);
+       avro_value_decref(&val3);
+
        return 0;
 }
 
@@ -586,6 +638,28 @@ test_int(void)
                check_copy(&val);
                avro_value_decref(&val);
        }
+
+       avro_value_t  val1;
+       avro_value_t  val2;
+       try(avro_generic_int_new(&val1, -10),
+           "Cannot create int");
+       try(avro_generic_int_new(&val2, 42),
+           "Cannot create int");
+       if (avro_value_cmp_fast(&val1, &val2) != -1) {
+               fprintf(stderr, "Incorrect sort order\n");
+               return EXIT_FAILURE;
+       }
+       if (avro_value_cmp_fast(&val2, &val1) != 1) {
+               fprintf(stderr, "Incorrect sort order\n");
+               return EXIT_FAILURE;
+       }
+       if (avro_value_cmp_fast(&val1, &val1) != 0) {
+               fprintf(stderr, "Incorrect sort order\n");
+               return EXIT_FAILURE;
+       }
+       avro_value_decref(&val1);
+       avro_value_decref(&val2);
+
        return 0;
 }
 


Reply via email to