You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@avro.apache.org by dc...@apache.org on 2011/10/15 15:38:44 UTC

svn commit: r1183638 - in /avro/trunk: CHANGES.txt lang/c/src/avro/value.h lang/c/src/value.c lang/c/tests/test_avro_values.c

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;
 }