1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to you under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * https://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
14 * implied. See the License for the specific language governing
15 * permissions and limitations under the License.
16 */
17
18 #include "avro_private.h"
19 #include <stdio.h>
20 #include <errno.h>
21 #include <string.h>
22
23 #include "schema.h"
24
25 enum specific_state {
26 START_STATE,
27 };
28 typedef enum specific_state specific_state;
29
30 struct specific_ctx {
31 FILE *header;
32 FILE *source;
33 int depth;
34 specific_state state;
35 };
36 typedef struct specific_ctx specific_ctx;
37
indent(specific_ctx * ctx,FILE * fp)38 static void indent(specific_ctx * ctx, FILE * fp)
39 {
40 int i;
41 for (i = 0; i < ctx->depth; i++) {
42 fprintf(fp, " ");
43 }
44 }
45
avro_schema_to_source(avro_schema_t schema,specific_ctx * ctx)46 static int avro_schema_to_source(avro_schema_t schema, specific_ctx * ctx)
47 {
48 switch (schema->type) {
49 default:
50 return 0;
51 }
52 return EINVAL;
53 }
54
avro_schema_to_header(avro_schema_t schema,specific_ctx * ctx)55 static int avro_schema_to_header(avro_schema_t schema, specific_ctx * ctx)
56 {
57 size_t i;
58 FILE *fp = ctx->header;
59
60 indent(ctx, fp);
61 ctx->depth++;
62
63 if (is_avro_primitive(schema) && !ctx->name) {
64 return 0;
65 }
66
67 switch (schema->type) {
68 case AVRO_STRING:
69 fprintf(fp, "char *%s;\n", ctx->name);
70 break;
71
72 case AVRO_BYTES:
73 fprintf(fp, "struct %s { size_t %s_len; char *%s_val } %s;\n",
74 ctx->name, ctx->name, ctx->name, ctx->name);
75 break;
76
77 case AVRO_INT:
78 fprintf(fp, "int %s;\n", ctx->name);
79 break;
80
81 case AVRO_LONG:
82 fprintf(fp, "long %s;\n", ctx->name);
83 break;
84
85 case AVRO_FLOAT:
86 fprintf(fp, "float %s;\n", ctx->name);
87 break;
88
89 case AVRO_DOUBLE:
90 fprintf(fp, "double %s;\n", ctx->name);
91 break;
92
93 case AVRO_BOOLEAN:
94 fprintf(fp, "int %s; /* boolean */\n", ctx->name);
95 break;
96
97 case AVRO_NULL:
98 break;
99
100 case AVRO_RECORD:
101 {
102 struct schema_record_t *record_schema =
103 avro_schema_to_record(schema);
104 fprintf(fp, "struct %s {\n", record_schema->name);
105 for (i = 0; i < record_schema->num_fields; i++) {
106 struct record_field_t *field =
107 record_schema->fields[i];
108 ctx->name = field->name;
109 avro_schema_to_header(field->type, ctx);
110 ctx->name = NULL;
111 }
112 fprintf(fp, "};\n");
113 fprintf(fp, "typedef struct %s %s;\n\n",
114 record_schema->name, record_schema->name);
115 }
116 break;
117
118 case AVRO_ENUM:
119 {
120 struct schema_enum_t *enum_schema =
121 avro_schema_to_enum(schema);
122 fprintf(fp, "enum %s {\n", enum_schema->name);
123 ctx->depth++;
124 for (i = 0; i < enum_schema->num_symbols; i++) {
125 indent(ctx, fp);
126 fprintf(fp, "%s = %ld,\n",
127 enum_schema->symbols[i], i);
128 }
129 ctx->depth--;
130 fprintf(fp, "};\n");
131 fprintf(fp, "typedef enum %s %s;\n\n",
132 enum_schema->name, enum_schema->name);
133 }
134 break;
135
136 case AVRO_FIXED:
137 {
138 struct schema_fixed_t *fixed_schema =
139 avro_schema_to_fixed(schema);
140 fprintf(fp, "char %s[%ld];\n", fixed_schema->name,
141 fixed_schema->size);
142 }
143 break;
144
145 case AVRO_MAP:
146 {
147
148 }
149 break;
150
151 case AVRO_ARRAY:
152 {
153 struct schema_array_t *array_schema =
154 avro_schema_to_array(schema);
155 if (!ctx->name) {
156 break;
157 }
158 fprintf(fp, "struct { size_t %s_len; ", ctx->name);
159 if (is_avro_named_type(array_schema->items)) {
160 fprintf(fp, "%s",
161 avro_schema_name(array_schema->items));
162 } else if (is_avro_link(array_schema->items)) {
163 struct schema_link_t *link_schema =
164 avro_schema_to_link(array_schema->items);
165 fprintf(fp, "struct %s",
166 avro_schema_name(link_schema->to));
167 } else {
168 avro_schema_to_header(array_schema->items, ctx);
169 }
170 fprintf(fp, " *%s_val;} %s;\n", ctx->name, ctx->name);
171 }
172 break;
173 case AVRO_UNION:
174 {
175 struct schema_union_t *union_schema =
176 avro_schema_to_array(schema);
177 if (!ctx->name) {
178 break;
179 }
180 fprintf(fp, "union {\n");
181 for (i = 0; i < union_schema->num_schemas; i++) {
182 avro_schema_to_header(union_schema->schemas[i],
183 ctx);
184 }
185 fprintf(fp, "%s_u;\n");
186 }
187 break;
188 case AVRO_LINK:
189 break;
190 default:
191 return EINVAL;
192 }
193
194 ctx->depth--;
195 return 0;
196 }
197
avro_schema_to_specific(avro_schema_t schema,const char * prefix)198 int avro_schema_to_specific(avro_schema_t schema, const char *prefix)
199 {
200 specific_ctx ctx;
201 char buf[1024];
202 int rval;
203
204 if (!schema) {
205 return EINVAL;
206 }
207
208 memset(&ctx, 0, sizeof(ctx));
209 snprintf(buf, sizeof(buf), "%s_avro.h", prefix);
210 ctx.header = fopen(buf, "w");
211 if (!ctx.header) {
212 return errno;
213 }
214 snprintf(buf, sizeof(buf), "%s_avro.c", prefix);
215 ctx.source = fopen(buf, "w");
216 if (!ctx.source) {
217 fclose(ctx.header);
218 return errno;
219 }
220
221 rval = avro_schema_to_header(schema, &ctx);
222 if (rval) {
223 goto out;
224 }
225
226 rval = avro_schema_to_source(schema, &ctx);
227
228 out:
229 fclose(ctx.header);
230 fclose(ctx.source);
231 return rval;
232 }
233