avro-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From mas...@apache.org
Subject svn commit: r899870 [7/8] - in /hadoop/avro/trunk: ./ lang/c/ lang/c/datatypes/ lang/c/docs/ lang/c/io/ lang/c/jansson/ lang/c/jansson/doc/ lang/c/jansson/doc/ext/ lang/c/jansson/src/ lang/c/jansson/test/ lang/c/jansson/test/testdata/ lang/c/jansson/te...
Date Sat, 16 Jan 2010 01:52:29 GMT
Added: hadoop/avro/trunk/lang/c/src/encoding.h
URL: http://svn.apache.org/viewvc/hadoop/avro/trunk/lang/c/src/encoding.h?rev=899870&view=auto
==============================================================================
--- hadoop/avro/trunk/lang/c/src/encoding.h (added)
+++ hadoop/avro/trunk/lang/c/src/encoding.h Sat Jan 16 01:52:24 2010
@@ -0,0 +1,72 @@
+/*
+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_ENCODING_H
+#define AVRO_ENCODING_H
+#include "avro.h"
+
+/* TODO: this will need more functions when JSON encoding is added */
+struct avro_encoding_t
+{
+  const char *description;
+  /* string */
+  int (*read_string) (avro_reader_t reader, char **s);
+  int (*skip_string) (avro_reader_t reader);
+  int (*write_string) (avro_writer_t writer, const char *s);
+  /* bytes */
+  int (*read_bytes) (avro_reader_t reader, char **bytes, int64_t * len);
+  int (*skip_bytes) (avro_reader_t reader);
+  int (*write_bytes) (avro_writer_t writer, const char *bytes,
+		      const int64_t len);
+  /* int */
+  int (*read_int) (avro_reader_t reader, int32_t * i);
+  int (*skip_int) (avro_reader_t reader);
+  int (*write_int) (avro_writer_t writer, const int32_t i);
+  /* long */
+  int (*read_long) (avro_reader_t reader, int64_t * l);
+  int (*skip_long) (avro_reader_t reader);
+  int (*write_long) (avro_writer_t writer, const int64_t l);
+  /* float */
+  int (*read_float) (avro_reader_t reader, float *f);
+  int (*skip_float) (avro_reader_t reader);
+  int (*write_float) (avro_writer_t writer, const float f);
+  /* double */
+  int (*read_double) (avro_reader_t reader, double *d);
+  int (*skip_double) (avro_reader_t reader);
+  int (*write_double) (avro_writer_t writer, const double d);
+  /* boolean */
+  int (*read_boolean) (avro_reader_t reader, int8_t * b);
+  int (*skip_boolean) (avro_reader_t reader);
+  int (*write_boolean) (avro_writer_t writer, const int8_t b);
+  /* null */
+  int (*read_null) (avro_reader_t reader);
+  int (*skip_null) (avro_reader_t reader);
+  int (*write_null) (avro_writer_t writer);
+};
+typedef struct avro_encoding_t avro_encoding_t;
+
+#define AVRO_WRITE(writer, buf, len) \
+{ int rval = avro_write( writer, buf, len ); if(rval) return rval; }
+#define AVRO_READ(reader, buf, len)  \
+{ int rval = avro_read( reader, buf, len ); if(rval) return rval; }
+#define AVRO_SKIP(reader, len) \
+{ int rval = avro_skip( reader, len); if (rval) return rval; }
+
+extern const avro_encoding_t avro_binary_encoding;	/* in encoding_binary */
+
+#endif

Added: hadoop/avro/trunk/lang/c/src/encoding_binary.c
URL: http://svn.apache.org/viewvc/hadoop/avro/trunk/lang/c/src/encoding_binary.c?rev=899870&view=auto
==============================================================================
--- hadoop/avro/trunk/lang/c/src/encoding_binary.c (added)
+++ hadoop/avro/trunk/lang/c/src/encoding_binary.c Sat Jan 16 01:52:24 2010
@@ -0,0 +1,363 @@
+/*
+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 "encoding.h"
+#include <stdlib.h>
+#include <limits.h>
+#include <errno.h>
+#include <string.h>
+
+#define MAX_VARINT_BUF_SIZE 10
+
+static int
+read_long (avro_reader_t reader, int64_t * l)
+{
+  uint64_t n = 0;
+  uint8_t b;
+  int offset = 0;
+  do
+    {
+      if (offset == MAX_VARINT_BUF_SIZE)
+	{
+	  /* illegal byte sequence */
+	  return EILSEQ;
+	}
+      AVRO_READ (reader, &b, 1);
+      n |= (int64_t) (b & 0x7F) << (7 * offset);
+      ++offset;
+    }
+  while (b & 0x80);
+  *l = (n >> 1) ^ -(n & 1);
+  return 0;
+}
+
+static int
+skip_long (avro_reader_t reader)
+{
+  uint8_t b;
+  int offset = 0;
+  do
+    {
+      if (offset == MAX_VARINT_BUF_SIZE)
+	{
+	  return EILSEQ;
+	}
+      AVRO_READ (reader, &b, 1);
+      ++offset;
+    }
+  while (b & 0x80);
+  return 0;
+}
+
+static int
+write_long (avro_writer_t writer, int64_t l)
+{
+  uint8_t b;
+  uint64_t n = (l << 1) ^ (l >> 63);
+  while ((n & ~0x7F) != 0)
+    {
+      b = ((((uint8_t) n) & 0x7F) | 0x80);
+      AVRO_WRITE (writer, &b, 1);
+      n >>= 7;
+    }
+  b = (uint8_t) n;
+  AVRO_WRITE (writer, &b, 1);
+  return 0;
+}
+
+static int
+read_int (avro_reader_t reader, int32_t * i)
+{
+  int64_t l;
+  int rval = read_long (reader, &l);
+  if (rval)
+    {
+      return rval;
+    }
+  if (!(INT_MIN <= l && l <= INT_MAX))
+    {
+      return ERANGE;
+    }
+  *i = l;
+  return 0;
+}
+
+static int
+skip_int (avro_reader_t reader)
+{
+  return skip_long (reader);
+}
+
+static int
+write_int (avro_writer_t writer, const int32_t i)
+{
+  int64_t l = i;
+  return write_long (writer, l);
+}
+
+static int
+read_bytes (avro_reader_t reader, char **bytes, int64_t * len)
+{
+  int rval = read_long (reader, len);
+  if (rval)
+    {
+      return rval;
+    }
+  *bytes = malloc (*len + 1);
+  if (!*bytes)
+    {
+      return ENOMEM;
+    }
+  *bytes[*len] = '\0';
+  AVRO_READ (reader, *bytes, *len);
+  return 0;
+}
+
+static int
+skip_bytes (avro_reader_t reader)
+{
+  int64_t len;
+  int rval = read_long (reader, &len);
+  if (rval)
+    {
+      return rval;
+    }
+  AVRO_SKIP (reader, len);
+  return 0;
+}
+
+static int
+write_bytes (avro_writer_t writer, const char *bytes, const int64_t len)
+{
+  if (len < 0)
+    {
+      return EINVAL;
+    }
+  AVRO_WRITE (writer, (char *) bytes, len);
+  return 0;
+}
+
+static int
+read_string (avro_reader_t reader, char **s)
+{
+  int64_t len;
+  return read_bytes (reader, s, &len);
+}
+
+static int
+skip_string (avro_reader_t reader)
+{
+  return skip_bytes (reader);
+}
+
+static int
+write_string (avro_writer_t writer, const char *s)
+{
+  int64_t len = strlen (s);
+  return write_bytes (writer, s, len);
+}
+
+static int
+read_float (avro_reader_t reader, float *f)
+{
+#if WORDS_BIGENDIAN
+  uint8_t buf[4];
+#endif
+  union
+  {
+    float f;
+    int32_t i;
+  } v;
+#if WORDS_BIGENDIAN
+  AVRO_READ (avro, buf, 4);
+  v.i = ((int32_t) buf[0] << 0)
+    | ((int32_t) buf[1] << 8)
+    | ((int32_t) buf[2] << 16) | ((int32_t) buf[3] << 24);
+#else
+  AVRO_READ (reader, (void *) &v.i, 4);
+#endif
+  *f = v.f;
+  return 0;
+}
+
+static int
+skip_float (avro_reader_t reader)
+{
+  AVRO_SKIP (reader, 4);
+  return 0;
+}
+
+static int
+write_float (avro_writer_t writer, const float f)
+{
+#if WORDS_BIGENDIAN
+  uint8_t buf[4];
+#endif
+  union
+  {
+    float f;
+    int32_t i;
+  } v;
+
+  v.f = f;
+#if WORDS_BIGENDIAN
+  buf[0] = (uint8_t) (v.i >> 0);
+  buf[1] = (uint8_t) (v.i >> 8);
+  buf[2] = (uint8_t) (v.i >> 16);
+  buf[3] = (uint8_t) (v.i >> 24);
+  AVRO_WRITE (writer, buf, 4);
+#else
+  AVRO_WRITE (writer, (void *) &v.i, 4);
+#endif
+  return 0;
+}
+
+static int
+read_double (avro_reader_t reader, double *d)
+{
+#if WORDS_BIGENDIAN
+  uint8_t buf[8];
+#endif
+  union
+  {
+    double d;
+    int64_t l;
+  } v;
+
+#if WORDS_BIGENDIAN
+  AVRO_READ (avro, buf, 8);
+  v.l = ((int64_t) buf[0] << 0)
+    | ((int64_t) buf[1] << 8)
+    | ((int64_t) buf[2] << 16)
+    | ((int64_t) buf[3] << 24)
+    | ((int64_t) buf[4] << 32)
+    | ((int64_t) buf[5] << 40)
+    | ((int64_t) buf[6] << 48) | ((int64_t) buf[7] << 56);
+#else
+  AVRO_READ (reader, (void *) &v.l, 8);
+#endif
+  *d = v.d;
+  return 0;
+}
+
+static int
+skip_double (avro_reader_t reader)
+{
+  AVRO_SKIP (reader, 8);
+  return 0;
+}
+
+static int
+write_double (avro_writer_t writer, const double d)
+{
+#if WORDS_BIGENDIAN
+  uint8_t buf[8];
+#endif
+  union
+  {
+    double d;
+    int64_t l;
+  } v;
+
+  v.d = d;
+#if WORDS_BIGENDIAN
+  buf[0] = (uint8_t) (v.l >> 0);
+  buf[1] = (uint8_t) (v.l >> 8);
+  buf[2] = (uint8_t) (v.l >> 16);
+  buf[3] = (uint8_t) (v.l >> 24);
+  buf[4] = (uint8_t) (v.l >> 32);
+  buf[5] = (uint8_t) (v.l >> 40);
+  buf[6] = (uint8_t) (v.l >> 48);
+  buf[7] = (uint8_t) (v.l >> 56);
+  AVRO_WRITE (writer, buf, 8);
+#else
+  AVRO_WRITE (writer, (void *) &v.l, 8);
+#endif
+  return 0;
+}
+
+static int
+read_boolean (avro_reader_t reader, int8_t * b)
+{
+  AVRO_READ (reader, b, 1);
+  return 0;
+}
+
+static int
+skip_boolean (avro_reader_t reader)
+{
+  AVRO_SKIP (reader, 1);
+  return 0;
+}
+
+static int
+write_boolean (avro_writer_t writer, const int8_t b)
+{
+  AVRO_WRITE (writer, (char *) &b, 1);
+  return 0;
+}
+
+static int
+read_skip_null (avro_reader_t reader)
+{
+  /* no-op */
+  return 0;
+}
+
+static int
+write_null (avro_writer_t writer)
+{
+  /* no-op */
+  return 0;
+}
+
+const avro_encoding_t avro_binary_encoding = {
+  .description = "BINARY FORMAT",
+  /* string */
+  .read_string = read_string,
+  .skip_string = skip_string,
+  .write_string = write_string,
+  /* bytes */
+  .read_bytes = read_bytes,
+  .skip_bytes = skip_bytes,
+  .write_bytes = write_bytes,
+  /* int */
+  .read_int = read_int,
+  .skip_int = skip_int,
+  .write_int = write_int,
+  /* long */
+  .read_long = read_long,
+  .skip_long = skip_long,
+  .write_long = write_long,
+  /* float */
+  .read_float = read_float,
+  .skip_float = skip_float,
+  .write_float = write_float,
+  /* double */
+  .read_double = read_double,
+  .skip_double = skip_double,
+  .write_double = write_double,
+  /* boolean */
+  .read_boolean = read_boolean,
+  .skip_boolean = skip_boolean,
+  .write_boolean = write_boolean,
+  /* null */
+  .read_null = read_skip_null,
+  .skip_null = read_skip_null,
+  .write_null = write_null
+};

