| /* |
| * 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_VALUE_H |
| #define AVRO_VALUE_H |
| #ifdef __cplusplus |
| extern "C" { |
| #define CLOSE_EXTERN } |
| #else |
| #define CLOSE_EXTERN |
| #endif |
| |
| #include <errno.h> |
| #include <avro/platform.h> |
| #include <stdlib.h> |
| |
| #include <avro/data.h> |
| #include <avro/schema.h> |
| |
| /* |
| * This file defines an interface struct for Avro data. Most of the |
| * interesting parts of this library will work with Avro data values |
| * that are expressed in whatever C type you want, as long as you can |
| * provide an implementation of this interface for that type. |
| */ |
| |
| typedef struct avro_value_iface avro_value_iface_t; |
| |
| typedef struct avro_value { |
| avro_value_iface_t *iface; |
| void *self; |
| } avro_value_t; |
| |
| struct avro_value_iface { |
| /*------------------------------------------------------------- |
| * "class" methods |
| */ |
| |
| /** |
| * Increment the reference count of the interface struct. This |
| * should be a no-op for static structs, since they don't need |
| * reference counts. |
| */ |
| avro_value_iface_t * |
| (*incref_iface)(avro_value_iface_t *iface); |
| |
| /** |
| * Decrement the reference count of the interface struct. If |
| * the count falls to 0, free the struct. This should be a |
| * no-op for static structs, since they don't need reference |
| * counts. |
| */ |
| void |
| (*decref_iface)(avro_value_iface_t *iface); |
| |
| /*------------------------------------------------------------- |
| * General "instance" methods |
| */ |
| |
| /** |
| * Increments the reference count of a value. |
| */ |
| |
| void |
| (*incref)(avro_value_t *value); |
| |
| /** |
| * Decrements the reference count of a value, and frees the |
| * value if the reference count drops to 0. After calling this |
| * method, your value instance is undefined, and cannot be used |
| * anymore. |
| */ |
| |
| void |
| (*decref)(avro_value_t *value); |
| |
| /** |
| * Reset the instance to its "empty", default value. You don't |
| * have to free the underlying storage, if you want to keep it |
| * around for later values. |
| */ |
| int |
| (*reset)(const avro_value_iface_t *iface, void *self); |
| |
| /** |
| * Return the general Avro type of a value instance. |
| */ |
| avro_type_t |
| (*get_type)(const avro_value_iface_t *iface, const void *self); |
| |
| /** |
| * Return the Avro schema that a value is an instance of. |
| */ |
| avro_schema_t |
| (*get_schema)(const avro_value_iface_t *iface, const void *self); |
| |
| /*------------------------------------------------------------- |
| * Primitive value getters |
| */ |
| int (*get_boolean)(const avro_value_iface_t *iface, |
| const void *self, int *out); |
| int (*get_bytes)(const avro_value_iface_t *iface, |
| const void *self, const void **buf, size_t *size); |
| int (*grab_bytes)(const avro_value_iface_t *iface, |
| const void *self, avro_wrapped_buffer_t *dest); |
| int (*get_double)(const avro_value_iface_t *iface, |
| const void *self, double *out); |
| int (*get_float)(const avro_value_iface_t *iface, |
| const void *self, float *out); |
| int (*get_int)(const avro_value_iface_t *iface, |
| const void *self, int32_t *out); |
| int (*get_long)(const avro_value_iface_t *iface, |
| const void *self, int64_t *out); |
| int (*get_null)(const avro_value_iface_t *iface, |
| const void *self); |
| /* The result will be NUL-terminated; the size will INCLUDE the |
| * NUL terminator. str will never be NULL unless there's an |
| * error. */ |
| int (*get_string)(const avro_value_iface_t *iface, |
| const void *self, const char **str, size_t *size); |
| int (*grab_string)(const avro_value_iface_t *iface, |
| const void *self, avro_wrapped_buffer_t *dest); |
| |
| int (*get_enum)(const avro_value_iface_t *iface, |
| const void *self, int *out); |
| int (*get_fixed)(const avro_value_iface_t *iface, |
| const void *self, const void **buf, size_t *size); |
| int (*grab_fixed)(const avro_value_iface_t *iface, |
| const void *self, avro_wrapped_buffer_t *dest); |
| |
| /*------------------------------------------------------------- |
| * Primitive value setters |
| */ |
| |
| /* |
| * The "give" setters can be used to give control of an existing |
| * buffer to a bytes, fixed, or string value. The free function |
| * will be called when the buffer is no longer needed. (It's |
| * okay for free to be NULL; that just means that nothing |
| * special needs to be done to free the buffer. That's useful |
| * for a static string, for instance.) |
| * |
| * If your class can't take control of an existing buffer, then |
| * your give functions should pass the buffer into the |
| * corresponding "set" method and then immediately free the |
| * buffer. |
| * |
| * Note that for strings, the free function will be called with |
| * a size that *includes* the NUL terminator, even though you |
| * provide a size that does *not*. |
| */ |
| |
| int (*set_boolean)(const avro_value_iface_t *iface, |
| void *self, int val); |
| int (*set_bytes)(const avro_value_iface_t *iface, |
| void *self, void *buf, size_t size); |
| int (*give_bytes)(const avro_value_iface_t *iface, |
| void *self, avro_wrapped_buffer_t *buf); |
| int (*set_double)(const avro_value_iface_t *iface, |
| void *self, double val); |
| int (*set_float)(const avro_value_iface_t *iface, |
| void *self, float val); |
| int (*set_int)(const avro_value_iface_t *iface, |
| void *self, int32_t val); |
| int (*set_long)(const avro_value_iface_t *iface, |
| void *self, int64_t val); |
| int (*set_null)(const avro_value_iface_t *iface, void *self); |
| /* The input must be NUL-terminated */ |
| int (*set_string)(const avro_value_iface_t *iface, |
| void *self, const char *str); |
| /* and size must INCLUDE the NUL terminator */ |
| int (*set_string_len)(const avro_value_iface_t *iface, |
| void *self, const char *str, size_t size); |
| int (*give_string_len)(const avro_value_iface_t *iface, |
| void *self, avro_wrapped_buffer_t *buf); |
| |
| int (*set_enum)(const avro_value_iface_t *iface, |
| void *self, int val); |
| int (*set_fixed)(const avro_value_iface_t *iface, |
| void *self, void *buf, size_t size); |
| int (*give_fixed)(const avro_value_iface_t *iface, |
| void *self, avro_wrapped_buffer_t *buf); |
| |
| /*------------------------------------------------------------- |
| * Compound value getters |
| */ |
| |
| /* Number of elements in array/map, or the number of fields in a |
| * record. */ |
| int (*get_size)(const avro_value_iface_t *iface, |
| const void *self, size_t *size); |
| |
| /* |
| * For arrays and maps, returns the element with the given |
| * index. (For maps, the "index" is based on the order that the |
| * keys were added to the map.) For records, returns the field |
| * with that index in the schema. |
| * |
| * For maps and records, the name parameter (if given) will be |
| * filled in with the key or field name of the returned value. |
| * For arrays, the name parameter will always be ignored. |
| */ |
| int (*get_by_index)(const avro_value_iface_t *iface, |
| const void *self, size_t index, |
| avro_value_t *child, const char **name); |
| |
| /* |
| * For maps, returns the element with the given key. For |
| * records, returns the element with the given field name. If |
| * index is given, it will be filled in with the numeric index |
| * of the returned value. |
| */ |
| int (*get_by_name)(const avro_value_iface_t *iface, |
| const void *self, const char *name, |
| avro_value_t *child, size_t *index); |
| |
| /* Discriminant of current union value */ |
| int (*get_discriminant)(const avro_value_iface_t *iface, |
| const void *self, int *out); |
| /* Current union value */ |
| int (*get_current_branch)(const avro_value_iface_t *iface, |
| const void *self, avro_value_t *branch); |
| |
| /*------------------------------------------------------------- |
| * Compound value setters |
| */ |
| |
| /* |
| * For all of these, the value class should know which class to |
| * use for its children. |
| */ |
| |
| /* Creates a new array element. */ |
| int (*append)(const avro_value_iface_t *iface, |
| void *self, avro_value_t *child_out, size_t *new_index); |
| |
| /* Creates a new map element, or returns an existing one. */ |
| int (*add)(const avro_value_iface_t *iface, |
| void *self, const char *key, |
| avro_value_t *child, size_t *index, int *is_new); |
| |
| /* Select a union branch. */ |
| int (*set_branch)(const avro_value_iface_t *iface, |
| void *self, int discriminant, |
| avro_value_t *branch); |
| }; |
| |
| |
| /** |
| * Increments the reference count of a value instance. Normally you |
| * don't need to call this directly; you'll have a reference whenever |
| * you create the value, and @ref avro_value_copy and @ref |
| * avro_value_move update the reference counts correctly for you. |
| */ |
| |
| void |
| avro_value_incref(avro_value_t *value); |
| |
| /** |
| * Decremenets the reference count of a value instance, freeing it if |
| * its reference count drops to 0. |
| */ |
| |
| void |
| avro_value_decref(avro_value_t *value); |
| |
| /** |
| * Copies a reference to a value. This does not copy any of the data |
| * in the value; you get two avro_value_t references that point at the |
| * same underlying value instance. |
| */ |
| |
| void |
| avro_value_copy_ref(avro_value_t *dest, const avro_value_t *src); |
| |
| /** |
| * Moves a reference to a value. This does not copy any of the data in |
| * the value. The @ref src value is invalidated by this function; its |
| * equivalent to the following: |
| * |
| * <code> |
| * avro_value_copy_ref(dest, src); |
| * avro_value_decref(src); |
| * </code> |
| */ |
| |
| void |
| avro_value_move_ref(avro_value_t *dest, avro_value_t *src); |
| |
| /** |
| * Compares two values for equality. The two values don't need to have |
| * the same implementation of the value interface, but they do need to |
| * represent Avro values of the same schema. This function ensures that |
| * the schemas match; if you want to skip this check, use |
| * avro_value_equal_fast. |
| */ |
| |
| int |
| avro_value_equal(avro_value_t *val1, avro_value_t *val2); |
| |
| /** |
| * Compares two values for equality. The two values don't need to have |
| * the same implementation of the value interface, but they do need to |
| * represent Avro values of the same schema. This function assumes that |
| * the schemas match; if you can't guarantee this, you should use |
| * avro_value_equal, which compares the schemas before comparing the |
| * values. |
| */ |
| |
| int |
| avro_value_equal_fast(avro_value_t *val1, avro_value_t *val2); |
| |
| /** |
| * Compares two values using the sort order defined in the Avro |
| * specification. The two values don't need to have the same |
| * implementation of the value interface, but they do need to represent |
| * Avro values of the same schema. This function ensures that the |
| * schemas match; if you want to skip this check, use |
| * avro_value_cmp_fast. |
| */ |
| |
| int |
| avro_value_cmp(avro_value_t *val1, avro_value_t *val2); |
| |
| /** |
| * Compares two values using the sort order defined in the Avro |
| * specification. The two values don't need to have the same |
| * implementation of the value interface, but they do need to represent |
| * Avro values of the same schema. This function assumes that the |
| * schemas match; if you can't guarantee this, you should use |
| * avro_value_cmp, which compares the schemas before comparing the |
| * values. |
| */ |
| |
| int |
| avro_value_cmp_fast(avro_value_t *val1, avro_value_t *val2); |
| |
| |
| |
| /** |
| * Copies the contents of src into dest. The two values don't need to |
| * have the same implementation of the value interface, but they do need |
| * to represent Avro values of the same schema. This function ensures |
| * that the schemas match; if you want to skip this check, use |
| * avro_value_copy_fast. |
| */ |
| |
| int |
| avro_value_copy(avro_value_t *dest, const avro_value_t *src); |
| |
| /** |
| * Copies the contents of src into dest. The two values don't need to |
| * have the same implementation of the value interface, but they do need |
| * to represent Avro values of the same schema. This function assumes |
| * that the schemas match; if you can't guarantee this, you should use |
| * avro_value_copy, which compares the schemas before comparing the |
| * values. |
| */ |
| |
| int |
| avro_value_copy_fast(avro_value_t *dest, const avro_value_t *src); |
| |
| /** |
| * Returns a hash value for a given Avro value. |
| */ |
| |
| uint32_t |
| avro_value_hash(avro_value_t *value); |
| |
| /* |
| * Returns a string containing the JSON encoding of an Avro value. You |
| * must free this string when you're done with it, using the standard |
| * free() function. (*Not* using the custom Avro allocator.) |
| */ |
| |
| int |
| avro_value_to_json(const avro_value_t *value, |
| int one_line, char **json_str); |
| |
| |
| /** |
| * A helper macro for calling a given method in a value instance, if |
| * it's present. If the value's class doesn't implement the given |
| * method, we return dflt. You usually won't call this directly; it's |
| * just here to implement the macros below. |
| */ |
| |
| #define avro_value_call0(value, method, dflt) \ |
| ((value)->iface->method == NULL? (dflt): \ |
| (value)->iface->method((value)->iface, (value)->self)) |
| |
| #define avro_value_call(value, method, dflt, ...) \ |
| ((value)->iface->method == NULL? (dflt): \ |
| (value)->iface->method((value)->iface, (value)->self, __VA_ARGS__)) |
| |
| |
| #define avro_value_iface_incref(cls) \ |
| ((cls)->incref_iface == NULL? (cls): (cls)->incref_iface((cls))) |
| #define avro_value_iface_decref(cls) \ |
| ((cls)->decref_iface == NULL? (void) 0: (cls)->decref_iface((cls))) |
| |
| #define avro_value_reset(value) \ |
| avro_value_call0(value, reset, EINVAL) |
| #define avro_value_get_type(value) \ |
| avro_value_call0(value, get_type, (avro_type_t) -1) |
| #define avro_value_get_schema(value) \ |
| avro_value_call0(value, get_schema, NULL) |
| |
| #define avro_value_get_boolean(value, out) \ |
| avro_value_call(value, get_boolean, EINVAL, out) |
| #define avro_value_get_bytes(value, buf, size) \ |
| avro_value_call(value, get_bytes, EINVAL, buf, size) |
| #define avro_value_grab_bytes(value, dest) \ |
| avro_value_call(value, grab_bytes, EINVAL, dest) |
| #define avro_value_get_double(value, out) \ |
| avro_value_call(value, get_double, EINVAL, out) |
| #define avro_value_get_float(value, out) \ |
| avro_value_call(value, get_float, EINVAL, out) |
| #define avro_value_get_int(value, out) \ |
| avro_value_call(value, get_int, EINVAL, out) |
| #define avro_value_get_long(value, out) \ |
| avro_value_call(value, get_long, EINVAL, out) |
| #define avro_value_get_null(value) \ |
| avro_value_call0(value, get_null, EINVAL) |
| #define avro_value_get_string(value, str, size) \ |
| avro_value_call(value, get_string, EINVAL, str, size) |
| #define avro_value_grab_string(value, dest) \ |
| avro_value_call(value, grab_string, EINVAL, dest) |
| #define avro_value_get_enum(value, out) \ |
| avro_value_call(value, get_enum, EINVAL, out) |
| #define avro_value_get_fixed(value, buf, size) \ |
| avro_value_call(value, get_fixed, EINVAL, buf, size) |
| #define avro_value_grab_fixed(value, dest) \ |
| avro_value_call(value, grab_fixed, EINVAL, dest) |
| |
| #define avro_value_set_boolean(value, val) \ |
| avro_value_call(value, set_boolean, EINVAL, val) |
| #define avro_value_set_bytes(value, buf, size) \ |
| avro_value_call(value, set_bytes, EINVAL, buf, size) |
| #define avro_value_give_bytes(value, buf) \ |
| avro_value_call(value, give_bytes, EINVAL, buf) |
| #define avro_value_set_double(value, val) \ |
| avro_value_call(value, set_double, EINVAL, val) |
| #define avro_value_set_float(value, val) \ |
| avro_value_call(value, set_float, EINVAL, val) |
| #define avro_value_set_int(value, val) \ |
| avro_value_call(value, set_int, EINVAL, val) |
| #define avro_value_set_long(value, val) \ |
| avro_value_call(value, set_long, EINVAL, val) |
| #define avro_value_set_null(value) \ |
| avro_value_call0(value, set_null, EINVAL) |
| #define avro_value_set_string(value, str) \ |
| avro_value_call(value, set_string, EINVAL, str) |
| #define avro_value_set_string_len(value, str, size) \ |
| avro_value_call(value, set_string_len, EINVAL, str, size) |
| #define avro_value_give_string_len(value, buf) \ |
| avro_value_call(value, give_string_len, EINVAL, buf) |
| #define avro_value_set_enum(value, val) \ |
| avro_value_call(value, set_enum, EINVAL, val) |
| #define avro_value_set_fixed(value, buf, size) \ |
| avro_value_call(value, set_fixed, EINVAL, buf, size) |
| #define avro_value_give_fixed(value, buf) \ |
| avro_value_call(value, give_fixed, EINVAL, buf) |
| |
| #define avro_value_get_size(value, size) \ |
| avro_value_call(value, get_size, EINVAL, size) |
| #define avro_value_get_by_index(value, idx, child, name) \ |
| avro_value_call(value, get_by_index, EINVAL, idx, child, name) |
| #define avro_value_get_by_name(value, name, child, index) \ |
| avro_value_call(value, get_by_name, EINVAL, name, child, index) |
| #define avro_value_get_discriminant(value, out) \ |
| avro_value_call(value, get_discriminant, EINVAL, out) |
| #define avro_value_get_current_branch(value, branch) \ |
| avro_value_call(value, get_current_branch, EINVAL, branch) |
| |
| #define avro_value_append(value, child, new_index) \ |
| avro_value_call(value, append, EINVAL, child, new_index) |
| #define avro_value_add(value, key, child, index, is_new) \ |
| avro_value_call(value, add, EINVAL, key, child, index, is_new) |
| #define avro_value_set_branch(value, discriminant, branch) \ |
| avro_value_call(value, set_branch, EINVAL, discriminant, branch) |
| |
| CLOSE_EXTERN |
| #endif |