blob: 5b1d429b3a8a9b46ab45ec0469012f2bf6b835c2 [file] [log] [blame]
/*
* 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