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
9
* http://www.apache.org/licenses/LICENSE-2.0
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.
21
#include <avro/platform.h>
22
#include <avro/platform.h>
28
#include "avro_private.h"
31
/* The path separator to use in the JSON output. */
33
static const char *separator = "/";
36
/*-- PROCESSING A FILE --*/
39
* Fills in a raw string with the path to an element of an array.
43
create_array_prefix(avro_raw_string_t *dest, const char *prefix, size_t index)
46
snprintf(buf, sizeof(buf), "%" PRIsz, index);
47
avro_raw_string_set(dest, prefix);
48
avro_raw_string_append(dest, separator);
49
avro_raw_string_append(dest, buf);
53
create_object_prefix(avro_raw_string_t *dest, const char *prefix, const char *key)
56
* Make sure that the key doesn't contain the separator
60
if (strstr(key, separator) != NULL) {
62
"Error: Element \"%s\" in object %s "
63
"contains the separator character.\n"
64
"Please use the --separator option to choose another.\n",
69
avro_raw_string_set(dest, prefix);
70
avro_raw_string_append(dest, separator);
71
avro_raw_string_append(dest, key);
75
print_bytes_value(const char *buf, size_t size)
79
for (i = 0; i < size; i++)
83
} else if (buf[i] == '\\') {
85
} else if (buf[i] == '\b') {
87
} else if (buf[i] == '\f') {
89
} else if (buf[i] == '\n') {
91
} else if (buf[i] == '\r') {
93
} else if (buf[i] == '\t') {
95
} else if (isprint(buf[i])) {
96
printf("%c", (int) buf[i]);
98
printf("\\u00%02x", (unsigned int) (unsigned char) buf[i]);
105
process_value(const char *prefix, avro_value_t *value);
108
process_array(const char *prefix, avro_value_t *value)
110
printf("%s\t[]\n", prefix);
111
size_t element_count;
112
avro_value_get_size(value, &element_count);
114
avro_raw_string_t element_prefix;
115
avro_raw_string_init(&element_prefix);
118
for (i = 0; i < element_count; i++) {
119
avro_value_t element_value;
120
avro_value_get_by_index(value, i, &element_value, NULL);
122
create_array_prefix(&element_prefix, prefix, i);
123
process_value((const char *) avro_raw_string_get(&element_prefix), &element_value);
126
avro_raw_string_done(&element_prefix);
130
process_enum(const char *prefix, avro_value_t *value)
133
const char *symbol_name;
135
avro_schema_t schema = avro_value_get_schema(value);
136
avro_value_get_enum(value, &val);
137
symbol_name = avro_schema_enum_get(schema, val);
138
printf("%s\t", prefix);
139
print_bytes_value(symbol_name, strlen(symbol_name));
144
process_map(const char *prefix, avro_value_t *value)
146
printf("%s\t{}\n", prefix);
147
size_t element_count;
148
avro_value_get_size(value, &element_count);
150
avro_raw_string_t element_prefix;
151
avro_raw_string_init(&element_prefix);
154
for (i = 0; i < element_count; i++) {
156
avro_value_t element_value;
157
avro_value_get_by_index(value, i, &element_value, &key);
159
create_object_prefix(&element_prefix, prefix, key);
160
process_value((const char *) avro_raw_string_get(&element_prefix), &element_value);
163
avro_raw_string_done(&element_prefix);
167
process_record(const char *prefix, avro_value_t *value)
169
printf("%s\t{}\n", prefix);
171
avro_value_get_size(value, &field_count);
173
avro_raw_string_t field_prefix;
174
avro_raw_string_init(&field_prefix);
177
for (i = 0; i < field_count; i++) {
178
avro_value_t field_value;
179
const char *field_name;
180
avro_value_get_by_index(value, i, &field_value, &field_name);
182
create_object_prefix(&field_prefix, prefix, field_name);
183
process_value((const char *) avro_raw_string_get(&field_prefix), &field_value);
186
avro_raw_string_done(&field_prefix);
190
process_union(const char *prefix, avro_value_t *value)
192
avro_value_t branch_value;
193
avro_value_get_current_branch(value, &branch_value);
195
/* nulls in a union aren't wrapped in a JSON object */
196
if (avro_value_get_type(&branch_value) == AVRO_NULL) {
197
printf("%s\tnull\n", prefix);
202
avro_value_get_discriminant(value, &discriminant);
204
avro_schema_t schema = avro_value_get_schema(value);
205
avro_schema_t branch_schema = avro_schema_union_branch(schema, discriminant);
206
const char *branch_name = avro_schema_type_name(branch_schema);
208
avro_raw_string_t branch_prefix;
209
avro_raw_string_init(&branch_prefix);
210
create_object_prefix(&branch_prefix, prefix, branch_name);
212
printf("%s\t{}\n", prefix);
213
process_value((const char *) avro_raw_string_get(&branch_prefix), &branch_value);
215
avro_raw_string_done(&branch_prefix);
219
process_value(const char *prefix, avro_value_t *value)
221
avro_type_t type = avro_value_get_type(value);
226
avro_value_get_boolean(value, &val);
227
printf("%s\t%s\n", prefix, val? "true": "false");
235
avro_value_get_bytes(value, &buf, &size);
236
printf("%s\t", prefix);
237
print_bytes_value((const char *) buf, size);
245
avro_value_get_double(value, &val);
246
printf("%s\t%lf\n", prefix, val);
253
avro_value_get_float(value, &val);
254
printf("%s\t%f\n", prefix, val);
261
avro_value_get_int(value, &val);
262
printf("%s\t%" PRId32 "\n", prefix, val);
269
avro_value_get_long(value, &val);
270
printf("%s\t%" PRId64 "\n", prefix, val);
276
avro_value_get_null(value);
277
printf("%s\tnull\n", prefix);
283
/* TODO: Convert the UTF-8 to the current
284
* locale's character set */
287
avro_value_get_string(value, &buf, &size);
288
printf("%s\t", prefix);
289
/* For strings, size includes the NUL terminator. */
290
print_bytes_value(buf, size-1);
296
process_array(prefix, value);
300
process_enum(prefix, value);
307
avro_value_get_fixed(value, &buf, &size);
308
printf("%s\t", prefix);
309
print_bytes_value((const char *) buf, size);
315
process_map(prefix, value);
319
process_record(prefix, value);
323
process_union(prefix, value);
328
fprintf(stderr, "Unknown schema type\n");
335
process_file(const char *filename)
337
avro_file_reader_t reader;
339
if (filename == NULL) {
340
if (avro_file_reader_fp(stdin, "<stdin>", 0, &reader)) {
341
fprintf(stderr, "Error opening <stdin>:\n %s\n",
346
if (avro_file_reader(filename, &reader)) {
347
fprintf(stderr, "Error opening %s:\n %s\n",
348
filename, avro_strerror());
353
/* The JSON root is an array */
354
printf("%s\t[]\n", separator);
356
avro_raw_string_t prefix;
357
avro_raw_string_init(&prefix);
359
avro_schema_t wschema = avro_file_reader_get_writer_schema(reader);
360
avro_value_iface_t *iface = avro_generic_class_from_schema(wschema);
362
avro_generic_value_new(iface, &value);
364
size_t record_number = 0;
367
for (; (rval = avro_file_reader_read_value(reader, &value)) == 0; record_number++) {
368
create_array_prefix(&prefix, "", record_number);
369
process_value((const char *) avro_raw_string_get(&prefix), &value);
370
avro_value_reset(&value);
374
fprintf(stderr, "Error reading value: %s", avro_strerror());
377
avro_raw_string_done(&prefix);
378
avro_value_decref(&value);
379
avro_value_iface_decref(iface);
380
avro_file_reader_close(reader);
381
avro_schema_decref(wschema);
385
/*-- MAIN PROGRAM --*/
386
static struct option longopts[] = {
387
{ "separator", required_argument, NULL, 's' },
391
static void usage(void)
394
"Usage: avropipe [--separator=<separator>]\n"
395
" <avro data file>\n");
399
int main(int argc, char **argv)
404
while ((ch = getopt_long(argc, argv, "s:", longopts, NULL) ) != -1) {
420
data_filename = argv[0];
421
} else if (argc == 0) {
422
data_filename = NULL;
424
fprintf(stderr, "Can't read from multiple input files.\n");
429
/* Process the data file */
430
process_file(data_filename);