avro-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From dcrea...@apache.org
Subject svn commit: r1146546 [2/5] - in /avro/trunk/lang/c: docs/ src/ src/avro/ tests/
Date Thu, 14 Jul 2011 02:35:09 GMT
Added: avro/trunk/lang/c/src/avro/schema.h
URL: http://svn.apache.org/viewvc/avro/trunk/lang/c/src/avro/schema.h?rev=1146546&view=auto
==============================================================================
--- avro/trunk/lang/c/src/avro/schema.h (added)
+++ avro/trunk/lang/c/src/avro/schema.h Thu Jul 14 02:35:04 2011
@@ -0,0 +1,106 @@
+/*
+ * 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.
+ */
+
+#ifndef AVRO_SCHEMA_H
+#define AVRO_SCHEMA_H
+#ifdef __cplusplus
+extern "C" {
+#define CLOSE_EXTERN }
+#else
+#define CLOSE_EXTERN
+#endif
+
+#include <stdint.h>
+#include <stdlib.h>
+
+#include <avro/basics.h>
+
+typedef struct avro_obj_t *avro_schema_t;
+
+avro_schema_t avro_schema_string(void);
+avro_schema_t avro_schema_bytes(void);
+avro_schema_t avro_schema_int(void);
+avro_schema_t avro_schema_long(void);
+avro_schema_t avro_schema_float(void);
+avro_schema_t avro_schema_double(void);
+avro_schema_t avro_schema_boolean(void);
+avro_schema_t avro_schema_null(void);
+
+avro_schema_t avro_schema_record(const char *name, const char *space);
+avro_schema_t avro_schema_record_field_get(const avro_schema_t
+					   record, const char *field_name);
+const char *avro_schema_record_field_name(const avro_schema_t schema, int index);
+int avro_schema_record_field_get_index(const avro_schema_t schema,
+				       const char *field_name);
+avro_schema_t avro_schema_record_field_get_by_index
+(const avro_schema_t record, int index);
+int avro_schema_record_field_append(const avro_schema_t record,
+				    const char *field_name,
+				    const avro_schema_t type);
+size_t avro_schema_record_size(const avro_schema_t record);
+
+avro_schema_t avro_schema_enum(const char *name);
+const char *avro_schema_enum_get(const avro_schema_t enump,
+				 int index);
+int avro_schema_enum_get_by_name(const avro_schema_t enump,
+				 const char *symbol_name);
+int avro_schema_enum_symbol_append(const avro_schema_t
+				   enump, const char *symbol);
+
+avro_schema_t avro_schema_fixed(const char *name, const int64_t len);
+int64_t avro_schema_fixed_size(const avro_schema_t fixed);
+
+avro_schema_t avro_schema_map(const avro_schema_t values);
+avro_schema_t avro_schema_map_values(avro_schema_t map);
+
+avro_schema_t avro_schema_array(const avro_schema_t items);
+avro_schema_t avro_schema_array_items(avro_schema_t array);
+
+avro_schema_t avro_schema_union(void);
+size_t avro_schema_union_size(const avro_schema_t union_schema);
+int avro_schema_union_append(const avro_schema_t
+			     union_schema, const avro_schema_t schema);
+avro_schema_t avro_schema_union_branch(avro_schema_t union_schema,
+				       int branch_index);
+avro_schema_t avro_schema_union_branch_by_name
+(avro_schema_t union_schema, int *branch_index, const char *name);
+
+avro_schema_t avro_schema_link(avro_schema_t schema);
+avro_schema_t avro_schema_link_target(avro_schema_t schema);
+
+typedef struct avro_schema_error_t_ *avro_schema_error_t;
+int avro_schema_from_json(const char *jsontext,
+			  const int32_t len,
+			  avro_schema_t * schema, avro_schema_error_t * error);
+
+int avro_schema_to_specific(avro_schema_t schema, const char *prefix);
+
+avro_schema_t avro_schema_get_subschema(const avro_schema_t schema,
+         const char *name);
+const char *avro_schema_name(const avro_schema_t schema);
+const char *avro_schema_type_name(const avro_schema_t schema);
+avro_schema_t avro_schema_copy(avro_schema_t schema);
+int avro_schema_equal(avro_schema_t a, avro_schema_t b);
+
+avro_schema_t avro_schema_incref(avro_schema_t schema);
+void avro_schema_decref(avro_schema_t schema);
+
+int avro_schema_match(avro_schema_t writers_schema,
+		      avro_schema_t readers_schema);
+
+CLOSE_EXTERN
+#endif

Added: avro/trunk/lang/c/src/avro/value.h
URL: http://svn.apache.org/viewvc/avro/trunk/lang/c/src/avro/value.h?rev=1146546&view=auto
==============================================================================
--- avro/trunk/lang/c/src/avro/value.h (added)
+++ avro/trunk/lang/c/src/avro/value.h Thu Jul 14 02:35:04 2011
@@ -0,0 +1,439 @@
+/*
+ * 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.
+ */
+
+#ifndef AVRO_VALUE_H
+#define AVRO_VALUE_H
+#ifdef __cplusplus
+extern "C" {
+#define CLOSE_EXTERN }
+#else
+#define CLOSE_EXTERN
+#endif
+
+#include <errno.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+#include <avro/data.h>
+#include <avro/schema.h>
+
+/*
+ * This file defines an interface struct for Avro data.  Most of the
+ * interesting parts of this library will work with Avro data values
+ * that are expressed in whatever C type you want, as long as you can
+ * provide an implementation of this interface for that type.
+ */
+
+typedef struct avro_value_iface  avro_value_iface_t;
+
+typedef struct avro_value {
+	const avro_value_iface_t  *iface;
+	void  *self;
+} avro_value_t;
+
+struct avro_value_iface {
+	/*-------------------------------------------------------------
+	 * "class" methods
+	 */
+
+	/**
+	 * Increment the reference count of the interface struct.  This
+	 * should be a no-op for static structs, since they don't need
+	 * reference counts.
+	 */
+	avro_value_iface_t *
+	(*incref)(avro_value_iface_t *iface);
+
+	/**
+	 * Decrement the reference count of the interface struct.  If
+	 * the count falls to 0, free the struct.  This should be a
+	 * no-op for static structs, since they don't need reference
+	 * counts.
+	 */
+	void
+	(*decref)(avro_value_iface_t *iface);
+
+	/**
+	 * Return the size of an instance of this value type.  If this
+	 * returns 0, then this value type can't be used with any
+	 * function or type (like avro_value_new) that expects to
+	 * allocate space for the value itself.
+	 */
+	size_t
+	(*instance_size)(const avro_value_iface_t *iface);
+
+	/*-------------------------------------------------------------
+	 * General "instance" methods
+	 */
+
+	/**
+	 * Initialize a new value instance.
+	 */
+	int
+	(*init)(const avro_value_iface_t *iface, void *self);
+
+	/**
+	 * Finalize a value instance.
+	 */
+	void
+	(*done)(const avro_value_iface_t *iface, void *self);
+
+	/**
+	 * Reset the instance to its "empty", default value.  You don't
+	 * have to free the underlying storage, if you want to keep it
+	 * around for later values.
+	 */
+	int
+	(*reset)(const avro_value_iface_t *iface, void *self);
+
+	/**
+	 * Return the general Avro type of a value instance.
+	 */
+	avro_type_t
+	(*get_type)(const avro_value_iface_t *iface, const void *self);
+
+	/**
+	 * Return the Avro schema that a value is an instance of.
+	 */
+	avro_schema_t
+	(*get_schema)(const avro_value_iface_t *iface, const void *self);
+
+	/*-------------------------------------------------------------
+	 * Primitive value getters
+	 */
+	int (*get_boolean)(const avro_value_iface_t *iface,
+			   const void *self, bool *out);
+	int (*get_bytes)(const avro_value_iface_t *iface,
+			 const void *self, const void **buf, size_t *size);
+	int (*grab_bytes)(const avro_value_iface_t *iface,
+			  const void *self, avro_wrapped_buffer_t *dest);
+	int (*get_double)(const avro_value_iface_t *iface,
+			  const void *self, double *out);
+	int (*get_float)(const avro_value_iface_t *iface,
+			 const void *self, float *out);
+	int (*get_int)(const avro_value_iface_t *iface,
+		       const void *self, int32_t *out);
+	int (*get_long)(const avro_value_iface_t *iface,
+			const void *self, int64_t *out);
+	int (*get_null)(const avro_value_iface_t *iface,
+			const void *self);
+	/* The result will be NUL-terminated; the size will INCLUDE the
+	 * NUL terminator.  str will never be NULL unless there's an
+	 * error. */
+	int (*get_string)(const avro_value_iface_t *iface,
+			  const void *self, const char **str, size_t *size);
+	int (*grab_string)(const avro_value_iface_t *iface,
+			   const void *self, avro_wrapped_buffer_t *dest);
+
+	int (*get_enum)(const avro_value_iface_t *iface,
+			const void *self, int *out);
+	int (*get_fixed)(const avro_value_iface_t *iface,
+			 const void *self, const void **buf, size_t *size);
+	int (*grab_fixed)(const avro_value_iface_t *iface,
+			  const void *self, avro_wrapped_buffer_t *dest);
+
+	/*-------------------------------------------------------------
+	 * Primitive value setters
+	 */
+
+	/*
+	 * The "give" setters can be used to give control of an existing
+	 * buffer to a bytes, fixed, or string value.  The free function
+	 * will be called when the buffer is no longer needed.  (It's
+	 * okay for free to be NULL; that just means that nothing
+	 * special needs to be done to free the buffer.  That's useful
+	 * for a static string, for instance.)
+	 *
+	 * If your class can't take control of an existing buffer, then
+	 * your give functions should pass the buffer into the
+	 * corresponding "set" method and then immediately free the
+	 * buffer.
+	 *
+	 * Note that for strings, the free function will be called with
+	 * a size that *includes* the NUL terminator, even though you
+	 * provide a size that does *not*.
+	 */
+
+	int (*set_boolean)(const avro_value_iface_t *iface,
+			   void *self, bool val);
+	int (*set_bytes)(const avro_value_iface_t *iface,
+			 void *self, void *buf, size_t size);
+	int (*give_bytes)(const avro_value_iface_t *iface,
+			  void *self, avro_wrapped_buffer_t *buf);
+	int (*set_double)(const avro_value_iface_t *iface,
+			  void *self, double val);
+	int (*set_float)(const avro_value_iface_t *iface,
+			 void *self, float val);
+	int (*set_int)(const avro_value_iface_t *iface,
+		       void *self, int32_t val);
+	int (*set_long)(const avro_value_iface_t *iface,
+			void *self, int64_t val);
+	int (*set_null)(const avro_value_iface_t *iface, void *self);
+	/* The input must be NUL-terminated */
+	int (*set_string)(const avro_value_iface_t *iface,
+			  void *self, char *str);
+	/* and size must INCLUDE the NUL terminator */
+	int (*set_string_len)(const avro_value_iface_t *iface,
+			      void *self, char *str, size_t size);
+	int (*give_string_len)(const avro_value_iface_t *iface,
+			       void *self, avro_wrapped_buffer_t *buf);
+
+	int (*set_enum)(const avro_value_iface_t *iface,
+			void *self, int val);
+	int (*set_fixed)(const avro_value_iface_t *iface,
+			 void *self, void *buf, size_t size);
+	int (*give_fixed)(const avro_value_iface_t *iface,
+			  void *self, avro_wrapped_buffer_t *buf);
+
+	/*-------------------------------------------------------------
+	 * Compound value getters
+	 */
+
+	/* Number of elements in array/map, or the number of fields in a
+	 * record. */
+	int (*get_size)(const avro_value_iface_t *iface,
+			const void *self, size_t *size);
+
+	/*
+	 * For arrays and maps, returns the element with the given
+	 * index.  (For maps, the "index" is based on the order that the
+	 * keys were added to the map.)  For records, returns the field
+	 * with that index in the schema.
+	 *
+	 * For maps and records, the name parameter (if given) will be
+	 * filled in with the key or field name of the returned value.
+	 * For arrays, the name parameter will always be ignored.
+	 */
+	int (*get_by_index)(const avro_value_iface_t *iface,
+			    const void *self, size_t index,
+			    avro_value_t *child, const char **name);
+
+	/*
+	 * For maps, returns the element with the given key.  For
+	 * records, returns the element with the given field name.  If
+	 * index is given, it will be filled in with the numeric index
+	 * of the returned value.
+	 */
+	int (*get_by_name)(const avro_value_iface_t *iface,
+			   const void *self, const char *name,
+			   avro_value_t *child, size_t *index);
+
+	/* Discriminant of current union value */
+	int (*get_discriminant)(const avro_value_iface_t *iface,
+				const void *self, int *out);
+	/* Current union value */
+	int (*get_current_branch)(const avro_value_iface_t *iface,
+				  const void *self, avro_value_t *branch);
+
+	/*-------------------------------------------------------------
+	 * Compound value setters
+	 */
+
+	/*
+	 * For all of these, the value class should know which class to
+	 * use for its children.
+	 */
+
+	/* Creates a new array element. */
+	int (*append)(const avro_value_iface_t *iface,
+		      void *self, avro_value_t *child_out, size_t *new_index);
+
+	/* Creates a new map element, or returns an existing one. */
+	int (*add)(const avro_value_iface_t *iface,
+		   void *self, const char *key,
+		   avro_value_t *child, size_t *index, bool *is_new);
+
+	/* Select a union branch. */
+	int (*set_branch)(const avro_value_iface_t *iface,
+			  void *self, int discriminant,
+			  avro_value_t *branch);
+};
+
+/**
+ * Allocate a new instance of the given value class, storing the result
+ * into val.
+ */
+
+int
+avro_value_new(const avro_value_iface_t *cls, avro_value_t *val);
+
+/**
+ * Finalize and deallocate a value instance.
+ */
+
+void
+avro_value_free(avro_value_t *val);
+
+/**
+ * Compares two values for equality.  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_equal_fast.
+ */
+
+bool
+avro_value_equal(avro_value_t *val1, avro_value_t *val2);
+
+/**
+ * Compares two values for equality.  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_equal, which compares the schemas before comparing the
+ * values.
+ */
+
+bool
+avro_value_equal_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
+ * that the schemas match; if you want to skip this check, use
+ * avro_value_copy_fast.
+ */
+
+int
+avro_value_copy(avro_value_t *dest, const avro_value_t *src);
+
+/**
+ * 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 assumes
+ * that the schemas match; if you can't guarantee this, you should use
+ * avro_value_copy, which compares the schemas before comparing the
+ * values.
+ */
+
+int
+avro_value_copy_fast(avro_value_t *dest, const avro_value_t *src);
+
+
+/**
+ * A helper macro for calling a given method in a value instance, if
+ * it's present.  If the value's class doesn't implement the given
+ * method, we return dflt.  You usually won't call this directly; it's
+ * just here to implement the macros below.
+ */
+
+#define avro_value_call0(value, method, dflt) \
+    ((value)->iface->method == NULL? (dflt): \
+     (value)->iface->method((value)->iface, (value)->self))
+
+#define avro_value_call(value, method, dflt, ...) \
+    ((value)->iface->method == NULL? (dflt): \
+     (value)->iface->method((value)->iface, (value)->self, __VA_ARGS__))
+
+
+#define avro_value_iface_incref(cls) \
+    ((cls)->incref == NULL? (cls): (cls)->incref((cls)))
+#define avro_value_iface_decref(cls) \
+    ((cls)->decref == NULL? (void) 0: (cls)->decref((cls)))
+
+#define avro_value_instance_size(cls) \
+    ((cls)->instance_size == NULL? 0: (cls)->instance_size((cls)))
+#define avro_value_init(cls, self) \
+    ((cls)->init == NULL? EINVAL: (cls)->init((cls), (self)))
+#define avro_value_done(value) \
+    avro_value_call0(value, done, (void) 0)
+
+#define avro_value_reset(value) \
+    avro_value_call0(value, reset, EINVAL)
+#define avro_value_get_type(value) \
+    avro_value_call0(value, get_type, (avro_type_t) -1)
+#define avro_value_get_schema(value) \
+    avro_value_call0(value, get_schema, NULL)
+
+#define avro_value_get_boolean(value, out) \
+    avro_value_call(value, get_boolean, EINVAL, out)
+#define avro_value_get_bytes(value, buf, size) \
+    avro_value_call(value, get_bytes, EINVAL, buf, size)
+#define avro_value_grab_bytes(value, dest) \
+    avro_value_call(value, grab_bytes, EINVAL, dest)
+#define avro_value_get_double(value, out) \
+    avro_value_call(value, get_double, EINVAL, out)
+#define avro_value_get_float(value, out) \
+    avro_value_call(value, get_float, EINVAL, out)
+#define avro_value_get_int(value, out) \
+    avro_value_call(value, get_int, EINVAL, out)
+#define avro_value_get_long(value, out) \
+    avro_value_call(value, get_long, EINVAL, out)
+#define avro_value_get_null(value) \
+    avro_value_call0(value, get_null, EINVAL)
+#define avro_value_get_string(value, str, size) \
+    avro_value_call(value, get_string, EINVAL, str, size)
+#define avro_value_grab_string(value, dest) \
+    avro_value_call(value, grab_string, EINVAL, dest)
+#define avro_value_get_enum(value, out) \
+    avro_value_call(value, get_enum, EINVAL, out)
+#define avro_value_get_fixed(value, buf, size) \
+    avro_value_call(value, get_fixed, EINVAL, buf, size)
+#define avro_value_grab_fixed(value, dest) \
+    avro_value_call(value, grab_fixed, EINVAL, dest)
+
+#define avro_value_set_boolean(value, val) \
+    avro_value_call(value, set_boolean, EINVAL, val)
+#define avro_value_set_bytes(value, buf, size) \
+    avro_value_call(value, set_bytes, EINVAL, buf, size)
+#define avro_value_give_bytes(value, buf) \
+    avro_value_call(value, give_bytes, EINVAL, buf)
+#define avro_value_set_double(value, val) \
+    avro_value_call(value, set_double, EINVAL, val)
+#define avro_value_set_float(value, val) \
+    avro_value_call(value, set_float, EINVAL, val)
+#define avro_value_set_int(value, val) \
+    avro_value_call(value, set_int, EINVAL, val)
+#define avro_value_set_long(value, val) \
+    avro_value_call(value, set_long, EINVAL, val)
+#define avro_value_set_null(value) \
+    avro_value_call0(value, set_null, EINVAL)
+#define avro_value_set_string(value, str) \
+    avro_value_call(value, set_string, EINVAL, str)
+#define avro_value_set_string_len(value, str, size) \
+    avro_value_call(value, set_string_len, EINVAL, str, size)
+#define avro_value_give_string_len(value, buf) \
+    avro_value_call(value, give_string_len, EINVAL, buf)
+#define avro_value_set_enum(value, val) \
+    avro_value_call(value, set_enum, EINVAL, val)
+#define avro_value_set_fixed(value, buf, size) \
+    avro_value_call(value, set_fixed, EINVAL, buf, size)
+#define avro_value_give_fixed(value, buf) \
+    avro_value_call(value, give_fixed, EINVAL, buf)
+
+#define avro_value_get_size(value, size) \
+    avro_value_call(value, get_size, EINVAL, size)
+#define avro_value_get_by_index(value, idx, child, name) \
+    avro_value_call(value, get_by_index, EINVAL, idx, child, name)
+#define avro_value_get_by_name(value, name, child, index) \
+    avro_value_call(value, get_by_name, EINVAL, name, child, index)
+#define avro_value_get_discriminant(value, out) \
+    avro_value_call(value, get_discriminant, EINVAL, out)
+#define avro_value_get_current_branch(value, branch) \
+    avro_value_call(value, get_current_branch, EINVAL, branch)
+
+#define avro_value_append(value, child, new_index) \
+    avro_value_call(value, append, EINVAL, child, new_index)
+#define avro_value_add(value, key, child, index, is_new) \
+    avro_value_call(value, add, EINVAL, key, child, index, is_new)
+#define avro_value_set_branch(value, discriminant, branch) \
+    avro_value_call(value, set_branch, EINVAL, discriminant, branch)
+
+CLOSE_EXTERN
+#endif

Modified: avro/trunk/lang/c/src/avro_private.h
URL: http://svn.apache.org/viewvc/avro/trunk/lang/c/src/avro_private.h?rev=1146546&r1=1146545&r2=1146546&view=diff
==============================================================================
--- avro/trunk/lang/c/src/avro_private.h (original)
+++ avro/trunk/lang/c/src/avro_private.h Thu Jul 14 02:35:04 2011
@@ -19,7 +19,7 @@
 
 #include <errno.h>
 
-#include "avro.h"
+#include "avro/errors.h"
 
 #ifdef HAVE_CONFIG_H
 /* This is only true for now in the autotools build */

Modified: avro/trunk/lang/c/src/datafile.c
URL: http://svn.apache.org/viewvc/avro/trunk/lang/c/src/datafile.c?rev=1146546&r1=1146545&r2=1146546&view=diff
==============================================================================
--- avro/trunk/lang/c/src/datafile.c (original)
+++ avro/trunk/lang/c/src/datafile.c Thu Jul 14 02:35:04 2011
@@ -15,9 +15,9 @@
  * permissions and limitations under the License. 
  */
 
-#include "avro_errors.h"
 #include "avro_private.h"
-#include "allocation.h"
+#include "avro/allocation.h"
+#include "avro/errors.h"
 #include "encoding.h"
 #include <stdio.h>
 #include <stdlib.h>

Modified: avro/trunk/lang/c/src/datum.c
URL: http://svn.apache.org/viewvc/avro/trunk/lang/c/src/datum.c?rev=1146546&r1=1146545&r2=1146546&view=diff
==============================================================================
--- avro/trunk/lang/c/src/datum.c (original)
+++ avro/trunk/lang/c/src/datum.c Thu Jul 14 02:35:04 2011
@@ -15,10 +15,13 @@
  * permissions and limitations under the License. 
  */
 
+#include "avro/allocation.h"
+#include "avro/basics.h"
+#include "avro/errors.h"
+#include "avro/legacy.h"
 #include "avro/refcount.h"
-#include "avro_errors.h"
+#include "avro/schema.h"
 #include "avro_private.h"
-#include "allocation.h"
 #include <stdlib.h>
 #include <string.h>
 #include <errno.h>
@@ -154,7 +157,7 @@ avro_datum_t avro_bytes(const char *byte
 	}
 	memcpy(bytes_copy, bytes, size);
 	avro_datum_t  result =
-		avro_bytes_private(bytes_copy, size, avro_alloc_free);
+		avro_bytes_private(bytes_copy, size, avro_alloc_free_func);
 	if (result == NULL) {
 		avro_free(bytes_copy, size);
 	}
@@ -194,7 +197,7 @@ int avro_bytes_set(avro_datum_t datum, c
 		return ENOMEM;
 	}
 	memcpy(bytes_copy, bytes, size);
-	rval = avro_bytes_set_private(datum, bytes_copy, size, avro_alloc_free);
+	rval = avro_bytes_set_private(datum, bytes_copy, size, avro_alloc_free_func);
 	if (rval) {
 		avro_free(bytes_copy, size);
 	}
@@ -636,7 +639,7 @@ avro_datum_t avro_fixed(avro_schema_t sc
 		return NULL;
 	}
 	memcpy(bytes_copy, bytes, size);
-	return avro_fixed_private(schema, bytes_copy, size, avro_alloc_free);
+	return avro_fixed_private(schema, bytes_copy, size, avro_alloc_free_func);
 }
 
 avro_datum_t avro_givefixed(avro_schema_t schema,
@@ -679,7 +682,7 @@ int avro_fixed_set(avro_datum_t datum, c
 		return ENOMEM;
 	}
 	memcpy(bytes_copy, bytes, size);
-	rval = avro_fixed_set_private(datum, bytes_copy, size, avro_alloc_free);
+	rval = avro_fixed_set_private(datum, bytes_copy, size, avro_alloc_free_func);
 	if (rval) {
 		avro_free(bytes_copy, size);
 	}
@@ -704,6 +707,30 @@ int avro_fixed_get(avro_datum_t datum, c
 	return 0;
 }
 
+static int
+avro_init_map(struct avro_map_datum_t *datum)
+{
+	datum->map = st_init_strtable_with_size(DEFAULT_TABLE_SIZE);
+	if (!datum->map) {
+		avro_set_error("Cannot create new map datum");
+		return ENOMEM;
+	}
+	datum->indices_by_key = st_init_strtable_with_size(DEFAULT_TABLE_SIZE);
+	if (!datum->indices_by_key) {
+		avro_set_error("Cannot create new map datum");
+		st_free_table(datum->map);
+		return ENOMEM;
+	}
+	datum->keys_by_index = st_init_numtable_with_size(DEFAULT_TABLE_SIZE);
+	if (!datum->keys_by_index) {
+		avro_set_error("Cannot create new map datum");
+		st_free_table(datum->indices_by_key);
+		st_free_table(datum->map);
+		return ENOMEM;
+	}
+	return 0;
+}
+
 avro_datum_t avro_map(avro_schema_t schema)
 {
 	check_param(NULL, is_avro_schema(schema), "schema");
@@ -714,16 +741,8 @@ avro_datum_t avro_map(avro_schema_t sche
 		avro_set_error("Cannot create new map datum");
 		return NULL;
 	}
-	datum->map = st_init_strtable_with_size(DEFAULT_TABLE_SIZE);
-	if (!datum->map) {
-		avro_set_error("Cannot create new map datum");
-		avro_freet(struct avro_map_datum_t, datum);
-		return NULL;
-	}
-	datum->keys_by_index = st_init_numtable_with_size(DEFAULT_TABLE_SIZE);
-	if (!datum->keys_by_index) {
-		avro_set_error("Cannot create new map datum");
-		st_free_table(datum->map);
+
+	if (avro_init_map(datum) != 0) {
 		avro_freet(struct avro_map_datum_t, datum);
 		return NULL;
 	}
@@ -786,6 +805,26 @@ int avro_map_get_key(const avro_datum_t 
 	return EINVAL;
 }
 
+int avro_map_get_index(const avro_datum_t datum, const char *key,
+		       int *index)
+{
+	check_param(EINVAL, is_avro_datum(datum), "datum");
+	check_param(EINVAL, is_avro_map(datum), "map datum");
+	check_param(EINVAL, key, "key");
+	check_param(EINVAL, index, "index");
+
+	st_data_t  data;
+
+	struct avro_map_datum_t *map = avro_datum_to_map(datum);
+	if (st_lookup(map->indices_by_key, (st_data_t) key, &data)) {
+		*index = (int) data;
+		return 0;
+	}
+
+	avro_set_error("No map element with key %s", key);
+	return EINVAL;
+}
+
 int
 avro_map_set(avro_datum_t datum, const char *key,
 	     const avro_datum_t value)
@@ -811,6 +850,8 @@ avro_map_set(avro_datum_t datum, const c
 			return ENOMEM;
 		}
 		int  new_index = map->map->num_entries;
+		st_insert(map->indices_by_key, (st_data_t) save_key,
+			  (st_data_t) new_index);
 		st_insert(map->keys_by_index, (st_data_t) new_index,
 			  (st_data_t) save_key);
 	}
@@ -819,6 +860,17 @@ avro_map_set(avro_datum_t datum, const c
 	return 0;
 }
 
+static int
+avro_init_array(struct avro_array_datum_t *datum)
+{
+	datum->els = st_init_numtable_with_size(DEFAULT_TABLE_SIZE);
+	if (!datum->els) {
+		avro_set_error("Cannot create new array datum");
+		return ENOMEM;
+	}
+	return 0;
+}
+
 avro_datum_t avro_array(avro_schema_t schema)
 {
 	check_param(NULL, is_avro_schema(schema), "schema");
@@ -829,9 +881,8 @@ avro_datum_t avro_array(avro_schema_t sc
 		avro_set_error("Cannot create new array datum");
 		return NULL;
 	}
-	datum->els = st_init_numtable_with_size(DEFAULT_TABLE_SIZE);
-	if (!datum->els) {
-		avro_set_error("Cannot create new array datum");
+
+	if (avro_init_array(datum) != 0) {
 		avro_freet(struct avro_array_datum_t, datum);
 		return NULL;
 	}
@@ -1067,6 +1118,7 @@ static void avro_datum_free(avro_datum_t
 				st_foreach(map->map, char_datum_free_foreach,
 					   0);
 				st_free_table(map->map);
+				st_free_table(map->indices_by_key);
 				st_free_table(map->keys_by_index);
 				avro_freet(struct avro_map_datum_t, map);
 			}
@@ -1096,6 +1148,84 @@ static void avro_datum_free(avro_datum_t
 	}
 }
 
+static int
+datum_reset_foreach(int i, avro_datum_t datum, void *arg)
+{
+	AVRO_UNUSED(i);
+	int  rval;
+	int  *result = arg;
+
+	rval = avro_datum_reset(datum);
+	if (rval == 0) {
+		return ST_CONTINUE;
+	} else {
+		*result = rval;
+		return ST_STOP;
+	}
+}
+
+int
+avro_datum_reset(avro_datum_t datum)
+{
+	check_param(EINVAL, is_avro_datum(datum), "datum");
+	int  rval;
+
+	switch (avro_typeof(datum)) {
+		case AVRO_ARRAY:
+		{
+			struct avro_array_datum_t *array;
+			array = avro_datum_to_array(datum);
+			st_foreach(array->els, array_free_foreach, 0);
+			st_free_table(array->els);
+
+			rval = avro_init_array(array);
+			if (rval != 0) {
+				avro_freet(struct avro_array_datum_t, array);
+				return rval;
+			}
+			return 0;
+		}
+
+		case AVRO_MAP:
+		{
+			struct avro_map_datum_t *map;
+			map = avro_datum_to_map(datum);
+			st_foreach(map->map, char_datum_free_foreach, 0);
+			st_free_table(map->map);
+			st_free_table(map->indices_by_key);
+			st_free_table(map->keys_by_index);
+
+			rval = avro_init_map(map);
+			if (rval != 0) {
+				avro_freet(struct avro_map_datum_t, map);
+				return rval;
+			}
+			return 0;
+		}
+
+		case AVRO_RECORD:
+		{
+			struct avro_record_datum_t *record;
+			record = avro_datum_to_record(datum);
+			rval = 0;
+			st_foreach(record->fields_byname,
+				   datum_reset_foreach, (st_data_t) &rval);
+			return rval;
+		}
+
+		case AVRO_UNION:
+		{
+			struct avro_union_datum_t *unionp;
+			unionp = avro_datum_to_union(datum);
+			return (unionp->value == NULL)? 0:
+			    avro_datum_reset(unionp->value);
+		}
+
+		default:
+			return 0;
+	}
+}
+
 avro_datum_t avro_datum_incref(avro_datum_t datum)
 {
 	if (datum) {

Modified: avro/trunk/lang/c/src/datum.h
URL: http://svn.apache.org/viewvc/avro/trunk/lang/c/src/datum.h?rev=1146546&r1=1146545&r2=1146546&view=diff
==============================================================================
--- avro/trunk/lang/c/src/datum.h (original)
+++ avro/trunk/lang/c/src/datum.h Thu Jul 14 02:35:04 2011
@@ -17,7 +17,11 @@
 
 #ifndef AVRO_DATUM_H
 #define AVRO_DATUM_H
-#include "avro.h"		/* for avro_schema_t */
+#include <stdint.h>
+#include "avro/basics.h"
+#include "avro/data.h"
+#include "avro/legacy.h"
+#include "avro/schema.h"
 #include "avro_private.h"
 #include "st.h"
 
@@ -72,6 +76,7 @@ struct avro_map_datum_t {
 	struct avro_obj_t obj;
 	avro_schema_t schema;
 	st_table *map;
+	st_table *indices_by_key;
 	st_table *keys_by_index;
 };
 

Modified: avro/trunk/lang/c/src/datum_json.c
URL: http://svn.apache.org/viewvc/avro/trunk/lang/c/src/datum_json.c?rev=1146546&r1=1146545&r2=1146546&view=diff
==============================================================================
--- avro/trunk/lang/c/src/datum_json.c (original)
+++ avro/trunk/lang/c/src/datum_json.c Thu Jul 14 02:35:04 2011
@@ -19,10 +19,10 @@
 #include <stdlib.h>
 #include <string.h>
 
-#include "avro.h"
-#include "avro_errors.h"
+#include "avro/allocation.h"
+#include "avro/errors.h"
+#include "avro/legacy.h"
 #include "avro_private.h"
-#include "allocation.h"
 #include "datum.h"
 #include "jansson.h"
 

Modified: avro/trunk/lang/c/src/datum_read.c
URL: http://svn.apache.org/viewvc/avro/trunk/lang/c/src/datum_read.c?rev=1146546&r1=1146545&r2=1146546&view=diff
==============================================================================
--- avro/trunk/lang/c/src/datum_read.c (original)
+++ avro/trunk/lang/c/src/datum_read.c Thu Jul 14 02:35:04 2011
@@ -15,10 +15,10 @@
  * permissions and limitations under the License. 
  */
 
-#include "avro_errors.h"
 #include "avro_private.h"
+#include "avro/allocation.h"
 #include "avro/consumer.h"
-#include "allocation.h"
+#include "avro/errors.h"
 #include <stdlib.h>
 #include <errno.h>
 #include <string.h>

Modified: avro/trunk/lang/c/src/datum_size.c
URL: http://svn.apache.org/viewvc/avro/trunk/lang/c/src/datum_size.c?rev=1146546&r1=1146545&r2=1146546&view=diff
==============================================================================
--- avro/trunk/lang/c/src/datum_size.c (original)
+++ avro/trunk/lang/c/src/datum_size.c Thu Jul 14 02:35:04 2011
@@ -15,8 +15,8 @@
  * permissions and limitations under the License. 
  */
 
-#include "avro_errors.h"
 #include "avro_private.h"
+#include "avro/errors.h"
 #include <errno.h>
 #include <assert.h>
 #include <string.h>

Modified: avro/trunk/lang/c/src/datum_skip.c
URL: http://svn.apache.org/viewvc/avro/trunk/lang/c/src/datum_skip.c?rev=1146546&r1=1146545&r2=1146546&view=diff
==============================================================================
--- avro/trunk/lang/c/src/datum_skip.c (original)
+++ avro/trunk/lang/c/src/datum_skip.c Thu Jul 14 02:35:04 2011
@@ -15,8 +15,8 @@
  * permissions and limitations under the License. 
  */
 
-#include "avro_errors.h"
 #include "avro_private.h"
+#include "avro/errors.h"
 #include <stdlib.h>
 #include <errno.h>
 #include <string.h>

Modified: avro/trunk/lang/c/src/datum_validate.c
URL: http://svn.apache.org/viewvc/avro/trunk/lang/c/src/datum_validate.c?rev=1146546&r1=1146545&r2=1146546&view=diff
==============================================================================
--- avro/trunk/lang/c/src/datum_validate.c (original)
+++ avro/trunk/lang/c/src/datum_validate.c Thu Jul 14 02:35:04 2011
@@ -15,8 +15,8 @@
  * permissions and limitations under the License. 
  */
 
-#include "avro_errors.h"
 #include "avro_private.h"
+#include "avro/errors.h"
 #include <limits.h>
 #include <errno.h>
 #include <string.h>

Added: avro/trunk/lang/c/src/datum_value.c
URL: http://svn.apache.org/viewvc/avro/trunk/lang/c/src/datum_value.c?rev=1146546&view=auto
==============================================================================
--- avro/trunk/lang/c/src/datum_value.c (added)
+++ avro/trunk/lang/c/src/datum_value.c Thu Jul 14 02:35:04 2011
@@ -0,0 +1,751 @@
+/*
+ * 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 <stdbool.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "avro/allocation.h"
+#include "avro/basics.h"
+#include "avro/errors.h"
+#include "avro/legacy.h"
+#include "avro/refcount.h"
+#include "avro/schema.h"
+#include "avro/value.h"
+#include "avro_private.h"
+
+static void
+avro_datum_value_done(const avro_value_iface_t *iface, void *vself)
+{
+	AVRO_UNUSED(iface);
+	avro_datum_t  self = vself;
+	avro_datum_decref(self);
+}
+
+static int
+avro_datum_value_reset(const avro_value_iface_t *iface, void *vself)
+{
+	AVRO_UNUSED(iface);
+	avro_datum_t  self = vself;
+	check_param(EINVAL, self, "datum instance");
+	return avro_datum_reset(self);
+}
+
+static avro_type_t
+avro_datum_value_get_type(const avro_value_iface_t *iface, const void *vself)
+{
+	AVRO_UNUSED(iface);
+	const avro_datum_t  self = (const avro_datum_t) vself;
+	check_param(EINVAL, self, "datum instance");
+	return avro_typeof(self);
+}
+
+static avro_schema_t
+avro_datum_value_get_schema(const avro_value_iface_t *iface, const void *vself)
+{
+	AVRO_UNUSED(iface);
+	const avro_datum_t  self = (const avro_datum_t) vself;
+	check_param(NULL, self, "datum instance");
+	return avro_datum_get_schema(self);
+}
+
+
+static int
+avro_datum_value_get_boolean(const avro_value_iface_t *iface,
+			     const void *vself, bool *out)
+{
+	AVRO_UNUSED(iface);
+	const avro_datum_t  self = (const avro_datum_t) vself;
+	check_param(EINVAL, self, "datum instance");
+
+	int  rval;
+	int8_t  value;
+	check(rval, avro_boolean_get(self, &value));
+	*out = value;
+	return 0;
+}
+
+static int
+avro_datum_value_get_bytes(const avro_value_iface_t *iface,
+			   const void *vself, const void **buf, size_t *size)
+{
+	AVRO_UNUSED(iface);
+	const avro_datum_t  self = (const avro_datum_t) vself;
+	check_param(EINVAL, self, "datum instance");
+
+	int  rval;
+	char  *bytes;
+	int64_t  sz;
+	check(rval, avro_bytes_get(self, &bytes, &sz));
+	if (buf != NULL) {
+		*buf = (const void *) bytes;
+	}
+	if (size != NULL) {
+		*size = sz;
+	}
+	return 0;
+}
+
+static int
+avro_datum_value_grab_bytes(const avro_value_iface_t *iface,
+			    const void *vself, avro_wrapped_buffer_t *dest)
+{
+	AVRO_UNUSED(iface);
+	const avro_datum_t  self = (const avro_datum_t) vself;
+	check_param(EINVAL, self, "datum instance");
+
+	int  rval;
+	char  *bytes;
+	int64_t  sz;
+	check(rval, avro_bytes_get(self, &bytes, &sz));
+
+	/* nothing clever, just make a copy */
+	return avro_wrapped_buffer_new_copy(dest, bytes, sz);
+}
+
+static int
+avro_datum_value_get_double(const avro_value_iface_t *iface,
+			    const void *vself, double *out)
+{
+	AVRO_UNUSED(iface);
+	const avro_datum_t  self = (const avro_datum_t) vself;
+	check_param(EINVAL, self, "datum instance");
+
+	int  rval;
+	double  value;
+	check(rval, avro_double_get(self, &value));
+	*out = value;
+	return 0;
+}
+
+static int
+avro_datum_value_get_float(const avro_value_iface_t *iface,
+			   const void *vself, float *out)
+{
+	AVRO_UNUSED(iface);
+	const avro_datum_t  self = (const avro_datum_t) vself;
+	check_param(EINVAL, self, "datum instance");
+
+	int  rval;
+	float  value;
+	check(rval, avro_float_get(self, &value));
+	*out = value;
+	return 0;
+}
+
+static int
+avro_datum_value_get_int(const avro_value_iface_t *iface,
+			 const void *vself, int32_t *out)
+{
+	AVRO_UNUSED(iface);
+	const avro_datum_t  self = (const avro_datum_t) vself;
+	check_param(EINVAL, self, "datum instance");
+
+	int  rval;
+	int32_t  value;
+	check(rval, avro_int32_get(self, &value));
+	*out = value;
+	return 0;
+}
+
+static int
+avro_datum_value_get_long(const avro_value_iface_t *iface,
+			  const void *vself, int64_t *out)
+{
+	AVRO_UNUSED(iface);
+	const avro_datum_t  self = (const avro_datum_t) vself;
+	check_param(EINVAL, self, "datum instance");
+
+	int  rval;
+	int64_t  value;
+	check(rval, avro_int64_get(self, &value));
+	*out = value;
+	return 0;
+}
+
+static int
+avro_datum_value_get_null(const avro_value_iface_t *iface,
+			  const void *vself)
+{
+	AVRO_UNUSED(iface);
+	const avro_datum_t  self = (const avro_datum_t) vself;
+	check_param(EINVAL, is_avro_null(self), "datum instance");
+	return 0;
+}
+
+static int
+avro_datum_value_get_string(const avro_value_iface_t *iface,
+			    const void *vself, const char **str, size_t *size)
+{
+	AVRO_UNUSED(iface);
+	const avro_datum_t  self = (const avro_datum_t) vself;
+	check_param(EINVAL, self, "datum instance");
+
+	int  rval;
+	char  *value;
+	check(rval, avro_string_get(self, &value));
+	if (str != NULL) {
+		*str = (const char *) value;
+	}
+	if (size != NULL) {
+		*size = strlen(value)+1;
+	}
+	return 0;
+}
+
+static int
+avro_datum_value_grab_string(const avro_value_iface_t *iface,
+			     const void *vself, avro_wrapped_buffer_t *dest)
+{
+	AVRO_UNUSED(iface);
+	const avro_datum_t  self = (const avro_datum_t) vself;
+	check_param(EINVAL, self, "datum instance");
+
+	int  rval;
+	char  *str;
+	size_t  sz;
+	check(rval, avro_string_get(self, &str));
+	sz = strlen(str);
+
+	/* nothing clever, just make a copy */
+	/* sz doesn't contain NUL terminator */
+	return avro_wrapped_buffer_new_copy(dest, str, sz+1);
+}
+
+static int
+avro_datum_value_get_enum(const avro_value_iface_t *iface,
+			  const void *vself, int *out)
+{
+	AVRO_UNUSED(iface);
+	const avro_datum_t  self = (const avro_datum_t) vself;
+	check_param(EINVAL, is_avro_enum(self), "datum instance");
+	*out = avro_enum_get(self);
+	return 0;
+}
+
+static int
+avro_datum_value_get_fixed(const avro_value_iface_t *iface,
+			   const void *vself, const void **buf, size_t *size)
+{
+	AVRO_UNUSED(iface);
+	const avro_datum_t  self = (const avro_datum_t) vself;
+	check_param(EINVAL, self, "datum instance");
+
+	int  rval;
+	char  *bytes;
+	int64_t  sz;
+	check(rval, avro_fixed_get(self, &bytes, &sz));
+	if (buf != NULL) {
+		*buf = (const void *) bytes;
+	}
+	if (size != NULL) {
+		*size = sz;
+	}
+	return 0;
+}
+
+static int
+avro_datum_value_grab_fixed(const avro_value_iface_t *iface,
+			    const void *vself, avro_wrapped_buffer_t *dest)
+{
+	AVRO_UNUSED(iface);
+	const avro_datum_t  self = (const avro_datum_t) vself;
+	check_param(EINVAL, self, "datum instance");
+
+	int  rval;
+	char  *bytes;
+	int64_t  sz;
+	check(rval, avro_fixed_get(self, &bytes, &sz));
+
+	/* nothing clever, just make a copy */
+	return avro_wrapped_buffer_new_copy(dest, bytes, sz);
+}
+
+
+static int
+avro_datum_value_set_boolean(const avro_value_iface_t *iface,
+			     void *vself, bool val)
+{
+	AVRO_UNUSED(iface);
+	avro_datum_t  self = vself;
+	check_param(EINVAL, self, "datum instance");
+	return avro_boolean_set(self, val);
+}
+
+static int
+avro_datum_value_set_bytes(const avro_value_iface_t *iface,
+			   void *vself, void *buf, size_t size)
+{
+	AVRO_UNUSED(iface);
+	avro_datum_t  self = vself;
+	check_param(EINVAL, self, "datum instance");
+	return avro_bytes_set(self, buf, size);
+}
+
+static int
+avro_datum_value_give_bytes(const avro_value_iface_t *iface,
+			    void *vself, avro_wrapped_buffer_t *buf)
+{
+	/*
+	 * We actually can't use avro_givebytes_set, since it can't
+	 * handle the extra free_ud parameter.  Ah well, this is
+	 * deprecated, so go ahead and make a copy.
+	 */
+
+	int rval = avro_datum_value_set_bytes
+	    (iface, vself, (void *) buf->buf, buf->size);
+	avro_wrapped_buffer_free(buf);
+	return rval;
+}
+
+static int
+avro_datum_value_set_double(const avro_value_iface_t *iface,
+			    void *vself, double val)
+{
+	AVRO_UNUSED(iface);
+	avro_datum_t  self = vself;
+	check_param(EINVAL, self, "datum instance");
+	return avro_double_set(self, val);
+}
+
+static int
+avro_datum_value_set_float(const avro_value_iface_t *iface,
+			   void *vself, float val)
+{
+	AVRO_UNUSED(iface);
+	avro_datum_t  self = vself;
+	check_param(EINVAL, self, "datum instance");
+	return avro_float_set(self, val);
+}
+
+static int
+avro_datum_value_set_int(const avro_value_iface_t *iface,
+			 void *vself, int32_t val)
+{
+	AVRO_UNUSED(iface);
+	avro_datum_t  self = vself;
+	check_param(EINVAL, self, "datum instance");
+	return avro_int32_set(self, val);
+}
+
+static int
+avro_datum_value_set_long(const avro_value_iface_t *iface,
+			  void *vself, int64_t val)
+{
+	AVRO_UNUSED(iface);
+	avro_datum_t  self = vself;
+	check_param(EINVAL, self, "datum instance");
+	return avro_int64_set(self, val);
+}
+
+static int
+avro_datum_value_set_null(const avro_value_iface_t *iface, void *vself)
+{
+	AVRO_UNUSED(iface);
+	avro_datum_t  self = vself;
+	check_param(EINVAL, is_avro_null(self), "datum instance");
+	return 0;
+}
+
+static int
+avro_datum_value_set_string(const avro_value_iface_t *iface,
+			    void *vself, char *str)
+{
+	AVRO_UNUSED(iface);
+	avro_datum_t  self = vself;
+	check_param(EINVAL, self, "datum instance");
+	return avro_string_set(self, str);
+}
+
+static int
+avro_datum_value_set_string_len(const avro_value_iface_t *iface,
+				void *vself, char *str, size_t size)
+{
+	AVRO_UNUSED(iface);
+	AVRO_UNUSED(size);
+	avro_datum_t  self = vself;
+	check_param(EINVAL, self, "datum instance");
+	return avro_string_set(self, str);
+}
+
+static int
+avro_datum_value_give_string_len(const avro_value_iface_t *iface,
+				 void *vself, avro_wrapped_buffer_t *buf)
+{
+	/*
+	 * We actually can't use avro_givestring_set, since it can't
+	 * handle the extra free_ud parameter.  Ah well, this is
+	 * deprecated, so go ahead and make a copy.
+	 */
+
+	int rval = avro_datum_value_set_string_len
+	    (iface, vself, (char *) buf->buf, buf->size-1);
+	avro_wrapped_buffer_free(buf);
+	return rval;
+}
+
+static int
+avro_datum_value_set_enum(const avro_value_iface_t *iface,
+			  void *vself, int val)
+{
+	AVRO_UNUSED(iface);
+	avro_datum_t  self = vself;
+	check_param(EINVAL, self, "datum instance");
+	return avro_enum_set(self, val);
+}
+
+static int
+avro_datum_value_set_fixed(const avro_value_iface_t *iface,
+			   void *vself, void *buf, size_t size)
+{
+	AVRO_UNUSED(iface);
+	avro_datum_t  self = vself;
+	check_param(EINVAL, self, "datum instance");
+	return avro_fixed_set(self, buf, size);
+}
+
+static int
+avro_datum_value_give_fixed(const avro_value_iface_t *iface,
+			    void *vself, avro_wrapped_buffer_t *buf)
+{
+	/*
+	 * We actually can't use avro_givefixed_set, since it can't
+	 * handle the extra free_ud parameter.  Ah well, this is
+	 * deprecated, so go ahead and make a copy.
+	 */
+
+	int rval = avro_datum_value_set_fixed
+	    (iface, vself, (void *) buf->buf, buf->size);
+	avro_wrapped_buffer_free(buf);
+	return rval;
+}
+
+
+static int
+avro_datum_value_get_size(const avro_value_iface_t *iface,
+			  const void *vself, size_t *size)
+{
+	AVRO_UNUSED(iface);
+	const avro_datum_t  self = (const avro_datum_t) vself;
+	check_param(EINVAL, self, "datum instance");
+
+	if (is_avro_array(self)) {
+		*size = avro_array_size(self);
+		return 0;
+	}
+
+	if (is_avro_map(self)) {
+		*size = avro_map_size(self);
+		return 0;
+	}
+
+	if (is_avro_record(self)) {
+		avro_schema_t  schema = avro_datum_get_schema(self);
+		*size = avro_schema_record_size(schema);
+		return 0;
+	}
+
+	avro_set_error("Can only get size of array or map");
+	return EINVAL;
+}
+
+static int
+avro_datum_value_get_by_index(const avro_value_iface_t *iface,
+			      const void *vself, size_t index,
+			      avro_value_t *child, const char **name)
+{
+	AVRO_UNUSED(iface);
+	const avro_datum_t  self = (const avro_datum_t) vself;
+	check_param(EINVAL, self, "datum instance");
+
+	int  rval;
+	avro_datum_t  child_datum;
+
+	if (is_avro_array(self)) {
+		check(rval, avro_array_get(self, index, &child_datum));
+		return avro_datum_as_value(child, child_datum);
+	}
+
+	if (is_avro_map(self)) {
+		const char  *real_key;
+		check(rval, avro_map_get_key(self, index, &real_key));
+		if (name != NULL) {
+			*name = real_key;
+		}
+		check(rval, avro_map_get(self, real_key, &child_datum));
+		return avro_datum_as_value(child, child_datum);
+	}
+
+	if (is_avro_record(self)) {
+		avro_schema_t  schema = avro_datum_get_schema(self);
+		const char  *field_name =
+		    avro_schema_record_field_name(schema, index);
+		if (field_name == NULL) {
+			return EINVAL;
+		}
+		if (name != NULL) {
+			*name = field_name;
+		}
+		check(rval, avro_record_get(self, field_name, &child_datum));
+		return avro_datum_as_value(child, child_datum);
+	}
+
+	avro_set_error("Can only get by index from array, map, or record");
+	return EINVAL;
+}
+
+static int
+avro_datum_value_get_by_name(const avro_value_iface_t *iface,
+			     const void *vself, const char *name,
+			     avro_value_t *child, size_t *index)
+{
+	AVRO_UNUSED(iface);
+	const avro_datum_t  self = (const avro_datum_t) vself;
+	check_param(EINVAL, self, "datum instance");
+
+	int  rval;
+	avro_datum_t  child_datum;
+
+	if (is_avro_map(self)) {
+		if (index != NULL) {
+			int  real_index;
+			check(rval, avro_map_get_index(self, name, &real_index));
+			*index = real_index;
+		}
+
+		check(rval, avro_map_get(self, name, &child_datum));
+		return avro_datum_as_value(child, child_datum);
+	}
+
+	if (is_avro_record(self)) {
+		if (index != NULL) {
+			avro_schema_t  schema = avro_datum_get_schema(self);
+			*index = avro_schema_record_field_get_index(schema, name);
+		}
+
+		check(rval, avro_record_get(self, name, &child_datum));
+		return avro_datum_as_value(child, child_datum);
+	}
+
+	avro_set_error("Can only get by name from map or record");
+	return EINVAL;
+}
+
+static int
+avro_datum_value_get_discriminant(const avro_value_iface_t *iface,
+				  const void *vself, int *out)
+{
+	AVRO_UNUSED(iface);
+	const avro_datum_t  self = (const avro_datum_t) vself;
+	check_param(EINVAL, self, "datum instance");
+
+	if (!is_avro_union(self)) {
+		avro_set_error("Can only get discriminant of union");
+		return EINVAL;
+	}
+
+	*out = avro_union_discriminant(self);
+	return 0;
+}
+
+static int
+avro_datum_value_get_current_branch(const avro_value_iface_t *iface,
+				    const void *vself, avro_value_t *branch)
+{
+	AVRO_UNUSED(iface);
+	const avro_datum_t  self = (const avro_datum_t) vself;
+	check_param(EINVAL, self, "datum instance");
+
+	if (!is_avro_union(self)) {
+		avro_set_error("Can only get current branch of union");
+		return EINVAL;
+	}
+
+	avro_datum_t  child_datum = avro_union_current_branch(self);
+	return avro_datum_as_value(branch, child_datum);
+}
+
+
+static int
+avro_datum_value_append(const avro_value_iface_t *iface,
+			void *vself, avro_value_t *child_out, size_t *new_index)
+{
+	AVRO_UNUSED(iface);
+	avro_datum_t  self = vself;
+	check_param(EINVAL, self, "datum instance");
+
+	if (!is_avro_array(self)) {
+		avro_set_error("Can only append to array");
+		return EINVAL;
+	}
+
+	int  rval;
+
+	avro_schema_t  array_schema = avro_datum_get_schema(self);
+	avro_schema_t  child_schema = avro_schema_array_items(array_schema);
+	avro_datum_t  child_datum = avro_datum_from_schema(child_schema);
+	if (child_datum == NULL) {
+		return ENOMEM;
+	}
+
+	check(rval, avro_array_append_datum(self, child_datum));
+	avro_datum_decref(child_datum);
+	if (new_index != NULL) {
+		*new_index = avro_array_size(self) - 1;
+	}
+	return avro_datum_as_value(child_out, child_datum);
+}
+
+static int
+avro_datum_value_add(const avro_value_iface_t *iface,
+		     void *vself, const char *key,
+		     avro_value_t *child, size_t *index, bool *is_new)
+{
+	AVRO_UNUSED(iface);
+	avro_datum_t  self = vself;
+	check_param(EINVAL, self, "datum instance");
+
+	if (!is_avro_map(self)) {
+		avro_set_error("Can only add to map");
+		return EINVAL;
+	}
+
+	int  rval;
+	avro_datum_t  child_datum;
+
+	if (avro_map_get(self, key, &child_datum) == 0) {
+		/* key already exists */
+		if (is_new != NULL) {
+			*is_new = false;
+		}
+		if (index != NULL) {
+			int  real_index;
+			avro_map_get_index(self, key, &real_index);
+			*index = real_index;
+		}
+		return avro_datum_as_value(child, child_datum);
+	}
+
+	/* key is new */
+	avro_schema_t  map_schema = avro_datum_get_schema(self);
+	avro_schema_t  child_schema = avro_schema_map_values(map_schema);
+	child_datum = avro_datum_from_schema(child_schema);
+	if (child_datum == NULL) {
+		return ENOMEM;
+	}
+	avro_datum_decref(child_datum);
+
+	check(rval, avro_map_set(self, key, child_datum));
+	if (is_new != NULL) {
+		*is_new = true;
+	}
+	if (index != NULL) {
+		*index = avro_map_size(self) - 1;
+	}
+
+	return avro_datum_as_value(child, child_datum);
+}
+
+static int
+avro_datum_value_set_branch(const avro_value_iface_t *iface,
+			    void *vself, int discriminant,
+			    avro_value_t *branch)
+{
+	AVRO_UNUSED(iface);
+	const avro_datum_t  self = (const avro_datum_t) vself;
+	check_param(EINVAL, self, "datum instance");
+
+	if (!is_avro_union(self)) {
+		avro_set_error("Can only set branch of union");
+		return EINVAL;
+	}
+
+	int  rval;
+	avro_datum_t  child_datum;
+	check(rval, avro_union_set_discriminant(self, discriminant, &child_datum));
+	return avro_datum_as_value(branch, child_datum);
+}
+
+
+static avro_value_iface_t  AVRO_DATUM_VALUE_CLASS =
+{
+	/* "class" methods */
+	NULL, /* incref */
+	NULL, /* decref */
+	NULL, /* instance_size */
+	/* general "instance" methods */
+	NULL, /* init */
+	avro_datum_value_done,
+	avro_datum_value_reset,
+	avro_datum_value_get_type,
+	avro_datum_value_get_schema,
+	/* primitive getters */
+	avro_datum_value_get_boolean,
+	avro_datum_value_get_bytes,
+	avro_datum_value_grab_bytes,
+	avro_datum_value_get_double,
+	avro_datum_value_get_float,
+	avro_datum_value_get_int,
+	avro_datum_value_get_long,
+	avro_datum_value_get_null,
+	avro_datum_value_get_string,
+	avro_datum_value_grab_string,
+	avro_datum_value_get_enum,
+	avro_datum_value_get_fixed,
+	avro_datum_value_grab_fixed,
+	/* primitive setters */
+	avro_datum_value_set_boolean,
+	avro_datum_value_set_bytes,
+	avro_datum_value_give_bytes,
+	avro_datum_value_set_double,
+	avro_datum_value_set_float,
+	avro_datum_value_set_int,
+	avro_datum_value_set_long,
+	avro_datum_value_set_null,
+	avro_datum_value_set_string,
+	avro_datum_value_set_string_len,
+	avro_datum_value_give_string_len,
+	avro_datum_value_set_enum,
+	avro_datum_value_set_fixed,
+	avro_datum_value_give_fixed,
+	/* compound getters */
+	avro_datum_value_get_size,
+	avro_datum_value_get_by_index,
+	avro_datum_value_get_by_name,
+	avro_datum_value_get_discriminant,
+	avro_datum_value_get_current_branch,
+	/* compound setters */
+	avro_datum_value_append,
+	avro_datum_value_add,
+	avro_datum_value_set_branch
+};
+
+avro_value_iface_t *
+avro_datum_class(void)
+{
+	return &AVRO_DATUM_VALUE_CLASS;
+}
+
+
+int
+avro_datum_as_value(avro_value_t *value, avro_datum_t src)
+{
+	value->iface = &AVRO_DATUM_VALUE_CLASS;
+	value->self = avro_datum_incref(src);
+	return 0;
+}

Modified: avro/trunk/lang/c/src/datum_write.c
URL: http://svn.apache.org/viewvc/avro/trunk/lang/c/src/datum_write.c?rev=1146546&r1=1146545&r2=1146546&view=diff
==============================================================================
--- avro/trunk/lang/c/src/datum_write.c (original)
+++ avro/trunk/lang/c/src/datum_write.c Thu Jul 14 02:35:04 2011
@@ -15,14 +15,23 @@
  * permissions and limitations under the License. 
  */
 
-#include "avro_errors.h"
-#include "avro_private.h"
-#include <errno.h>
 #include <assert.h>
+#include <errno.h>
 #include <string.h>
-#include "schema.h"
+
+#include "avro/errors.h"
+#include "avro/legacy.h"
+#include "avro/schema.h"
+#include "avro/value.h"
+#include "avro_private.h"
 #include "datum.h"
 #include "encoding.h"
+#include "schema.h"
+
+/*
+ * Oof, we have to leave this legacy implementation in place for when
+ * you write to write with a different schema.
+ */
 
 static int write_datum(avro_writer_t writer, const avro_encoding_t * enc,
 		       avro_schema_t writers_schema, avro_datum_t datum);
@@ -271,12 +280,24 @@ int avro_write_data(avro_writer_t writer
 {
 	check_param(EINVAL, writer, "writer");
 	check_param(EINVAL, is_avro_datum(datum), "datum");
+
 	/* Only validate datum if a writer's schema is provided */
-	if (is_avro_schema(writers_schema)
-	    && !avro_schema_datum_validate(writers_schema, datum)) {
+	if (is_avro_schema(writers_schema)) {
+	    if (!avro_schema_datum_validate(writers_schema, datum)) {
 		avro_set_error("Datum doesn't validate against schema");
 		return EINVAL;
+	    }
+	    return write_datum(writer, &avro_binary_encoding,
+			       writers_schema, datum);
 	}
-	return write_datum(writer, &avro_binary_encoding,
-			   writers_schema, datum);
+
+	/* If we're writing using the datum's actual schema, use the new
+	 * value implementation. */
+
+	int  rval;
+	avro_value_t  value;
+	check(rval, avro_datum_as_value(&value, datum));
+	check(rval, avro_value_write(writer, &value));
+	avro_value_done(&value);
+	return 0;
 }

Modified: avro/trunk/lang/c/src/dump.c
URL: http://svn.apache.org/viewvc/avro/trunk/lang/c/src/dump.c?rev=1146546&r1=1146545&r2=1146546&view=diff
==============================================================================
--- avro/trunk/lang/c/src/dump.c (original)
+++ avro/trunk/lang/c/src/dump.c Thu Jul 14 02:35:04 2011
@@ -15,10 +15,11 @@
  * permissions and limitations under the License. 
  */
 
-#include "avro_private.h"
-#include "dump.h"
 #include <ctype.h>
+#include <stdint.h>
 #include <string.h>
+#include "avro_private.h"
+#include "dump.h"
 
 static void dump_line(FILE * out, const caddr_t addr, const long len)
 {

Modified: avro/trunk/lang/c/src/encoding.h
URL: http://svn.apache.org/viewvc/avro/trunk/lang/c/src/encoding.h?rev=1146546&r1=1146545&r2=1146546&view=diff
==============================================================================
--- avro/trunk/lang/c/src/encoding.h (original)
+++ avro/trunk/lang/c/src/encoding.h Thu Jul 14 02:35:04 2011
@@ -16,7 +16,8 @@
  */
 #ifndef AVRO_ENCODING_H
 #define AVRO_ENCODING_H
-#include "avro.h"
+#include <stdint.h>
+#include "avro/io.h"
 
 /*
  * TODO: this will need more functions when JSON encoding is added 

Modified: avro/trunk/lang/c/src/encoding_binary.c
URL: http://svn.apache.org/viewvc/avro/trunk/lang/c/src/encoding_binary.c?rev=1146546&r1=1146545&r2=1146546&view=diff
==============================================================================
--- avro/trunk/lang/c/src/encoding_binary.c (original)
+++ avro/trunk/lang/c/src/encoding_binary.c Thu Jul 14 02:35:04 2011
@@ -15,9 +15,9 @@
  * permissions and limitations under the License. 
  */
 
-#include "avro_errors.h"
 #include "avro_private.h"
-#include "allocation.h"
+#include "avro/allocation.h"
+#include "avro/errors.h"
 #include "encoding.h"
 #include <stdlib.h>
 #include <limits.h>

Modified: avro/trunk/lang/c/src/errors.c
URL: http://svn.apache.org/viewvc/avro/trunk/lang/c/src/errors.c?rev=1146546&r1=1146545&r2=1146546&view=diff
==============================================================================
--- avro/trunk/lang/c/src/errors.c (original)
+++ avro/trunk/lang/c/src/errors.c Thu Jul 14 02:35:04 2011
@@ -16,10 +16,10 @@
  */
 
 #include <stdarg.h>
+#include <stdio.h>
 #include <string.h>
 
-#include "avro.h"
-#include "avro_errors.h"
+#include "avro/errors.h"
 
 /* 4K should be enough, right? */
 #define AVRO_ERROR_SIZE 4096

Added: avro/trunk/lang/c/src/generic-array.c
URL: http://svn.apache.org/viewvc/avro/trunk/lang/c/src/generic-array.c?rev=1146546&view=auto
==============================================================================
--- avro/trunk/lang/c/src/generic-array.c (added)
+++ avro/trunk/lang/c/src/generic-array.c Thu Jul 14 02:35:04 2011
@@ -0,0 +1,283 @@
+/*
+ * 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 <errno.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "avro/allocation.h"
+#include "avro/data.h"
+#include "avro/errors.h"
+#include "avro/generic.h"
+#include "avro/refcount.h"
+#include "avro/schema.h"
+#include "avro/value.h"
+#include "avro_private.h"
+
+
+/*
+ * For generic arrays, we need to store the value implementation for the
+ * array's elements.
+ */
+
+typedef struct avro_generic_array_value_iface {
+	avro_value_iface_t  iface;
+	volatile int  refcount;
+	avro_schema_t  schema;
+	avro_value_iface_t  *child_iface;
+} avro_generic_array_value_iface_t;
+
+typedef struct avro_generic_array {
+	avro_raw_array_t  array;
+} avro_generic_array_t;
+
+
+static avro_value_iface_t *
+avro_generic_array_incref(avro_value_iface_t *viface)
+{
+	avro_generic_array_value_iface_t  *iface =
+	    (avro_generic_array_value_iface_t *) viface;
+	avro_refcount_inc(&iface->refcount);
+	return viface;
+}
+
+static void
+avro_generic_array_decref(avro_value_iface_t *viface)
+{
+	avro_generic_array_value_iface_t  *iface =
+	    (avro_generic_array_value_iface_t *) viface;
+	if (avro_refcount_dec(&iface->refcount)) {
+		avro_schema_decref(iface->schema);
+		avro_value_iface_decref(iface->child_iface);
+		avro_freet(avro_generic_array_value_iface_t, iface);
+	}
+}
+
+static size_t
+avro_generic_array_instance_size(const avro_value_iface_t *viface)
+{
+	AVRO_UNUSED(viface);
+	return sizeof(avro_generic_array_t);
+}
+
+static int
+avro_generic_array_init(const avro_value_iface_t *viface, void *vself)
+{
+	const avro_generic_array_value_iface_t  *iface =
+	    (const avro_generic_array_value_iface_t *) viface;
+	avro_generic_array_t  *self = vself;
+
+	size_t  child_size = avro_value_instance_size(iface->child_iface);
+	avro_raw_array_init(&self->array, child_size);
+	return 0;
+}
+
+static void
+avro_generic_array_free_elements(const avro_value_iface_t *child_iface,
+				 avro_generic_array_t *self)
+{
+	size_t  i;
+	for (i = 0; i < avro_raw_array_size(&self->array); i++) {
+		avro_value_t  element;
+		element.iface = child_iface;
+		element.self = avro_raw_array_get_raw(&self->array, i);
+		avro_value_done(&element);
+	}
+}
+
+static void
+avro_generic_array_done(const avro_value_iface_t *viface, void *vself)
+{
+	const avro_generic_array_value_iface_t  *iface =
+	    (const avro_generic_array_value_iface_t *) viface;
+	avro_generic_array_t  *self = vself;
+	avro_generic_array_free_elements(iface->child_iface, self);
+	avro_raw_array_done(&self->array);
+}
+
+static int
+avro_generic_array_reset(const avro_value_iface_t *viface, void *vself)
+{
+	const avro_generic_array_value_iface_t  *iface =
+	    (const avro_generic_array_value_iface_t *) viface;
+	avro_generic_array_t  *self = vself;
+	avro_generic_array_free_elements(iface->child_iface, self);
+	avro_raw_array_clear(&self->array);
+	return 0;
+}
+
+static avro_type_t
+avro_generic_array_get_type(const avro_value_iface_t *viface, const void *vself)
+{
+	AVRO_UNUSED(viface);
+	AVRO_UNUSED(vself);
+	return AVRO_ARRAY;
+}
+
+static avro_schema_t
+avro_generic_array_get_schema(const avro_value_iface_t *viface, const void *vself)
+{
+	const avro_generic_array_value_iface_t  *iface =
+	    (const avro_generic_array_value_iface_t *) viface;
+	AVRO_UNUSED(vself);
+	return iface->schema;
+}
+
+static int
+avro_generic_array_get_size(const avro_value_iface_t *viface,
+			    const void *vself, size_t *size)
+{
+	AVRO_UNUSED(viface);
+	const avro_generic_array_t  *self = vself;
+	if (size != NULL) {
+		*size = avro_raw_array_size(&self->array);
+	}
+	return 0;
+}
+
+static int
+avro_generic_array_get_by_index(const avro_value_iface_t *viface,
+				const void *vself, size_t index,
+				avro_value_t *child, const char **name)
+{
+	const avro_generic_array_value_iface_t  *iface =
+	    (const avro_generic_array_value_iface_t *) viface;
+	AVRO_UNUSED(name);
+	const avro_generic_array_t  *self = vself;
+	if (index >= avro_raw_array_size(&self->array)) {
+		avro_set_error("Array index %zu out of range", index);
+		return EINVAL;
+	}
+	child->iface = iface->child_iface;
+	child->self = avro_raw_array_get_raw(&self->array, index);
+	return 0;
+}
+
+static int
+avro_generic_array_append(const avro_value_iface_t *viface,
+			  void *vself, avro_value_t *child,
+			  size_t *new_index)
+{
+	const avro_generic_array_value_iface_t  *iface =
+	    (const avro_generic_array_value_iface_t *) viface;
+	avro_generic_array_t  *self = vself;
+	child->iface = iface->child_iface;
+	child->self = avro_raw_array_append(&self->array);
+	if (child->self == NULL) {
+		avro_set_error("Couldn't expand array");
+		return ENOMEM;
+	}
+	if (new_index != NULL) {
+		*new_index = avro_raw_array_size(&self->array) - 1;
+	}
+	return 0;
+}
+
+static avro_value_iface_t  AVRO_GENERIC_ARRAY_CLASS =
+{
+	/* "class" methods */
+	avro_generic_array_incref,
+	avro_generic_array_decref,
+	avro_generic_array_instance_size,
+	/* general "instance" methods */
+	avro_generic_array_init,
+	avro_generic_array_done,
+	avro_generic_array_reset,
+	avro_generic_array_get_type,
+	avro_generic_array_get_schema,
+	/* primitive getters */
+	NULL, /* get_boolean */
+	NULL, /* get_bytes */
+	NULL, /* grab_bytes */
+	NULL, /* get_double */
+	NULL, /* get_float */
+	NULL, /* get_int */
+	NULL, /* get_long */
+	NULL, /* get_null */
+	NULL, /* get_string */
+	NULL, /* grab_string */
+	NULL, /* get_enum */
+	NULL, /* get_fixed */
+	NULL, /* grab_fixed */
+	/* primitive setters */
+	NULL, /* set_boolean */
+	NULL, /* set_bytes */
+	NULL, /* give_bytes */
+	NULL, /* set_double */
+	NULL, /* set_float */
+	NULL, /* set_int */
+	NULL, /* set_long */
+	NULL, /* set_null */
+	NULL, /* set_string */
+	NULL, /* set_string_length */
+	NULL, /* give_string_length */
+	NULL, /* set_enum */
+	NULL, /* set_fixed */
+	NULL, /* give_fixed */
+	/* compound getters */
+	avro_generic_array_get_size,
+	avro_generic_array_get_by_index,
+	NULL, /* get_by_name */
+	NULL, /* get_discriminant */
+	NULL, /* get_current_branch */
+	/* compound setters */
+	avro_generic_array_append,
+	NULL, /* add */
+	NULL  /* set_branch */
+};
+
+avro_value_iface_t *
+avro_generic_array_class(avro_schema_t schema,
+			 avro_value_iface_creator_t creator,
+			 void *user_data)
+{
+	if (!is_avro_array(schema)) {
+		avro_set_error("Expected array schema");
+		return NULL;
+	}
+
+	avro_schema_t  child_schema = avro_schema_array_items(schema);
+	avro_value_iface_t  *child_iface = creator(child_schema, user_data);
+	if (child_iface == NULL) {
+		return NULL;
+	}
+
+	size_t  child_size = avro_value_instance_size(child_iface);
+	if (child_size == 0) {
+		avro_set_error("Array item class must provide instance_size");
+		avro_value_iface_decref(child_iface);
+		return NULL;
+	}
+
+	avro_generic_array_value_iface_t  *iface =
+		avro_new(avro_generic_array_value_iface_t);
+	if (iface == NULL) {
+		return NULL;
+	}
+
+	/*
+	 * TODO: Maybe check that schema.items matches
+	 * child_iface.get_schema?
+	 */
+
+	memcpy(&iface->iface, &AVRO_GENERIC_ARRAY_CLASS,
+	       sizeof(avro_value_iface_t));
+	iface->refcount = 1;
+	iface->schema = avro_schema_incref(schema);
+	iface->child_iface = child_iface;
+	return &iface->iface;
+}

Added: avro/trunk/lang/c/src/generic-enum.c
URL: http://svn.apache.org/viewvc/avro/trunk/lang/c/src/generic-enum.c?rev=1146546&view=auto
==============================================================================
--- avro/trunk/lang/c/src/generic-enum.c (added)
+++ avro/trunk/lang/c/src/generic-enum.c Thu Jul 14 02:35:04 2011
@@ -0,0 +1,210 @@
+/*
+ * 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 <errno.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "avro/allocation.h"
+#include "avro/errors.h"
+#include "avro/generic.h"
+#include "avro/refcount.h"
+#include "avro/schema.h"
+#include "avro/value.h"
+#include "avro_private.h"
+
+
+/*-----------------------------------------------------------------------
+ * enum
+ */
+
+typedef struct avro_generic_enum_value_iface {
+	avro_value_iface_t  iface;
+	volatile int  refcount;
+	avro_schema_t  schema;
+} avro_generic_enum_value_iface_t;
+
+
+static avro_value_iface_t *
+avro_generic_enum_incref(avro_value_iface_t *viface)
+{
+	avro_generic_enum_value_iface_t  *iface =
+	    (avro_generic_enum_value_iface_t *) viface;
+	avro_refcount_inc(&iface->refcount);
+	return viface;
+}
+
+static void
+avro_generic_enum_decref(avro_value_iface_t *viface)
+{
+	avro_generic_enum_value_iface_t  *iface =
+	    (avro_generic_enum_value_iface_t *) viface;
+	if (avro_refcount_dec(&iface->refcount)) {
+		avro_schema_decref(iface->schema);
+		avro_freet(avro_generic_enum_value_iface_t, iface);
+	}
+}
+
+static size_t
+avro_generic_enum_instance_size(const avro_value_iface_t *viface)
+{
+	AVRO_UNUSED(viface);
+	return sizeof(int);
+}
+
+static int
+avro_generic_enum_init(const avro_value_iface_t *viface, void *vself)
+{
+	AVRO_UNUSED(viface);
+	int  *self = vself;
+	*self = 0;
+	return 0;
+}
+
+static void
+avro_generic_enum_done(const avro_value_iface_t *viface, void *vself)
+{
+	AVRO_UNUSED(viface);
+	AVRO_UNUSED(vself);
+}
+
+static int
+avro_generic_enum_reset(const avro_value_iface_t *viface, void *vself)
+{
+	AVRO_UNUSED(viface);
+	int  *self = vself;
+	*self = 0;
+	return 0;
+}
+
+static avro_type_t
+avro_generic_enum_get_type(const avro_value_iface_t *iface, const void *vself)
+{
+	AVRO_UNUSED(iface);
+	AVRO_UNUSED(vself);
+	return AVRO_ENUM;
+}
+
+static avro_schema_t
+avro_generic_enum_get_schema(const avro_value_iface_t *viface, const void *vself)
+{
+	const avro_generic_enum_value_iface_t  *iface =
+	    (const avro_generic_enum_value_iface_t *) viface;
+	AVRO_UNUSED(vself);
+	return iface->schema;
+}
+
+static int
+avro_generic_enum_get(const avro_value_iface_t *viface,
+		      const void *vself, int *out)
+{
+	AVRO_UNUSED(viface);
+	const int  *self = vself;
+	*out = *self;
+	return 0;
+}
+
+static int
+avro_generic_enum_set(const avro_value_iface_t *viface,
+		      void *vself, int val)
+{
+	AVRO_UNUSED(viface);
+	int  *self = vself;
+	*self = val;
+	return 0;
+}
+
+static avro_value_iface_t  AVRO_GENERIC_ENUM_CLASS =
+{
+	/* "class" methods */
+	avro_generic_enum_incref,
+	avro_generic_enum_decref,
+	avro_generic_enum_instance_size,
+	/* general "instance" methods */
+	avro_generic_enum_init,
+	avro_generic_enum_done,
+	avro_generic_enum_reset,
+	avro_generic_enum_get_type,
+	avro_generic_enum_get_schema,
+	/* primitive getters */
+	NULL, /* get_boolean */
+	NULL, /* get_bytes */
+	NULL, /* grab_bytes */
+	NULL, /* get_double */
+	NULL, /* get_float */
+	NULL, /* get_int */
+	NULL, /* get_long */
+	NULL, /* get_null */
+	NULL, /* get_string */
+	NULL, /* grab_string */
+	avro_generic_enum_get,
+	NULL, /* get_fixed */
+	NULL, /* grab_fixed */
+	/* primitive setters */
+	NULL, /* set_boolean */
+	NULL, /* set_bytes */
+	NULL, /* give_bytes */
+	NULL, /* set_double */
+	NULL, /* set_float */
+	NULL, /* set_int */
+	NULL, /* set_long */
+	NULL, /* set_null */
+	NULL, /* set_string */
+	NULL, /* set_string_length */
+	NULL, /* give_string_length */
+	avro_generic_enum_set,
+	NULL, /* set_fixed */
+	NULL, /* give_fixed */
+	/* compound getters */
+	NULL, /* get_size */
+	NULL, /* get_by_index */
+	NULL, /* get_by_name */
+	NULL, /* get_discriminant */
+	NULL, /* get_current_branch */
+	/* compound setters */
+	NULL, /* append */
+	NULL, /* add */
+	NULL  /* set_branch */
+};
+
+avro_value_iface_t *avro_generic_enum_class(avro_schema_t schema)
+{
+	if (!is_avro_enum(schema)) {
+		avro_set_error("Expected enum schema");
+		return NULL;
+	}
+
+	avro_generic_enum_value_iface_t  *iface =
+		avro_new(avro_generic_enum_value_iface_t);
+	if (iface == NULL) {
+		return NULL;
+	}
+
+	memcpy(&iface->iface, &AVRO_GENERIC_ENUM_CLASS,
+	       sizeof(avro_value_iface_t));
+	iface->refcount = 1;
+	iface->schema = avro_schema_incref(schema);
+	return &iface->iface;
+}
+
+int avro_generic_enum_new(avro_value_t *value, bool val)
+{
+	int  rval;
+	check(rval, avro_value_new(&AVRO_GENERIC_ENUM_CLASS, value));
+	return avro_generic_enum_set(value->iface, value->self, val);
+}

Added: avro/trunk/lang/c/src/generic-fixed.c
URL: http://svn.apache.org/viewvc/avro/trunk/lang/c/src/generic-fixed.c?rev=1146546&view=auto
==============================================================================
--- avro/trunk/lang/c/src/generic-fixed.c (added)
+++ avro/trunk/lang/c/src/generic-fixed.c Thu Jul 14 02:35:04 2011
@@ -0,0 +1,241 @@
+/*
+ * 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 <errno.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "avro/allocation.h"
+#include "avro/errors.h"
+#include "avro/generic.h"
+#include "avro/refcount.h"
+#include "avro/schema.h"
+#include "avro/value.h"
+#include "avro_private.h"
+
+
+/*-----------------------------------------------------------------------
+ * fixed
+ */
+
+typedef struct avro_generic_fixed_value_iface {
+	avro_value_iface_t  iface;
+
+	/** The reference count for this interface. */
+	volatile int  refcount;
+
+	/** The schema for this fixed. */
+	avro_schema_t  schema;
+
+	/** The data size of for this fixed. */
+	size_t  data_size;
+} avro_generic_fixed_value_iface_t;
+
+
+static avro_value_iface_t *
+avro_generic_fixed_incref(avro_value_iface_t *viface)
+{
+	avro_generic_fixed_value_iface_t  *iface =
+	    (avro_generic_fixed_value_iface_t *) viface;
+	avro_refcount_inc(&iface->refcount);
+	return viface;
+}
+
+static void
+avro_generic_fixed_decref(avro_value_iface_t *viface)
+{
+	avro_generic_fixed_value_iface_t  *iface =
+	    (avro_generic_fixed_value_iface_t *) viface;
+	if (avro_refcount_dec(&iface->refcount)) {
+		avro_schema_decref(iface->schema);
+		avro_freet(avro_generic_fixed_value_iface_t, iface);
+	}
+}
+
+static size_t
+avro_generic_fixed_instance_size(const avro_value_iface_t *viface)
+{
+	const avro_generic_fixed_value_iface_t  *iface =
+	    (const avro_generic_fixed_value_iface_t *) viface;
+	return iface->data_size;
+}
+
+static int
+avro_generic_fixed_init(const avro_value_iface_t *viface, void *vself)
+{
+	const avro_generic_fixed_value_iface_t  *iface =
+	    (const avro_generic_fixed_value_iface_t *) viface;
+	memset(vself, 0, iface->data_size);
+	return 0;
+}
+
+static void
+avro_generic_fixed_done(const avro_value_iface_t *viface, void *vself)
+{
+	AVRO_UNUSED(viface);
+	AVRO_UNUSED(vself);
+}
+
+static int
+avro_generic_fixed_reset(const avro_value_iface_t *viface, void *vself)
+{
+	const avro_generic_fixed_value_iface_t  *iface =
+	    (const avro_generic_fixed_value_iface_t *) viface;
+	memset(vself, 0, iface->data_size);
+	return 0;
+}
+
+static avro_type_t
+avro_generic_fixed_get_type(const avro_value_iface_t *iface, const void *vself)
+{
+	AVRO_UNUSED(iface);
+	AVRO_UNUSED(vself);
+	return AVRO_FIXED;
+}
+
+static avro_schema_t
+avro_generic_fixed_get_schema(const avro_value_iface_t *viface, const void *vself)
+{
+	const avro_generic_fixed_value_iface_t  *iface =
+	    (const avro_generic_fixed_value_iface_t *) viface;
+	AVRO_UNUSED(vself);
+	return iface->schema;
+}
+
+static int
+avro_generic_fixed_get(const avro_value_iface_t *viface,
+		       const void *vself, const void **buf, size_t *size)
+{
+	const avro_generic_fixed_value_iface_t  *iface =
+	    (const avro_generic_fixed_value_iface_t *) viface;
+	if (buf != NULL) {
+		*buf = vself;
+	}
+	if (size != NULL) {
+		*size = iface->data_size;
+	}
+	return 0;
+}
+
+static int
+avro_generic_fixed_grab(const avro_value_iface_t *viface,
+			const void *vself, avro_wrapped_buffer_t *dest)
+{
+	const avro_generic_fixed_value_iface_t  *iface =
+	    (const avro_generic_fixed_value_iface_t *) viface;
+	return avro_wrapped_buffer_new(dest, vself, iface->data_size);
+}
+
+static int
+avro_generic_fixed_set(const avro_value_iface_t *viface,
+		       void *vself, void *buf, size_t size)
+{
+	check_param(EINVAL, buf != NULL, "fixed contents");
+	const avro_generic_fixed_value_iface_t  *iface =
+	    (const avro_generic_fixed_value_iface_t *) viface;
+	if (size != iface->data_size) {
+		avro_set_error("Invalid data size in set_fixed");
+		return EINVAL;
+	}
+	memcpy(vself, buf, size);
+	return 0;
+}
+
+static int
+avro_generic_fixed_give(const avro_value_iface_t *viface,
+			void *vself, avro_wrapped_buffer_t *buf)
+{
+	int  rval = avro_generic_fixed_set
+	    (viface, vself, (void *) buf->buf, buf->size);
+	avro_wrapped_buffer_free(buf);
+	return rval;
+}
+
+static avro_value_iface_t  AVRO_GENERIC_FIXED_CLASS =
+{
+	/* "class" methods */
+	avro_generic_fixed_incref,
+	avro_generic_fixed_decref,
+	avro_generic_fixed_instance_size,
+	/* general "instance" methods */
+	avro_generic_fixed_init,
+	avro_generic_fixed_done,
+	avro_generic_fixed_reset,
+	avro_generic_fixed_get_type,
+	avro_generic_fixed_get_schema,
+	/* primitive getters */
+	NULL, /* get_boolean */
+	NULL, /* get_bytes */
+	NULL, /* grab_bytes */
+	NULL, /* get_double */
+	NULL, /* get_float */
+	NULL, /* get_int */
+	NULL, /* get_long */
+	NULL, /* get_null */
+	NULL, /* get_string */
+	NULL, /* grab_string */
+	NULL, /* get_enum */
+	avro_generic_fixed_get,
+	avro_generic_fixed_grab,
+	/* primitive setters */
+	NULL, /* set_boolean */
+	NULL, /* set_bytes */
+	NULL, /* give_bytes */
+	NULL, /* set_double */
+	NULL, /* set_float */
+	NULL, /* set_int */
+	NULL, /* set_long */
+	NULL, /* set_null */
+	NULL, /* set_string */
+	NULL, /* set_string_length */
+	NULL, /* give_string_length */
+	NULL, /* set_enum */
+	avro_generic_fixed_set,
+	avro_generic_fixed_give,
+	/* compound getters */
+	NULL, /* get_size */
+	NULL, /* get_by_index */
+	NULL, /* get_by_name */
+	NULL, /* get_discriminant */
+	NULL, /* get_current_branch */
+	/* compound setters */
+	NULL, /* append */
+	NULL, /* add */
+	NULL  /* set_branch */
+};
+
+avro_value_iface_t *avro_generic_fixed_class(avro_schema_t schema)
+{
+	if (!is_avro_fixed(schema)) {
+		avro_set_error("Expected fixed schema");
+		return NULL;
+	}
+
+	avro_generic_fixed_value_iface_t  *iface =
+		avro_new(avro_generic_fixed_value_iface_t);
+	if (iface == NULL) {
+		return NULL;
+	}
+
+	memcpy(&iface->iface, &AVRO_GENERIC_FIXED_CLASS,
+	       sizeof(avro_value_iface_t));
+	iface->refcount = 1;
+	iface->schema = avro_schema_incref(schema);
+	iface->data_size = avro_schema_fixed_size(schema);
+	return &iface->iface;
+}

Added: avro/trunk/lang/c/src/generic-map.c
URL: http://svn.apache.org/viewvc/avro/trunk/lang/c/src/generic-map.c?rev=1146546&view=auto
==============================================================================
--- avro/trunk/lang/c/src/generic-map.c (added)
+++ avro/trunk/lang/c/src/generic-map.c Thu Jul 14 02:35:04 2011
@@ -0,0 +1,299 @@
+/*
+ * 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 <errno.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "avro/allocation.h"
+#include "avro/data.h"
+#include "avro/errors.h"
+#include "avro/generic.h"
+#include "avro/refcount.h"
+#include "avro/schema.h"
+#include "avro/value.h"
+#include "avro_private.h"
+
+
+/*
+ * For generic maps, we need to store the value implementation for the
+ * map's elements.
+ */
+
+typedef struct avro_generic_map_value_iface {
+	avro_value_iface_t  iface;
+	volatile int  refcount;
+	avro_schema_t  schema;
+	avro_value_iface_t  *child_iface;
+} avro_generic_map_value_iface_t;
+
+typedef struct avro_generic_map {
+	avro_raw_map_t  map;
+} avro_generic_map_t;
+
+
+static avro_value_iface_t *
+avro_generic_map_incref(avro_value_iface_t *viface)
+{
+	avro_generic_map_value_iface_t  *iface =
+	    (avro_generic_map_value_iface_t *) viface;
+	avro_refcount_inc(&iface->refcount);
+	return viface;
+}
+
+static void
+avro_generic_map_decref(avro_value_iface_t *viface)
+{
+	avro_generic_map_value_iface_t  *iface =
+	    (avro_generic_map_value_iface_t *) viface;
+	if (avro_refcount_dec(&iface->refcount)) {
+		avro_schema_decref(iface->schema);
+		avro_value_iface_decref(iface->child_iface);
+		avro_freet(avro_generic_map_value_iface_t, iface);
+	}
+}
+
+static size_t
+avro_generic_map_instance_size(const avro_value_iface_t *viface)
+{
+	AVRO_UNUSED(viface);
+	return sizeof(avro_generic_map_t);
+}
+
+static int
+avro_generic_map_init(const avro_value_iface_t *viface, void *vself)
+{
+	const avro_generic_map_value_iface_t  *iface =
+	    (const avro_generic_map_value_iface_t *) viface;
+	avro_generic_map_t  *self = vself;
+
+	size_t  child_size = avro_value_instance_size(iface->child_iface);
+	avro_raw_map_init(&self->map, child_size);
+	return 0;
+}
+
+static void
+avro_generic_map_free_elements(const avro_value_iface_t *child_iface,
+			       avro_generic_map_t *self)
+{
+	size_t  i;
+	for (i = 0; i < avro_raw_map_size(&self->map); i++) {
+		avro_value_t  element;
+		element.iface = child_iface;
+		element.self = avro_raw_map_get_raw(&self->map, i);
+		avro_value_done(&element);
+	}
+}
+
+static void
+avro_generic_map_done(const avro_value_iface_t *viface, void *vself)
+{
+	const avro_generic_map_value_iface_t  *iface =
+	    (const avro_generic_map_value_iface_t *) viface;
+	avro_generic_map_t  *self = vself;
+	avro_generic_map_free_elements(iface->child_iface, self);
+	avro_raw_map_done(&self->map);
+}
+
+static int
+avro_generic_map_reset(const avro_value_iface_t *viface, void *vself)
+{
+	const avro_generic_map_value_iface_t  *iface =
+	    (const avro_generic_map_value_iface_t *) viface;
+	avro_generic_map_t  *self = vself;
+	avro_generic_map_free_elements(iface->child_iface, self);
+	avro_raw_map_clear(&self->map);
+	return 0;
+}
+
+static avro_type_t
+avro_generic_map_get_type(const avro_value_iface_t *viface, const void *vself)
+{
+	AVRO_UNUSED(viface);
+	AVRO_UNUSED(vself);
+	return AVRO_MAP;
+}
+
+static avro_schema_t
+avro_generic_map_get_schema(const avro_value_iface_t *viface, const void *vself)
+{
+	const avro_generic_map_value_iface_t  *iface =
+	    (const avro_generic_map_value_iface_t *) viface;
+	AVRO_UNUSED(vself);
+	return iface->schema;
+}
+
+static int
+avro_generic_map_get_size(const avro_value_iface_t *viface,
+			  const void *vself, size_t *size)
+{
+	AVRO_UNUSED(viface);
+	const avro_generic_map_t  *self = vself;
+	if (size != NULL) {
+		*size = avro_raw_map_size(&self->map);
+	}
+	return 0;
+}
+
+static int
+avro_generic_map_get_by_index(const avro_value_iface_t *viface,
+			      const void *vself, size_t index,
+			      avro_value_t *child, const char **name)
+{
+	const avro_generic_map_value_iface_t  *iface =
+	    (const avro_generic_map_value_iface_t *) viface;
+	const avro_generic_map_t  *self = vself;
+	if (index >= avro_raw_map_size(&self->map)) {
+		avro_set_error("Map index %zu out of range", index);
+		return EINVAL;
+	}
+	child->iface = iface->child_iface;
+	child->self = avro_raw_map_get_raw(&self->map, index);
+	if (name != NULL) {
+		*name = avro_raw_map_get_key(&self->map, index);
+	}
+	return 0;
+}
+
+static int
+avro_generic_map_get_by_name(const avro_value_iface_t *viface,
+			     const void *vself, const char *name,
+			     avro_value_t *child, size_t *index)
+{
+	const avro_generic_map_value_iface_t  *iface =
+	    (const avro_generic_map_value_iface_t *) viface;
+	const avro_generic_map_t  *self = vself;
+	child->iface = iface->child_iface;
+	child->self = avro_raw_map_get(&self->map, name, index);
+	return 0;
+}
+
+static int
+avro_generic_map_add(const avro_value_iface_t *viface,
+		     void *vself, const char *key,
+		     avro_value_t *child, size_t *index, bool *is_new)
+{
+	const avro_generic_map_value_iface_t  *iface =
+	    (const avro_generic_map_value_iface_t *) viface;
+	int  rval;
+	avro_generic_map_t  *self = vself;
+	child->iface = iface->child_iface;
+	rval = avro_raw_map_get_or_create(&self->map, key,
+					  &child->self, index);
+	if (rval < 0) {
+		return -rval;
+	}
+	if (is_new != NULL) {
+		*is_new = rval;
+	}
+	return 0;
+}
+
+static avro_value_iface_t  AVRO_GENERIC_MAP_CLASS =
+{
+	/* "class" methods */
+	avro_generic_map_incref,
+	avro_generic_map_decref,
+	avro_generic_map_instance_size,
+	/* general "instance" methods */
+	avro_generic_map_init,
+	avro_generic_map_done,
+	avro_generic_map_reset,
+	avro_generic_map_get_type,
+	avro_generic_map_get_schema,
+	/* primitive getters */
+	NULL, /* get_boolean */
+	NULL, /* get_bytes */
+	NULL, /* grab_bytes */
+	NULL, /* get_double */
+	NULL, /* get_float */
+	NULL, /* get_int */
+	NULL, /* get_long */
+	NULL, /* get_null */
+	NULL, /* get_string */
+	NULL, /* grab_string */
+	NULL, /* get_enum */
+	NULL, /* get_fixed */
+	NULL, /* grab_fixed */
+	/* primitive setters */
+	NULL, /* set_boolean */
+	NULL, /* set_bytes */
+	NULL, /* give_bytes */
+	NULL, /* set_double */
+	NULL, /* set_float */
+	NULL, /* set_int */
+	NULL, /* set_long */
+	NULL, /* set_null */
+	NULL, /* set_string */
+	NULL, /* set_string_length */
+	NULL, /* give_string_length */
+	NULL, /* set_enum */
+	NULL, /* set_fixed */
+	NULL, /* give_fixed */
+	/* compound getters */
+	avro_generic_map_get_size,
+	avro_generic_map_get_by_index,
+	avro_generic_map_get_by_name,
+	NULL, /* get_discriminant */
+	NULL, /* get_current_branch */
+	/* compound setters */
+	NULL, /* append */
+	avro_generic_map_add,
+	NULL  /* set_branch */
+};
+
+avro_value_iface_t *
+avro_generic_map_class(avro_schema_t schema,
+		       avro_value_iface_creator_t creator,
+		       void *user_data)
+{
+	if (!is_avro_map(schema)) {
+		avro_set_error("Expected map schema");
+		return NULL;
+	}
+
+	avro_schema_t  child_schema = avro_schema_array_items(schema);
+	avro_value_iface_t  *child_iface = creator(child_schema, user_data);
+	if (child_iface == NULL) {
+		return NULL;
+	}
+
+	size_t  child_size = avro_value_instance_size(child_iface);
+	if (child_size == 0) {
+		avro_set_error("Map value class must provide instance_size");
+		avro_value_iface_decref(child_iface);
+		return NULL;
+	}
+
+	avro_generic_map_value_iface_t  *iface =
+		avro_new(avro_generic_map_value_iface_t);
+	if (iface == NULL) {
+		return NULL;
+	}
+
+	/*
+	 * TODO: Maybe check that schema.items matches
+	 * child_iface.get_schema?
+	 */
+
+	memcpy(&iface->iface, &AVRO_GENERIC_MAP_CLASS,
+	       sizeof(avro_value_iface_t));
+	iface->refcount = 1;
+	iface->schema = avro_schema_incref(schema);
+	iface->child_iface = child_iface;
+	return &iface->iface;
+}



Mime
View raw message