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/07/14 04:35:09 UTC
svn commit: r1146546 [3/5] - in /avro/trunk/lang/c: docs/ src/ src/avro/
tests/
Added: avro/trunk/lang/c/src/generic-primitives.c
URL: http://svn.apache.org/viewvc/avro/trunk/lang/c/src/generic-primitives.c?rev=1146546&view=auto
==============================================================================
--- avro/trunk/lang/c/src/generic-primitives.c (added)
+++ avro/trunk/lang/c/src/generic-primitives.c Thu Jul 14 02:35:04 2011
@@ -0,0 +1,1210 @@
+/*
+ * 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 <stdbool.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+#include "avro/allocation.h"
+#include "avro/data.h"
+#include "avro/generic.h"
+#include "avro/schema.h"
+#include "avro/value.h"
+#include "avro_private.h"
+
+
+/*-----------------------------------------------------------------------
+ * boolean
+ */
+
+static size_t
+avro_generic_boolean_instance_size(const avro_value_iface_t *iface)
+{
+ AVRO_UNUSED(iface);
+ return sizeof(int);
+}
+
+static int
+avro_generic_boolean_init(const avro_value_iface_t *iface, void *vself)
+{
+ AVRO_UNUSED(iface);
+ int *self = vself;
+ *self = 0;
+ return 0;
+}
+
+static void
+avro_generic_boolean_done(const avro_value_iface_t *iface, void *vself)
+{
+ AVRO_UNUSED(iface);
+ AVRO_UNUSED(vself);
+}
+
+static int
+avro_generic_boolean_reset(const avro_value_iface_t *iface, void *vself)
+{
+ AVRO_UNUSED(iface);
+ int *self = vself;
+ *self = 0;
+ return 0;
+}
+
+static avro_type_t
+avro_generic_boolean_get_type(const avro_value_iface_t *iface, const void *vself)
+{
+ AVRO_UNUSED(iface);
+ AVRO_UNUSED(vself);
+ return AVRO_BOOLEAN;
+}
+
+static avro_schema_t
+avro_generic_boolean_get_schema(const avro_value_iface_t *iface, const void *vself)
+{
+ AVRO_UNUSED(iface);
+ AVRO_UNUSED(vself);
+ return avro_schema_boolean();
+}
+
+static int
+avro_generic_boolean_get(const avro_value_iface_t *iface,
+ const void *vself, bool *out)
+{
+ AVRO_UNUSED(iface);
+ const int *self = vself;
+ *out = *self;
+ return 0;
+}
+
+static int
+avro_generic_boolean_set(const avro_value_iface_t *iface,
+ void *vself, bool val)
+{
+ AVRO_UNUSED(iface);
+ int *self = vself;
+ *self = val;
+ return 0;
+}
+
+static avro_value_iface_t AVRO_GENERIC_BOOLEAN_CLASS =
+{
+ /* "class" methods */
+ NULL, /* incref */
+ NULL, /* decref */
+ avro_generic_boolean_instance_size,
+ /* general "instance" methods */
+ avro_generic_boolean_init,
+ avro_generic_boolean_done,
+ avro_generic_boolean_reset,
+ avro_generic_boolean_get_type,
+ avro_generic_boolean_get_schema,
+ /* primitive getters */
+ avro_generic_boolean_get,
+ 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 */
+ avro_generic_boolean_set,
+ 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 */
+ 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_boolean_class(void)
+{
+ return &AVRO_GENERIC_BOOLEAN_CLASS;
+}
+
+int avro_generic_boolean_new(avro_value_t *value, bool val)
+{
+ int rval;
+ check(rval, avro_value_new(&AVRO_GENERIC_BOOLEAN_CLASS, value));
+ return avro_generic_boolean_set(value->iface, value->self, val);
+}
+
+/*-----------------------------------------------------------------------
+ * bytes
+ */
+
+static size_t
+avro_generic_bytes_instance_size(const avro_value_iface_t *iface)
+{
+ AVRO_UNUSED(iface);
+ return sizeof(avro_raw_string_t);
+}
+
+static int
+avro_generic_bytes_init(const avro_value_iface_t *iface, void *vself)
+{
+ AVRO_UNUSED(iface);
+ avro_raw_string_t *self = vself;
+ avro_raw_string_init(self);
+ return 0;
+}
+
+static void
+avro_generic_bytes_done(const avro_value_iface_t *iface, void *vself)
+{
+ AVRO_UNUSED(iface);
+ avro_raw_string_t *self = vself;
+ avro_raw_string_done(self);
+}
+
+static int
+avro_generic_bytes_reset(const avro_value_iface_t *iface, void *vself)
+{
+ AVRO_UNUSED(iface);
+ avro_raw_string_t *self = vself;
+ avro_raw_string_clear(self);
+ return 0;
+}
+
+static avro_type_t
+avro_generic_bytes_get_type(const avro_value_iface_t *iface, const void *vself)
+{
+ AVRO_UNUSED(iface);
+ AVRO_UNUSED(vself);
+ return AVRO_BYTES;
+}
+
+static avro_schema_t
+avro_generic_bytes_get_schema(const avro_value_iface_t *iface, const void *vself)
+{
+ AVRO_UNUSED(iface);
+ AVRO_UNUSED(vself);
+ return avro_schema_bytes();
+}
+
+static int
+avro_generic_bytes_get(const avro_value_iface_t *iface,
+ const void *vself, const void **buf, size_t *size)
+{
+ AVRO_UNUSED(iface);
+ const avro_raw_string_t *self = vself;
+ if (buf != NULL) {
+ *buf = avro_raw_string_get(self);
+ }
+ if (size != NULL) {
+ *size = avro_raw_string_length(self);
+ }
+ return 0;
+}
+
+static int
+avro_generic_bytes_grab(const avro_value_iface_t *iface,
+ const void *vself, avro_wrapped_buffer_t *dest)
+{
+ AVRO_UNUSED(iface);
+ const avro_raw_string_t *self = vself;
+ return avro_raw_string_grab(self, dest);
+}
+
+static int
+avro_generic_bytes_set(const avro_value_iface_t *iface,
+ void *vself, void *buf, size_t size)
+{
+ AVRO_UNUSED(iface);
+ check_param(EINVAL, buf != NULL, "bytes contents");
+ avro_raw_string_t *self = vself;
+ avro_raw_string_set_length(self, buf, size);
+ return 0;
+}
+
+static int
+avro_generic_bytes_give(const avro_value_iface_t *iface,
+ void *vself, avro_wrapped_buffer_t *buf)
+{
+ AVRO_UNUSED(iface);
+ avro_raw_string_t *self = vself;
+ avro_raw_string_give(self, buf);
+ return 0;
+}
+
+static avro_value_iface_t AVRO_GENERIC_BYTES_CLASS =
+{
+ /* "class" methods */
+ NULL, /* incref */
+ NULL, /* decref */
+ avro_generic_bytes_instance_size,
+ /* general "instance" methods */
+ avro_generic_bytes_init,
+ avro_generic_bytes_done,
+ avro_generic_bytes_reset,
+ avro_generic_bytes_get_type,
+ avro_generic_bytes_get_schema,
+ /* primitive getters */
+ NULL, /* get_boolean */
+ avro_generic_bytes_get,
+ avro_generic_bytes_grab,
+ 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 */
+ avro_generic_bytes_set,
+ avro_generic_bytes_give,
+ 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 */
+ 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_bytes_class(void)
+{
+ return &AVRO_GENERIC_BYTES_CLASS;
+}
+
+int avro_generic_bytes_new(avro_value_t *value, void *buf, size_t size)
+{
+ int rval;
+ check(rval, avro_value_new(&AVRO_GENERIC_BYTES_CLASS, value));
+ return avro_generic_bytes_set(value->iface, value->self, buf, size);
+}
+
+/*-----------------------------------------------------------------------
+ * double
+ */
+
+static size_t
+avro_generic_double_instance_size(const avro_value_iface_t *iface)
+{
+ AVRO_UNUSED(iface);
+ return sizeof(double);
+}
+
+static int
+avro_generic_double_init(const avro_value_iface_t *iface, void *vself)
+{
+ AVRO_UNUSED(iface);
+ double *self = vself;
+ *self = 0.0;
+ return 0;
+}
+
+static void
+avro_generic_double_done(const avro_value_iface_t *iface, void *vself)
+{
+ AVRO_UNUSED(iface);
+ AVRO_UNUSED(vself);
+}
+
+static int
+avro_generic_double_reset(const avro_value_iface_t *iface, void *vself)
+{
+ AVRO_UNUSED(iface);
+ double *self = vself;
+ *self = 0.0;
+ return 0;
+}
+
+static avro_type_t
+avro_generic_double_get_type(const avro_value_iface_t *iface, const void *vself)
+{
+ AVRO_UNUSED(iface);
+ AVRO_UNUSED(vself);
+ return AVRO_DOUBLE;
+}
+
+static avro_schema_t
+avro_generic_double_get_schema(const avro_value_iface_t *iface, const void *vself)
+{
+ AVRO_UNUSED(iface);
+ AVRO_UNUSED(vself);
+ return avro_schema_double();
+}
+
+static int
+avro_generic_double_get(const avro_value_iface_t *iface,
+ const void *vself, double *out)
+{
+ AVRO_UNUSED(iface);
+ const double *self = vself;
+ *out = *self;
+ return 0;
+}
+
+static int
+avro_generic_double_set(const avro_value_iface_t *iface,
+ void *vself, double val)
+{
+ AVRO_UNUSED(iface);
+ double *self = vself;
+ *self = val;
+ return 0;
+}
+
+static avro_value_iface_t AVRO_GENERIC_DOUBLE_CLASS =
+{
+ /* "class" methods */
+ NULL, /* incref */
+ NULL, /* decref */
+ avro_generic_double_instance_size,
+ /* general "instance" methods */
+ avro_generic_double_init,
+ avro_generic_double_done,
+ avro_generic_double_reset,
+ avro_generic_double_get_type,
+ avro_generic_double_get_schema,
+ /* primitive getters */
+ NULL, /* get_boolean */
+ NULL, /* get_bytes */
+ NULL, /* grab_bytes */
+ avro_generic_double_get,
+ 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 */
+ avro_generic_double_set,
+ 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 */
+ 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_double_class(void)
+{
+ return &AVRO_GENERIC_DOUBLE_CLASS;
+}
+
+int avro_generic_double_new(avro_value_t *value, double val)
+{
+ int rval;
+ check(rval, avro_value_new(&AVRO_GENERIC_DOUBLE_CLASS, value));
+ return avro_generic_double_set(value->iface, value->self, val);
+}
+
+/*-----------------------------------------------------------------------
+ * float
+ */
+
+static size_t
+avro_generic_float_instance_size(const avro_value_iface_t *iface)
+{
+ AVRO_UNUSED(iface);
+ return sizeof(float);
+}
+
+static int
+avro_generic_float_init(const avro_value_iface_t *iface, void *vself)
+{
+ AVRO_UNUSED(iface);
+ float *self = vself;
+ *self = 0.0f;
+ return 0;
+}
+
+static void
+avro_generic_float_done(const avro_value_iface_t *iface, void *vself)
+{
+ AVRO_UNUSED(iface);
+ AVRO_UNUSED(vself);
+}
+
+static int
+avro_generic_float_reset(const avro_value_iface_t *iface, void *vself)
+{
+ AVRO_UNUSED(iface);
+ float *self = vself;
+ *self = 0.0f;
+ return 0;
+}
+
+static avro_type_t
+avro_generic_float_get_type(const avro_value_iface_t *iface, const void *vself)
+{
+ AVRO_UNUSED(iface);
+ AVRO_UNUSED(vself);
+ return AVRO_FLOAT;
+}
+
+static avro_schema_t
+avro_generic_float_get_schema(const avro_value_iface_t *iface, const void *vself)
+{
+ AVRO_UNUSED(iface);
+ AVRO_UNUSED(vself);
+ return avro_schema_float();
+}
+
+static int
+avro_generic_float_get(const avro_value_iface_t *iface,
+ const void *vself, float *out)
+{
+ AVRO_UNUSED(iface);
+ const float *self = vself;
+ *out = *self;
+ return 0;
+}
+
+static int
+avro_generic_float_set(const avro_value_iface_t *iface,
+ void *vself, float val)
+{
+ AVRO_UNUSED(iface);
+ float *self = vself;
+ *self = val;
+ return 0;
+}
+
+static avro_value_iface_t AVRO_GENERIC_FLOAT_CLASS =
+{
+ /* "class" methods */
+ NULL, /* incref */
+ NULL, /* decref */
+ avro_generic_float_instance_size,
+ /* general "instance" methods */
+ avro_generic_float_init,
+ avro_generic_float_done,
+ avro_generic_float_reset,
+ avro_generic_float_get_type,
+ avro_generic_float_get_schema,
+ /* primitive getters */
+ NULL, /* get_boolean */
+ NULL, /* get_bytes */
+ NULL, /* grab_bytes */
+ NULL, /* get_double */
+ avro_generic_float_get,
+ 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 */
+ avro_generic_float_set,
+ 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 */
+ 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_float_class(void)
+{
+ return &AVRO_GENERIC_FLOAT_CLASS;
+}
+
+int avro_generic_float_new(avro_value_t *value, float val)
+{
+ int rval;
+ check(rval, avro_value_new(&AVRO_GENERIC_FLOAT_CLASS, value));
+ return avro_generic_float_set(value->iface, value->self, val);
+}
+
+/*-----------------------------------------------------------------------
+ * int
+ */
+
+static size_t
+avro_generic_int_instance_size(const avro_value_iface_t *iface)
+{
+ AVRO_UNUSED(iface);
+ return sizeof(int32_t);
+}
+
+static int
+avro_generic_int_init(const avro_value_iface_t *iface, void *vself)
+{
+ AVRO_UNUSED(iface);
+ int32_t *self = vself;
+ *self = 0;
+ return 0;
+}
+
+static void
+avro_generic_int_done(const avro_value_iface_t *iface, void *vself)
+{
+ AVRO_UNUSED(iface);
+ AVRO_UNUSED(vself);
+}
+
+static int
+avro_generic_int_reset(const avro_value_iface_t *iface, void *vself)
+{
+ AVRO_UNUSED(iface);
+ int32_t *self = vself;
+ *self = 0;
+ return 0;
+}
+
+static avro_type_t
+avro_generic_int_get_type(const avro_value_iface_t *iface, const void *vself)
+{
+ AVRO_UNUSED(iface);
+ AVRO_UNUSED(vself);
+ return AVRO_INT32;
+}
+
+static avro_schema_t
+avro_generic_int_get_schema(const avro_value_iface_t *iface, const void *vself)
+{
+ AVRO_UNUSED(iface);
+ AVRO_UNUSED(vself);
+ return avro_schema_int();
+}
+
+static int
+avro_generic_int_get(const avro_value_iface_t *iface,
+ const void *vself, int32_t *out)
+{
+ AVRO_UNUSED(iface);
+ const int32_t *self = vself;
+ *out = *self;
+ return 0;
+}
+
+static int
+avro_generic_int_set(const avro_value_iface_t *iface,
+ void *vself, int32_t val)
+{
+ AVRO_UNUSED(iface);
+ int32_t *self = vself;
+ *self = val;
+ return 0;
+}
+
+static avro_value_iface_t AVRO_GENERIC_INT_CLASS =
+{
+ /* "class" methods */
+ NULL, /* incref */
+ NULL, /* decref */
+ avro_generic_int_instance_size,
+ /* general "instance" methods */
+ avro_generic_int_init,
+ avro_generic_int_done,
+ avro_generic_int_reset,
+ avro_generic_int_get_type,
+ avro_generic_int_get_schema,
+ /* primitive getters */
+ NULL, /* get_boolean */
+ NULL, /* get_bytes */
+ NULL, /* grab_bytes */
+ NULL, /* get_double */
+ NULL, /* get_float */
+ avro_generic_int_get,
+ 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 */
+ avro_generic_int_set,
+ 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 */
+ 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_int_class(void)
+{
+ return &AVRO_GENERIC_INT_CLASS;
+}
+
+int avro_generic_int_new(avro_value_t *value, int32_t val)
+{
+ int rval;
+ check(rval, avro_value_new(&AVRO_GENERIC_INT_CLASS, value));
+ return avro_generic_int_set(value->iface, value->self, val);
+}
+
+/*-----------------------------------------------------------------------
+ * long
+ */
+
+static size_t
+avro_generic_long_instance_size(const avro_value_iface_t *iface)
+{
+ AVRO_UNUSED(iface);
+ return sizeof(int64_t);
+}
+
+static int
+avro_generic_long_init(const avro_value_iface_t *iface, void *vself)
+{
+ AVRO_UNUSED(iface);
+ int64_t *self = vself;
+ *self = 0;
+ return 0;
+}
+
+static void
+avro_generic_long_done(const avro_value_iface_t *iface, void *vself)
+{
+ AVRO_UNUSED(iface);
+ AVRO_UNUSED(vself);
+}
+
+static int
+avro_generic_long_reset(const avro_value_iface_t *iface, void *vself)
+{
+ AVRO_UNUSED(iface);
+ int64_t *self = vself;
+ *self = 0;
+ return 0;
+}
+
+static avro_type_t
+avro_generic_long_get_type(const avro_value_iface_t *iface, const void *vself)
+{
+ AVRO_UNUSED(iface);
+ AVRO_UNUSED(vself);
+ return AVRO_INT64;
+}
+
+static avro_schema_t
+avro_generic_long_get_schema(const avro_value_iface_t *iface, const void *vself)
+{
+ AVRO_UNUSED(iface);
+ AVRO_UNUSED(vself);
+ return avro_schema_long();
+}
+
+static int
+avro_generic_long_get(const avro_value_iface_t *iface,
+ const void *vself, int64_t *out)
+{
+ AVRO_UNUSED(iface);
+ const int64_t *self = vself;
+ *out = *self;
+ return 0;
+}
+
+static int
+avro_generic_long_set(const avro_value_iface_t *iface,
+ void *vself, int64_t val)
+{
+ AVRO_UNUSED(iface);
+ int64_t *self = vself;
+ *self = val;
+ return 0;
+}
+
+static avro_value_iface_t AVRO_GENERIC_LONG_CLASS =
+{
+ /* "class" methods */
+ NULL, /* incref */
+ NULL, /* decref */
+ avro_generic_long_instance_size,
+ /* general "instance" methods */
+ avro_generic_long_init,
+ avro_generic_long_done,
+ avro_generic_long_reset,
+ avro_generic_long_get_type,
+ avro_generic_long_get_schema,
+ /* primitive getters */
+ NULL, /* get_boolean */
+ NULL, /* get_bytes */
+ NULL, /* grab_bytes */
+ NULL, /* get_double */
+ NULL, /* get_float */
+ NULL, /* get_int */
+ avro_generic_long_get,
+ 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 */
+ avro_generic_long_set,
+ 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 */
+ 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_long_class(void)
+{
+ return &AVRO_GENERIC_LONG_CLASS;
+}
+
+int avro_generic_long_new(avro_value_t *value, int64_t val)
+{
+ int rval;
+ check(rval, avro_value_new(&AVRO_GENERIC_LONG_CLASS, value));
+ return avro_generic_long_set(value->iface, value->self, val);
+}
+
+/*-----------------------------------------------------------------------
+ * null
+ */
+
+static size_t
+avro_generic_null_instance_size(const avro_value_iface_t *iface)
+{
+ AVRO_UNUSED(iface);
+ return sizeof(int);
+}
+
+static int
+avro_generic_null_init(const avro_value_iface_t *iface, void *vself)
+{
+ AVRO_UNUSED(iface);
+ int *self = vself;
+ *self = 0;
+ return 0;
+}
+
+static void
+avro_generic_null_done(const avro_value_iface_t *iface, void *vself)
+{
+ AVRO_UNUSED(iface);
+ AVRO_UNUSED(vself);
+}
+
+static int
+avro_generic_null_reset(const avro_value_iface_t *iface, void *vself)
+{
+ AVRO_UNUSED(iface);
+ int *self = vself;
+ *self = 0;
+ return 0;
+}
+
+static avro_type_t
+avro_generic_null_get_type(const avro_value_iface_t *iface, const void *vself)
+{
+ AVRO_UNUSED(iface);
+ AVRO_UNUSED(vself);
+ return AVRO_NULL;
+}
+
+static avro_schema_t
+avro_generic_null_get_schema(const avro_value_iface_t *iface, const void *vself)
+{
+ AVRO_UNUSED(iface);
+ AVRO_UNUSED(vself);
+ return avro_schema_null();
+}
+
+static int
+avro_generic_null_get(const avro_value_iface_t *iface, const void *vself)
+{
+ AVRO_UNUSED(iface);
+ AVRO_UNUSED(vself);
+ return 0;
+}
+
+static int
+avro_generic_null_set(const avro_value_iface_t *iface, void *vself)
+{
+ AVRO_UNUSED(iface);
+ AVRO_UNUSED(vself);
+ return 0;
+}
+
+static avro_value_iface_t AVRO_GENERIC_NULL_CLASS =
+{
+ /* "class" methods */
+ NULL, /* incref */
+ NULL, /* decref */
+ avro_generic_null_instance_size,
+ /* general "instance" methods */
+ avro_generic_null_init,
+ avro_generic_null_done,
+ avro_generic_null_reset,
+ avro_generic_null_get_type,
+ avro_generic_null_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 */
+ avro_generic_null_get,
+ 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 */
+ avro_generic_null_set,
+ NULL, /* set_string */
+ NULL, /* set_string_length */
+ NULL, /* give_string_length */
+ NULL, /* set_enum */
+ 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_null_class(void)
+{
+ return &AVRO_GENERIC_NULL_CLASS;
+}
+
+int avro_generic_null_new(avro_value_t *value)
+{
+ return avro_value_new(&AVRO_GENERIC_NULL_CLASS, value);
+}
+
+/*-----------------------------------------------------------------------
+ * string
+ */
+
+static size_t
+avro_generic_string_instance_size(const avro_value_iface_t *iface)
+{
+ AVRO_UNUSED(iface);
+ return sizeof(avro_raw_string_t);
+}
+
+static int
+avro_generic_string_init(const avro_value_iface_t *iface, void *vself)
+{
+ AVRO_UNUSED(iface);
+ avro_raw_string_t *self = vself;
+ avro_raw_string_init(self);
+ return 0;
+}
+
+static void
+avro_generic_string_done(const avro_value_iface_t *iface, void *vself)
+{
+ AVRO_UNUSED(iface);
+ avro_raw_string_t *self = vself;
+ avro_raw_string_done(self);
+}
+
+static int
+avro_generic_string_reset(const avro_value_iface_t *iface, void *vself)
+{
+ AVRO_UNUSED(iface);
+ avro_raw_string_t *self = vself;
+ avro_raw_string_clear(self);
+ return 0;
+}
+
+static avro_type_t
+avro_generic_string_get_type(const avro_value_iface_t *iface, const void *vself)
+{
+ AVRO_UNUSED(iface);
+ AVRO_UNUSED(vself);
+ return AVRO_STRING;
+}
+
+static avro_schema_t
+avro_generic_string_get_schema(const avro_value_iface_t *iface, const void *vself)
+{
+ AVRO_UNUSED(iface);
+ AVRO_UNUSED(vself);
+ return avro_schema_string();
+}
+
+static int
+avro_generic_string_get(const avro_value_iface_t *iface,
+ const void *vself, const char **str, size_t *size)
+{
+ AVRO_UNUSED(iface);
+ const avro_raw_string_t *self = vself;
+ const char *contents = avro_raw_string_get(self);
+
+ if (str != NULL) {
+ /*
+ * We can't return a NULL string, we have to return an
+ * *empty* string
+ */
+
+ *str = (contents == NULL)? "": contents;
+ }
+ if (size != NULL) {
+ /* raw_string's length includes the NUL terminator,
+ * unless it's empty */
+ *size = (contents == NULL)? 1: avro_raw_string_length(self);
+ }
+ return 0;
+}
+
+static int
+avro_generic_string_grab(const avro_value_iface_t *iface,
+ const void *vself, avro_wrapped_buffer_t *dest)
+{
+ AVRO_UNUSED(iface);
+ const avro_raw_string_t *self = vself;
+ const char *contents = avro_raw_string_get(self);
+
+ if (contents == NULL) {
+ return avro_wrapped_buffer_new(dest, "", 1);
+ } else {
+ return avro_raw_string_grab(self, dest);
+ }
+}
+
+static int
+avro_generic_string_set(const avro_value_iface_t *iface,
+ void *vself, char *val)
+{
+ AVRO_UNUSED(iface);
+ check_param(EINVAL, val != NULL, "string contents");
+
+ /*
+ * This raw_string method ensures that we copy the NUL
+ * terminator from val, and will include the NUL terminator in
+ * the raw_string's length, which is what we want.
+ */
+ avro_raw_string_t *self = vself;
+ avro_raw_string_set(self, val);
+ return 0;
+}
+
+static int
+avro_generic_string_set_length(const avro_value_iface_t *iface,
+ void *vself, char *val, size_t size)
+{
+ AVRO_UNUSED(iface);
+ check_param(EINVAL, val != NULL, "string contents");
+ avro_raw_string_t *self = vself;
+ avro_raw_string_set_length(self, val, size);
+ return 0;
+}
+
+static int
+avro_generic_string_give_length(const avro_value_iface_t *iface,
+ void *vself, avro_wrapped_buffer_t *buf)
+{
+ AVRO_UNUSED(iface);
+ avro_raw_string_t *self = vself;
+ avro_raw_string_give(self, buf);
+ return 0;
+}
+
+static avro_value_iface_t AVRO_GENERIC_STRING_CLASS =
+{
+ /* "class" methods */
+ NULL, /* incref */
+ NULL, /* decref */
+ avro_generic_string_instance_size,
+ /* general "instance" methods */
+ avro_generic_string_init,
+ avro_generic_string_done,
+ avro_generic_string_reset,
+ avro_generic_string_get_type,
+ avro_generic_string_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 */
+ avro_generic_string_get,
+ avro_generic_string_grab,
+ 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 */
+ avro_generic_string_set,
+ avro_generic_string_set_length,
+ avro_generic_string_give_length,
+ NULL, /* set_enum */
+ 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_string_class(void)
+{
+ return &AVRO_GENERIC_STRING_CLASS;
+}
+
+int avro_generic_string_new(avro_value_t *value, char *str)
+{
+ int rval;
+ check(rval, avro_value_new(&AVRO_GENERIC_STRING_CLASS, value));
+ return avro_generic_string_set(value->iface, value->self, str);
+}
+
+int avro_generic_string_new_length(avro_value_t *value, char *str, size_t size)
+{
+ int rval;
+ check(rval, avro_value_new(&AVRO_GENERIC_STRING_CLASS, value));
+ return avro_generic_string_set_length(value->iface, value->self, str, size);
+}
Added: avro/trunk/lang/c/src/generic-record.c
URL: http://svn.apache.org/viewvc/avro/trunk/lang/c/src/generic-record.c?rev=1146546&view=auto
==============================================================================
--- avro/trunk/lang/c/src/generic-record.c (added)
+++ avro/trunk/lang/c/src/generic-record.c Thu Jul 14 02:35:04 2011
@@ -0,0 +1,396 @@
+/*
+ * 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"
+
+
+#ifndef DEBUG_FIELD_OFFSETS
+#define DEBUG_FIELD_OFFSETS 0
+#endif
+
+
+/*
+ * For generic records, we need to store the value implementation for
+ * each field. We also need to store an offset for each field, since
+ * we're going to store the contents of each field directly in the
+ * record, rather than via pointers.
+ */
+
+typedef struct avro_generic_record_value_iface {
+ avro_value_iface_t iface;
+
+ /** The reference count for this interface. */
+ volatile int refcount;
+
+ /** The schema for this record. */
+ avro_schema_t schema;
+
+ /** The total size of each value struct for this record. */
+ size_t instance_size;
+
+ /** The number of fields in this record. Yes, we could get this
+ * from schema, but this is easier. */
+ size_t field_count;
+
+ /** The offset of each field within the record struct. */
+ size_t *field_offsets;
+
+ /** The value implementation for each field. */
+ avro_value_iface_t **field_ifaces;
+} avro_generic_record_value_iface_t;
+
+typedef struct avro_generic_record {
+ /* The rest of the struct is taken up by the inline storage
+ * needed for each field. */
+} avro_generic_record_t;
+
+
+/** Return a pointer to the given field within a record struct. */
+#define avro_generic_record_field(iface, rec, index) \
+ (((void *) (rec)) + (iface)->field_offsets[(index)])
+
+
+static avro_value_iface_t *
+avro_generic_record_incref(avro_value_iface_t *viface)
+{
+ avro_generic_record_value_iface_t *iface =
+ (avro_generic_record_value_iface_t *) viface;
+ avro_refcount_inc(&iface->refcount);
+ return viface;
+}
+
+static void
+avro_generic_record_decref(avro_value_iface_t *viface)
+{
+ avro_generic_record_value_iface_t *iface =
+ (avro_generic_record_value_iface_t *) viface;
+
+ if (avro_refcount_dec(&iface->refcount)) {
+ size_t i;
+ for (i = 0; i < iface->field_count; i++) {
+ avro_value_iface_decref(iface->field_ifaces[i]);
+ }
+
+ avro_schema_decref(iface->schema);
+ avro_free(iface->field_offsets,
+ sizeof(size_t) * iface->field_count);
+ avro_free(iface->field_ifaces,
+ sizeof(avro_value_iface_t *) * iface->field_count);
+
+ avro_freet(avro_generic_record_value_iface_t, iface);
+ }
+}
+
+static size_t
+avro_generic_record_instance_size(const avro_value_iface_t *viface)
+{
+ const avro_generic_record_value_iface_t *iface =
+ (avro_generic_record_value_iface_t *) viface;
+ return iface->instance_size;
+}
+
+static int
+avro_generic_record_init(const avro_value_iface_t *viface, void *vself)
+{
+ int rval;
+ const avro_generic_record_value_iface_t *iface =
+ (const avro_generic_record_value_iface_t *) viface;
+ avro_generic_record_t *self = vself;
+
+ /* Initialize each field */
+ size_t i;
+ for (i = 0; i < iface->field_count; i++) {
+ check(rval, avro_value_init
+ (iface->field_ifaces[i],
+ avro_generic_record_field(iface, self, i)));
+ }
+
+ return 0;
+}
+
+static void
+avro_generic_record_done(const avro_value_iface_t *viface, void *vself)
+{
+ const avro_generic_record_value_iface_t *iface =
+ (const avro_generic_record_value_iface_t *) viface;
+ avro_generic_record_t *self = vself;
+ size_t i;
+ for (i = 0; i < iface->field_count; i++) {
+ avro_value_t value = {
+ iface->field_ifaces[i],
+ avro_generic_record_field(iface, self, i)
+ };
+ avro_value_done(&value);
+ }
+}
+
+static int
+avro_generic_record_reset(const avro_value_iface_t *viface, void *vself)
+{
+ const avro_generic_record_value_iface_t *iface =
+ (const avro_generic_record_value_iface_t *) viface;
+ int rval;
+ avro_generic_record_t *self = vself;
+ size_t i;
+ for (i = 0; i < iface->field_count; i++) {
+ avro_value_t value = {
+ iface->field_ifaces[i],
+ avro_generic_record_field(iface, self, i)
+ };
+ check(rval, avro_value_reset(&value));
+ }
+ return 0;
+}
+
+static avro_type_t
+avro_generic_record_get_type(const avro_value_iface_t *viface, const void *vself)
+{
+ AVRO_UNUSED(viface);
+ AVRO_UNUSED(vself);
+ return AVRO_RECORD;
+}
+
+static avro_schema_t
+avro_generic_record_get_schema(const avro_value_iface_t *viface, const void *vself)
+{
+ const avro_generic_record_value_iface_t *iface =
+ (const avro_generic_record_value_iface_t *) viface;
+ AVRO_UNUSED(vself);
+ return iface->schema;
+}
+
+static int
+avro_generic_record_get_size(const avro_value_iface_t *viface,
+ const void *vself, size_t *size)
+{
+ const avro_generic_record_value_iface_t *iface =
+ (const avro_generic_record_value_iface_t *) viface;
+ AVRO_UNUSED(vself);
+ if (size != NULL) {
+ *size = iface->field_count;
+ }
+ return 0;
+}
+
+static int
+avro_generic_record_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_record_value_iface_t *iface =
+ (const avro_generic_record_value_iface_t *) viface;
+ const avro_generic_record_t *self = vself;
+ if (index >= iface->field_count) {
+ avro_set_error("Field index %zu out of range", index);
+ return EINVAL;
+ }
+ child->iface = iface->field_ifaces[index];
+ child->self = avro_generic_record_field(iface, self, index);
+
+ /*
+ * Grab the field name from the schema if asked for.
+ */
+ if (name != NULL) {
+ avro_schema_t schema = iface->schema;
+ *name = avro_schema_record_field_name(schema, index);
+ }
+
+ return 0;
+}
+
+static int
+avro_generic_record_get_by_name(const avro_value_iface_t *viface,
+ const void *vself, const char *name,
+ avro_value_t *child, size_t *index_out)
+{
+ const avro_generic_record_value_iface_t *iface =
+ (const avro_generic_record_value_iface_t *) viface;
+ const avro_generic_record_t *self = vself;
+
+ avro_schema_t schema = iface->schema;
+ int index = avro_schema_record_field_get_index(schema, name);
+ if (index < 0) {
+ avro_set_error("Unknown record field %s", name);
+ return EINVAL;
+ }
+
+ child->iface = iface->field_ifaces[index];
+ child->self = avro_generic_record_field(iface, self, index);
+ if (index_out != NULL) {
+ *index_out = index;
+ }
+ return 0;
+}
+
+static avro_value_iface_t AVRO_GENERIC_RECORD_CLASS =
+{
+ /* "class" methods */
+ avro_generic_record_incref,
+ avro_generic_record_decref,
+ avro_generic_record_instance_size,
+ /* general "instance" methods */
+ avro_generic_record_init,
+ avro_generic_record_done,
+ avro_generic_record_reset,
+ avro_generic_record_get_type,
+ avro_generic_record_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_record_get_size,
+ avro_generic_record_get_by_index,
+ avro_generic_record_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_record_class(avro_schema_t schema,
+ avro_value_iface_creator_t creator,
+ void *user_data)
+{
+ if (!is_avro_record(schema)) {
+ avro_set_error("Expected record schema");
+ return NULL;
+ }
+
+ avro_generic_record_value_iface_t *iface =
+ avro_new(avro_generic_record_value_iface_t);
+ if (iface == NULL) {
+ return NULL;
+ }
+
+ memset(iface, 0, sizeof(avro_generic_record_value_iface_t));
+ memcpy(&iface->iface, &AVRO_GENERIC_RECORD_CLASS,
+ sizeof(avro_value_iface_t));
+ iface->refcount = 1;
+ iface->schema = avro_schema_incref(schema);
+
+ iface->field_count = avro_schema_record_size(schema);
+ size_t field_offsets_size =
+ sizeof(size_t) * iface->field_count;
+ size_t field_ifaces_size =
+ sizeof(avro_value_iface_t *) * iface->field_count;
+
+ iface->field_offsets = avro_malloc(field_offsets_size);
+ if (iface->field_offsets == NULL) {
+ goto error;
+ }
+
+ iface->field_ifaces = avro_malloc(field_ifaces_size);
+ if (iface->field_ifaces == NULL) {
+ goto error;
+ }
+
+ size_t next_offset = sizeof(avro_generic_record_t);
+#if DEBUG_FIELD_OFFSETS
+ fprintf(stderr, " Record %s\n Header: Offset 0, size %zu\n",
+ avro_schema_type_name(schema),
+ sizeof(avro_generic_record_t));
+#endif
+ size_t i;
+ for (i = 0; i < iface->field_count; i++) {
+ avro_schema_t field_schema =
+ avro_schema_record_field_get_by_index(schema, i);
+
+ iface->field_offsets[i] = next_offset;
+
+ iface->field_ifaces[i] = creator(field_schema, user_data);
+ if (iface->field_ifaces[i] == NULL) {
+ goto error;
+ }
+
+ size_t field_size =
+ avro_value_instance_size(iface->field_ifaces[i]);
+ if (field_size == 0) {
+ avro_set_error("Record field class must provide instance_size");
+ goto error;
+ }
+
+#if DEBUG_FIELD_OFFSETS
+ fprintf(stderr, " Field %zu (%s): Offset %zu, size %zu\n",
+ i, avro_schema_type_name(field_schema),
+ next_offset, field_size);
+#endif
+ next_offset += field_size;
+ }
+
+ iface->instance_size = next_offset;
+#if DEBUG_FIELD_OFFSETS
+ fprintf(stderr, " TOTAL SIZE: %zu\n", next_offset);
+#endif
+
+ return &iface->iface;
+
+error:
+ avro_schema_decref(iface->schema);
+ if (iface->field_offsets != NULL) {
+ avro_free(iface->field_offsets, field_offsets_size);
+ }
+ if (iface->field_ifaces != NULL) {
+ for (i = 0; i < iface->field_count; i++) {
+ if (iface->field_ifaces[i] != NULL) {
+ avro_value_iface_decref(iface->field_ifaces[i]);
+ }
+ }
+ avro_free(iface->field_ifaces, field_ifaces_size);
+ }
+ avro_freet(avro_generic_record_value_iface_t, iface);
+ return NULL;
+}
Added: avro/trunk/lang/c/src/generic-union.c
URL: http://svn.apache.org/viewvc/avro/trunk/lang/c/src/generic-union.c?rev=1146546&view=auto
==============================================================================
--- avro/trunk/lang/c/src/generic-union.c (added)
+++ avro/trunk/lang/c/src/generic-union.c Thu Jul 14 02:35:04 2011
@@ -0,0 +1,398 @@
+/*
+ * 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"
+
+
+#ifndef DEBUG_BRANCHES
+#define DEBUG_BRANCHES 0
+#endif
+
+
+/*
+ * For generic unions, we need to store the value implementation for
+ * each branch, just like for generic records. However, for unions, we
+ * can only have one branch active at a time, so we can reuse the space
+ * in the union struct, just like is done with C unions.
+ */
+
+typedef struct avro_generic_union_value_iface {
+ avro_value_iface_t iface;
+
+ /** The reference count for this interface. */
+ volatile int refcount;
+
+ /** The schema for this union. */
+ avro_schema_t schema;
+
+ /** The total size of each value struct for this union. */
+ size_t instance_size;
+
+ /** The number of branches in this union. Yes, we could get
+ * this from schema, but this is easier. */
+ size_t branch_count;
+
+ /** The value implementation for each branch. */
+ avro_value_iface_t **branch_ifaces;
+} avro_generic_union_value_iface_t;
+
+typedef struct avro_generic_union {
+ /** The currently active branch of the union. -1 if no branch
+ * is selected. */
+ int discriminant;
+
+ /* The rest of the struct is taken up by the inline storage
+ * needed for the active branch. */
+} avro_generic_union_t;
+
+
+/** Return the child interface for the active branch. */
+#define avro_generic_union_branch_iface(iface, _union) \
+ ((iface)->branch_ifaces[(_union)->discriminant])
+
+/** Return a pointer to the active branch within a union struct. */
+#define avro_generic_union_branch(_union) \
+ (((void *) (_union)) + sizeof(avro_generic_union_t))
+
+
+static avro_value_iface_t *
+avro_generic_union_incref(avro_value_iface_t *viface)
+{
+ avro_generic_union_value_iface_t *iface =
+ (avro_generic_union_value_iface_t *) viface;
+ avro_refcount_inc(&iface->refcount);
+ return viface;
+}
+
+static void
+avro_generic_union_decref(avro_value_iface_t *viface)
+{
+ avro_generic_union_value_iface_t *iface =
+ (avro_generic_union_value_iface_t *) viface;
+
+ if (avro_refcount_dec(&iface->refcount)) {
+ size_t i;
+ for (i = 0; i < iface->branch_count; i++) {
+ avro_value_iface_decref(iface->branch_ifaces[i]);
+ }
+
+ avro_schema_decref(iface->schema);
+ avro_free(iface->branch_ifaces,
+ sizeof(avro_value_iface_t *) * iface->branch_count);
+
+ avro_freet(avro_generic_union_value_iface_t, iface);
+ }
+}
+
+static size_t
+avro_generic_union_instance_size(const avro_value_iface_t *viface)
+{
+ const avro_generic_union_value_iface_t *iface =
+ (const avro_generic_union_value_iface_t *) viface;
+ return iface->instance_size;
+}
+
+static int
+avro_generic_union_init(const avro_value_iface_t *viface, void *vself)
+{
+ AVRO_UNUSED(viface);
+ avro_generic_union_t *self = vself;
+ self->discriminant = -1;
+ return 0;
+}
+
+static void
+avro_generic_union_done(const avro_value_iface_t *viface, void *vself)
+{
+ const avro_generic_union_value_iface_t *iface =
+ (const avro_generic_union_value_iface_t *) viface;
+ avro_generic_union_t *self = vself;
+ if (self->discriminant >= 0) {
+#if DEBUG_BRANCHES
+ fprintf(stderr, "Finalizing branch %d\n",
+ self->discriminant);
+#endif
+ avro_value_t value = {
+ avro_generic_union_branch_iface(iface, self),
+ avro_generic_union_branch(self)
+ };
+ avro_value_done(&value);
+ self->discriminant = -1;
+ }
+}
+
+static int
+avro_generic_union_reset(const avro_value_iface_t *viface, void *vself)
+{
+ const avro_generic_union_value_iface_t *iface =
+ (const avro_generic_union_value_iface_t *) viface;
+ avro_generic_union_t *self = vself;
+ /* Keep the same branch selected, for the common case that we're
+ * about to reuse it. */
+ if (self->discriminant >= 0) {
+#if DEBUG_BRANCHES
+ fprintf(stderr, "Resetting branch %d\n",
+ self->discriminant);
+#endif
+ avro_value_t value = {
+ avro_generic_union_branch_iface(iface, self),
+ avro_generic_union_branch(self)
+ };
+ return avro_value_reset(&value);
+ }
+ return 0;
+}
+
+static avro_type_t
+avro_generic_union_get_type(const avro_value_iface_t *viface, const void *vself)
+{
+ AVRO_UNUSED(viface);
+ AVRO_UNUSED(vself);
+ return AVRO_UNION;
+}
+
+static avro_schema_t
+avro_generic_union_get_schema(const avro_value_iface_t *viface, const void *vself)
+{
+ const avro_generic_union_value_iface_t *iface =
+ (const avro_generic_union_value_iface_t *) viface;
+ AVRO_UNUSED(vself);
+ return iface->schema;
+}
+
+static int
+avro_generic_union_get_discriminant(const avro_value_iface_t *viface,
+ const void *vself, int *out)
+{
+ AVRO_UNUSED(viface);
+ const avro_generic_union_t *self = vself;
+ *out = self->discriminant;
+ return 0;
+}
+
+static int
+avro_generic_union_get_current_branch(const avro_value_iface_t *viface,
+ const void *vself, avro_value_t *branch)
+{
+ const avro_generic_union_value_iface_t *iface =
+ (const avro_generic_union_value_iface_t *) viface;
+ const avro_generic_union_t *self = vself;
+ if (self->discriminant < 0) {
+ avro_set_error("Union has no selected branch");
+ return EINVAL;
+ }
+ branch->iface = avro_generic_union_branch_iface(iface, self);
+ branch->self = avro_generic_union_branch(self);
+ return 0;
+}
+
+static int
+avro_generic_union_set_branch(const avro_value_iface_t *viface,
+ void *vself, int discriminant,
+ avro_value_t *branch)
+{
+ const avro_generic_union_value_iface_t *iface =
+ (const avro_generic_union_value_iface_t *) viface;
+ int rval;
+ avro_generic_union_t *self = vself;
+
+#if DEBUG_BRANCHES
+ fprintf(stderr, "Selecting branch %d (was %d)\n",
+ discriminant, self->discriminant);
+#endif
+
+ /*
+ * If the new desired branch is different than the currently
+ * active one, then finalize the old branch and initialize the
+ * new one.
+ */
+ if (self->discriminant != discriminant) {
+ if (self->discriminant >= 0) {
+#if DEBUG_BRANCHES
+ fprintf(stderr, "Finalizing branch %d\n",
+ self->discriminant);
+#endif
+ avro_value_t value = {
+ avro_generic_union_branch_iface(iface, self),
+ avro_generic_union_branch(self)
+ };
+ avro_value_done(&value);
+ }
+ self->discriminant = discriminant;
+ if (discriminant >= 0) {
+#if DEBUG_BRANCHES
+ fprintf(stderr, "Initializing branch %d\n",
+ self->discriminant);
+#endif
+ check(rval, avro_value_init
+ (avro_generic_union_branch_iface(iface, self),
+ avro_generic_union_branch(self)));
+ }
+ }
+
+ if (branch != NULL) {
+ branch->iface = avro_generic_union_branch_iface(iface, self);
+ branch->self = avro_generic_union_branch(self);
+ }
+
+ return 0;
+}
+
+static avro_value_iface_t AVRO_GENERIC_UNION_CLASS =
+{
+ /* "class" methods */
+ avro_generic_union_incref,
+ avro_generic_union_decref,
+ avro_generic_union_instance_size,
+ /* general "instance" methods */
+ avro_generic_union_init,
+ avro_generic_union_done,
+ avro_generic_union_reset,
+ avro_generic_union_get_type,
+ avro_generic_union_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 */
+ NULL, /* get_size */
+ NULL, /* get_by_index */
+ NULL, /* get_by_name */
+ avro_generic_union_get_discriminant,
+ avro_generic_union_get_current_branch,
+ /* compound setters */
+ NULL, /* append */
+ NULL, /* add */
+ avro_generic_union_set_branch
+};
+
+avro_value_iface_t *
+avro_generic_union_class(avro_schema_t schema,
+ avro_value_iface_creator_t creator,
+ void *user_data)
+{
+ if (!is_avro_union(schema)) {
+ avro_set_error("Expected union schema");
+ return NULL;
+ }
+
+ avro_generic_union_value_iface_t *iface =
+ avro_new(avro_generic_union_value_iface_t);
+ if (iface == NULL) {
+ return NULL;
+ }
+
+ memset(iface, 0, sizeof(avro_generic_union_value_iface_t));
+ memcpy(&iface->iface, &AVRO_GENERIC_UNION_CLASS,
+ sizeof(avro_value_iface_t));
+ iface->refcount = 1;
+ iface->schema = avro_schema_incref(schema);
+
+ iface->branch_count = avro_schema_union_size(schema);
+ size_t branch_ifaces_size =
+ sizeof(avro_value_iface_t *) * iface->branch_count;
+
+ iface->branch_ifaces = avro_malloc(branch_ifaces_size);
+ if (iface->branch_ifaces == NULL) {
+ goto error;
+ }
+
+ size_t max_branch_size = 0;
+ size_t i;
+ for (i = 0; i < iface->branch_count; i++) {
+ avro_schema_t branch_schema =
+ avro_schema_union_branch(schema, i);
+
+ iface->branch_ifaces[i] = creator(branch_schema, user_data);
+ if (iface->branch_ifaces[i] == NULL) {
+ goto error;
+ }
+
+ size_t branch_size =
+ avro_value_instance_size(iface->branch_ifaces[i]);
+ if (branch_size == 0) {
+ avro_set_error("Union branch class must provide instance_size");
+ goto error;
+ }
+
+#if DEBUG_BRANCHES
+ fprintf(stderr, "Branch %zu, size %zu\n",
+ i, branch_size);
+#endif
+
+ if (branch_size > max_branch_size) {
+ max_branch_size = branch_size;
+ }
+ }
+
+ iface->instance_size =
+ sizeof(avro_generic_union_t) + max_branch_size;
+#if DEBUG_BRANCHES
+ fprintf(stderr, "MAX BRANCH SIZE: %zu\n", max_branch_size);
+#endif
+
+ return &iface->iface;
+
+error:
+ avro_schema_decref(iface->schema);
+ if (iface->branch_ifaces != NULL) {
+ for (i = 0; i < iface->branch_count; i++) {
+ if (iface->branch_ifaces[i] != NULL) {
+ avro_value_iface_decref(iface->branch_ifaces[i]);
+ }
+ }
+ avro_free(iface->branch_ifaces, branch_ifaces_size);
+ }
+ avro_freet(avro_generic_union_value_iface_t, iface);
+ return NULL;
+}
Added: avro/trunk/lang/c/src/generic.c
URL: http://svn.apache.org/viewvc/avro/trunk/lang/c/src/generic.c?rev=1146546&view=auto
==============================================================================
--- avro/trunk/lang/c/src/generic.c (added)
+++ avro/trunk/lang/c/src/generic.c Thu Jul 14 02:35:04 2011
@@ -0,0 +1,684 @@
+/*
+ * 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/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"
+
+/*-----------------------------------------------------------------------
+ * recursive schemas
+ */
+
+/*
+ * Recursive schemas are handled specially; the value implementation for
+ * an AVRO_LINK schema is simply a wrapper around the value
+ * implementation for the link's target schema. The value methods all
+ * delegate to the wrapped implementation.
+ *
+ * We don't set the target_iface pointer when the link implementation is
+ * first created, since we might not have finished creating the
+ * implementation for the target schema. (We create the implementations
+ * for child schemas depth-first, so the target schema's implementation
+ * won't be done until all of its descendants â including the link
+ * schema â have been instantiated.)
+ *
+ * So anyway, we set the target_iface pointer to NULL at first. And
+ * then in a fix-up stage, once all of the non-link schemas have been
+ * instantiated, we go through and set the target_iface pointers for any
+ * link schemas we encountered.
+ */
+
+typedef struct avro_generic_link_value_iface {
+ avro_value_iface_t iface;
+
+ /** The reference count for this interface. */
+ volatile int refcount;
+
+ /** The schema for this interface. */
+ avro_schema_t schema;
+
+ /** The target's implementation. */
+ avro_value_iface_t *target_iface;
+} avro_generic_link_value_iface_t;
+
+
+static avro_value_iface_t *
+avro_generic_link_incref(avro_value_iface_t *viface)
+{
+ avro_generic_link_value_iface_t *iface =
+ (avro_generic_link_value_iface_t *) viface;
+ avro_refcount_inc(&iface->refcount);
+ return viface;
+}
+
+static void
+avro_generic_link_decref(avro_value_iface_t *viface)
+{
+ avro_generic_link_value_iface_t *iface =
+ (avro_generic_link_value_iface_t *) viface;
+
+ if (avro_refcount_dec(&iface->refcount)) {
+ avro_value_iface_decref(iface->target_iface);
+ avro_freet(avro_generic_link_value_iface_t, iface);
+ }
+}
+
+static size_t
+avro_generic_link_instance_size(const avro_value_iface_t *viface)
+{
+ AVRO_UNUSED(viface);
+ return sizeof(avro_value_t);
+}
+
+static int
+avro_generic_link_init(const avro_value_iface_t *viface, void *vself)
+{
+ avro_generic_link_value_iface_t *iface =
+ (avro_generic_link_value_iface_t *) viface;
+ avro_value_t *self = vself;
+
+ return avro_value_new(iface->target_iface, self);
+}
+
+static void
+avro_generic_link_done(const avro_value_iface_t *iface, void *vself)
+{
+ AVRO_UNUSED(iface);
+ avro_value_t *self = vself;
+ avro_value_free(self);
+}
+
+static int
+avro_generic_link_reset(const avro_value_iface_t *iface, void *vself)
+{
+ AVRO_UNUSED(iface);
+ avro_value_t *self = vself;
+ return avro_value_reset(self);
+}
+
+static avro_type_t
+avro_generic_link_get_type(const avro_value_iface_t *viface, const void *vself)
+{
+ AVRO_UNUSED(viface);
+ const avro_value_t *self = vself;
+ return avro_value_get_type(self);
+}
+
+static avro_schema_t
+avro_generic_link_get_schema(const avro_value_iface_t *viface, const void *vself)
+{
+ AVRO_UNUSED(viface);
+ const avro_value_t *self = vself;
+ return avro_value_get_schema(self);
+}
+
+static int
+avro_generic_link_get_boolean(const avro_value_iface_t *iface,
+ const void *vself, bool *out)
+{
+ AVRO_UNUSED(iface);
+ const avro_value_t *self = vself;
+ return avro_value_get_boolean(self, out);
+}
+
+static int
+avro_generic_link_get_bytes(const avro_value_iface_t *iface,
+ const void *vself, const void **buf, size_t *size)
+{
+ AVRO_UNUSED(iface);
+ const avro_value_t *self = vself;
+ return avro_value_get_bytes(self, buf, size);
+}
+
+static int
+avro_generic_link_grab_bytes(const avro_value_iface_t *iface,
+ const void *vself, avro_wrapped_buffer_t *dest)
+{
+ AVRO_UNUSED(iface);
+ const avro_value_t *self = vself;
+ return avro_value_grab_bytes(self, dest);
+}
+
+static int
+avro_generic_link_get_double(const avro_value_iface_t *iface,
+ const void *vself, double *out)
+{
+ AVRO_UNUSED(iface);
+ const avro_value_t *self = vself;
+ return avro_value_get_double(self, out);
+}
+
+static int
+avro_generic_link_get_float(const avro_value_iface_t *iface,
+ const void *vself, float *out)
+{
+ AVRO_UNUSED(iface);
+ const avro_value_t *self = vself;
+ return avro_value_get_float(self, out);
+}
+
+static int
+avro_generic_link_get_int(const avro_value_iface_t *iface,
+ const void *vself, int32_t *out)
+{
+ AVRO_UNUSED(iface);
+ const avro_value_t *self = vself;
+ return avro_value_get_int(self, out);
+}
+
+static int
+avro_generic_link_get_long(const avro_value_iface_t *iface,
+ const void *vself, int64_t *out)
+{
+ AVRO_UNUSED(iface);
+ const avro_value_t *self = vself;
+ return avro_value_get_long(self, out);
+}
+
+static int
+avro_generic_link_get_null(const avro_value_iface_t *iface, const void *vself)
+{
+ AVRO_UNUSED(iface);
+ const avro_value_t *self = vself;
+ return avro_value_get_null(self);
+}
+
+static int
+avro_generic_link_get_string(const avro_value_iface_t *iface,
+ const void *vself, const char **str, size_t *size)
+{
+ AVRO_UNUSED(iface);
+ const avro_value_t *self = vself;
+ return avro_value_get_string(self, str, size);
+}
+
+static int
+avro_generic_link_grab_string(const avro_value_iface_t *iface,
+ const void *vself, avro_wrapped_buffer_t *dest)
+{
+ AVRO_UNUSED(iface);
+ const avro_value_t *self = vself;
+ return avro_value_grab_string(self, dest);
+}
+
+static int
+avro_generic_link_get_enum(const avro_value_iface_t *iface,
+ const void *vself, int *out)
+{
+ AVRO_UNUSED(iface);
+ const avro_value_t *self = vself;
+ return avro_value_get_enum(self, out);
+}
+
+static int
+avro_generic_link_get_fixed(const avro_value_iface_t *iface,
+ const void *vself, const void **buf, size_t *size)
+{
+ AVRO_UNUSED(iface);
+ const avro_value_t *self = vself;
+ return avro_value_get_fixed(self, buf, size);
+}
+
+static int
+avro_generic_link_grab_fixed(const avro_value_iface_t *iface,
+ const void *vself, avro_wrapped_buffer_t *dest)
+{
+ AVRO_UNUSED(iface);
+ const avro_value_t *self = vself;
+ return avro_value_grab_fixed(self, dest);
+}
+
+static int
+avro_generic_link_set_boolean(const avro_value_iface_t *iface,
+ void *vself, bool val)
+{
+ AVRO_UNUSED(iface);
+ avro_value_t *self = vself;
+ return avro_value_set_boolean(self, val);
+}
+
+static int
+avro_generic_link_set_bytes(const avro_value_iface_t *iface,
+ void *vself, void *buf, size_t size)
+{
+ AVRO_UNUSED(iface);
+ avro_value_t *self = vself;
+ return avro_value_set_bytes(self, buf, size);
+}
+
+static int
+avro_generic_link_give_bytes(const avro_value_iface_t *iface,
+ void *vself, avro_wrapped_buffer_t *buf)
+{
+ AVRO_UNUSED(iface);
+ avro_value_t *self = vself;
+ return avro_value_give_bytes(self, buf);
+}
+
+static int
+avro_generic_link_set_double(const avro_value_iface_t *iface,
+ void *vself, double val)
+{
+ AVRO_UNUSED(iface);
+ avro_value_t *self = vself;
+ return avro_value_set_double(self, val);
+}
+
+static int
+avro_generic_link_set_float(const avro_value_iface_t *iface,
+ void *vself, float val)
+{
+ AVRO_UNUSED(iface);
+ avro_value_t *self = vself;
+ return avro_value_set_float(self, val);
+}
+
+static int
+avro_generic_link_set_int(const avro_value_iface_t *iface,
+ void *vself, int32_t val)
+{
+ AVRO_UNUSED(iface);
+ avro_value_t *self = vself;
+ return avro_value_set_int(self, val);
+}
+
+static int
+avro_generic_link_set_long(const avro_value_iface_t *iface,
+ void *vself, int64_t val)
+{
+ AVRO_UNUSED(iface);
+ avro_value_t *self = vself;
+ return avro_value_set_long(self, val);
+}
+
+static int
+avro_generic_link_set_null(const avro_value_iface_t *iface, void *vself)
+{
+ AVRO_UNUSED(iface);
+ avro_value_t *self = vself;
+ return avro_value_set_null(self);
+}
+
+static int
+avro_generic_link_set_string(const avro_value_iface_t *iface,
+ void *vself, char *str)
+{
+ AVRO_UNUSED(iface);
+ avro_value_t *self = vself;
+ return avro_value_set_string(self, str);
+}
+
+static int
+avro_generic_link_set_string_len(const avro_value_iface_t *iface,
+ void *vself, char *str, size_t size)
+{
+ AVRO_UNUSED(iface);
+ avro_value_t *self = vself;
+ return avro_value_set_string_len(self, str, size);
+}
+
+static int
+avro_generic_link_give_string_len(const avro_value_iface_t *iface,
+ void *vself, avro_wrapped_buffer_t *buf)
+{
+ AVRO_UNUSED(iface);
+ avro_value_t *self = vself;
+ return avro_value_give_string_len(self, buf);
+}
+
+static int
+avro_generic_link_set_enum(const avro_value_iface_t *iface,
+ void *vself, int val)
+{
+ AVRO_UNUSED(iface);
+ avro_value_t *self = vself;
+ return avro_value_set_enum(self, val);
+}
+
+static int
+avro_generic_link_set_fixed(const avro_value_iface_t *iface,
+ void *vself, void *buf, size_t size)
+{
+ AVRO_UNUSED(iface);
+ avro_value_t *self = vself;
+ return avro_value_set_fixed(self, buf, size);
+}
+
+static int
+avro_generic_link_give_fixed(const avro_value_iface_t *iface,
+ void *vself, avro_wrapped_buffer_t *buf)
+{
+ AVRO_UNUSED(iface);
+ avro_value_t *self = vself;
+ return avro_value_give_fixed(self, buf);
+}
+
+static int
+avro_generic_link_get_size(const avro_value_iface_t *iface,
+ const void *vself, size_t *size)
+{
+ AVRO_UNUSED(iface);
+ const avro_value_t *self = vself;
+ return avro_value_get_size(self, size);
+}
+
+static int
+avro_generic_link_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_value_t *self = vself;
+ return avro_value_get_by_index(self, index, child, name);
+}
+
+static int
+avro_generic_link_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_value_t *self = vself;
+ return avro_value_get_by_name(self, name, child, index);
+}
+
+static int
+avro_generic_link_get_discriminant(const avro_value_iface_t *iface,
+ const void *vself, int *out)
+{
+ AVRO_UNUSED(iface);
+ const avro_value_t *self = vself;
+ return avro_value_get_discriminant(self, out);
+}
+
+static int
+avro_generic_link_get_current_branch(const avro_value_iface_t *iface,
+ const void *vself, avro_value_t *branch)
+{
+ AVRO_UNUSED(iface);
+ const avro_value_t *self = vself;
+ return avro_value_get_current_branch(self, branch);
+}
+
+static int
+avro_generic_link_append(const avro_value_iface_t *iface,
+ void *vself, avro_value_t *child_out,
+ size_t *new_index)
+{
+ AVRO_UNUSED(iface);
+ avro_value_t *self = vself;
+ return avro_value_append(self, child_out, new_index);
+}
+
+static int
+avro_generic_link_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_value_t *self = vself;
+ return avro_value_add(self, key, child, index, is_new);
+}
+
+static int
+avro_generic_link_set_branch(const avro_value_iface_t *iface,
+ void *vself, int discriminant,
+ avro_value_t *branch)
+{
+ AVRO_UNUSED(iface);
+ avro_value_t *self = vself;
+ return avro_value_set_branch(self, discriminant, branch);
+}
+
+static avro_value_iface_t AVRO_GENERIC_LINK_CLASS =
+{
+ /* "class" methods */
+ avro_generic_link_incref,
+ avro_generic_link_decref,
+ avro_generic_link_instance_size,
+ /* general "instance" methods */
+ avro_generic_link_init,
+ avro_generic_link_done,
+ avro_generic_link_reset,
+ avro_generic_link_get_type,
+ avro_generic_link_get_schema,
+ /* primitive getters */
+ avro_generic_link_get_boolean,
+ avro_generic_link_get_bytes,
+ avro_generic_link_grab_bytes,
+ avro_generic_link_get_double,
+ avro_generic_link_get_float,
+ avro_generic_link_get_int,
+ avro_generic_link_get_long,
+ avro_generic_link_get_null,
+ avro_generic_link_get_string,
+ avro_generic_link_grab_string,
+ avro_generic_link_get_enum,
+ avro_generic_link_get_fixed,
+ avro_generic_link_grab_fixed,
+ /* primitive setters */
+ avro_generic_link_set_boolean,
+ avro_generic_link_set_bytes,
+ avro_generic_link_give_bytes,
+ avro_generic_link_set_double,
+ avro_generic_link_set_float,
+ avro_generic_link_set_int,
+ avro_generic_link_set_long,
+ avro_generic_link_set_null,
+ avro_generic_link_set_string,
+ avro_generic_link_set_string_len,
+ avro_generic_link_give_string_len,
+ avro_generic_link_set_enum,
+ avro_generic_link_set_fixed,
+ avro_generic_link_give_fixed,
+ /* compound getters */
+ avro_generic_link_get_size,
+ avro_generic_link_get_by_index,
+ avro_generic_link_get_by_name,
+ avro_generic_link_get_discriminant,
+ avro_generic_link_get_current_branch,
+ /* compound setters */
+ avro_generic_link_append,
+ avro_generic_link_add,
+ avro_generic_link_set_branch
+};
+
+static avro_value_iface_t *
+avro_generic_link_class(avro_schema_t schema)
+{
+ if (!is_avro_link(schema)) {
+ avro_set_error("Expected link schema");
+ return NULL;
+ }
+
+ avro_generic_link_value_iface_t *iface =
+ avro_new(avro_generic_link_value_iface_t);
+ if (iface == NULL) {
+ return NULL;
+ }
+
+ memcpy(&iface->iface, &AVRO_GENERIC_LINK_CLASS,
+ sizeof(avro_value_iface_t));
+ iface->refcount = 1;
+ iface->schema = avro_schema_incref(schema);
+ return &iface->iface;
+}
+
+
+/*-----------------------------------------------------------------------
+ * schema type dispatcher
+ */
+
+typedef struct memoize_state_t {
+ avro_memoize_t mem;
+ avro_raw_array_t links;
+} memoize_state_t;
+
+static avro_value_iface_t *
+avro_generic_class_from_schema_memoized(avro_schema_t schema,
+ void *user_data)
+{
+ memoize_state_t *state = user_data;
+
+ /*
+ * If we've already instantiated a value class for this schema,
+ * just return it.
+ */
+
+ avro_value_iface_t *result = NULL;
+ if (avro_memoize_get(&state->mem, schema, NULL, (void **) &result)) {
+ return avro_value_iface_incref(result);
+ }
+
+ /*
+ * Otherwise instantiate the value class based on the schema
+ * type.
+ */
+
+ switch (schema->type) {
+ case AVRO_BOOLEAN:
+ result = avro_generic_boolean_class();
+ break;
+ case AVRO_BYTES:
+ result = avro_generic_bytes_class();
+ break;
+ case AVRO_DOUBLE:
+ result = avro_generic_double_class();
+ break;
+ case AVRO_FLOAT:
+ result = avro_generic_float_class();
+ break;
+ case AVRO_INT32:
+ result = avro_generic_int_class();
+ break;
+ case AVRO_INT64:
+ result = avro_generic_long_class();
+ break;
+ case AVRO_NULL:
+ result = avro_generic_null_class();
+ break;
+ case AVRO_STRING:
+ result = avro_generic_string_class();
+ break;
+
+ case AVRO_ARRAY:
+ result = avro_generic_array_class
+ (schema, avro_generic_class_from_schema_memoized, state);
+ break;
+ case AVRO_ENUM:
+ result = avro_generic_enum_class(schema);
+ break;
+ case AVRO_FIXED:
+ result = avro_generic_fixed_class(schema);
+ break;
+ case AVRO_MAP:
+ result = avro_generic_map_class
+ (schema, avro_generic_class_from_schema_memoized, state);
+ break;
+ case AVRO_RECORD:
+ result = avro_generic_record_class
+ (schema, avro_generic_class_from_schema_memoized, state);
+ break;
+ case AVRO_UNION:
+ result = avro_generic_union_class
+ (schema, avro_generic_class_from_schema_memoized, state);
+ break;
+
+ case AVRO_LINK:
+ {
+ avro_value_iface_t **link_ptr =
+ avro_raw_array_append(&state->links);
+ result = avro_generic_link_class(schema);
+ *link_ptr = result;
+ break;
+ }
+
+ default:
+ avro_set_error("Unknown schema type");
+ return NULL;
+ }
+
+ /*
+ * Add the new value implementation to the memoized state before
+ * we return.
+ */
+
+ avro_memoize_set(&state->mem, schema, NULL, result);
+ return result;
+}
+
+avro_value_iface_t *
+avro_generic_class_from_schema(avro_schema_t schema)
+{
+ /*
+ * Create a state to keep track of the value implementations
+ * that we create for each subschema.
+ */
+
+ memoize_state_t state;
+ avro_memoize_init(&state.mem);
+ avro_raw_array_init(&state.links, sizeof(avro_value_iface_t *));
+
+ /*
+ * Create the value implementations.
+ */
+
+ avro_value_iface_t *result =
+ avro_generic_class_from_schema_memoized(schema, &state);
+
+ /*
+ * Fix up any link schemas so that their value implementations
+ * point to their target schemas' implementations.
+ */
+
+ size_t i;
+ for (i = 0; i < avro_raw_array_size(&state.links); i++) {
+ avro_generic_link_value_iface_t *link_iface =
+ avro_raw_array_get
+ (&state.links, avro_generic_link_value_iface_t *, i);
+ avro_schema_t target_schema =
+ avro_schema_link_target(link_iface->schema);
+
+ avro_value_iface_t *target_iface = NULL;
+ if (!avro_memoize_get(&state.mem, target_schema, NULL,
+ (void **) &target_iface)) {
+ avro_set_error("Never created a value implementation for %s",
+ avro_schema_type_name(target_schema));
+ return NULL;
+ }
+
+ link_iface->target_iface = avro_value_iface_incref(target_iface);
+ }
+
+ /*
+ * And now we can return.
+ */
+
+ avro_memoize_done(&state.mem);
+ avro_raw_array_done(&state.links);
+ return result;
+}
Modified: avro/trunk/lang/c/src/io.c
URL: http://svn.apache.org/viewvc/avro/trunk/lang/c/src/io.c?rev=1146546&r1=1146545&r2=1146546&view=diff
==============================================================================
--- avro/trunk/lang/c/src/io.c (original)
+++ avro/trunk/lang/c/src/io.c Thu Jul 14 02:35:04 2011
@@ -15,10 +15,11 @@
* permissions and limitations under the License.
*/
+#include "avro/allocation.h"
#include "avro/refcount.h"
-#include "avro_errors.h"
+#include "avro/errors.h"
+#include "avro/io.h"
#include "avro_private.h"
-#include "allocation.h"
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
Added: avro/trunk/lang/c/src/map.c
URL: http://svn.apache.org/viewvc/avro/trunk/lang/c/src/map.c?rev=1146546&view=auto
==============================================================================
--- avro/trunk/lang/c/src/map.c (added)
+++ avro/trunk/lang/c/src/map.c Thu Jul 14 02:35:04 2011
@@ -0,0 +1,129 @@
+/*
+ * 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 <string.h>
+
+#include "avro/data.h"
+#include "avro/allocation.h"
+#include "avro/errors.h"
+#include "st.h"
+
+
+#define raw_entry_size(element_size) \
+ (sizeof(avro_raw_map_entry_t) + element_size)
+
+void avro_raw_map_init(avro_raw_map_t *map, size_t element_size)
+{
+ memset(map, 0, sizeof(avro_raw_map_t));
+ avro_raw_array_init(&map->elements, raw_entry_size(element_size));
+ map->indices_by_key = st_init_strtable();
+}
+
+
+static void
+avro_raw_map_free_keys(avro_raw_map_t *map)
+{
+ unsigned int i;
+ for (i = 0; i < avro_raw_map_size(map); i++) {
+ void *ventry =
+ (map->elements.data + map->elements.element_size * i);
+ avro_raw_map_entry_t *entry = ventry;
+ avro_str_free((char *) entry->key);
+ }
+}
+
+
+void avro_raw_map_done(avro_raw_map_t *map)
+{
+ avro_raw_map_free_keys(map);
+ avro_raw_array_done(&map->elements);
+ st_free_table(map->indices_by_key);
+ memset(map, 0, sizeof(avro_raw_map_t));
+}
+
+
+void avro_raw_map_clear(avro_raw_map_t *map)
+{
+ avro_raw_map_free_keys(map);
+ avro_raw_array_clear(&map->elements);
+ st_free_table(map->indices_by_key);
+ map->indices_by_key = st_init_strtable();
+}
+
+
+int
+avro_raw_map_ensure_size(avro_raw_map_t *map, size_t desired_count)
+{
+ return avro_raw_array_ensure_size(&map->elements, desired_count);
+}
+
+
+void *avro_raw_map_get(const avro_raw_map_t *map, const char *key,
+ size_t *index)
+{
+ st_data_t data;
+ if (st_lookup(map->indices_by_key, (st_data_t) key, &data)) {
+ unsigned int i = (unsigned int) data;
+ if (index) {
+ *index = i;
+ }
+ void *raw_entry =
+ (map->elements.data + map->elements.element_size * i);
+ return raw_entry + sizeof(avro_raw_map_entry_t);
+ } else {
+ return NULL;
+ }
+}
+
+
+int avro_raw_map_get_or_create(avro_raw_map_t *map, const char *key,
+ void **element, size_t *index)
+{
+ st_data_t data;
+ void *el;
+ unsigned int i;
+ int is_new;
+
+ if (st_lookup(map->indices_by_key, (st_data_t) key, &data)) {
+ i = (unsigned int) data;
+ void *raw_entry =
+ (map->elements.data + map->elements.element_size * i);
+ el = raw_entry + sizeof(avro_raw_map_entry_t);
+ is_new = 0;
+ } else {
+ i = map->elements.element_count;
+ avro_raw_map_entry_t *raw_entry =
+ avro_raw_array_append(&map->elements);
+ raw_entry->key = avro_strdup(key);
+ st_insert(map->indices_by_key,
+ (st_data_t) raw_entry->key, (st_data_t) i);
+ if (!raw_entry) {
+ return -ENOMEM;
+ }
+ el = ((void *) raw_entry) + sizeof(avro_raw_map_entry_t);
+ is_new = 1;
+ }
+
+ if (element) {
+ *element = el;
+ }
+ if (index) {
+ *index = i;
+ }
+ return is_new;
+}
Added: avro/trunk/lang/c/src/memoize.c
URL: http://svn.apache.org/viewvc/avro/trunk/lang/c/src/memoize.c?rev=1146546&view=auto
==============================================================================
--- avro/trunk/lang/c/src/memoize.c (added)
+++ avro/trunk/lang/c/src/memoize.c Thu Jul 14 02:35:04 2011
@@ -0,0 +1,165 @@
+/*
+ * 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 <string.h>
+
+#include "avro/data.h"
+#include "avro/allocation.h"
+#include "avro/errors.h"
+#include "avro_private.h"
+#include "st.h"
+
+
+typedef struct avro_memoize_key {
+ void *key1;
+ void *key2;
+} avro_memoize_key_t;
+
+
+static int
+avro_memoize_key_cmp(avro_memoize_key_t *a, avro_memoize_key_t *b)
+{
+ /*
+ * This isn't a proper cmp operation, since it always returns 1
+ * if the keys are different. But that's okay for the hash
+ * table implementation we're using.
+ */
+
+ return (a->key1 != b->key1) || (a->key2 != b->key2);
+}
+
+
+static int
+avro_memoize_key_hash(avro_memoize_key_t *a)
+{
+ return ((uintptr_t) a->key1) ^ ((uintptr_t) a->key2);
+}
+
+
+static struct st_hash_type avro_memoize_hash_type = {
+ avro_memoize_key_cmp,
+ avro_memoize_key_hash
+};
+
+
+void
+avro_memoize_init(avro_memoize_t *mem)
+{
+ memset(mem, 0, sizeof(avro_memoize_t));
+ mem->cache = st_init_table(&avro_memoize_hash_type);
+}
+
+
+static int
+avro_memoize_free_key(avro_memoize_key_t *key, void *result, void *dummy)
+{
+ AVRO_UNUSED(result);
+ AVRO_UNUSED(dummy);
+ avro_freet(avro_memoize_key_t, key);
+ return ST_CONTINUE;
+}
+
+
+void
+avro_memoize_done(avro_memoize_t *mem)
+{
+ st_foreach(mem->cache, avro_memoize_free_key, 0);
+ st_free_table(mem->cache);
+ memset(mem, 0, sizeof(avro_memoize_t));
+}
+
+
+int
+avro_memoize_get(avro_memoize_t *mem,
+ void *key1, void *key2,
+ void **result)
+{
+ avro_memoize_key_t key;
+ key.key1 = key1;
+ key.key2 = key2;
+
+ union {
+ st_data_t data;
+ void *value;
+ } val;
+
+ if (st_lookup(mem->cache, (st_data_t) &key, &val.data)) {
+ if (result) {
+ *result = val.value;
+ }
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+
+void
+avro_memoize_set(avro_memoize_t *mem,
+ void *key1, void *key2,
+ void *result)
+{
+ /*
+ * First see if there's already a cached value for this key. If
+ * so, we don't want to allocate a new avro_memoize_key_t
+ * instance.
+ */
+
+ avro_memoize_key_t key;
+ key.key1 = key1;
+ key.key2 = key2;
+
+ union {
+ st_data_t data;
+ void *value;
+ } val;
+
+ if (st_lookup(mem->cache, (st_data_t) &key, &val.data)) {
+ st_insert(mem->cache, (st_data_t) &key, (st_data_t) result);
+ return;
+ }
+
+ /*
+ * If it's a new key pair, then we do need to allocate.
+ */
+
+ avro_memoize_key_t *real_key = avro_new(avro_memoize_key_t);
+ real_key->key1 = key1;
+ real_key->key2 = key2;
+
+ st_insert(mem->cache, (st_data_t) real_key, (st_data_t) result);
+}
+
+
+void
+avro_memoize_delete(avro_memoize_t *mem, void *key1, void *key2)
+{
+ avro_memoize_key_t key;
+ key.key1 = key1;
+ key.key2 = key2;
+
+ union {
+ st_data_t data;
+ avro_memoize_key_t *key;
+ } real_key;
+
+ real_key.key = &key;
+ if (st_delete(mem->cache, &real_key.data, NULL)) {
+ avro_freet(avro_memoize_key_t, real_key.key);
+ }
+}