Added: hadoop/avro/trunk/lang/c/src/io.c
URL: http://svn.apache.org/viewvc/hadoop/avro/trunk/lang/c/src/io.c?rev=899870&view=auto
==============================================================================
--- hadoop/avro/trunk/lang/c/src/io.c (added)
+++ hadoop/avro/trunk/lang/c/src/io.c Sat Jan 16 01:52:24 2010
@@ -0,0 +1,267 @@
+/*
+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 <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <errno.h>
+#include <string.h>
+#include "avro.h"
+#include "container_of.h"
+
+enum avro_io_type_t
+{
+  AVRO_FILE_IO,
+  AVRO_MEMORY_IO
+};
+typedef enum avro_io_type_t avro_io_type_t;
+
+struct avro_reader_t
+{
+  avro_io_type_t type;
+  unsigned long refcount;
+};
+
+struct avro_writer_t
+{
+  avro_io_type_t type;
+  unsigned long refcount;
+};
+
+struct avro_file_reader_t
+{
+  struct avro_reader_t reader;
+  FILE *fp;
+};
+
+struct avro_file_writer_t
+{
+  struct avro_writer_t writer;
+  FILE *fp;
+};
+
+struct avro_memory_reader_t
+{
+  struct avro_reader_t reader;
+  const char *buf;
+  int64_t len;
+  int64_t read;
+};
+
+struct avro_memory_writer_t
+{
+  struct avro_writer_t writer;
+  const char *buf;
+  int64_t len;
+  int64_t written;
+};
+
+#define avro_io_typeof(obj)      ((obj)->type)
+#define is_memory_io(obj)        (obj && avro_io_typeof(obj) == AVRO_MEMORY_IO)
+#define is_file_io(obj)          (obj && avro_io_typeof(obj) == AVRO_FILE_IO)
+
+#define avro_reader_to_memory(reader_)  container_of(reader_, struct avro_memory_reader_t, reader)
+#define avro_reader_to_file(reader_)    container_of(reader_, struct avro_file_reader_t, reader)
+#define avro_writer_to_memory(writer_)  container_of(writer_, struct avro_memory_writer_t, writer)
+#define avro_writer_to_file(writer_)    container_of(writer_, struct avro_file_writer_t, writer)
+
+static void
+reader_init (avro_reader_t reader, avro_io_type_t type)
+{
+  reader->type = type;
+  reader->refcount = 1;
+}
+
+static void
+writer_init (avro_writer_t writer, avro_io_type_t type)
+{
+  writer->type = type;
+  writer->refcount = 1;
+}
+
+avro_reader_t
+avro_reader_file (FILE * fp)
+{
+  struct avro_file_reader_t *file_reader =
+    malloc (sizeof (struct avro_file_reader_t));
+  if (!file_reader)
+    {
+      return NULL;
+    }
+  file_reader->fp = fp;
+  reader_init (&file_reader->reader, AVRO_FILE_IO);
+  return &file_reader->reader;
+}
+
+avro_writer_t
+avro_writer_file (FILE * fp)
+{
+  struct avro_file_writer_t *file_writer =
+    malloc (sizeof (struct avro_file_writer_t));
+  if (!file_writer)
+    {
+      return NULL;
+    }
+  file_writer->fp = fp;
+  writer_init (&file_writer->writer, AVRO_FILE_IO);
+  return &file_writer->writer;
+}
+
+avro_reader_t
+avro_reader_memory (const char *buf, size_t len)
+{
+  struct avro_memory_reader_t *mem_reader =
+    malloc (sizeof (struct avro_memory_reader_t));
+  if (!mem_reader)
+    {
+      return NULL;
+    }
+  mem_reader->buf = buf;
+  mem_reader->len = len;
+  mem_reader->read = 0;
+  reader_init (&mem_reader->reader, AVRO_MEMORY_IO);
+  return &mem_reader->reader;
+}
+
+avro_writer_t
+avro_writer_memory (const char *buf, size_t len)
+{
+  struct avro_memory_writer_t *mem_writer =
+    malloc (sizeof (struct avro_memory_writer_t));
+  if (!mem_writer)
+    {
+      return NULL;
+    }
+  mem_writer->buf = buf;
+  mem_writer->len = len;
+  mem_writer->written = 0;
+  writer_init (&mem_writer->writer, AVRO_MEMORY_IO);
+  return &mem_writer->writer;
+}
+
+static int
+avro_read_memory (struct avro_memory_reader_t *reader, void *buf, int64_t len)
+{
+  if (len)
+    {
+      if ((reader->len - reader->read) < len)
+	{
+	  return ENOSPC;
+	}
+      memcpy (buf, reader->buf + reader->read, len);
+      reader->read += len;
+    }
+  return 0;
+}
+
+static int
+avro_read_file (struct avro_file_reader_t *reader, void *buf, int64_t len)
+{
+  /* TODO */
+  return -1;
+}
+
+int
+avro_read (avro_reader_t reader, void *buf, int64_t len)
+{
+  if (buf && len >= 0)
+    {
+      if (is_memory_io (reader))
+	{
+	  return avro_read_memory (avro_reader_to_memory (reader), buf, len);
+	}
+      else if (is_file_io (reader))
+	{
+	  return avro_read_file (avro_reader_to_file (reader), buf, len);
+	}
+    }
+  return EINVAL;
+}
+
+static int
+avro_write_memory (struct avro_memory_writer_t *writer, void *buf,
+		   int64_t len)
+{
+  if (len)
+    {
+      if ((writer->len - writer->written) < len)
+	{
+	  return ENOSPC;
+	}
+      memcpy ((void *) (writer->buf + writer->written), buf, len);
+      writer->written += len;
+    }
+  return 0;
+}
+
+static int
+avro_write_file (struct avro_file_writer_t *writer, void *buf, int64_t len)
+{
+  /* TODO */
+  return -1;
+}
+
+int
+avro_write (avro_writer_t writer, void *buf, int64_t len)
+{
+  if (buf && len >= 0)
+    {
+      if (is_memory_io (writer))
+	{
+	  return avro_write_memory (avro_writer_to_memory (writer), buf, len);
+	}
+      else if (is_memory_io (writer))
+	{
+	  return avro_write_file (avro_writer_to_file (writer), buf, len);
+	}
+    }
+  return EINVAL;
+}
+
+int
+avro_skip (avro_reader_t reader, int64_t len)
+{
+  /* TODO */
+  return -1;
+}
+
+void
+avro_reader_free (avro_reader_t reader)
+{
+  if (is_memory_io (reader))
+    {
+      free (avro_reader_to_memory (reader));
+    }
+  else if (is_file_io (reader))
+    {
+      free (avro_reader_to_file (reader));
+    }
+}
+
+void
+avro_writer_free (avro_writer_t writer)
+{
+  if (is_memory_io (writer))
+    {
+      free (avro_writer_to_memory (writer));
+    }
+  else if (is_file_io (writer))
+    {
+      free (avro_writer_to_file (writer));
+    }
+}

