Return-Path: Delivered-To: apmail-hadoop-avro-commits-archive@minotaur.apache.org Received: (qmail 17824 invoked from network); 16 Jan 2010 01:53:28 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (140.211.11.3) by minotaur.apache.org with SMTP; 16 Jan 2010 01:53:28 -0000 Received: (qmail 55706 invoked by uid 500); 16 Jan 2010 01:53:28 -0000 Delivered-To: apmail-hadoop-avro-commits-archive@hadoop.apache.org Received: (qmail 55675 invoked by uid 500); 16 Jan 2010 01:53:28 -0000 Mailing-List: contact avro-commits-help@hadoop.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: avro-dev@hadoop.apache.org Delivered-To: mailing list avro-commits@hadoop.apache.org Received: (qmail 55665 invoked by uid 99); 16 Jan 2010 01:53:28 -0000 Received: from nike.apache.org (HELO nike.apache.org) (192.87.106.230) by apache.org (qpsmtpd/0.29) with ESMTP; Sat, 16 Jan 2010 01:53:28 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=10.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Sat, 16 Jan 2010 01:53:22 +0000 Received: by eris.apache.org (Postfix, from userid 65534) id 40D942388A9B; Sat, 16 Jan 2010 01:52:31 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit 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 -0000 To: avro-commits@hadoop.apache.org From: massie@apache.org X-Mailer: svnmailer-1.0.8 Message-Id: <20100116015231.40D942388A9B@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org 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 +#include +#include +#include + +#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 +#include +#include +#include +#include +#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 +#include +#include +#include + +#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 + +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 +#include +#include +#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; +}