Blame src/rdlist.h

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_ */