Added: hadoop/avro/trunk/lang/c/src/queue.h
URL: http://svn.apache.org/viewvc/hadoop/avro/trunk/lang/c/src/queue.h?rev=899870&view=auto
==============================================================================
--- hadoop/avro/trunk/lang/c/src/queue.h (added)
+++ hadoop/avro/trunk/lang/c/src/queue.h Sat Jan 16 01:52:24 2010
@@ -0,0 +1,557 @@
+/*
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)queue.h	8.5 (Berkeley) 8/20/94
+ */
+
+#ifndef	_SYS_QUEUE_H_
+#define	_SYS_QUEUE_H_
+
+/*
+ * This file defines five types of data structures: singly-linked lists,
+ * lists, simple queues, tail queues, and circular queues.
+ *
+ * A singly-linked list is headed by a single forward pointer. The
+ * elements are singly linked for minimum space and pointer manipulation
+ * overhead at the expense of O(n) removal for arbitrary elements. New
+ * elements can be added to the list after an existing element or at the
+ * head of the list.  Elements being removed from the head of the list
+ * should use the explicit macro for this purpose for optimum
+ * efficiency. A singly-linked list may only be traversed in the forward
+ * direction.  Singly-linked lists are ideal for applications with large
+ * datasets and few or no removals or for implementing a LIFO queue.
+ *
+ * A list is headed by a single forward pointer (or an array of forward
+ * pointers for a hash table header). The elements are doubly linked
+ * so that an arbitrary element can be removed without a need to
+ * traverse the list. New elements can be added to the list before
+ * or after an existing element or at the head of the list. A list
+ * may only be traversed in the forward direction.
+ *
+ * A simple queue is headed by a pair of pointers, one the head of the
+ * list and the other to the tail of the list. The elements are singly
+ * linked to save space, so elements can only be removed from the
+ * head of the list. New elements can be added to the list after
+ * an existing element, at the head of the list, or at the end of the
+ * list. A simple queue may only be traversed in the forward direction.
+ *
+ * A tail queue is headed by a pair of pointers, one to the head of the
+ * list and the other to the tail of the list. The elements are doubly
+ * linked so that an arbitrary element can be removed without a need to
+ * traverse the list. New elements can be added to the list before or
+ * after an existing element, at the head of the list, or at the end of
+ * the list. A tail queue may be traversed in either direction.
+ *
+ * A circle queue is headed by a pair of pointers, one to the head of the
+ * list and the other to the tail of the list. The elements are doubly
+ * linked so that an arbitrary element can be removed without a need to
+ * traverse the list. New elements can be added to the list before or after
+ * an existing element, at the head of the list, or at the end of the list.
+ * A circle queue may be traversed in either direction, but has a more
+ * complex end of list detection.
+ *
+ * For details on the use of these macros, see the queue(3) manual page.
+ */
+
+/*
+ * List definitions.
+ */
+#define	LIST_HEAD(name, type)						\
+struct name {								\
+	struct type *lh_first;	/* first element */			\
+}
+
+#define	LIST_HEAD_INITIALIZER(head)					\
+	{ NULL }
+
+#define	LIST_ENTRY(type)						\
+struct {								\
+	struct type *le_next;	/* next element */			\
+	struct type **le_prev;	/* address of previous next element */	\
+}
+
+/*
+ * List functions.
+ */
+#define	LIST_INIT(head) do {						\
+	(head)->lh_first = NULL;					\
+} while (/*CONSTCOND*/0)
+
+#define	LIST_INSERT_AFTER(listelm, elm, field) do {			\
+	if (((elm)->field.le_next = (listelm)->field.le_next) != NULL)	\
+		(listelm)->field.le_next->field.le_prev =		\
+		    &(elm)->field.le_next;				\
+	(listelm)->field.le_next = (elm);				\
+	(elm)->field.le_prev = &(listelm)->field.le_next;		\
+} while (/*CONSTCOND*/0)
+
+#define	LIST_INSERT_BEFORE(listelm, elm, field) do {			\
+	(elm)->field.le_prev = (listelm)->field.le_prev;		\
+	(elm)->field.le_next = (listelm);				\
+	*(listelm)->field.le_prev = (elm);				\
+	(listelm)->field.le_prev = &(elm)->field.le_next;		\
+} while (/*CONSTCOND*/0)
+
+#define	LIST_INSERT_HEAD(head, elm, field) do {				\
+	if (((elm)->field.le_next = (head)->lh_first) != NULL)		\
+		(head)->lh_first->field.le_prev = &(elm)->field.le_next;\
+	(head)->lh_first = (elm);					\
+	(elm)->field.le_prev = &(head)->lh_first;			\
+} while (/*CONSTCOND*/0)
+
+#define	LIST_REMOVE(elm, field) do {					\
+	if ((elm)->field.le_next != NULL)				\
+		(elm)->field.le_next->field.le_prev = 			\
+		    (elm)->field.le_prev;				\
+	*(elm)->field.le_prev = (elm)->field.le_next;			\
+} while (/*CONSTCOND*/0)
+
+#define	LIST_FOREACH(var, head, field)					\
+	for ((var) = ((head)->lh_first);				\
+		(var);							\
+		(var) = ((var)->field.le_next))
+
+/*
+ * List access methods.
+ */
+#define	LIST_EMPTY(head)		((head)->lh_first == NULL)
+#define	LIST_FIRST(head)		((head)->lh_first)
+#define	LIST_NEXT(elm, field)		((elm)->field.le_next)
+
+
+/*
+ * Singly-linked List definitions.
+ */
+#define	SLIST_HEAD(name, type)						\
+struct name {								\
+	struct type *slh_first;	/* first element */			\
+}
+
+#define	SLIST_HEAD_INITIALIZER(head)					\
+	{ NULL }
+
+#define	SLIST_ENTRY(type)						\
+struct {								\
+	struct type *sle_next;	/* next element */			\
+}
+
+/*
+ * Singly-linked List functions.
+ */
+#define	SLIST_INIT(head) do {						\
+	(head)->slh_first = NULL;					\
+} while (/*CONSTCOND*/0)
+
+#define	SLIST_INSERT_AFTER(slistelm, elm, field) do {			\
+	(elm)->field.sle_next = (slistelm)->field.sle_next;		\
+	(slistelm)->field.sle_next = (elm);				\
+} while (/*CONSTCOND*/0)
+
+#define	SLIST_INSERT_HEAD(head, elm, field) do {			\
+	(elm)->field.sle_next = (head)->slh_first;			\
+	(head)->slh_first = (elm);					\
+} while (/*CONSTCOND*/0)
+
+#define	SLIST_REMOVE_HEAD(head, field) do {				\
+	(head)->slh_first = (head)->slh_first->field.sle_next;		\
+} while (/*CONSTCOND*/0)
+
+#define	SLIST_REMOVE(head, elm, type, field) do {			\
+	if ((head)->slh_first == (elm)) {				\
+		SLIST_REMOVE_HEAD((head), field);			\
+	}								\
+	else {								\
+		struct type *curelm = (head)->slh_first;		\
+		while(curelm->field.sle_next != (elm))			\
+			curelm = curelm->field.sle_next;		\
+		curelm->field.sle_next =				\
+		    curelm->field.sle_next->field.sle_next;		\
+	}								\
+} while (/*CONSTCOND*/0)
+
+#define	SLIST_FOREACH(var, head, field)					\
+	for((var) = (head)->slh_first; (var); (var) = (var)->field.sle_next)
+
+/*
+ * Singly-linked List access methods.
+ */
+#define	SLIST_EMPTY(head)	((head)->slh_first == NULL)
+#define	SLIST_FIRST(head)	((head)->slh_first)
+#define	SLIST_NEXT(elm, field)	((elm)->field.sle_next)
+
+
+/*
+ * Singly-linked Tail queue declarations.
+ */
+#define	STAILQ_HEAD(name, type)					\
+struct name {								\
+	struct type *stqh_first;	/* first element */			\
+	struct type **stqh_last;	/* addr of last next element */		\
+}
+
+#define	STAILQ_HEAD_INITIALIZER(head)					\
+	{ NULL, &(head).stqh_first }
+
+#define	STAILQ_ENTRY(type)						\
+struct {								\
+	struct type *stqe_next;	/* next element */			\
+}
+
+/*
+ * Singly-linked Tail queue functions.
+ */
+#define	STAILQ_INIT(head) do {						\
+	(head)->stqh_first = NULL;					\
+	(head)->stqh_last = &(head)->stqh_first;				\
+} while (/*CONSTCOND*/0)
+
+#define	STAILQ_INSERT_HEAD(head, elm, field) do {			\
+	if (((elm)->field.stqe_next = (head)->stqh_first) == NULL)	\
+		(head)->stqh_last = &(elm)->field.stqe_next;		\
+	(head)->stqh_first = (elm);					\
+} while (/*CONSTCOND*/0)
+
+#define	STAILQ_INSERT_TAIL(head, elm, field) do {			\
+	(elm)->field.stqe_next = NULL;					\
+	*(head)->stqh_last = (elm);					\
+	(head)->stqh_last = &(elm)->field.stqe_next;			\
+} while (/*CONSTCOND*/0)
+
+#define	STAILQ_INSERT_AFTER(head, listelm, elm, field) do {		\
+	if (((elm)->field.stqe_next = (listelm)->field.stqe_next) == NULL)\
+		(head)->stqh_last = &(elm)->field.stqe_next;		\
+	(listelm)->field.stqe_next = (elm);				\
+} while (/*CONSTCOND*/0)
+
+#define	STAILQ_REMOVE_HEAD(head, field) do {				\
+	if (((head)->stqh_first = (head)->stqh_first->field.stqe_next) == NULL) \
+		(head)->stqh_last = &(head)->stqh_first;			\
+} while (/*CONSTCOND*/0)
+
+#define	STAILQ_REMOVE(head, elm, type, field) do {			\
+	if ((head)->stqh_first == (elm)) {				\
+		STAILQ_REMOVE_HEAD((head), field);			\
+	} else {							\
+		struct type *curelm = (head)->stqh_first;		\
+		while (curelm->field.stqe_next != (elm))			\
+			curelm = curelm->field.stqe_next;		\
+		if ((curelm->field.stqe_next =				\
+			curelm->field.stqe_next->field.stqe_next) == NULL) \
+			    (head)->stqh_last = &(curelm)->field.stqe_next; \
+	}								\
+} while (/*CONSTCOND*/0)
+
+#define	STAILQ_FOREACH(var, head, field)				\
+	for ((var) = ((head)->stqh_first);				\
+		(var);							\
+		(var) = ((var)->field.stqe_next))
+
+/*
+ * Singly-linked Tail queue access methods.
+ */
+#define	STAILQ_EMPTY(head)	((head)->stqh_first == NULL)
+#define	STAILQ_FIRST(head)	((head)->stqh_first)
+#define	STAILQ_NEXT(elm, field)	((elm)->field.stqe_next)
+
+
+/*
+ * Simple queue definitions.
+ */
+#define	SIMPLEQ_HEAD(name, type)					\
+struct name {								\
+	struct type *sqh_first;	/* first element */			\
+	struct type **sqh_last;	/* addr of last next element */		\
+}
+
+#define	SIMPLEQ_HEAD_INITIALIZER(head)					\
+	{ NULL, &(head).sqh_first }
+
+#define	SIMPLEQ_ENTRY(type)						\
+struct {								\
+	struct type *sqe_next;	/* next element */			\
+}
+
+/*
+ * Simple queue functions.
+ */
+#define	SIMPLEQ_INIT(head) do {						\
+	(head)->sqh_first = NULL;					\
+	(head)->sqh_last = &(head)->sqh_first;				\
+} while (/*CONSTCOND*/0)
+
+#define	SIMPLEQ_INSERT_HEAD(head, elm, field) do {			\
+	if (((elm)->field.sqe_next = (head)->sqh_first) == NULL)	\
+		(head)->sqh_last = &(elm)->field.sqe_next;		\
+	(head)->sqh_first = (elm);					\
+} while (/*CONSTCOND*/0)
+
+#define	SIMPLEQ_INSERT_TAIL(head, elm, field) do {			\
+	(elm)->field.sqe_next = NULL;					\
+	*(head)->sqh_last = (elm);					\
+	(head)->sqh_last = &(elm)->field.sqe_next;			\
+} while (/*CONSTCOND*/0)
+
+#define	SIMPLEQ_INSERT_AFTER(head, listelm, elm, field) do {		\
+	if (((elm)->field.sqe_next = (listelm)->field.sqe_next) == NULL)\
+		(head)->sqh_last = &(elm)->field.sqe_next;		\
+	(listelm)->field.sqe_next = (elm);				\
+} while (/*CONSTCOND*/0)
+
+#define	SIMPLEQ_REMOVE_HEAD(head, field) do {				\
+	if (((head)->sqh_first = (head)->sqh_first->field.sqe_next) == NULL) \
+		(head)->sqh_last = &(head)->sqh_first;			\
+} while (/*CONSTCOND*/0)
+
+#define	SIMPLEQ_REMOVE(head, elm, type, field) do {			\
+	if ((head)->sqh_first == (elm)) {				\
+		SIMPLEQ_REMOVE_HEAD((head), field);			\
+	} else {							\
+		struct type *curelm = (head)->sqh_first;		\
+		while (curelm->field.sqe_next != (elm))			\
+			curelm = curelm->field.sqe_next;		\
+		if ((curelm->field.sqe_next =				\
+			curelm->field.sqe_next->field.sqe_next) == NULL) \
+			    (head)->sqh_last = &(curelm)->field.sqe_next; \
+	}								\
+} while (/*CONSTCOND*/0)
+
+#define	SIMPLEQ_FOREACH(var, head, field)				\
+	for ((var) = ((head)->sqh_first);				\
+		(var);							\
+		(var) = ((var)->field.sqe_next))
+
+/*
+ * Simple queue access methods.
+ */
+#define	SIMPLEQ_EMPTY(head)		((head)->sqh_first == NULL)
+#define	SIMPLEQ_FIRST(head)		((head)->sqh_first)
+#define	SIMPLEQ_NEXT(elm, field)	((elm)->field.sqe_next)
+
+
+/*
+ * Tail queue definitions.
+ */
+#define	_TAILQ_HEAD(name, type, qual)					\
+struct name {								\
+	qual type *tqh_first;		/* first element */		\
+	qual type *qual *tqh_last;	/* addr of last next element */	\
+}
+#define TAILQ_HEAD(name, type)	_TAILQ_HEAD(name, struct type,)
+
+#define	TAILQ_HEAD_INITIALIZER(head)					\
+	{ NULL, &(head).tqh_first }
+
+#define	_TAILQ_ENTRY(type, qual)					\
+struct {								\
+	qual type *tqe_next;		/* next element */		\
+	qual type *qual *tqe_prev;	/* address of previous next element */\
+}
+#define TAILQ_ENTRY(type)	_TAILQ_ENTRY(struct type,)
+
+/*
+ * Tail queue functions.
+ */
+#define	TAILQ_INIT(head) do {						\
+	(head)->tqh_first = NULL;					\
+	(head)->tqh_last = &(head)->tqh_first;				\
+} while (/*CONSTCOND*/0)
+
+#define	TAILQ_INSERT_HEAD(head, elm, field) do {			\
+	if (((elm)->field.tqe_next = (head)->tqh_first) != NULL)	\
+		(head)->tqh_first->field.tqe_prev =			\
+		    &(elm)->field.tqe_next;				\
+	else								\
+		(head)->tqh_last = &(elm)->field.tqe_next;		\
+	(head)->tqh_first = (elm);					\
+	(elm)->field.tqe_prev = &(head)->tqh_first;			\
+} while (/*CONSTCOND*/0)
+
+#define	TAILQ_INSERT_TAIL(head, elm, field) do {			\
+	(elm)->field.tqe_next = NULL;					\
+	(elm)->field.tqe_prev = (head)->tqh_last;			\
+	*(head)->tqh_last = (elm);					\
+	(head)->tqh_last = &(elm)->field.tqe_next;			\
+} while (/*CONSTCOND*/0)
+
+#define	TAILQ_INSERT_AFTER(head, listelm, elm, field) do {		\
+	if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != NULL)\
+		(elm)->field.tqe_next->field.tqe_prev = 		\
+		    &(elm)->field.tqe_next;				\
+	else								\
+		(head)->tqh_last = &(elm)->field.tqe_next;		\
+	(listelm)->field.tqe_next = (elm);				\
+	(elm)->field.tqe_prev = &(listelm)->field.tqe_next;		\
+} while (/*CONSTCOND*/0)
+
+#define	TAILQ_INSERT_BEFORE(listelm, elm, field) do {			\
+	(elm)->field.tqe_prev = (listelm)->field.tqe_prev;		\
+	(elm)->field.tqe_next = (listelm);				\
+	*(listelm)->field.tqe_prev = (elm);				\
+	(listelm)->field.tqe_prev = &(elm)->field.tqe_next;		\
+} while (/*CONSTCOND*/0)
+
+#define	TAILQ_REMOVE(head, elm, field) do {				\
+	if (((elm)->field.tqe_next) != NULL)				\
+		(elm)->field.tqe_next->field.tqe_prev = 		\
+		    (elm)->field.tqe_prev;				\
+	else								\
+		(head)->tqh_last = (elm)->field.tqe_prev;		\
+	*(elm)->field.tqe_prev = (elm)->field.tqe_next;			\
+} while (/*CONSTCOND*/0)
+
+#define	TAILQ_FOREACH(var, head, field)					\
+	for ((var) = ((head)->tqh_first);				\
+		(var);							\
+		(var) = ((var)->field.tqe_next))
+
+#define	TAILQ_FOREACH_REVERSE(var, head, headname, field)		\
+	for ((var) = (*(((struct headname *)((head)->tqh_last))->tqh_last));	\
+		(var);							\
+		(var) = (*(((struct headname *)((var)->field.tqe_prev))->tqh_last)))
+
+/*
+ * Tail queue access methods.
+ */
+#define	TAILQ_EMPTY(head)		((head)->tqh_first == NULL)
+#define	TAILQ_FIRST(head)		((head)->tqh_first)
+#define	TAILQ_NEXT(elm, field)		((elm)->field.tqe_next)
+
+#define	TAILQ_LAST(head, headname) \
+	(*(((struct headname *)((head)->tqh_last))->tqh_last))
+#define	TAILQ_PREV(elm, headname, field) \
+	(*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
+
+
+/*
+ * Circular queue definitions.
+ */
+#define	CIRCLEQ_HEAD(name, type)					\
+struct name {								\
+	struct type *cqh_first;		/* first element */		\
+	struct type *cqh_last;		/* last element */		\
+}
+
+#define	CIRCLEQ_HEAD_INITIALIZER(head)					\
+	{ (void *)&head, (void *)&head }
+
+#define	CIRCLEQ_ENTRY(type)						\
+struct {								\
+	struct type *cqe_next;		/* next element */		\
+	struct type *cqe_prev;		/* previous element */		\
+}
+
+/*
+ * Circular queue functions.
+ */
+#define	CIRCLEQ_INIT(head) do {						\
+	(head)->cqh_first = (void *)(head);				\
+	(head)->cqh_last = (void *)(head);				\
+} while (/*CONSTCOND*/0)
+
+#define	CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) do {		\
+	(elm)->field.cqe_next = (listelm)->field.cqe_next;		\
+	(elm)->field.cqe_prev = (listelm);				\
+	if ((listelm)->field.cqe_next == (void *)(head))		\
+		(head)->cqh_last = (elm);				\
+	else								\
+		(listelm)->field.cqe_next->field.cqe_prev = (elm);	\
+	(listelm)->field.cqe_next = (elm);				\
+} while (/*CONSTCOND*/0)
+
+#define	CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) do {		\
+	(elm)->field.cqe_next = (listelm);				\
+	(elm)->field.cqe_prev = (listelm)->field.cqe_prev;		\
+	if ((listelm)->field.cqe_prev == (void *)(head))		\
+		(head)->cqh_first = (elm);				\
+	else								\
+		(listelm)->field.cqe_prev->field.cqe_next = (elm);	\
+	(listelm)->field.cqe_prev = (elm);				\
+} while (/*CONSTCOND*/0)
+
+#define	CIRCLEQ_INSERT_HEAD(head, elm, field) do {			\
+	(elm)->field.cqe_next = (head)->cqh_first;			\
+	(elm)->field.cqe_prev = (void *)(head);				\
+	if ((head)->cqh_last == (void *)(head))				\
+		(head)->cqh_last = (elm);				\
+	else								\
+		(head)->cqh_first->field.cqe_prev = (elm);		\
+	(head)->cqh_first = (elm);					\
+} while (/*CONSTCOND*/0)
+
+#define	CIRCLEQ_INSERT_TAIL(head, elm, field) do {			\
+	(elm)->field.cqe_next = (void *)(head);				\
+	(elm)->field.cqe_prev = (head)->cqh_last;			\
+	if ((head)->cqh_first == (void *)(head))			\
+		(head)->cqh_first = (elm);				\
+	else								\
+		(head)->cqh_last->field.cqe_next = (elm);		\
+	(head)->cqh_last = (elm);					\
+} while (/*CONSTCOND*/0)
+
+#define	CIRCLEQ_REMOVE(head, elm, field) do {				\
+	if ((elm)->field.cqe_next == (void *)(head))			\
+		(head)->cqh_last = (elm)->field.cqe_prev;		\
+	else								\
+		(elm)->field.cqe_next->field.cqe_prev =			\
+		    (elm)->field.cqe_prev;				\
+	if ((elm)->field.cqe_prev == (void *)(head))			\
+		(head)->cqh_first = (elm)->field.cqe_next;		\
+	else								\
+		(elm)->field.cqe_prev->field.cqe_next =			\
+		    (elm)->field.cqe_next;				\
+} while (/*CONSTCOND*/0)
+
+#define	CIRCLEQ_FOREACH(var, head, field)				\
+	for ((var) = ((head)->cqh_first);				\
+		(var) != (const void *)(head);				\
+		(var) = ((var)->field.cqe_next))
+
+#define	CIRCLEQ_FOREACH_REVERSE(var, head, field)			\
+	for ((var) = ((head)->cqh_last);				\
+		(var) != (const void *)(head);				\
+		(var) = ((var)->field.cqe_prev))
+
+/*
+ * Circular queue access methods.
+ */
+#define	CIRCLEQ_EMPTY(head)		((head)->cqh_first == (void *)(head))
+#define	CIRCLEQ_FIRST(head)		((head)->cqh_first)
+#define	CIRCLEQ_LAST(head)		((head)->cqh_last)
+#define	CIRCLEQ_NEXT(elm, field)	((elm)->field.cqe_next)
+#define	CIRCLEQ_PREV(elm, field)	((elm)->field.cqe_prev)
+
+#define CIRCLEQ_LOOP_NEXT(head, elm, field)				\
+	(((elm)->field.cqe_next == (void *)(head))			\
+	    ? ((head)->cqh_first)					\
+	    : (elm->field.cqe_next))
+#define CIRCLEQ_LOOP_PREV(head, elm, field)				\
+	(((elm)->field.cqe_prev == (void *)(head))			\
+	    ? ((head)->cqh_last)					\
+	    : (elm->field.cqe_prev))
+
+#endif /* sys/queue.h */

