| /* |
| * 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 |
| * |
| * https://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 "avro_private.h" |
| #include <stdio.h> |
| #include <errno.h> |
| #include <string.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) { |
| fclose(ctx.header); |
| 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; |
| } |