| /* |
| * 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. |
| */ |
| |
| #ifndef AVRO_CONSUMER_H |
| #define AVRO_CONSUMER_H |
| #ifdef __cplusplus |
| extern "C" { |
| #define CLOSE_EXTERN } |
| #else |
| #define CLOSE_EXTERN |
| #endif |
| |
| #include <avro/platform.h> |
| #include <stdlib.h> |
| |
| #include <avro/io.h> |
| #include <avro/schema.h> |
| |
| |
| /*--------------------------------------------------------------------- |
| * Consumers |
| */ |
| |
| /** |
| * A <i>consumer</i> is an object that knows how to process Avro data. |
| * There are consumer methods for each type of Avro data. The |
| * <code>avro_consumer_t</code> struct is an abstract superclass, which |
| * you don't instantiate directly. Later in this file, we define |
| * several consumer classes that know how to process Avro data in |
| * specific ways. |
| * |
| * For compound Avro values (records, arrays, maps, and unions), the |
| * consumer callbacks provide a nested consumer that should be used to |
| * process subvalues. Each consumer instance, including these |
| * "subconsumers", contains a reference to the schema of the data that |
| * it expects to process. This means that the functions that produce |
| * Avro data (such as avro_consume_binary) don't need to maintain their |
| * own references to any schemas, since they'll be encapsulated in the |
| * consumer that they pass their data off to. |
| */ |
| |
| typedef struct avro_consumer_t avro_consumer_t; |
| |
| struct avro_consumer_t { |
| /** |
| * The schema of the data that this consumer expects to process. |
| */ |
| |
| avro_schema_t schema; |
| |
| /** |
| * Called when this consumer is freed. This function should |
| * free any additional resources acquired by a consumer |
| * subclass. |
| */ |
| |
| void (*free)(avro_consumer_t *consumer); |
| |
| /* PRIMITIVE VALUES */ |
| |
| /** |
| * Called when a boolean value is encountered. |
| */ |
| |
| int (*boolean_value)(avro_consumer_t *consumer, |
| int value, |
| void *user_data); |
| |
| /** |
| * Called when a bytes value is encountered. The @ref value |
| * pointer is only guaranteed to be valid for the duration of |
| * the callback function. If you need to save the data for |
| * processing later, you must copy it into another buffer. |
| */ |
| |
| int (*bytes_value)(avro_consumer_t *consumer, |
| const void *value, size_t value_len, |
| void *user_data); |
| |
| /** |
| * Called when a double value is encountered. |
| */ |
| |
| int (*double_value)(avro_consumer_t *consumer, |
| double value, |
| void *user_data); |
| |
| /** |
| * Called when a float value is encountered. |
| */ |
| |
| int (*float_value)(avro_consumer_t *consumer, |
| float value, |
| void *user_data); |
| |
| /** |
| * Called when an int value is encountered. |
| */ |
| |
| int (*int_value)(avro_consumer_t *consumer, |
| int32_t value, |
| void *user_data); |
| |
| /** |
| * Called when a long value is encountered. |
| */ |
| |
| int (*long_value)(avro_consumer_t *consumer, |
| int64_t value, |
| void *user_data); |
| |
| /** |
| * Called when a null value is encountered. |
| */ |
| |
| int (*null_value)(avro_consumer_t *consumer, void *user_data); |
| |
| /** |
| * Called when a string value is encountered. The @ref value |
| * pointer will point at UTF-8 encoded data. (If the data |
| * you're representing isn't a UTF-8 Unicode string, you |
| * should use the bytes type.) The @ref value_len parameter |
| * gives the length of the data in bytes, not in Unicode |
| * characters. The @ref value pointer is only guaranteed to |
| * be valid for the duration of the callback function. If you |
| * need to save the data for processing later, you must copy |
| * it into another buffer. |
| */ |
| |
| int (*string_value)(avro_consumer_t *consumer, |
| const void *value, size_t value_len, |
| void *user_data); |
| |
| /* COMPOUND VALUES */ |
| |
| /** |
| * Called when the beginning of an array block is encountered. |
| * The @ref block_count parameter will contain the number of |
| * elements in this block. |
| */ |
| |
| int (*array_start_block)(avro_consumer_t *consumer, |
| int is_first_block, |
| unsigned int block_count, |
| void *user_data); |
| |
| /** |
| * Called before each individual element of an array is |
| * processed. The index of the current element is passed into |
| * the callback. The callback should fill in @ref |
| * element_consumer and @ref element_user_data with the consumer |
| * and <code>user_data</code> pointer to use to process the |
| * element. |
| */ |
| |
| int (*array_element)(avro_consumer_t *consumer, |
| unsigned int index, |
| avro_consumer_t **element_consumer, |
| void **element_user_data, |
| void *user_data); |
| |
| /** |
| * Called when an enum value is encountered. |
| */ |
| |
| int (*enum_value)(avro_consumer_t *consumer, int value, |
| void *user_data); |
| |
| /** |
| * Called when a fixed value is encountered. The @ref value |
| * pointer is only guaranteed to be valid for the duration of |
| * the callback function. If you need to save the data for |
| * processing later, you must copy it into another buffer. |
| */ |
| |
| int (*fixed_value)(avro_consumer_t *consumer, |
| const void *value, size_t value_len, |
| void *user_data); |
| |
| /** |
| * Called when the beginning of a map block is encountered. |
| * The @ref block_count parameter will contain the number of |
| * elements in this block. |
| */ |
| |
| int (*map_start_block)(avro_consumer_t *consumer, |
| int is_first_block, |
| unsigned int block_count, |
| void *user_data); |
| |
| /** |
| * Called before each individual element of a map is |
| * processed. The index and key of the current element is |
| * passed into the callback. The key is only guaranteed to be |
| * valid for the duration of the map_element_start callback, |
| * and the map's subschema callback. If you need to save it for |
| * later use, you must copy the key into another memory |
| * location. The callback should fill in @ref value_consumer |
| * and @ref value_user_data with the consumer and |
| * <code>user_data</code> pointer to use to process the value. |
| */ |
| |
| int (*map_element)(avro_consumer_t *consumer, |
| unsigned int index, |
| const char *key, |
| avro_consumer_t **value_consumer, |
| void **value_user_data, |
| void *user_data); |
| |
| /** |
| * Called when the beginning of a record is encountered. |
| */ |
| |
| int (*record_start)(avro_consumer_t *consumer, |
| void *user_data); |
| |
| /** |
| * Called before each individual field of a record is |
| * processed. The index and name of the current field is |
| * passed into the callback. The name is only guaranteed to |
| * be valid for the duration of the record_field_start |
| * callback, and the field's subschema callback. If you need to |
| * save it for later use, you must copy the key into another |
| * memory location. The callback should fill in @ref |
| * field_consumer and @ref field_user_data with the consumer |
| * <code>user_data</code> pointer to use to process the field. |
| */ |
| |
| int (*record_field)(avro_consumer_t *consumer, |
| unsigned int index, |
| avro_consumer_t **field_consumer, |
| void **field_user_data, |
| void *user_data); |
| |
| /** |
| * Called when a union value is encountered. The callback |
| * should fill in @ref branch_consumer and @ref branch_user_data |
| * with the consumer <code>user_data</code> pointer to use to |
| * process the branch. |
| */ |
| |
| int (*union_branch)(avro_consumer_t *consumer, |
| unsigned int discriminant, |
| avro_consumer_t **branch_consumer, |
| void **branch_user_data, |
| void *user_data); |
| }; |
| |
| |
| /** |
| * Calls the given callback in consumer, if it's present. If the |
| * callback is NULL, it just returns a success code. |
| */ |
| |
| #define avro_consumer_call(consumer, callback, ...) \ |
| (((consumer)->callback == NULL)? 0: \ |
| (consumer)->callback((consumer), __VA_ARGS__)) |
| |
| |
| /** |
| * Frees an @ref avro_consumer_t instance. (This function works on |
| * consumer subclasses, too.) |
| */ |
| |
| void avro_consumer_free(avro_consumer_t *consumer); |
| |
| |
| /*--------------------------------------------------------------------- |
| * Resolvers |
| */ |
| |
| /** |
| * A <i>resolver</i> is a special kind of consumer that knows how to |
| * implement Avro's schema resolution rules to translate between a |
| * writer schema and a reader schema. The consumer callbacks line up |
| * with the writer schema; as each element of the datum is produced, the |
| * resolver fills in the contents of an @ref avro_datum_t instance. |
| * (The datum is provided as the user_data when you use the consumer.) |
| */ |
| |
| avro_consumer_t * |
| avro_resolver_new(avro_schema_t writer_schema, |
| avro_schema_t reader_schema); |
| |
| |
| /*--------------------------------------------------------------------- |
| * Binary encoding |
| */ |
| |
| /** |
| * Reads an Avro datum from the given @ref avro_reader_t. As the |
| * datum is read, each portion of it is passed off to the appropriate |
| * callback in @ref consumer. |
| */ |
| |
| int |
| avro_consume_binary(avro_reader_t reader, |
| avro_consumer_t *consumer, |
| void *ud); |
| |
| |
| CLOSE_EXTERN |
| #endif |