Added: hadoop/avro/trunk/lang/c/src/schema.c
URL: http://svn.apache.org/viewvc/hadoop/avro/trunk/lang/c/src/schema.c?rev=899870&view=auto
==============================================================================
--- hadoop/avro/trunk/lang/c/src/schema.c (added)
+++ hadoop/avro/trunk/lang/c/src/schema.c Sat Jan 16 01:52:24 2010
@@ -0,0 +1,907 @@
+/*
+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 <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <ctype.h>
+
+#include "avro.h"
+#include "jansson.h"
+#include "st.h"
+#include "schema.h"
+
+struct avro_schema_error_t
+{
+  st_table *named_schemas;
+  json_error_t json_error;
+};
+
+static void
+avro_schema_init (avro_schema_t schema, avro_type_t type)
+{
+  schema->type = type;
+  schema->class_type = AVRO_SCHEMA;
+  schema->refcount = 1;
+}
+
+static int
+is_avro_id (const char *name)
+{
+  size_t i, len;
+  if (name)
+    {
+      len = strlen (name);
+      if (len < 1)
+	{
+	  return 0;
+	}
+      for (i = 0; i < len; i++)
+	{
+	  if (!
+	      (isalpha (name[i]) || name[i] == '_'
+	       || (i && isdigit (name[i]))))
+	    {
+	      return 0;
+	    }
+	}
+      /* starts with [A-Za-z_] subsequent [A-Za-z0-9_] */
+      return 1;
+    }
+  return 0;
+}
+
+/* TODO */
+void
+avro_schema_free (avro_schema_t schema)
+{
+  return;
+}
+
+avro_schema_t
+avro_schema_string (void)
+{
+  static struct avro_obj_t obj = {
+    .type = AVRO_STRING,
+    .class_type = AVRO_SCHEMA,
+    .refcount = 1
+  };
+  return &obj;
+}
+
+avro_schema_t
+avro_schema_bytes (void)
+{
+  static struct avro_obj_t obj = {
+    .type = AVRO_BYTES,
+    .class_type = AVRO_SCHEMA,
+    .refcount = 1
+  };
+  return &obj;
+}
+
+avro_schema_t
+avro_schema_int (void)
+{
+  static struct avro_obj_t obj = {
+    .type = AVRO_INT,
+    .class_type = AVRO_SCHEMA,
+    .refcount = 1
+  };
+  return &obj;
+}
+
+avro_schema_t
+avro_schema_long (void)
+{
+  static struct avro_obj_t obj = {
+    .type = AVRO_LONG,
+    .class_type = AVRO_SCHEMA,
+    .refcount = 1
+  };
+  return &obj;
+}
+
+avro_schema_t
+avro_schema_float (void)
+{
+  static struct avro_obj_t obj = {
+    .type = AVRO_FLOAT,
+    .class_type = AVRO_SCHEMA,
+    .refcount = 1
+  };
+  return &obj;
+}
+
+avro_schema_t
+avro_schema_double (void)
+{
+  static struct avro_obj_t obj = {
+    .type = AVRO_DOUBLE,
+    .class_type = AVRO_SCHEMA,
+    .refcount = 1
+  };
+  return &obj;
+}
+
+avro_schema_t
+avro_schema_boolean (void)
+{
+  static struct avro_obj_t obj = {
+    .type = AVRO_BOOLEAN,
+    .class_type = AVRO_SCHEMA,
+    .refcount = 1
+  };
+  return &obj;
+}
+
+avro_schema_t
+avro_schema_null (void)
+{
+  static struct avro_obj_t obj = {
+    .type = AVRO_NULL,
+    .class_type = AVRO_SCHEMA,
+    .refcount = 1
+  };
+  return &obj;
+}
+
+avro_schema_t
+avro_schema_fixed (const char *name, const size_t size)
+{
+  struct schema_fixed_t *fixed = malloc (sizeof (struct schema_fixed_t));
+  if (!fixed)
+    {
+      return NULL;
+    }
+  if (!is_avro_id (name))
+    {
+      return NULL;
+    }
+  fixed->name = strdup (name);
+  fixed->size = size;
+  avro_schema_init (&fixed->obj, AVRO_FIXED);
+  return &fixed->obj;
+}
+
+avro_schema_t
+avro_schema_union (void)
+{
+  struct schema_union_t *unionp = malloc (sizeof (struct schema_union_t));
+  if (!unionp)
+    {
+      return NULL;
+    }
+  TAILQ_INIT (&unionp->schemas);
+  avro_schema_init (&unionp->obj, AVRO_UNION);
+  return &unionp->obj;
+}
+
+int
+avro_schema_union_append (const avro_schema_t union_schema,
+			  const avro_schema_t schema)
+{
+  struct schema_union_t *unionp;
+  struct union_schema_t *s;
+
+  if (!union_schema || !schema || !is_avro_union (union_schema))
+    {
+      return EINVAL;
+    }
+  unionp = avro_schema_to_union (union_schema);
+  s = malloc (sizeof (struct union_schema_t));
+  if (!s)
+    {
+      return ENOMEM;
+    }
+  s->schema = schema;
+  TAILQ_INSERT_TAIL (&unionp->schemas, s, schemas);
+  return 0;
+}
+
+avro_schema_t
+avro_schema_array (const avro_schema_t items)
+{
+  struct schema_array_t *array = malloc (sizeof (struct schema_array_t));
+  if (!array)
+    {
+      return NULL;
+    }
+  array->items = avro_schema_incref (items);
+  avro_schema_init (&array->obj, AVRO_ARRAY);
+  return &array->obj;
+}
+
+avro_schema_t
+avro_schema_map (const avro_schema_t values)
+{
+  struct schema_map_t *map = malloc (sizeof (struct schema_map_t));
+  if (!map)
+    {
+      return NULL;
+    }
+  map->values = avro_schema_incref (values);
+  avro_schema_init (&map->obj, AVRO_MAP);
+  return &map->obj;
+}
+
+avro_schema_t
+avro_schema_enum (const char *name)
+{
+  struct schema_enum_t *enump = malloc (sizeof (struct schema_enum_t));
+  if (!enump)
+    {
+      return NULL;
+    }
+  if (!is_avro_id (name))
+    {
+      return NULL;
+    }
+  enump->name = strdup (name);
+  if (!enump->name)
+    {
+      return NULL;
+    }
+  TAILQ_INIT (&enump->symbols);
+  avro_schema_init (&enump->obj, AVRO_ENUM);
+  return &enump->obj;
+}
+
+int
+avro_schema_enum_symbol_append (const avro_schema_t enum_schema,
+				const char *symbol)
+{
+  struct schema_enum_t *enump;
+  struct enum_symbol_t *enum_symbol;
+  if (!enum_schema || !symbol || !is_avro_enum (enum_schema))
+    {
+      return EINVAL;
+    }
+  enump = avro_schema_to_enum (enum_schema);
+  enum_symbol = malloc (sizeof (struct enum_symbol_t));
+  if (!enum_symbol)
+    {
+      return ENOMEM;
+    }
+  enum_symbol->symbol = strdup (symbol);
+  TAILQ_INSERT_TAIL (&enump->symbols, enum_symbol, symbols);
+  return 0;
+}
+
+int
+avro_schema_record_field_append (const avro_schema_t record_schema,
+				 const char *field_name,
+				 const avro_schema_t field_schema)
+{
+  struct schema_record_t *record;
+  struct record_field_t *new_field;
+  if (!record_schema || !field_name || !field_schema
+      || !is_avro_record (record_schema) || record_schema == field_schema
+      || !is_avro_id (field_name))
+    {
+      return EINVAL;
+    }
+  record = avro_schema_to_record (record_schema);
+  new_field = malloc (sizeof (struct record_field_t));
+  if (!new_field)
+    {
+      return ENOMEM;
+    }
+  new_field->name = strdup (field_name);
+  new_field->type = avro_schema_incref (field_schema);
+  TAILQ_INSERT_TAIL (&record->fields, new_field, fields);
+  return 0;
+}
+
+avro_schema_t
+avro_schema_record (const char *name)
+{
+  struct schema_record_t *record = malloc (sizeof (struct schema_record_t));
+  if (!record)
+    {
+      return NULL;
+    }
+  if (!is_avro_id (name))
+    {
+      return NULL;
+    }
+  record->name = strdup (name);
+  TAILQ_INIT (&record->fields);
+  avro_schema_init (&record->obj, AVRO_RECORD);
+  return &record->obj;
+}
+
+static int
+save_named_schemas (const char *name, avro_schema_t schema,
+		    avro_schema_error_t * error)
+{
+  st_table *st = (*error)->named_schemas;
+  return st_insert (st, (st_data_t) name, (st_data_t) schema);
+}
+
+static avro_schema_t
+find_named_schemas (const char *name, avro_schema_error_t * error)
+{
+  st_table *st = (*error)->named_schemas;
+  avro_schema_t schema;
+  if (st_lookup (st, (st_data_t) name, (st_data_t *) & schema))
+    {
+      return schema;
+    }
+  return NULL;
+};
+
+avro_schema_t
+avro_schema_link (avro_schema_t to)
+{
+  struct schema_link_t *link;
+  if (!is_avro_named_type (to))
+    {
+      return NULL;
+    }
+  link = malloc (sizeof (struct schema_link_t));
+  if (!link)
+    {
+      return NULL;
+    }
+  link->to = avro_schema_incref (to);
+  avro_schema_init (&link->obj, AVRO_LINK);
+  return &link->obj;
+}
+
+static int
+avro_type_from_json_t (json_t * json, avro_type_t * type,
+		       avro_schema_error_t * error,
+		       avro_schema_t * named_type)
+{
+  json_t *json_type;
+  const char *type_str;
+
+  if (json_is_array (json))
+    {
+      *type = AVRO_UNION;
+      return 0;
+    }
+  else if (json_is_object (json))
+    {
+      json_type = json_object_get (json, "type");
+    }
+  else
+    {
+      json_type = json;
+    }
+  if (!json_is_string (json_type))
+    {
+      return EINVAL;
+    }
+  type_str = json_string_value (json_type);
+  if (!type_str)
+    {
+      return EINVAL;
+    }
+  /* TODO: gperf/re2c this */
+  if (strcmp (type_str, "string") == 0)
+    {
+      *type = AVRO_STRING;
+    }
+  else if (strcmp (type_str, "bytes") == 0)
+    {
+      *type = AVRO_BYTES;
+    }
+  else if (strcmp (type_str, "int") == 0)
+    {
+      *type = AVRO_INT;
+    }
+  else if (strcmp (type_str, "long") == 0)
+    {
+      *type = AVRO_LONG;
+    }
+  else if (strcmp (type_str, "float") == 0)
+    {
+      *type = AVRO_FLOAT;
+    }
+  else if (strcmp (type_str, "double") == 0)
+    {
+      *type = AVRO_DOUBLE;
+    }
+  else if (strcmp (type_str, "boolean") == 0)
+    {
+      *type = AVRO_BOOLEAN;
+    }
+  else if (strcmp (type_str, "null") == 0)
+    {
+      *type = AVRO_NULL;
+    }
+  else if (strcmp (type_str, "record") == 0)
+    {
+      *type = AVRO_RECORD;
+    }
+  else if (strcmp (type_str, "enum") == 0)
+    {
+      *type = AVRO_ENUM;
+    }
+  else if (strcmp (type_str, "array") == 0)
+    {
+      *type = AVRO_ARRAY;
+    }
+  else if (strcmp (type_str, "map") == 0)
+    {
+      *type = AVRO_MAP;
+    }
+  else if (strcmp (type_str, "fixed") == 0)
+    {
+      *type = AVRO_FIXED;
+    }
+  else if ((*named_type = find_named_schemas (type_str, error)))
+    {
+      *type = AVRO_LINK;
+    }
+  else
+    {
+      return EINVAL;
+    }
+  return 0;
+}
+
+static int
+avro_schema_from_json_t (json_t * json, avro_schema_t * schema,
+			 avro_schema_error_t * error)
+{
+  avro_type_t type = 0;
+  unsigned int i;
+  avro_schema_t named_schemas = NULL;
+
+  if (avro_type_from_json_t (json, &type, error, &named_schemas))
+    {
+      return EINVAL;
+    }
+
+  switch (type)
+    {
+    case AVRO_LINK:
+      *schema = avro_schema_link (named_schemas);
+      break;
+
+    case AVRO_STRING:
+      *schema = avro_schema_string ();
+      break;
+
+    case AVRO_BYTES:
+      *schema = avro_schema_bytes ();
+      break;
+
+    case AVRO_INT:
+      *schema = avro_schema_int ();
+      break;
+
+    case AVRO_LONG:
+      *schema = avro_schema_long ();
+      break;
+
+    case AVRO_FLOAT:
+      *schema = avro_schema_float ();
+      break;
+
+    case AVRO_DOUBLE:
+      *schema = avro_schema_double ();
+      break;
+
+    case AVRO_BOOLEAN:
+      *schema = avro_schema_boolean ();
+      break;
+
+    case AVRO_NULL:
+      *schema = avro_schema_null ();
+      break;
+
+    case AVRO_RECORD:
+      {
+	json_t *json_name = json_object_get (json, "name");
+	json_t *json_fields = json_object_get (json, "fields");
+	unsigned int num_fields;
+	const char *record_name;
+
+	if (!json_is_string (json_name))
+	  {
+	    return EINVAL;
+	  }
+	if (!json_is_array (json_fields))
+	  {
+	    return EINVAL;
+	  }
+	num_fields = json_array_size (json_fields);
+	if (num_fields == 0)
+	  {
+	    return EINVAL;
+	  }
+	record_name = json_string_value (json_name);
+	if (!record_name)
+	  {
+	    return EINVAL;
+	  }
+	*schema = avro_schema_record (record_name);
+	if (save_named_schemas (record_name, *schema, error))
+	  {
+	    return ENOMEM;
+	  }
+	for (i = 0; i < num_fields; i++)
+	  {
+	    json_t *json_field = json_array_get (json_fields, i);
+	    json_t *json_field_name;
+	    json_t *json_field_type;
+	    avro_schema_t json_field_type_schema;
+	    int field_rval;
+
+	    if (!json_is_object (json_field))
+	      {
+		avro_schema_decref (*schema);
+		return EINVAL;
+	      }
+	    json_field_name = json_object_get (json_field, "name");
+	    if (!json_field_name)
+	      {
+		avro_schema_decref (*schema);
+		return EINVAL;
+	      }
+	    json_field_type = json_object_get (json_field, "type");
+	    if (!json_field_type)
+	      {
+		avro_schema_decref (*schema);
+		return EINVAL;
+	      }
+	    field_rval =
+	      avro_schema_from_json_t (json_field_type,
+				       &json_field_type_schema, error);
+	    if (field_rval)
+	      {
+		avro_schema_decref (*schema);
+		return field_rval;
+	      }
+	    field_rval =
+	      avro_schema_record_field_append (*schema,
+					       json_string_value
+					       (json_field_name),
+					       json_field_type_schema);
+	    if (field_rval != 0)
+	      {
+		avro_schema_decref (*schema);
+		return field_rval;
+	      }
+	  }
+      }
+      break;
+
+    case AVRO_ENUM:
+      {
+	json_t *json_name = json_object_get (json, "name");
+	json_t *json_symbols = json_object_get (json, "symbols");
+	const char *name;
+	unsigned int num_symbols;
+
+	if (!json_is_string (json_name))
+	  {
+	    return EINVAL;
+	  }
+	if (!json_is_array (json_symbols))
+	  {
+	    return EINVAL;
+	  }
+
+	name = json_string_value (json_name);
+	if (!name)
+	  {
+	    return EINVAL;
+	  }
+	num_symbols = json_array_size (json_symbols);
+	if (num_symbols == 0)
+	  {
+	    return EINVAL;
+	  }
+	*schema = avro_schema_enum (name);
+	if (save_named_schemas (name, *schema, error))
+	  {
+	    return ENOMEM;
+	  }
+	for (i = 0; i < num_symbols; i++)
+	  {
+	    int enum_rval;
+	    json_t *json_symbol = json_array_get (json_symbols, i);
+	    const char *symbol;
+	    if (!json_is_string (json_symbol))
+	      {
+		avro_schema_decref (*schema);
+		return EINVAL;
+	      }
+	    symbol = json_string_value (json_symbol);
+	    enum_rval = avro_schema_enum_symbol_append (*schema, symbol);
+	    if (enum_rval != 0)
+	      {
+		avro_schema_decref (*schema);
+		return enum_rval;
+	      }
+	  }
+      }
+      break;
+
+    case AVRO_ARRAY:
+      {
+	int items_rval;
+	json_t *json_items = json_object_get (json, "items");
+	avro_schema_t items_schema;
+	if (!json_items)
+	  {
+	    return EINVAL;
+	  }
+	items_rval =
+	  avro_schema_from_json_t (json_items, &items_schema, error);
+	if (items_rval)
+	  {
+	    return items_rval;
+	  }
+	*schema = avro_schema_array (items_schema);
+      }
+      break;
+
+    case AVRO_MAP:
+      {
+	int values_rval;
+	json_t *json_values = json_object_get (json, "values");
+	avro_schema_t values_schema;
+
+	if (!json_values)
+	  {
+	    return EINVAL;
+	  }
+	values_rval =
+	  avro_schema_from_json_t (json_values, &values_schema, error);
+	if (values_rval)
+	  {
+	    return values_rval;
+	  }
+	*schema = avro_schema_map (values_schema);
+      }
+      break;
+
+    case AVRO_UNION:
+      {
+	unsigned int num_schemas = json_array_size (json);
+	avro_schema_t s;
+	if (num_schemas == 0)
+	  {
+	    return EINVAL;
+	  }
+	*schema = avro_schema_union ();
+	for (i = 0; i < num_schemas; i++)
+	  {
+	    int schema_rval;
+	    json_t *schema_json = json_array_get (json, i);
+	    if (!schema_json)
+	      {
+		return EINVAL;
+	      }
+	    schema_rval = avro_schema_from_json_t (schema_json, &s, error);
+	    if (schema_rval != 0)
+	      {
+		avro_schema_decref (*schema);
+		return schema_rval;
+	      }
+	    schema_rval = avro_schema_union_append (*schema, s);
+	    if (schema_rval != 0)
+	      {
+		avro_schema_decref (*schema);
+		return schema_rval;
+	      }
+	  }
+      }
+      break;
+
+    case AVRO_FIXED:
+      {
+	json_t *json_size = json_object_get (json, "size");
+	json_t *json_name = json_object_get (json, "name");
+	int size;
+	const char *name;
+	if (!json_is_integer (json_size))
+	  {
+	    return EINVAL;
+	  }
+	if (!json_is_string (json_name))
+	  {
+	    return EINVAL;
+	  }
+	size = json_integer_value (json_size);
+	name = json_string_value (json_name);
+	*schema = avro_schema_fixed (name, size);
+	if (save_named_schemas (name, *schema, error))
+	  {
+	    return ENOMEM;
+	  }
+      }
+      break;
+
+    default:
+      return EINVAL;
+    }
+  return 0;
+}
+
+int
+avro_schema_from_json (const char *jsontext, size_t len,
+		       avro_schema_t * schema, avro_schema_error_t * e)
+{
+  json_t *root;
+  int rval = 0;
+  struct avro_schema_error_t *error;
+
+  if (!jsontext || !schema)
+    {
+      return EINVAL;
+    }
+
+  error = malloc (sizeof (struct avro_schema_error_t));
+  if (!error)
+    {
+      return ENOMEM;
+    }
+  *e = error;
+
+  error->named_schemas = st_init_strtable ();
+  if (!error->named_schemas)
+    {
+      free (error);
+      return ENOMEM;
+    }
+
+  root = json_loads (jsontext, &error->json_error);
+  if (!root)
+    {
+      return EINVAL;
+    }
+
+  /*json_dumpf(root, stderr, 0); */
+  rval = avro_schema_from_json_t (root, schema, e);
+  json_decref (root);
+  return rval;
+}
+
+avro_schema_t
+avro_schema_copy (avro_schema_t schema)
+{
+  avro_schema_t new_schema = NULL;
+  if (!schema)
+    {
+      return NULL;
+    }
+  switch (avro_typeof (schema))
+    {
+    case AVRO_STRING:
+    case AVRO_BYTES:
+    case AVRO_INT:
+    case AVRO_LONG:
+    case AVRO_FLOAT:
+    case AVRO_DOUBLE:
+    case AVRO_BOOLEAN:
+    case AVRO_NULL:
+      /* No need to copy primitives since they're static */
+      new_schema = schema;
+      break;
+    case AVRO_RECORD:
+      {
+	struct schema_record_t *record_schema =
+	  avro_schema_to_record (schema);
+	struct record_field_t *field;
+	new_schema = avro_schema_record (record_schema->name);
+	for (field = TAILQ_FIRST (&record_schema->fields);
+	     field != NULL; field = TAILQ_NEXT (field, fields))
+	  {
+	    avro_schema_t field_copy = avro_schema_copy (field->type);
+	    if (!field_copy)
+	      {
+		avro_schema_decref (new_schema);
+		return NULL;
+	      }
+	    if (avro_schema_record_field_append
+		(new_schema, field->name, field_copy))
+	      {
+		avro_schema_decref (new_schema);
+		return NULL;
+	      }
+	  }
+      }
+      break;
+    case AVRO_ENUM:
+      {
+	struct schema_enum_t *enum_schema = avro_schema_to_enum (schema);
+	new_schema = avro_schema_enum (enum_schema->name);
+	struct enum_symbol_t *enum_symbol;
+	for (enum_symbol = TAILQ_FIRST (&enum_schema->symbols);
+	     enum_symbol != NULL;
+	     enum_symbol = TAILQ_NEXT (enum_symbol, symbols))
+	  {
+	    if (avro_schema_enum_symbol_append
+		(new_schema, enum_symbol->symbol))
+	      {
+		avro_schema_decref (new_schema);
+		return NULL;
+	      }
+	  }
+      }
+      break;
+    case AVRO_FIXED:
+      {
+	struct schema_fixed_t *fixed_schema = avro_schema_to_fixed (schema);
+	new_schema =
+	  avro_schema_fixed (fixed_schema->name, fixed_schema->size);
+      }
+      break;
+    case AVRO_MAP:
+      {
+	struct schema_map_t *map_schema = avro_schema_to_map (schema);
+	avro_schema_t values_copy = avro_schema_copy (map_schema->values);
+	if (!values_copy)
+	  {
+	    return NULL;
+	  }
+	new_schema = avro_schema_map (values_copy);
+      }
+      break;
+    case AVRO_ARRAY:
+      {
+	struct schema_array_t *array_schema = avro_schema_to_array (schema);
+	avro_schema_t items_copy = avro_schema_copy (array_schema->items);
+	if (!items_copy)
+	  {
+	    return NULL;
+	  }
+	new_schema = avro_schema_array (items_copy);
+      }
+      break;
+    case AVRO_UNION:
+      {
+	struct schema_union_t *union_schema = avro_schema_to_union (schema);
+	struct union_schema_t *s;
+
+	new_schema = avro_schema_union ();
+
+	for (s = TAILQ_FIRST (&union_schema->schemas);
+	     s != NULL; s = TAILQ_NEXT (s, schemas))
+	  {
+	    avro_schema_t schema_copy = avro_schema_copy (s->schema);
+	    if (avro_schema_union_append (new_schema, schema_copy))
+	      {
+		avro_schema_decref (new_schema);
+		return NULL;
+	      }
+	  }
+      }
+      break;
+
+    case AVRO_LINK:
+      {
+	struct schema_link_t *link_schema = avro_schema_to_link (schema);
+	/* TODO: use an avro_schema_copy of to instead of pointing to the same reference */
+	avro_schema_incref (link_schema->to);
+	new_schema = avro_schema_link (link_schema->to);
+      }
+      break;
+
+    default:
+      return NULL;
+    }
+  return new_schema;
+}

