Modified: avro/trunk/lang/c/src/string.c
URL: 
http://svn.apache.org/viewvc/avro/trunk/lang/c/src/string.c?rev=1175832&r1=1175831&r2=1175832&view=diff
==============================================================================
--- avro/trunk/lang/c/src/string.c (original)
+++ avro/trunk/lang/c/src/string.c Mon Sep 26 12:36:26 2011
@@ -24,6 +24,21 @@
 #include "avro/allocation.h"
 #include "avro/errors.h"
 
+#ifndef AVRO_STRING_DEBUG
+#define AVRO_STRING_DEBUG 0
+#endif
+
+#if AVRO_STRING_DEBUG
+#include <stdio.h>
+#define DEBUG(...) \
+       do { \
+               fprintf(stderr, __VA_ARGS__); \
+               fprintf(stderr, "\n"); \
+       } while (0)
+#else
+#define DEBUG(...)  /* don't print messages */
+#endif
+
 
 /*
  * A resizable wrapped buffer implementation.  This implementation makes
@@ -43,6 +58,7 @@ struct avro_wrapped_resizable {
 static void
 avro_wrapped_resizable_free(avro_wrapped_buffer_t *self)
 {
+       DEBUG("--- Freeing resizable <%p:%zu> (%p)", self->buf, self->size, 
self->user_data);
        struct avro_wrapped_resizable  *resizable = self->user_data;
        avro_free(resizable, avro_wrapped_resizable_size(resizable->buf_size));
 }
@@ -52,11 +68,23 @@ avro_wrapped_resizable_resize(avro_wrapp
 {
        struct avro_wrapped_resizable  *resizable = self->user_data;
 
+       /*
+        * If we've already allocated enough memory for the desired
+        * size, there's nothing to do.
+        */
+
+       if (resizable->buf_size >= desired) {
+               return 0;
+       }
+
        size_t  new_buf_size = resizable->buf_size * 2;
        if (desired > new_buf_size) {
                new_buf_size = desired;
        }
 
