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/09/26 14:36:27 UTC
svn commit: r1175832 [5/5] - in /avro/trunk: ./ lang/c/docs/
lang/c/examples/ lang/c/src/ lang/c/src/avro/ lang/c/tests/
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);