Added: hadoop/avro/trunk/lang/c/src/schema.h
URL: http://svn.apache.org/viewvc/hadoop/avro/trunk/lang/c/src/schema.h?rev=899870&view=auto
==============================================================================
--- hadoop/avro/trunk/lang/c/src/schema.h (added)
+++ hadoop/avro/trunk/lang/c/src/schema.h Sat Jan 16 01:52:24 2010
@@ -0,0 +1,122 @@
+/*
+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
+
+#include "avro.h"
+#include "container_of.h"
+#include "queue.h"
+
+struct record_field_t
+{
+  char *name;
+  avro_schema_t type;
+  /* TODO: default */
+    TAILQ_ENTRY (record_field_t) fields;
+};
+
+struct schema_record_t
+{
+  struct avro_obj_t obj;
+  char *name;
+    TAILQ_HEAD (fields, record_field_t) fields;
+};
+
+struct enum_symbol_t
+{
+  char *symbol;
+    TAILQ_ENTRY (enum_symbol_t) symbols;
+};
+
+struct schema_enum_t
+{
+  struct avro_obj_t obj;
+  char *name;
+    TAILQ_HEAD (symbols, enum_symbol_t) symbols;
+};
+
+struct schema_array_t
+{
+  struct avro_obj_t obj;
+  avro_schema_t items;
+};
+
+struct schema_map_t
+{
+  struct avro_obj_t obj;
+  avro_schema_t values;
+};
+
+struct union_schema_t
+{
+  avro_schema_t schema;
+    TAILQ_ENTRY (union_schema_t) schemas;
+};
+
+struct schema_union_t
+{
+  struct avro_obj_t obj;
+    TAILQ_HEAD (schemas, union_schema_t) schemas;
+};
+
+struct schema_fixed_t
+{
+  struct avro_obj_t obj;
+  const char *name;
+  size_t size;
+};
+
+struct schema_link_t
+{
+  struct avro_obj_t obj;
+  avro_schema_t to;
+};
+
+#define avro_schema_to_record(schema_)  container_of(schema_, struct schema_record_t, obj)
+#define avro_schema_to_enum(schema_)    container_of(schema_, struct schema_enum_t, obj)
+#define avro_schema_to_array(schema_)   container_of(schema_, struct schema_array_t, obj)
+#define avro_schema_to_map(schema_)     container_of(schema_, struct schema_map_t, obj)
+#define avro_schema_to_union(schema_)   container_of(schema_, struct schema_union_t, obj)
+#define avro_schema_to_fixed(schema_)   container_of(schema_, struct schema_fixed_t, obj)
+#define avro_schema_to_link(schema_)    container_of(schema_, struct schema_link_t, obj)
+
+static inline avro_schema_t
+avro_schema_incref (avro_schema_t schema)
+{
+  if (schema && schema->refcount != (unsigned int) -1)
+    {
+      ++schema->refcount;
+    }
+  return schema;
+}
+
+void avro_schema_free (avro_schema_t schema);
+
+static inline void
+avro_schema_decref (avro_schema_t schema)
+{
+  if (schema && schema->refcount != (unsigned int) -1
+      && --schema->refcount == 0)
+    {
+      avro_schema_free (schema);
+    }
+}
+
+
+#endif