+       DEBUG("--- Resizing <%p:%zu> (%p) -> %zu",
+             self->buf, self->buf_size, self->user_data, new_buf_size);
+
        struct avro_wrapped_resizable  *new_resizable =
            avro_realloc(resizable,
                         avro_wrapped_resizable_size(resizable->buf_size),
@@ -64,6 +92,7 @@ avro_wrapped_resizable_resize(avro_wrapp
        if (new_resizable == NULL) {
                return ENOMEM;
        }
+       DEBUG("--- New buffer <%p:%zu>", new_buf, new_buf_size);
 
        new_resizable->buf_size = new_buf_size;
 
@@ -71,8 +100,10 @@ avro_wrapped_resizable_resize(avro_wrapp
        void  *new_buf = new_resizable;
 
        ptrdiff_t  offset = self->buf - old_buf;
+       DEBUG("--- Old data pointer is %p", self->buf);
        self->buf = new_buf + offset;
        self->user_data = new_resizable;
+       DEBUG("--- New data pointer is %p", self->buf);
        return 0;
 }
 
@@ -89,6 +120,7 @@ avro_wrapped_resizable_new(avro_wrapped_
        resizable->buf_size = buf_size;
 
        dest->buf = ((void *) resizable) + sizeof(struct 
avro_wrapped_resizable);
+       DEBUG("--- Creating resizable <%p:%zu> (%p)", dest->buf, buf_size, 
resizable);
        dest->size = buf_size;
        dest->user_data = resizable;
        dest->free = avro_wrapped_resizable_free;
@@ -119,8 +151,10 @@ avro_raw_string_clear(avro_raw_string_t 
         */
 
        if (is_resizable(str->wrapped)) {
+               DEBUG("--- Clearing resizable buffer");
                str->wrapped.size = 0;
        } else {
+               DEBUG("--- Freeing wrapped buffer");
                avro_wrapped_buffer_free(&str->wrapped);
                avro_raw_string_init(str);
        }
@@ -146,6 +180,7 @@ avro_raw_string_ensure_buf(avro_raw_stri
 {
        int  rval;
 
+       DEBUG("--- Ensuring resizable buffer of size %zu", length);
        if (is_resizable(str->wrapped)) {
                /*
                 * If we've already got a resizable buffer, just have it
@@ -191,6 +226,20 @@ avro_raw_string_set_length(avro_raw_stri
 }
 
 
+void avro_raw_string_append_length(avro_raw_string_t *str,
+                                  const void *src,
+                                  size_t length)
+{
+       if (avro_raw_string_length(str) == 0) {
+               return avro_raw_string_set_length(str, src, length);
+       }
+
+       avro_raw_string_ensure_buf(str, str->wrapped.size + length);
+       memcpy((void *) str->wrapped.buf + str->wrapped.size, src, length);
+       str->wrapped.size += length;
+}
+
+
 void
 avro_raw_string_set(avro_raw_string_t *str, const char *src)
 {
@@ -210,7 +259,7 @@ avro_raw_string_append(avro_raw_string_t
 
        /* Assume that str->wrapped.size includes a NUL terminator */
        size_t  length = strlen(src);
-       avro_raw_string_ensure_buf(str, str->wrapped.size+length);
+       avro_raw_string_ensure_buf(str, str->wrapped.size + length);
        memcpy((void *) str->wrapped.buf + str->wrapped.size - 1, src, 
length+1);
        str->wrapped.size += length;
 }
@@ -220,6 +269,8 @@ void
 avro_raw_string_give(avro_raw_string_t *str,
                     avro_wrapped_buffer_t *src)
 {
+       DEBUG("--- Giving control of <%p:%zu> (%p) to string",
+             src->buf, src->size, src);
        avro_wrapped_buffer_free(&str->wrapped);
        avro_wrapped_buffer_move(&str->wrapped, src);
 }

Added: avro/trunk/lang/c/src/value-hash.c
URL: 
http://svn.apache.org/viewvc/avro/trunk/lang/c/src/value-hash.c?rev=1175832&view=auto
==============================================================================
--- avro/trunk/lang/c/src/value-hash.c (added)
+++ avro/trunk/lang/c/src/value-hash.c Mon Sep 26 12:36:26 2011
@@ -0,0 +1,294 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.  See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "avro/allocation.h"
+#include "avro/data.h"
+#include "avro/errors.h"
+#include "avro/value.h"
+#include "avro_private.h"
+
+#define check_return(retval, call) \
+       do { \
+               int  rval = call; \
+               if (rval != 0) { return (retval); } \
+       } while (0)
+
+/*
+ * We currently use MurmurHash3 [1], which is public domain, as our hash
+ * implementation.
+ *
+ * [1] http://code.google.com/p/smhasher/
+ */
+
+/* Our seed is the MurmurHash3 of the string "avro.value" */
+#define SEED  0xaf4c78df
+
+#define ROTL32(a,b) (((a) << ((b) & 0x1f)) | ((a) >> (32 - ((b) & 0x1f))))
+
+static inline uint32_t
+fmix(uint32_t h)
+{
+       h ^= h >> 16;
+       h *= 0x85ebca6b;
+       h ^= h >> 13;
+       h *= 0xc2b2ae35;
+       h ^= h >> 16;
+       return h;
+}
+
+static const uint32_t  c1 = 0xcc9e2d51;
+static const uint32_t  c2 = 0x1b873593;
+
+static inline uint32_t
+add_hash(uint32_t start, uint32_t current)
+{
+       current *= c1;
+       current = ROTL32(current, 15);
+       current *= c2;
+
+       start ^= current;
+       start = ROTL32(start, 13);
+       start = start * 5 + 0xe6546b64;
+
+       return start;
+}
+
+static inline uint32_t
+hash_buffer(uint32_t start, const void *src, size_t len)
+{
+       const uint8_t  *data = (const uint8_t *) src;
+       const int  nblocks = len / 4;
+
+       uint32_t  h1 = start;
+
+       //----------
+       // body
+
+       const uint32_t  *blocks = (const uint32_t *) (data + nblocks*4);
+       int  i;
+
+       for (i = -nblocks; i != 0; i++) {
+               uint32_t  k1 = blocks[i];
+
+               k1 *= c1;
+               k1 = ROTL32(k1,15);
+               k1 *= c2;
+
+               h1 ^= k1;
+               h1 = ROTL32(h1,13);
+               h1 = h1*5+0xe6546b64;
+       }
+
+       //----------
+       // tail
+
+       const uint8_t  *tail = (const uint8_t *) (data + nblocks*4);
+
+       uint32_t  k1 = 0;
+
+       switch (len & 3)
+       {
+               case 3: k1 ^= tail[2] << 16;
+               case 2: k1 ^= tail[1] << 8;
+               case 1: k1 ^= tail[0];
+                       k1 *= c1; k1 = ROTL32(k1,15); k1 *= c2; h1 ^= k1;
+       };
+
+       //----------
+       // finalization
+
+       h1 ^= len;
+       return h1;
+}
+
+static uint32_t
+avro_value_hash_fast(avro_value_t *value, uint32_t start)
+{
+       avro_type_t  type = avro_value_get_type(value);
+
+       switch (type) {
+               case AVRO_BOOLEAN:
+               {
+                       int  v;
+                       check_return(0, avro_value_get_boolean(value, &v));
+                       return add_hash(start, v);
+               }
+
+               case AVRO_BYTES:
+               {
+                       const void  *buf;
+                       size_t  size;
+                       check_return(0, avro_value_get_bytes(value, &buf, 
&size));
+                       return hash_buffer(start, buf, size);
+               }
+
+               case AVRO_DOUBLE:
+               {
+                       union {
+                               double  d;
+                               uint32_t  u32[2];
+                       } v;
+                       check_return(0, avro_value_get_double(value, &v.d));
+                       return add_hash(add_hash(start, v.u32[0]), v.u32[1]);
+               }
+
+               case AVRO_FLOAT:
+               {
+                       union {
+                               float  f;
+                               uint32_t  u32;
+                       } v;
+                       check_return(0, avro_value_get_float(value, &v.f));
+                       return add_hash(start, v.u32);
+               }
+
+               case AVRO_INT32:
+               {
+                       int32_t  v;
+                       check_return(0, avro_value_get_int(value, &v));
+                       return add_hash(start, v);
+               }
+
+               case AVRO_INT64:
+               {
+                       union {
+                               int64_t  u64;
+                               uint32_t  u32[2];
+                       } v;
+                       check_return(0, avro_value_get_long(value, &v.u64));
+                       return add_hash(add_hash(start, v.u32[0]), v.u32[1]);
+               }
+
+               case AVRO_NULL:
+               {
+                       check_return(0, avro_value_get_null(value));
+                       return add_hash(start, 0);
+               }
+
+               case AVRO_STRING:
+               {
+                       const char  *buf;
+                       size_t  size;
+                       check_return(0, avro_value_get_string(value, &buf, 
&size));
+                       return hash_buffer(start, buf, size);
+               }
+
+               case AVRO_ARRAY:
+               {
+                       size_t  count;
+                       size_t  i;
+                       check_return(0, avro_value_get_size(value, &count));
+
+                       for (i = 0; i < count; i++) {
+                               avro_value_t  child;
+                               check_return(0, avro_value_get_by_index
+                                            (value, i, &child, NULL));
+                               start = avro_value_hash_fast(&child, start);
+                       }
+
+                       start ^= count;
+                       return start;
+               }
+
+               case AVRO_ENUM:
+               {
+                       int  v;
+                       check_return(0, avro_value_get_enum(value, &v));
+                       return add_hash(start, v);
+               }
+
+               case AVRO_FIXED:
+               {
+                       const void  *buf;
+                       size_t  size;
+                       check_return(0, avro_value_get_fixed(value, &buf, 
&size));
+                       return hash_buffer(start, buf, size);
+               }
+
+               case AVRO_MAP:
+               {
+                       size_t  count;
+                       size_t  i;
+                       check_return(0, avro_value_get_size(value, &count));
+
+                       /*
+                        * The hash for a map must be built up without
+                        * taking into account the order of the elements
+                        */
+                       uint32_t  map_hash = 0;
+                       for (i = 0; i < count; i++) {
+                               avro_value_t  child;
+                               const char  *key;
+                               check_return(0, avro_value_get_by_index
+                                            (value, i, &child, &key));
+
+                               uint32_t  element = SEED;
+                               element = hash_buffer(element, key, 
strlen(key));
+                               element = avro_value_hash_fast(&child, element);
+                               element = fmix(element);
+
+                               map_hash ^= element;
+                       }
+                       map_hash ^= count;
+
+                       return add_hash(start, map_hash);
+               }
+
+               case AVRO_RECORD:
+               {
+                       size_t  count;
+                       size_t  i;
+                       check_return(0, avro_value_get_size(value, &count));
+
+                       for (i = 0; i < count; i++) {
+                               avro_value_t  child;
+                               check_return(0, avro_value_get_by_index
+                                            (value, i, &child, NULL));
+                               start = avro_value_hash_fast(&child, start);
+                       }
+
+                       start ^= count;
+                       return start;
+               }
+
+               case AVRO_UNION:
+               {
+                       int  disc;
+                       avro_value_t  branch;
+                       check_return(0, avro_value_get_discriminant(value, 
&disc));
+                       check_return(0, avro_value_get_current_branch(value, 
&branch));
+
+                       start = add_hash(start, disc);
+                       start = avro_value_hash_fast(&branch, start);
+                       return start;
+               }
+
+               default:
+                       return 0;
+       }
+}
+
+uint32_t
+avro_value_hash(avro_value_t *value)
+{
+       uint32_t  hash = avro_value_hash_fast(value, SEED);
+       return (hash == 0)? hash: fmix(hash);
+}

Modified: avro/trunk/lang/c/src/value-read.c
URL: 
http://svn.apache.org/viewvc/avro/trunk/lang/c/src/value-read.c?rev=1175832&r1=1175831&r2=1175832&view=diff
==============================================================================
--- avro/trunk/lang/c/src/value-read.c (original)
+++ avro/trunk/lang/c/src/value-read.c Mon Sep 26 12:36:26 2011
@@ -141,8 +141,8 @@ read_record_value(avro_reader_t reader, 
        for (i = 0; i < field_count; i++) {
                avro_value_t  field;
 
-               rval = avro_value_get_by_index(dest, i, &field, NULL);
-               if (rval == 0) {
+               check(rval, avro_value_get_by_index(dest, i, &field, NULL));
+               if (field.iface != NULL) {
                        check(rval, read_value(reader, &field));
                } else {
                        avro_schema_t  field_schema =

Modified: avro/trunk/lang/c/src/value.c
URL: 
http://svn.apache.org/viewvc/avro/trunk/lang/c/src/value.c?rev=1175832&r1=1175831&r2=1175832&view=diff
==============================================================================
--- avro/trunk/lang/c/src/value.c (original)
+++ avro/trunk/lang/c/src/value.c Mon Sep 26 12:36:26 2011
@@ -25,50 +25,47 @@
 #include "avro/value.h"
 #include "avro_private.h"
 
-int
-avro_value_new(const avro_value_iface_t *cls, avro_value_t *val)
-{
-       int  rval;
 
-       val->iface = cls;
+#define check_return(retval, call) \
+       do { \
+               int  rval = call; \
+               if (rval != 0) { return (retval); } \
+       } while (0)
 
-       size_t  instance_size = avro_value_instance_size(cls);
-       if (instance_size == 0) {
-               val->iface = NULL;
-               avro_set_error("Value class doesn't declare instance_size");
-               return EINVAL;
-       }
 
-       val->self = avro_malloc(instance_size);
-       if (val->self == NULL) {
-               avro_set_error(strerror(ENOMEM));
-               return ENOMEM;
-       }
+void
+avro_value_incref(avro_value_t *value)
+{
+       value->iface->incref(value);
+}
 
-       rval = avro_value_init(cls, val->self);
-       if (rval) {
-               avro_free(val->self, instance_size);
-               val->self = NULL;
-               return rval;
-       }
+void
+avro_value_decref(avro_value_t *value)
+{
+       value->iface->decref(value);
+       avro_value_iface_decref(value->iface);
+       value->iface = NULL;
+       value->self = NULL;
+}
 
-       return 0;
+void
+avro_value_copy_ref(avro_value_t *dest, const avro_value_t *src)
+{
+       dest->iface = src->iface;
+       dest->self = src->self;
+       avro_value_iface_incref(dest->iface);
+       dest->iface->incref(dest);
 }
 
 void
-avro_value_free(avro_value_t *val)
+avro_value_move_ref(avro_value_t *dest, avro_value_t *src)
 {
-       if (val->self != NULL) {
-               avro_value_done(val);
-               avro_free(val->self, avro_value_instance_size(val->iface));
-       }
+       dest->iface = src->iface;
+       dest->self = src->self;
+       src->iface = NULL;
+       src->self = NULL;
 }
 
-#define check_return(retval, call) \
-       do { \
-               int  rval = call; \
-               if (rval != 0) { return (retval); } \
-       } while (0)
 
 int
 avro_value_equal_fast(avro_value_t *val1, avro_value_t *val2)

Modified: avro/trunk/lang/c/tests/performance.c
URL: 
http://svn.apache.org/viewvc/avro/trunk/lang/c/tests/performance.c?rev=1175832&r1=1175831&r2=1175832&view=diff
==============================================================================
--- avro/trunk/lang/c/tests/performance.c (original)
+++ avro/trunk/lang/c/tests/performance.c Mon Sep 26 12:36:26 2011
@@ -210,10 +210,10 @@ test_nested_record_value_by_index(unsign
        avro_value_iface_t  *iface = avro_generic_class_from_schema(schema);
 
        avro_value_t  val;
-       avro_value_new(iface, &val);
+       avro_generic_value_new(iface, &val);
 
        avro_value_t  out;
-       avro_value_new(iface, &out);
+       avro_generic_value_new(iface, &out);
 
        for (i = 0; i < num_tests; i++) {
                avro_value_t  field;
@@ -249,8 +249,8 @@ test_nested_record_value_by_index(unsign
                avro_value_equal_fast(&val, &out);
        }
 
-       avro_value_free(&val);
-       avro_value_free(&out);
+       avro_value_decref(&val);
+       avro_value_decref(&out);
        avro_value_iface_decref(iface);
        avro_schema_decref(schema);
 }
@@ -310,10 +310,10 @@ test_nested_record_value_by_name(unsigne
        avro_value_iface_t  *iface = avro_generic_class_from_schema(schema);
 
        avro_value_t  val;
-       avro_value_new(iface, &val);
+       avro_generic_value_new(iface, &val);
 
        avro_value_t  out;
-       avro_value_new(iface, &out);
+       avro_generic_value_new(iface, &out);
 
        for (i = 0; i < num_tests; i++) {
                avro_value_t  field;
@@ -349,8 +349,8 @@ test_nested_record_value_by_name(unsigne
                avro_value_equal_fast(&val, &out);
        }
 
-       avro_value_free(&val);
-       avro_value_free(&out);
+       avro_value_decref(&val);
+       avro_value_decref(&out);
        avro_value_iface_decref(iface);
        avro_schema_decref(schema);
 }

Modified: avro/trunk/lang/c/tests/test_avro_data.c
URL: 
http://svn.apache.org/viewvc/avro/trunk/lang/c/tests/test_avro_data.c?rev=1175832&r1=1175831&r2=1175832&view=diff
==============================================================================
--- avro/trunk/lang/c/tests/test_avro_data.c (original)
+++ avro/trunk/lang/c/tests/test_avro_data.c Mon Sep 26 12:36:26 2011
@@ -49,7 +49,8 @@ test_allocator(void *ud, void *ptr, size
                                "doesn't match size passed to "
                                "avro_malloc (%zu)\n",
                                ptr, osize, *size);
-                       exit(EXIT_FAILURE);
+                       abort();
+                       //exit(EXIT_FAILURE);
                }
                free(size);
                return NULL;

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=1175832&r1=1175831&r2=1175832&view=diff
==============================================================================
--- avro/trunk/lang/c/tests/test_avro_values.c (original)
+++ avro/trunk/lang/c/tests/test_avro_values.c Mon Sep 26 12:36:26 2011
@@ -316,7 +316,7 @@ _check_write_read(avro_value_t *val)
        }
 
        avro_value_t  val_in;
-       if (avro_value_new(val->iface, &val_in)) {
+       if (avro_generic_value_new(val->iface, &val_in)) {
                fprintf(stderr, "Cannot allocate new value instance:\n  %s\n",
                        avro_strerror());
                return EXIT_FAILURE;
@@ -333,7 +333,7 @@ _check_write_read(avro_value_t *val)
                exit(EXIT_FAILURE);
        }
 
-       avro_value_free(&val_in);
+       avro_value_decref(&val_in);
        avro_reader_free(reader);
        avro_writer_free(writer);
 
@@ -344,10 +344,25 @@ _check_write_read(avro_value_t *val)
        check_(_check_write_read(val))
 
 static int
+_check_hash(avro_value_t *val1, avro_value_t *val2)
+{
+       uint32_t  hash1 = avro_value_hash(val1);
+       uint32_t  hash2 = avro_value_hash(val2);
+       if (hash1 != hash2) {
+               fprintf(stderr, "Copied hashed not equal\n");
+               return EXIT_FAILURE;
+       }
+       return EXIT_SUCCESS;
+}
+
+#define check_hash(val1, val2) \
+       check_(_check_hash(val1, val2))
+
+static int
 _check_copy(avro_value_t *val)
 {
        avro_value_t  copied_val;
-       if (avro_value_new(val->iface, &copied_val)) {
+       if (avro_generic_value_new(val->iface, &copied_val)) {
                fprintf(stderr, "Cannot allocate new value instance:\n  %s\n",
                        avro_strerror());
                return EXIT_FAILURE;
@@ -361,10 +376,12 @@ _check_copy(avro_value_t *val)
 
        if (!avro_value_equal(val, &copied_val)) {
                fprintf(stderr, "Copied values not equal\n");
-               exit(EXIT_FAILURE);
+               return EXIT_FAILURE;
        }
 
-       avro_value_free(&copied_val);
+       check_hash(val, &copied_val);
+
+       avro_value_decref(&copied_val);
        return EXIT_SUCCESS;
 }
 
@@ -403,7 +420,7 @@ test_boolean(void)
                check_invalid_methods("boolean", &val);
                check_write_read(&val);
                check_copy(&val);
-               avro_value_free(&val);
+               avro_value_decref(&val);
        }
        return 0;
 }
@@ -460,7 +477,7 @@ test_bytes(void)
        check_invalid_methods("bytes", &val);
        check_write_read(&val);
        check_copy(&val);
-       avro_value_free(&val);
+       avro_value_decref(&val);
        return 0;
 }
 
@@ -495,7 +512,7 @@ test_double(void)
                check_invalid_methods("double", &val);
                check_write_read(&val);
                check_copy(&val);
-               avro_value_free(&val);
+               avro_value_decref(&val);
        }
        return 0;
 }
@@ -531,7 +548,7 @@ test_float(void)
                check_invalid_methods("float", &val);
                check_write_read(&val);
                check_copy(&val);
-               avro_value_free(&val);
+               avro_value_decref(&val);
        }
        return 0;
 }
@@ -567,7 +584,7 @@ test_int(void)
                check_invalid_methods("int", &val);
                check_write_read(&val);
                check_copy(&val);
-               avro_value_free(&val);
+               avro_value_decref(&val);
        }
        return 0;
 }
@@ -603,7 +620,7 @@ test_long(void)
                check_invalid_methods("long", &val);
                check_write_read(&val);
                check_copy(&val);
-               avro_value_free(&val);
+               avro_value_decref(&val);
        }
        return 0;
 }
@@ -629,7 +646,7 @@ test_null(void)
        check_invalid_methods("null", &val);
        check_write_read(&val);
        check_copy(&val);
-       avro_value_free(&val);
+       avro_value_decref(&val);
        return 0;
 }
 
@@ -735,7 +752,7 @@ test_string(void)
                check_invalid_methods("string", &val);
                check_write_read(&val);
                check_copy(&val);
-               avro_value_free(&val);
+               avro_value_decref(&val);
        }
 
        return 0;
@@ -757,7 +774,7 @@ test_array(void)
                size_t  count = rand_count();
 
                avro_value_t  val;
-               try(avro_value_new(array_class, &val),
+               try(avro_generic_value_new(array_class, &val),
                    "Cannot create array");
                check(rval, check_type_and_schema
                            ("array", &val, AVRO_ARRAY,
@@ -813,7 +830,7 @@ test_array(void)
                }
 
                check_invalid_methods("array", &val);
-               avro_value_free(&val);
+               avro_value_decref(&val);
        }
 
        avro_schema_decref(double_schema);
@@ -842,7 +859,7 @@ test_enum(void)
        }
 
        avro_value_iface_t  *enum_class =
-           avro_generic_enum_class(enum_schema);
+           avro_generic_class_from_schema(enum_schema);
 
        int  rval;
 
@@ -850,7 +867,7 @@ test_enum(void)
        for (i = 0; i < 4; i++) {
                int  expected = i;
                avro_value_t  val;
-               try(avro_value_new(enum_class, &val),
+               try(avro_generic_value_new(enum_class, &val),
                    "Cannot create enum");
                check(rval, check_type_and_schema
                            ("enum", &val, AVRO_ENUM,
@@ -872,7 +889,7 @@ test_enum(void)
                check_invalid_methods("enum", &val);
                check_write_read(&val);
                check_copy(&val);
-               avro_value_free(&val);
+               avro_value_decref(&val);
        }
 
        avro_schema_decref(enum_schema);
@@ -900,14 +917,14 @@ test_fixed(void)
        }
 
        avro_value_iface_t  *fixed_class =
-           avro_generic_fixed_class(fixed_schema);
+           avro_generic_class_from_schema(fixed_schema);
 
        int  rval;
 
        char fixed[] = { 0xDE, 0xAD, 0xBE, 0xEF };
 
        avro_value_t  val;
-       try(avro_value_new(fixed_class, &val),
+       try(avro_generic_value_new(fixed_class, &val),
            "Cannot create fixed");
        check(rval, check_type_and_schema
                    ("fixed", &val, AVRO_FIXED,
@@ -956,7 +973,7 @@ test_fixed(void)
        check_invalid_methods("fixed", &val);
        check_write_read(&val);
        check_copy(&val);
-       avro_value_free(&val);
+       avro_value_decref(&val);
        avro_schema_decref(fixed_schema);
        avro_value_iface_decref(fixed_class);
        return 0;
@@ -978,7 +995,7 @@ test_map(void)
                size_t  count = rand_count();
 
                avro_value_t  val;
-               try(avro_value_new(map_class, &val),
+               try(avro_generic_value_new(map_class, &val),
                    "Cannot create map");
                check(rval, check_type_and_schema
                            ("map", &val, AVRO_MAP,
@@ -1048,6 +1065,38 @@ test_map(void)
                        return EXIT_FAILURE;
                }
 
+               /*
+                * Create a reversed copy of the map to ensure that the
+                * element ordering doesn't affect the hash value.
+                */
+
+               avro_value_t  reversed;
+               try(avro_generic_value_new(map_class, &reversed),
+                   "Cannot create map");
+
+               for (j = count; j-- > 0; ) {
+                       avro_value_t  element;
+                       const char  *key = NULL;
+                       double  element_value = 0.0;
+                       try(avro_value_get_by_index(&val, j, &element, &key),
+                           "Cannot get from map");
+                       try(avro_value_get_double(&element, &element_value),
+                           "Cannot get double value");
+
+                       try(avro_value_add(&reversed, key, &element, NULL, 
NULL),
+                           "Cannot add to map");
+                       try(avro_value_set_double(&element, element_value),
+                           "Cannot set double");
+               }
+
+               check_hash(&val, &reversed);
+               if (!avro_value_equal(&val, &reversed)) {
+                       fprintf(stderr, "Reversed values not equal\n");
+                       return EXIT_FAILURE;
+               }
+
+               /* Final tests and cleanup */
+
                check_write_read(&val);
                check_copy(&val);
 
@@ -1062,7 +1111,8 @@ test_map(void)
                }
 
                check_invalid_methods("map", &val);
-               avro_value_free(&val);
+               avro_value_decref(&val);
+               avro_value_decref(&reversed);
        }
 
        avro_schema_decref(double_schema);
@@ -1113,7 +1163,7 @@ test_record(void)
        int  rval;
 
        avro_value_t  val;
-       try(avro_value_new(record_class, &val),
+       try(avro_generic_value_new(record_class, &val),
            "Cannot create record");
        check(rval, check_type_and_schema
                    ("record", &val, AVRO_RECORD,
@@ -1214,7 +1264,7 @@ test_record(void)
        }
 
        check_invalid_methods("record", &val);
-       avro_value_free(&val);
+       avro_value_decref(&val);
        avro_value_iface_decref(record_class);
        avro_schema_decref(record_schema);
        return EXIT_SUCCESS;
@@ -1246,7 +1296,7 @@ test_union(void)
        int  rval;
 
        avro_value_t  val;
-       try(avro_value_new(union_class, &val),
+       try(avro_generic_value_new(union_class, &val),
            "Cannot create union");
        check(rval, check_type_and_schema
                    ("union", &val, AVRO_UNION,
@@ -1294,7 +1344,7 @@ test_union(void)
        check_invalid_methods("union", &val);
        check_write_read(&val);
        check_copy(&val);
-       avro_value_free(&val);
+       avro_value_decref(&val);
 
        avro_schema_decref(union_schema);
        avro_value_iface_decref(union_class);


Reply via email to