| /* |
| * 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_DATA_H |
| #define AVRO_DATA_H |
| #ifdef __cplusplus |
| extern "C" { |
| #define CLOSE_EXTERN } |
| #else |
| #define CLOSE_EXTERN |
| #endif |
| |
| #include <stdlib.h> |
| #include <string.h> |
| |
| /* |
| * This file defines some helper data structures that are used within |
| * Avro, and in the schema-specific types created by avrocc. |
| */ |
| |
| |
| /*--------------------------------------------------------------------- |
| * Arrays |
| */ |
| |
| /** |
| * A resizeable array of fixed-size elements. |
| */ |
| |
| typedef struct avro_raw_array { |
| size_t element_size; |
| size_t element_count; |
| size_t allocated_size; |
| void *data; |
| } avro_raw_array_t; |
| |
| /** |
| * Initializes a new avro_raw_array_t that you've allocated yourself. |
| */ |
| |
| void avro_raw_array_init(avro_raw_array_t *array, size_t element_size); |
| |
| /** |
| * Finalizes an avro_raw_array_t. |
| */ |
| |
| void avro_raw_array_done(avro_raw_array_t *array); |
| |
| /** |
| * Clears an avro_raw_array_t. This does not deallocate any space; this |
| * allows us to reuse the underlying array buffer as we start to re-add |
| * elements to the array. |
| */ |
| |
| void avro_raw_array_clear(avro_raw_array_t *array); |
| |
| /** |
| * Ensures that there is enough allocated space to store the given |
| * number of elements in an avro_raw_array_t. If we can't allocate that |
| * much space, we return ENOMEM. |
| */ |
| |
| int |
| avro_raw_array_ensure_size(avro_raw_array_t *array, size_t desired_count); |
| |
| /** |
| * Ensures that there is enough allocated space to store the given |
| * number of elements in an avro_raw_array_t. If the array grows as a |
| * result of this operation, we will fill in any newly allocated space |
| * with 0 bytes. If we can't allocate that much space, we return |
| * ENOMEM. |
| */ |
| |
| int |
| avro_raw_array_ensure_size0(avro_raw_array_t *array, size_t desired_count); |
| |
| /** |
| * Returns the number of elements in an avro_raw_array_t. |
| */ |
| |
| #define avro_raw_array_size(array) ((array)->element_count) |
| |
| /** |
| * Returns the given element of an avro_raw_array_t as a <code>void |
| * *</code>. |
| */ |
| |
| #define avro_raw_array_get_raw(array, index) \ |
| ((char *) (array)->data + (array)->element_size * index) |
| |
| /** |
| * Returns the given element of an avro_raw_array_t, using element_type |
| * as the type of the elements. The result is *not* a pointer to the |
| * element; you get the element itself. |
| */ |
| |
| #define avro_raw_array_get(array, element_type, index) \ |
| (((element_type *) (array)->data)[index]) |
| |
| /** |
| * Appends a new element to an avro_raw_array_t, expanding it if |
| * necessary. Returns a pointer to the new element, or NULL if we |
| * needed to reallocate the array and couldn't. |
| */ |
| |
| void *avro_raw_array_append(avro_raw_array_t *array); |
| |
| |
| /*--------------------------------------------------------------------- |
| * Maps |
| */ |
| |
| /** |
| * The type of the elements in a map's elements array. |
| */ |
| |
| typedef struct avro_raw_map_entry { |
| const char *key; |
| } avro_raw_map_entry_t; |
| |
| /** |
| * A string-indexed map of fixed-size elements. |
| */ |
| |
| typedef struct avro_raw_map { |
| avro_raw_array_t elements; |
| void *indices_by_key; |
| } avro_raw_map_t; |
| |
| /** |
| * Initializes a new avro_raw_map_t that you've allocated yourself. |
| */ |
| |
| void avro_raw_map_init(avro_raw_map_t *map, size_t element_size); |
| |
| /** |
| * Finalizes an avro_raw_map_t. |
| */ |
| |
| void avro_raw_map_done(avro_raw_map_t *map); |
| |
| /** |
| * Clears an avro_raw_map_t. |
| */ |
| |
| void avro_raw_map_clear(avro_raw_map_t *map); |
| |
| /** |
| * Ensures that there is enough allocated space to store the given |
| * number of elements in an avro_raw_map_t. If we can't allocate that |
| * much space, we return ENOMEM. |
| */ |
| |
| int |
| avro_raw_map_ensure_size(avro_raw_map_t *map, size_t desired_count); |
| |
| /** |
| * Returns the number of elements in an avro_raw_map_t. |
| */ |
| |
| #define avro_raw_map_size(map) avro_raw_array_size(&((map)->elements)) |
| |
| /** |
| * Returns the avro_raw_map_entry_t for a given index. |
| */ |
| |
| #define avro_raw_get_entry(map, index) \ |
| ((avro_raw_map_entry_t *) \ |
| avro_raw_array_get_raw(&(map)->elements, index)) |
| |
| /** |
| * Returns the given element of an avro_raw_array_t as a <code>void |
| * *</code>. The indexes are assigned based on the order that the |
| * elements are added to the map. |
| */ |
| |
| #define avro_raw_map_get_raw(map, index) \ |
| (avro_raw_array_get_raw(&(map)->elements, index) + \ |
| sizeof(avro_raw_map_entry_t)) |
| |
| /** |
| * Returns the element of an avro_raw_map_t with the given numeric |
| * index. The indexes are assigned based on the order that the elements |
| * are added to the map. |
| */ |
| |
| #define avro_raw_map_get_by_index(map, element_type, index) \ |
| (*((element_type *) avro_raw_map_get_raw(map, index))) |
| |
| /** |
| * Returns the key of the element with the given numeric index. |
| */ |
| |
| #define avro_raw_map_get_key(map, index) \ |
| (avro_raw_get_entry(map, index)->key) |
| |
| /** |
| * Returns the element of an avro_raw_map_t with the given string key. |
| * If the given element doesn't exist, returns NULL. If @ref index |
| * isn't NULL, it will be filled in with the index of the element. |
| */ |
| |
| void *avro_raw_map_get(const avro_raw_map_t *map, const char *key, |
| size_t *index); |
| |
| /** |
| * Retrieves the element of an avro_raw_map_t with the given string key, |
| * creating it if necessary. A pointer to the element is placed into |
| * @ref element. If @ref index isn't NULL, it will be filled in with |
| * the index of the element. We return 1 if the element is new; 0 if |
| * it's not, and a negative error code if there was some problem. |
| */ |
| |
| int avro_raw_map_get_or_create(avro_raw_map_t *map, const char *key, |
| void **element, size_t *index); |
| |
| |
| /*--------------------------------------------------------------------- |
| * Wrapped buffers |
| */ |
| |
| /** |
| * A pointer to an unmodifiable external memory region, along with |
| * functions for freeing that buffer when it's no longer needed, and |
| * copying it. |
| */ |
| |
| typedef struct avro_wrapped_buffer avro_wrapped_buffer_t; |
| |
| struct avro_wrapped_buffer { |
| /** A pointer to the memory region */ |
| const void *buf; |
| |
| /** The size of the memory region */ |
| size_t size; |
| |
| /** Additional data needed by the methods below */ |
| void *user_data; |
| |
| /** |
| * A function that will be called when the memory region is no |
| * longer needed. This pointer can be NULL if nothing special |
| * needs to be done to free the buffer. |
| */ |
| void |
| (*free)(avro_wrapped_buffer_t *self); |
| |
| /** |
| * A function that makes a copy of a portion of a wrapped |
| * buffer. This doesn't have to involve duplicating the memory |
| * region, but it should ensure that the free method can be |
| * safely called on both copies without producing any errors or |
| * memory corruption. If this function is NULL, then we'll use |
| * a default implementation that calls @ref |
| * avro_wrapped_buffer_new_copy. |
| */ |
| int |
| (*copy)(avro_wrapped_buffer_t *dest, const avro_wrapped_buffer_t *src, |
| size_t offset, size_t length); |
| |
| /** |
| * A function that "slices" a wrapped buffer, causing it to |
| * point at a subset of the existing buffer. Usually, this just |
| * requires * updating the @ref buf and @ref size fields. If |
| * you don't need to do anything other than this, this function |
| * pointer can be left @c NULL. The function can assume that |
| * the @a offset and @a length parameters point to a valid |
| * subset of the existing wrapped buffer. |
| */ |
| int |
| (*slice)(avro_wrapped_buffer_t *self, size_t offset, size_t length); |
| }; |
| |
| /** |
| * Free a wrapped buffer. |
| */ |
| |
| #define avro_wrapped_buffer_free(self) \ |
| do { \ |
| if ((self)->free != NULL) { \ |
| (self)->free((self)); \ |
| } \ |
| } while (0) |
| |
| /** |
| * A static initializer for an empty wrapped buffer. |
| */ |
| |
| #define AVRO_WRAPPED_BUFFER_EMPTY { NULL, 0, NULL, NULL, NULL, NULL } |
| |
| /** |
| * Moves a wrapped buffer. After returning, @a dest will wrap the |
| * buffer that @a src used to point at, and @a src will be empty. |
| */ |
| |
| void |
| avro_wrapped_buffer_move(avro_wrapped_buffer_t *dest, |
| avro_wrapped_buffer_t *src); |
| |
| /** |
| * Copies a buffer. |
| */ |
| |
| int |
| avro_wrapped_buffer_copy(avro_wrapped_buffer_t *dest, |
| const avro_wrapped_buffer_t *src, |
| size_t offset, size_t length); |
| |
| /** |
| * Slices a buffer. |
| */ |
| |
| int |
| avro_wrapped_buffer_slice(avro_wrapped_buffer_t *self, |
| size_t offset, size_t length); |
| |
| /** |
| * Creates a new wrapped buffer wrapping the given memory region. You |
| * have to ensure that buf stays around for as long as you need to new |
| * wrapped buffer. If you copy the wrapped buffer (using |
| * avro_wrapped_buffer_copy), this will create a copy of the data. |
| * Additional copies will reuse this new copy. |
| */ |
| |
| int |
| avro_wrapped_buffer_new(avro_wrapped_buffer_t *dest, |
| const void *buf, size_t length); |
| |
| /** |
| * Creates a new wrapped buffer wrapping the given C string. |
| */ |
| |
| #define avro_wrapped_buffer_new_string(dest, str) \ |
| (avro_wrapped_buffer_new((dest), (str), strlen((str))+1)) |
| |
| /** |
| * Creates a new wrapped buffer containing a copy of the given memory |
| * region. This new copy will be reference counted; if you copy it |
| * further (using avro_wrapped_buffer_copy), the new copies will share a |
| * single underlying buffer. |
| */ |
| |
| int |
| avro_wrapped_buffer_new_copy(avro_wrapped_buffer_t *dest, |
| const void *buf, size_t length); |
| |
| /** |
| * Creates a new wrapped buffer containing a copy of the given C string. |
| */ |
| |
| #define avro_wrapped_buffer_new_string_copy(dest, str) \ |
| (avro_wrapped_buffer_new_copy((dest), (str), strlen((str))+1)) |
| |
| |
| /*--------------------------------------------------------------------- |
| * Strings |
| */ |
| |
| /** |
| * A resizable buffer for storing strings and bytes values. |
| */ |
| |
| typedef struct avro_raw_string { |
| avro_wrapped_buffer_t wrapped; |
| } avro_raw_string_t; |
| |
| /** |
| * Initializes an avro_raw_string_t that you've allocated yourself. |
| */ |
| |
| void avro_raw_string_init(avro_raw_string_t *str); |
| |
| /** |
| * Finalizes an avro_raw_string_t. |
| */ |
| |
| void avro_raw_string_done(avro_raw_string_t *str); |
| |
| /** |
| * Returns the length of the data stored in an avro_raw_string_t. If |
| * the buffer contains a C string, this length includes the NUL |
| * terminator. |
| */ |
| |
| #define avro_raw_string_length(str) ((str)->wrapped.size) |
| |
| /** |
| * Returns a pointer to the data stored in an avro_raw_string_t. |
| */ |
| |
| #define avro_raw_string_get(str) ((str)->wrapped.buf) |
| |
| /** |
| * Fills an avro_raw_string_t with a copy of the given buffer. |
| */ |
| |
| void avro_raw_string_set_length(avro_raw_string_t *str, |
| const void *src, |
| size_t length); |
| |
| /** |
| * Fills an avro_raw_string_t with a copy of the given C string. |
| */ |
| |
| void avro_raw_string_set(avro_raw_string_t *str, const char *src); |
| |
| /** |
| * Appends the given C string to an avro_raw_string_t. |
| */ |
| |
| void avro_raw_string_append(avro_raw_string_t *str, const char *src); |
| |
| /** |
| * Appends the given C string to an avro_raw_string_t, using the |
| * provided length instead of calling strlen(src). |
| */ |
| |
| void avro_raw_string_append_length(avro_raw_string_t *str, |
| const void *src, |
| size_t length); |
| /** |
| * Gives control of a buffer to an avro_raw_string_t. |
| */ |
| |
| void |
| avro_raw_string_give(avro_raw_string_t *str, |
| avro_wrapped_buffer_t *src); |
| |
| /** |
| * Returns an avro_wrapped_buffer_t for the content of the string, |
| * ideally without copying it. |
| */ |
| |
| int |
| avro_raw_string_grab(const avro_raw_string_t *str, |
| avro_wrapped_buffer_t *dest); |
| |
| /** |
| * Clears an avro_raw_string_t. |
| */ |
| |
| void avro_raw_string_clear(avro_raw_string_t *str); |
| |
| |
| /** |
| * Tests two avro_raw_string_t instances for equality. |
| */ |
| |
| int avro_raw_string_equals(const avro_raw_string_t *str1, |
| const avro_raw_string_t *str2); |
| |
| |
| /*--------------------------------------------------------------------- |
| * Memoization |
| */ |
| |
| /** |
| * A specialized map that can be used to memoize the results of a |
| * function. The API allows you to use two keys as the memoization |
| * keys; if you only need one key, just use NULL for the second key. |
| * The result of the function should be a single pointer, or an integer |
| * that can be cast into a pointer (i.e., an intptr_t). |
| */ |
| |
| typedef struct avro_memoize { |
| void *cache; |
| } avro_memoize_t; |
| |
| /** |
| * Initialize an avro_memoize_t that you've allocated for yourself. |
| */ |
| |
| void |
| avro_memoize_init(avro_memoize_t *mem); |
| |
| /** |
| * Finalizes an avro_memoize_t. |
| */ |
| |
| void |
| avro_memoize_done(avro_memoize_t *mem); |
| |
| /** |
| * Search for a cached value in an avro_memoize_t. Returns a boolean |
| * indicating whether there's a value in the cache for the given keys. |
| * If there is, the cached result is placed into @ref result. |
| */ |
| |
| int |
| avro_memoize_get(avro_memoize_t *mem, |
| void *key1, void *key2, |
| void **result); |
| |
| /** |
| * Stores a new cached value into an avro_memoize_t, overwriting it if |
| * necessary. |
| */ |
| |
| void |
| avro_memoize_set(avro_memoize_t *mem, |
| void *key1, void *key2, |
| void *result); |
| |
| /** |
| * Removes any cached value for the given key from an avro_memoize_t. |
| */ |
| |
| void |
| avro_memoize_delete(avro_memoize_t *mem, void *key1, void *key2); |
| |
| CLOSE_EXTERN |
| #endif |