Added: hadoop/avro/trunk/lang/c/src/schema_equal.c
URL: http://svn.apache.org/viewvc/hadoop/avro/trunk/lang/c/src/schema_equal.c?rev=899870&view=auto
==============================================================================
--- hadoop/avro/trunk/lang/c/src/schema_equal.c (added)
+++ hadoop/avro/trunk/lang/c/src/schema_equal.c Sat Jan 16 01:52:24 2010
@@ -0,0 +1,196 @@
+/*
+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 "schema.h"
+#include <string.h>
+
+static int
+schema_record_equal (struct schema_record_t *a, struct schema_record_t *b)
+{
+  struct record_field_t *field_a, *field_b;
+  if (strcmp (a->name, b->name))
+    {
+      /* They have different names */
+      return 0;
+    }
+
+  for (field_a = TAILQ_FIRST (&a->fields),
+       field_b = TAILQ_FIRST (&b->fields);
+       !(field_a == NULL && field_b == NULL);
+       field_a = TAILQ_NEXT (field_a, fields),
+       field_b = TAILQ_NEXT (field_b, fields))
+    {
+      if (field_a == NULL || field_b == NULL)
+	{
+	  return 0;		/* different num fields */
+	}
+      if (strcmp (field_a->name, field_b->name))
+	{
+	  /* They have fields with different names */
+	  return 0;
+	}
+      if (!avro_schema_equal (field_a->type, field_b->type))
+	{
+	  /* They have fields with different schemas */
+	  return 0;
+	}
+    }
+  return 1;
+}
+
+static int
+schema_enum_equal (struct schema_enum_t *a, struct schema_enum_t *b)
+{
+  struct enum_symbol_t *sym_a, *sym_b;
+
+  if (strcmp (a->name, b->name))
+    {
+      /* They have different names */
+      return 0;
+    }
+  for (sym_a = TAILQ_FIRST (&a->symbols),
+       sym_b = TAILQ_FIRST (&b->symbols);
+       !(sym_a == NULL && sym_b == NULL);
+       sym_a = TAILQ_NEXT (sym_a, symbols),
+       sym_b = TAILQ_NEXT (sym_b, symbols))
+    {
+      if (sym_a == NULL || sym_b == NULL)
+	{
+	  return 0;		/* different num symbols */
+	}
+      if (strcmp (sym_a->symbol, sym_b->symbol))
+	{
+	  /* They have different symbol names */
+	  return 0;
+	}
+    }
+  return 1;
+}
+
+static int
+schema_fixed_equal (struct schema_fixed_t *a, struct schema_fixed_t *b)
+{
+  if (strcmp (a->name, b->name))
+    {
+      /* They have different names */
+      return 0;
+    }
+  return (a->size == b->size);
+}
+
+static int
+schema_map_equal (struct schema_map_t *a, struct schema_map_t *b)
+{
+  return avro_schema_equal (a->values, b->values);
+}
+
+static int
+schema_array_equal (struct schema_array_t *a, struct schema_array_t *b)
+{
+  return avro_schema_equal (a->items, b->items);
+}
+
+static int
+schema_union_equal (struct schema_union_t *a, struct schema_union_t *b)
+{
+  struct union_schema_t *schema_a, *schema_b;
+
+  for (schema_a = TAILQ_FIRST (&a->schemas),
+       schema_b = TAILQ_FIRST (&b->schemas);
+       !(schema_a == NULL && schema_b == NULL);
+       schema_a = TAILQ_NEXT (schema_a, schemas),
+       schema_b = TAILQ_NEXT (schema_b, schemas))
+    {
+      if (schema_a == NULL || schema_b == NULL)
+	{
+	  return 0;		/* different num symbols */
+	}
+      if (!avro_schema_equal (schema_a->schema, schema_b->schema))
+	{
+	  /* They don't have the same schema types */
+	  return 0;
+	}
+    }
+  return 1;
+}
+
+static int
+schema_link_equal (struct schema_link_t *a, struct schema_link_t *b)
+{
+  /* NOTE: links can only be used for named types. They are used
+     in recursive schemas so we just check the name of the 
+     schema pointed to instead of a deep check.  Otherwise, we
+     recurse forever... */
+  return (strcmp (avro_schema_name (a->to), avro_schema_name (b->to)) == 0);
+}
+
+int
+avro_schema_equal (avro_schema_t a, avro_schema_t b)
+{
+  if (!a || !b)
+    {
+      /* this is an error. protecting from segfault. */
+      return 0;
+    }
+  else if (a == b)
+    {
+      /* an object is equal to itself */
+      return 1;
+    }
+  else if (avro_typeof (a) != avro_typeof (b))
+    {
+      return 0;
+    }
+  else if (is_avro_record (a))
+    {
+      return schema_record_equal (avro_schema_to_record (a),
+				  avro_schema_to_record (b));
+    }
+  else if (is_avro_enum (a))
+    {
+      return schema_enum_equal (avro_schema_to_enum (a),
+				avro_schema_to_enum (b));
+    }
+  else if (is_avro_fixed (a))
+    {
+      return schema_fixed_equal (avro_schema_to_fixed (a),
+				 avro_schema_to_fixed (b));
+    }
+  else if (is_avro_map (a))
+    {
+      return schema_map_equal (avro_schema_to_map (a),
+			       avro_schema_to_map (b));
+    }
+  else if (is_avro_array (a))
+    {
+      return schema_array_equal (avro_schema_to_array (a),
+				 avro_schema_to_array (b));
+    }
+  else if (is_avro_union (a))
+    {
+      return schema_union_equal (avro_schema_to_union (a),
+				 avro_schema_to_union (b));
+    }
+  else if (is_avro_link (a))
+    {
+      return schema_link_equal (avro_schema_to_link (a),
+				avro_schema_to_link (b));
+    }
+  return 1;
+}

