|
Packit |
2997f0 |
/*
|
|
Packit |
2997f0 |
* librdkafka - Apache Kafka C library
|
|
Packit |
2997f0 |
*
|
|
Packit |
2997f0 |
* Copyright (c) 2012-2015, Magnus Edenhill
|
|
Packit |
2997f0 |
* All rights reserved.
|
|
Packit |
2997f0 |
*
|
|
Packit |
2997f0 |
* Redistribution and use in source and binary forms, with or without
|
|
Packit |
2997f0 |
* modification, are permitted provided that the following conditions are met:
|
|
Packit |
2997f0 |
*
|
|
Packit |
2997f0 |
* 1. Redistributions of source code must retain the above copyright notice,
|
|
Packit |
2997f0 |
* this list of conditions and the following disclaimer.
|
|
Packit |
2997f0 |
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
Packit |
2997f0 |
* this list of conditions and the following disclaimer in the documentation
|
|
Packit |
2997f0 |
* and/or other materials provided with the distribution.
|
|
Packit |
2997f0 |
*
|
|
Packit |
2997f0 |
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
Packit |
2997f0 |
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
Packit |
2997f0 |
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
Packit |
2997f0 |
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
|
Packit |
2997f0 |
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
Packit |
2997f0 |
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
Packit |
2997f0 |
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
Packit |
2997f0 |
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
Packit |
2997f0 |
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
Packit |
2997f0 |
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
Packit |
2997f0 |
* POSSIBILITY OF SUCH DAMAGE.
|
|
Packit |
2997f0 |
*/
|
|
Packit |
2997f0 |
|
|
Packit |
2997f0 |
#ifndef _RDLIST_H_
|
|
Packit |
2997f0 |
#define _RDLIST_H_
|
|
Packit |
2997f0 |
|
|
Packit |
2997f0 |
|
|
Packit |
2997f0 |
/**
|
|
Packit |
2997f0 |
*
|
|
Packit |
2997f0 |
* Simple light-weight append-only list to be used as a collection convenience.
|
|
Packit |
2997f0 |
*
|
|
Packit |
2997f0 |
*/
|
|
Packit |
2997f0 |
|
|
Packit |
2997f0 |
typedef struct rd_list_s {
|
|
Packit |
2997f0 |
int rl_size;
|
|
Packit |
2997f0 |
int rl_cnt;
|
|
Packit |
2997f0 |
void **rl_elems;
|
|
Packit |
2997f0 |
void (*rl_free_cb) (void *);
|
|
Packit |
2997f0 |
int rl_flags;
|
|
Packit |
2997f0 |
#define RD_LIST_F_ALLOCATED 0x1 /* The rd_list_t is allocated,
|
|
Packit |
2997f0 |
* will be free on destroy() */
|
|
Packit |
2997f0 |
#define RD_LIST_F_SORTED 0x2 /* Set by sort(), cleared by any mutations.
|
|
Packit |
2997f0 |
* When this flag is set bsearch() is used
|
|
Packit |
2997f0 |
* by find(), otherwise a linear search. */
|
|
Packit |
2997f0 |
#define RD_LIST_F_FIXED_SIZE 0x4 /* Assert on grow */
|
|
Packit |
2997f0 |
#define RD_LIST_F_UNIQUE 0x8 /* Don't allow duplicates:
|
|
Packit |
2997f0 |
* ONLY ENFORCED BY CALLER. */
|
|
Packit |
2997f0 |
} rd_list_t;
|
|
Packit |
2997f0 |
|
|
Packit |
2997f0 |
|
|
Packit |
2997f0 |
/**
|
|
Packit |
2997f0 |
* @brief Initialize a list, preallocate space for 'initial_size' elements
|
|
Packit |
2997f0 |
* (optional).
|
|
Packit |
2997f0 |
* List elements will optionally be freed by \p free_cb.
|
|
Packit |
2997f0 |
*
|
|
Packit |
2997f0 |
* @returns \p rl
|
|
Packit |
2997f0 |
*/
|
|
Packit |
2997f0 |
rd_list_t *
|
|
Packit |
2997f0 |
rd_list_init (rd_list_t *rl, int initial_size, void (*free_cb) (void *));
|
|
Packit |
2997f0 |
|
|
Packit |
2997f0 |
|
|
Packit |
2997f0 |
/**
|
|
Packit |
2997f0 |
* Allocate a new list pointer and initialize it according to rd_list_init().
|
|
Packit |
2997f0 |
*
|
|
Packit |
2997f0 |
* Use rd_list_destroy() to free.
|
|
Packit |
2997f0 |
*/
|
|
Packit |
2997f0 |
rd_list_t *rd_list_new (int initial_size, void (*free_cb) (void *));
|
|
Packit |
2997f0 |
|
|
Packit |
2997f0 |
|
|
Packit |
2997f0 |
/**
|
|
Packit |
2997f0 |
* @brief Prepare list to for an additional \p size elements.
|
|
Packit |
2997f0 |
* This is an optimization to avoid incremental grows.
|
|
Packit |
2997f0 |
*/
|
|
Packit |
2997f0 |
void rd_list_grow (rd_list_t *rl, size_t size);
|
|
Packit |
2997f0 |
|
|
Packit |
2997f0 |
/**
|
|
Packit |
2997f0 |
* @brief Preallocate elements to avoid having to pass an allocated pointer to
|
|
Packit |
2997f0 |
* rd_list_add(), instead pass NULL to rd_list_add() and use the returned
|
|
Packit |
2997f0 |
* pointer as the element.
|
|
Packit |
2997f0 |
*
|
|
Packit |
2997f0 |
* @param elemsize element size
|
|
Packit |
2997f0 |
* @param size number of elements
|
|
Packit |
2997f0 |
*
|
|
Packit |
2997f0 |
* @remark Preallocated element lists can't grow past \p size.
|
|
Packit |
2997f0 |
*/
|
|
Packit |
2997f0 |
void rd_list_prealloc_elems (rd_list_t *rl, size_t elemsize, size_t size);
|
|
Packit |
2997f0 |
|
|
Packit |
2997f0 |
|
|
Packit |
2997f0 |
/**
|
|
Packit |
2997f0 |
* @brief Free a pointer using the list's free_cb
|
|
Packit |
2997f0 |
*
|
|
Packit |
2997f0 |
* @remark If no free_cb is set, or \p ptr is NULL, dont do anything
|
|
Packit |
2997f0 |
*
|
|
Packit |
2997f0 |
* Typical use is rd_list_free_cb(rd_list_remove_cmp(....));
|
|
Packit |
2997f0 |
*/
|
|
Packit |
2997f0 |
void rd_list_free_cb (rd_list_t *rl, void *ptr);
|
|
Packit |
2997f0 |
|
|
Packit |
2997f0 |
|
|
Packit |
2997f0 |
/**
|
|
Packit |
2997f0 |
* @brief Append element to list
|
|
Packit |
2997f0 |
*
|
|
Packit |
2997f0 |
* @returns \p elem. If \p elem is NULL the default element for that index
|
|
Packit |
2997f0 |
* will be returned (for use with set_elems).
|
|
Packit |
2997f0 |
*/
|
|
Packit |
2997f0 |
void *rd_list_add (rd_list_t *rl, void *elem);
|
|
Packit |
2997f0 |
|
|
Packit |
2997f0 |
|
|
Packit |
2997f0 |
/**
|
|
Packit |
2997f0 |
* Remove element from list.
|
|
Packit |
2997f0 |
* This is a slow O(n) + memmove operation.
|
|
Packit |
2997f0 |
* Returns the removed element.
|
|
Packit |
2997f0 |
*/
|
|
Packit |
2997f0 |
void *rd_list_remove (rd_list_t *rl, void *match_elem);
|
|
Packit |
2997f0 |
|
|
Packit |
2997f0 |
/**
|
|
Packit |
2997f0 |
* Remove element from list using comparator.
|
|
Packit |
2997f0 |
* See rd_list_remove()
|
|
Packit |
2997f0 |
*/
|
|
Packit |
2997f0 |
void *rd_list_remove_cmp (rd_list_t *rl, void *match_elem,
|
|
Packit |
2997f0 |
int (*cmp) (void *_a, void *_b));
|
|
Packit |
2997f0 |
|
|
Packit |
2997f0 |
|
|
Packit |
2997f0 |
/**
|
|
Packit |
2997f0 |
* @brief Remove element at index \p idx.
|
|
Packit |
2997f0 |
*
|
|
Packit |
2997f0 |
* This is a O(1) + memmove operation
|
|
Packit |
2997f0 |
*/
|
|
Packit |
2997f0 |
void rd_list_remove_elem (rd_list_t *rl, int idx);
|
|
Packit |
2997f0 |
|
|
Packit |
2997f0 |
|
|
Packit |
2997f0 |
/**
|
|
Packit |
2997f0 |
* @brief Remove all elements matching comparator.
|
|
Packit |
2997f0 |
*
|
|
Packit |
2997f0 |
* @returns the number of elements removed.
|
|
Packit |
2997f0 |
*
|
|
Packit |
2997f0 |
* @sa rd_list_remove()
|
|
Packit |
2997f0 |
*/
|
|
Packit |
2997f0 |
int rd_list_remove_multi_cmp (rd_list_t *rl, void *match_elem,
|
|
Packit |
2997f0 |
int (*cmp) (void *_a, void *_b));
|
|
Packit |
2997f0 |
|
|
Packit |
2997f0 |
|
|
Packit |
2997f0 |
/**
|
|
Packit |
2997f0 |
* Sort list using comparator
|
|
Packit |
2997f0 |
*/
|
|
Packit |
2997f0 |
void rd_list_sort (rd_list_t *rl, int (*cmp) (const void *, const void *));
|
|
Packit |
2997f0 |
|
|
Packit |
2997f0 |
|
|
Packit |
2997f0 |
/**
|
|
Packit |
2997f0 |
* Empties the list (but does not free any memory)
|
|
Packit |
2997f0 |
*/
|
|
Packit |
2997f0 |
void rd_list_clear (rd_list_t *rl);
|
|
Packit |
2997f0 |
|
|
Packit |
2997f0 |
|
|
Packit |
2997f0 |
/**
|
|
Packit |
2997f0 |
* Empties the list, frees the element array, and optionally frees
|
|
Packit |
2997f0 |
* each element using the registered \c rl->rl_free_cb.
|
|
Packit |
2997f0 |
*
|
|
Packit |
2997f0 |
* If the list was previously allocated with rd_list_new() it will be freed.
|
|
Packit |
2997f0 |
*/
|
|
Packit |
2997f0 |
void rd_list_destroy (rd_list_t *rl);
|
|
Packit |
2997f0 |
|
|
Packit |
2997f0 |
|
|
Packit |
2997f0 |
/**
|
|
Packit |
2997f0 |
* Returns the element at index 'idx', or NULL if out of range.
|
|
Packit |
2997f0 |
*
|
|
Packit |
2997f0 |
* Typical iteration is:
|
|
Packit |
2997f0 |
* int i = 0;
|
|
Packit |
2997f0 |
* my_type_t *obj;
|
|
Packit |
2997f0 |
* while ((obj = rd_list_elem(rl, i++)))
|
|
Packit |
2997f0 |
* do_something(obj);
|
|
Packit |
2997f0 |
*/
|
|
Packit |
2997f0 |
void *rd_list_elem (const rd_list_t *rl, int idx);
|
|
Packit |
2997f0 |
|
|
Packit |
2997f0 |
#define RD_LIST_FOREACH(elem,listp,idx) \
|
|
Packit |
2997f0 |
for (idx = 0 ; (elem = rd_list_elem(listp, idx)) ; idx++)
|
|
Packit |
2997f0 |
|
|
Packit |
2997f0 |
#define RD_LIST_FOREACH_REVERSE(elem,listp,idx) \
|
|
Packit |
2997f0 |
for (idx = (listp)->rl_cnt-1 ; \
|
|
Packit |
2997f0 |
idx >= 0 && (elem = rd_list_elem(listp, idx)) ; idx--)
|
|
Packit |
2997f0 |
|
|
Packit |
2997f0 |
/**
|
|
Packit |
2997f0 |
* Returns the number of elements in list.
|
|
Packit |
2997f0 |
*/
|
|
Packit |
2997f0 |
static RD_INLINE RD_UNUSED int rd_list_cnt (const rd_list_t *rl) {
|
|
Packit |
2997f0 |
return rl->rl_cnt;
|
|
Packit |
2997f0 |
}
|
|
Packit |
2997f0 |
|
|
Packit |
2997f0 |
|
|
Packit |
2997f0 |
/**
|
|
Packit |
2997f0 |
* Returns true if list is empty
|
|
Packit |
2997f0 |
*/
|
|
Packit |
2997f0 |
#define rd_list_empty(rl) (rd_list_cnt(rl) == 0)
|
|
Packit |
2997f0 |
|
|
Packit |
2997f0 |
|
|
Packit |
2997f0 |
|
|
Packit |
2997f0 |
/**
|
|
Packit |
2997f0 |
* Find element using comparator
|
|
Packit |
2997f0 |
* 'match' will be the first argument to 'cmp', and each element (up to a match)
|
|
Packit |
2997f0 |
* will be the second argument to 'cmp'.
|
|
Packit |
2997f0 |
*/
|
|
Packit |
2997f0 |
void *rd_list_find (const rd_list_t *rl, const void *match,
|
|
Packit |
2997f0 |
int (*cmp) (const void *, const void *));
|
|
Packit |
2997f0 |
|
|
Packit |
2997f0 |
|
|
Packit |
2997f0 |
|
|
Packit |
2997f0 |
/**
|
|
Packit |
2997f0 |
* @brief Compare list \p a to \p b.
|
|
Packit |
2997f0 |
*
|
|
Packit |
2997f0 |
* @returns < 0 if a was "lesser" than b,
|
|
Packit |
2997f0 |
* > 0 if a was "greater" than b,
|
|
Packit |
2997f0 |
* 0 if a and b are equal.
|
|
Packit |
2997f0 |
*/
|
|
Packit |
2997f0 |
int rd_list_cmp (const rd_list_t *a, rd_list_t *b,
|
|
Packit |
2997f0 |
int (*cmp) (const void *, const void *));
|
|
Packit |
2997f0 |
|
|
Packit |
2997f0 |
/**
|
|
Packit |
2997f0 |
* @brief Simple element pointer comparator
|
|
Packit |
2997f0 |
*/
|
|
Packit |
2997f0 |
int rd_list_cmp_ptr (const void *a, const void *b);
|
|
Packit |
2997f0 |
|
|
Packit |
2997f0 |
|
|
Packit |
2997f0 |
/**
|
|
Packit |
2997f0 |
* @brief Apply \p cb to each element in list, if \p cb returns 0
|
|
Packit |
2997f0 |
* the element will be removed (but not freed).
|
|
Packit |
2997f0 |
*/
|
|
Packit |
2997f0 |
void rd_list_apply (rd_list_t *rl,
|
|
Packit |
2997f0 |
int (*cb) (void *elem, void *opaque), void *opaque);
|
|
Packit |
2997f0 |
|
|
Packit |
2997f0 |
|
|
Packit |
2997f0 |
|
|
Packit |
2997f0 |
/**
|
|
Packit |
2997f0 |
* @brief Copy list \p src, returning a new list,
|
|
Packit |
2997f0 |
* using optional \p copy_cb (per elem)
|
|
Packit |
2997f0 |
*/
|
|
Packit |
2997f0 |
rd_list_t *rd_list_copy (const rd_list_t *src,
|
|
Packit |
2997f0 |
void *(*copy_cb) (const void *elem, void *opaque),
|
|
Packit |
2997f0 |
void *opaque);
|
|
Packit |
2997f0 |
|
|
Packit |
2997f0 |
|
|
Packit |
2997f0 |
/**
|
|
Packit |
2997f0 |
* @brief Copy list \p src to \p dst using optional \p copy_cb (per elem)
|
|
Packit |
2997f0 |
* @remark The destination list is not initialized or copied by this function.
|
|
Packit |
2997f0 |
* @remark copy_cb() may return NULL in which case no element is added,
|
|
Packit |
2997f0 |
* but the copy callback might have done so itself.
|
|
Packit |
2997f0 |
*/
|
|
Packit |
2997f0 |
void rd_list_copy_to (rd_list_t *dst, const rd_list_t *src,
|
|
Packit |
2997f0 |
void *(*copy_cb) (const void *elem, void *opaque),
|
|
Packit |
2997f0 |
void *opaque);
|
|
Packit |
2997f0 |
|
|
Packit |
2997f0 |
/**
|
|
Packit |
2997f0 |
* @brief String copier for rd_list_copy()
|
|
Packit |
2997f0 |
*/
|
|
Packit |
2997f0 |
static RD_UNUSED
|
|
Packit |
2997f0 |
void *rd_list_string_copy (const void *elem, void *opaque) {
|
|
Packit |
2997f0 |
return rd_strdup((const char *)elem);
|
|
Packit |
2997f0 |
}
|
|
Packit |
2997f0 |
|
|
Packit |
2997f0 |
|
|
Packit |
2997f0 |
/**
|
|
Packit |
2997f0 |
* Debugging: Print list to stdout.
|
|
Packit |
2997f0 |
*/
|
|
Packit |
2997f0 |
void rd_list_dump (const char *what, const rd_list_t *rl);
|
|
Packit |
2997f0 |
|
|
Packit |
2997f0 |
#endif /* _RDLIST_H_ */
|