Added: hadoop/avro/trunk/lang/c/src/schema_printf.c
URL: http://svn.apache.org/viewvc/hadoop/avro/trunk/lang/c/src/schema_printf.c?rev=899870&view=auto
==============================================================================
--- hadoop/avro/trunk/lang/c/src/schema_printf.c (added)
+++ hadoop/avro/trunk/lang/c/src/schema_printf.c Sat Jan 16 01:52:24 2010
@@ -0,0 +1,223 @@
+/*
+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 "schema.h"
+
+/* print */
+struct avro_schema_args_t
+{
+  int depth;
+  FILE *fp;
+};
+
+static void
+avro_schema_printf_internal (avro_schema_t schema,
+			     struct avro_schema_args_t *args);
+
+static void
+avro_schema_printf_indent (struct avro_schema_args_t *args)
+{
+  int i;
+  for (i = 0; i < args->depth; i++)
+    {
+      fprintf (args->fp, "  ");
+    }
+}
+
+static void
+avro_schema_union_print (struct schema_union_t *unionp,
+			 struct avro_schema_args_t *args)
+{
+  fprintf (args->fp, "union");
+}
+
+static void
+avro_schema_array_print (struct schema_array_t *array,
+			 struct avro_schema_args_t *args)
+{
+  avro_schema_printf_indent (args);
+  fprintf (args->fp, "array\n");
+  args->depth++;
+  avro_schema_printf_internal (array->items, args);
+  args->depth--;
+}
+
+static void
+avro_schema_map_print (struct schema_map_t *map,
+		       struct avro_schema_args_t *args)
+{
+  avro_schema_printf_indent (args);
+  fprintf (args->fp, "map\n");
+  args->depth++;
+  avro_schema_printf_internal (map->values, args);
+  args->depth--;
+}
+
+static void
+avro_schema_fixed_print (struct schema_fixed_t *fixed,
+			 struct avro_schema_args_t *args)
+{
+  fprintf (args->fp, "fixed \"%s\" size=%ld", fixed->name, fixed->size);
+}
+
+static void
+avro_schema_enum_print (struct schema_enum_t *enump,
+			struct avro_schema_args_t *args)
+{
+  fprintf (args->fp, "enum \"%s\"", enump->name);
+}
+
+static void
+avro_schema_record_field_print (struct record_field_t *field,
+				struct avro_schema_args_t *args)
+{
+  avro_schema_printf_indent (args);
+  fprintf (args->fp, "field \"%s\"\n", field->name);
+  args->depth++;
+  avro_schema_printf_internal (field->type, args);
+  args->depth--;
+}
+
+static void
+avro_schema_record_print (struct schema_record_t *record,
+			  struct avro_schema_args_t *args)
+{
+  size_t i;
+  struct record_field_t *field;
+  avro_schema_printf_indent (args);
+  fprintf (args->fp, "record \"%s\"\n", record->name);
+  args->depth++;
+  for (field = TAILQ_FIRST (&record->fields);
+       field != NULL; field = TAILQ_NEXT (field, fields))
+    {
+      avro_schema_record_field_print (field, args);
+    }
+  args->depth--;
+}
+
+const char *
+avro_schema_name (const avro_schema_t schema)
+{
+  if (is_avro_record (schema))
+    {
+      return (avro_schema_to_record (schema))->name;
+    }
+  else if (is_avro_enum (schema))
+    {
+      return (avro_schema_to_enum (schema))->name;
+    }
+  else if (is_avro_fixed (schema))
+    {
+      return (avro_schema_to_fixed (schema))->name;
+    }
+  return NULL;
+}
+
+static void
+avro_schema_link_print (const struct schema_link_t *link,
+			struct avro_schema_args_t *args)
+{
+  avro_schema_printf_indent (args);
+  fprintf (args->fp, "linkto \"%s\"\n", avro_schema_name (link->to));
+}
+
+static void
+avro_schema_primitive_print (const char *type,
+			     struct avro_schema_args_t *args)
+{
+  avro_schema_printf_indent (args);
+  fprintf (args->fp, "primitive %s\n", type);
+}
+
+static void
+avro_schema_printf_internal (avro_schema_t schema,
+			     struct avro_schema_args_t *args)
+{
+  if (is_avro_link (schema))
+    {
+      avro_schema_link_print (avro_schema_to_link (schema), args);
+    }
+  else if (is_avro_record (schema))
+    {
+      avro_schema_record_print (avro_schema_to_record (schema), args);
+    }
+  else if (is_avro_enum (schema))
+    {
+      avro_schema_enum_print (avro_schema_to_enum (schema), args);
+    }
+  else if (is_avro_fixed (schema))
+    {
+      avro_schema_fixed_print (avro_schema_to_fixed (schema), args);
+    }
+  else if (is_avro_map (schema))
+    {
+      avro_schema_map_print (avro_schema_to_map (schema), args);
+    }
+  else if (is_avro_array (schema))
+    {
+      avro_schema_array_print (avro_schema_to_array (schema), args);
+    }
+  else if (is_avro_union (schema))
+    {
+      avro_schema_union_print (avro_schema_to_union (schema), args);
+    }
+  else if (is_avro_string (schema))
+    {
+      avro_schema_primitive_print ("string", args);
+    }
+  else if (is_avro_bytes (schema))
+    {
+      avro_schema_primitive_print ("bytes", args);
+    }
+  else if (is_avro_int (schema))
+    {
+      avro_schema_primitive_print ("int", args);
+    }
+  else if (is_avro_long (schema))
+    {
+      avro_schema_primitive_print ("long", args);
+    }
+  else if (is_avro_float (schema))
+    {
+      avro_schema_primitive_print ("float", args);
+    }
+  else if (is_avro_double (schema))
+    {
+      avro_schema_primitive_print ("double", args);
+    }
+  else if (is_avro_boolean (schema))
+    {
+      avro_schema_primitive_print ("boolean", args);
+    }
+  else if (is_avro_null (schema))
+    {
+      avro_schema_primitive_print ("null", args);
+    }
+}
+
+void
+avro_schema_printf (avro_schema_t schema, FILE * fp)
+{
+  struct avro_schema_args_t args = {.depth = 0,.fp = fp };
+  if (fp)
+    {
+      avro_schema_printf_internal (schema, &args);
+      fprintf (fp, "\n");
+    }
+}

Added: hadoop/avro/trunk/lang/c/src/schema_specific.c
URL: http://svn.apache.org/viewvc/hadoop/avro/trunk/lang/c/src/schema_specific.c?rev=899870&view=auto
==============================================================================
--- hadoop/avro/trunk/lang/c/src/schema_specific.c (added)
+++ hadoop/avro/trunk/lang/c/src/schema_specific.c Sat Jan 16 01:52:24 2010
@@ -0,0 +1,248 @@
+/*
+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 <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include "avro.h"
+#include "schema.h"
+
+enum specific_state
+{
+  START_STATE,
+};
+typedef enum specific_state specific_state;
+
+struct specific_ctx
+{
+  FILE *header;
+  FILE *source;
+  int depth;
+  specific_state state;
+};
+typedef struct specific_ctx specific_ctx;
+
+static void
+indent (specific_ctx * ctx, FILE * fp)
+{
+  int i;
+  for (i = 0; i < ctx->depth; i++)
+    {
+      fprintf (fp, "   ");
+    }
+}
+
+static int
+avro_schema_to_source (avro_schema_t schema, specific_ctx * ctx)
+{
+  switch (schema->type)
+    {
+    default:
+      return 0;
+    }
+  return EINVAL;
+}
+
+static int
+avro_schema_to_header (avro_schema_t schema, specific_ctx * ctx)
+{
+  size_t i;
+  FILE *fp = ctx->header;
+
+  indent (ctx, fp);
+  ctx->depth++;
+
+  if (is_avro_primitive (schema) && !ctx->name)
+    {
+      return 0;
+    }
+
+  switch (schema->type)
+    {
+    case AVRO_STRING:
+      fprintf (fp, "char *%s;\n", ctx->name);
+      break;
+
+    case AVRO_BYTES:
+      fprintf (fp, "struct %s { size_t %s_len; char *%s_val } %s;\n",
+	       ctx->name, ctx->name, ctx->name, ctx->name);
+      break;
+
+    case AVRO_INT:
+      fprintf (fp, "int %s;\n", ctx->name);
+      break;
+
+    case AVRO_LONG:
+      fprintf (fp, "long %s;\n", ctx->name);
+      break;
+
+    case AVRO_FLOAT:
+      fprintf (fp, "float %s;\n", ctx->name);
+      break;
+
+    case AVRO_DOUBLE:
+      fprintf (fp, "double %s;\n", ctx->name);
+      break;
+
+    case AVRO_BOOLEAN:
+      fprintf (fp, "int %s; /* boolean */\n", ctx->name);
+      break;
+
+    case AVRO_NULL:
+      break;
+
+    case AVRO_RECORD:
+      {
+	struct schema_record_t *record_schema =
+	  avro_schema_to_record (schema);
+	fprintf (fp, "struct %s {\n", record_schema->name);
+	for (i = 0; i < record_schema->num_fields; i++)
+	  {
+	    struct record_field_t *field = record_schema->fields[i];
+	    ctx->name = field->name;
+	    avro_schema_to_header (field->type, ctx);
+	    ctx->name = NULL;
+	  }
+	fprintf (fp, "};\n");
+	fprintf (fp, "typedef struct %s %s;\n\n", record_schema->name,
+		 record_schema->name);
+      }
+      break;
+
+    case AVRO_ENUM:
+      {
+	struct schema_enum_t *enum_schema = avro_schema_to_enum (schema);
+	fprintf (fp, "enum %s {\n", enum_schema->name);
+	ctx->depth++;
+	for (i = 0; i < enum_schema->num_symbols; i++)
+	  {
+	    indent (ctx, fp);
+	    fprintf (fp, "%s = %ld,\n", enum_schema->symbols[i], i);
+	  }
+	ctx->depth--;
+	fprintf (fp, "};\n");
+	fprintf (fp, "typedef enum %s %s;\n\n", enum_schema->name,
+		 enum_schema->name);
+      }
+      break;
+
+    case AVRO_FIXED:
+      {
+	struct schema_fixed_t *fixed_schema = avro_schema_to_fixed (schema);
+	fprintf (fp, "char %s[%ld];\n", fixed_schema->name,
+		 fixed_schema->size);
+      }
+      break;
+
+    case AVRO_MAP:
+      {
+
+
+      }
+      break;
+
+    case AVRO_ARRAY:
+      {
+	struct schema_array_t *array_schema = avro_schema_to_array (schema);
+	if (!ctx->name)
+	  {
+	    break;
+	  }
+	fprintf (fp, "struct { size_t %s_len; ", ctx->name);
+	if (is_avro_named_type (array_schema->items))
+	  {
+	    fprintf (fp, "%s", avro_schema_name (array_schema->items));
+	  }
+	else if (is_avro_link (array_schema->items))
+	  {
+	    struct schema_link_t *link_schema =
+	      avro_schema_to_link (array_schema->items);
+	    fprintf (fp, "struct %s", avro_schema_name (link_schema->to));
+	  }
+	else
+	  {
+	    avro_schema_to_header (array_schema->items, ctx);
+	  }
+	fprintf (fp, " *%s_val;} %s;\n", ctx->name, ctx->name);
+      }
+      break;
+    case AVRO_UNION:
+      {
+	struct schema_union_t *union_schema = avro_schema_to_array (schema);
+	if (!ctx->name)
+	  {
+	    break;
+	  }
+	fprintf (fp, "union {\n");
+	for (i = 0; i < union_schema->num_schemas; i++)
+	  {
+	    avro_schema_to_header (union_schema->schemas[i], ctx);
+	  }
+	fprintf (fp, "%s_u;\n");
+      }
+      break;
+    case AVRO_LINK:
+      break;
+    default:
+      return EINVAL;
+    }
+
+  ctx->depth--;
+  return 0;
+}
+
+int
+avro_schema_to_specific (avro_schema_t schema, const char *prefix)
+{
+  specific_ctx ctx;
+  char buf[1024];
+  int rval;
+
+  if (!schema)
+    {
+      return EINVAL;
+    }
+
+  memset (&ctx, 0, sizeof (ctx));
+  snprintf (buf, sizeof (buf), "%s_avro.h", prefix);
+  ctx.header = fopen (buf, "w");
+  if (!ctx.header)
+    {
+      return errno;
+    }
+  snprintf (buf, sizeof (buf), "%s_avro.c", prefix);
+  ctx.source = fopen (buf, "w");
+  if (!ctx.source)
+    {
+      return errno;
+    }
+
+  rval = avro_schema_to_header (schema, &ctx);
+  if (rval)
+    {
+      goto out;
+    }
+
+  rval = avro_schema_to_source (schema, &ctx);
+
+out:
+  fclose (ctx.header);
+  fclose (ctx.source);
+  return rval;
+}



Mime
View raw message