// Copyright 2011-2022 David Robillard // SPDX-License-Identifier: ISC #ifndef ZIX_TREE_H #define ZIX_TREE_H #include "zix/allocator.h" #include "zix/attributes.h" #include "zix/status.h" #include #include ZIX_BEGIN_DECLS /** @defgroup zix_tree Tree @ingroup zix_data_structures @{ */ /** @defgroup zix_tree_setup Setup @{ */ /// A balanced binary search tree typedef struct ZixTreeImpl ZixTree; /// Function for comparing two Tree elements typedef int (*ZixTreeCompareFunc)(const void* ZIX_UNSPECIFIED a, const void* ZIX_UNSPECIFIED b, const void* ZIX_UNSPECIFIED user_data); /// Function to destroy a Tree element typedef void (*ZixTreeDestroyFunc)(void* ZIX_UNSPECIFIED ptr, const void* ZIX_UNSPECIFIED user_data); /// Create a new (empty) tree ZIX_API ZIX_NODISCARD ZixTree* ZIX_ALLOCATED zix_tree_new(ZixAllocator* ZIX_NULLABLE allocator, bool allow_duplicates, ZixTreeCompareFunc ZIX_NONNULL cmp, void* ZIX_UNSPECIFIED cmp_data, ZixTreeDestroyFunc ZIX_NULLABLE destroy, const void* ZIX_NULLABLE destroy_user_data); /// Free `t` ZIX_API void zix_tree_free(ZixTree* ZIX_NULLABLE t); /// Return the number of elements in `t` ZIX_PURE_API size_t zix_tree_size(const ZixTree* ZIX_NONNULL t); /** @} @defgroup zix_tree_iteration Iteration @{ */ /// An iterator over a @ref ZixTree typedef struct ZixTreeNodeImpl ZixTreeIter; /// Return the data associated with the given tree item ZIX_PURE_API void* ZIX_UNSPECIFIED zix_tree_get(const ZixTreeIter* ZIX_NULLABLE ti); /// Return an iterator to the first (smallest) element in `t` ZIX_PURE_API ZixTreeIter* ZIX_NULLABLE zix_tree_begin(ZixTree* ZIX_NONNULL t); /// Return an iterator the the element one past the last element in `t` ZIX_CONST_API ZixTreeIter* ZIX_NULLABLE zix_tree_end(ZixTree* ZIX_NONNULL t); /// Return true iff `i` is an iterator to the end of its tree ZIX_CONST_API bool zix_tree_iter_is_end(const ZixTreeIter* ZIX_NULLABLE i); /// Return an iterator to the last (largest) element in `t` ZIX_PURE_API ZixTreeIter* ZIX_NULLABLE zix_tree_rbegin(ZixTree* ZIX_NONNULL t); /// Return an iterator the the element one before the first element in `t` ZIX_CONST_API ZixTreeIter* ZIX_NULLABLE zix_tree_rend(ZixTree* ZIX_NONNULL t); /// Return true iff `i` is an iterator to the reverse end of its tree ZIX_CONST_API bool zix_tree_iter_is_rend(const ZixTreeIter* ZIX_NULLABLE i); /// Return an iterator that points to the element one past `i` ZIX_PURE_API ZixTreeIter* ZIX_NULLABLE zix_tree_iter_next(ZixTreeIter* ZIX_NULLABLE i); /// Return an iterator that points to the element one before `i` ZIX_PURE_API ZixTreeIter* ZIX_NULLABLE zix_tree_iter_prev(ZixTreeIter* ZIX_NULLABLE i); /** @} @defgroup zix_tree_modification Modification @{ */ /// Insert the element `e` into `t` and point `ti` at the new element ZIX_API ZixStatus zix_tree_insert(ZixTree* ZIX_NONNULL t, void* ZIX_UNSPECIFIED e, ZixTreeIter* ZIX_NULLABLE* ZIX_NULLABLE ti); /// Remove the item pointed at by `ti` from `t` ZIX_API ZixStatus zix_tree_remove(ZixTree* ZIX_NONNULL t, ZixTreeIter* ZIX_NONNULL ti); /** @} @defgroup zix_tree_searching Searching @{ */ /** Set `ti` to an element equal to `e` in `t`. If no such item exists, `ti` is set to NULL. */ ZIX_API ZixStatus zix_tree_find(const ZixTree* ZIX_NONNULL t, const void* ZIX_UNSPECIFIED e, ZixTreeIter* ZIX_NULLABLE* ZIX_NONNULL ti); /** @} @} */ ZIX_END_DECLS #endif /* ZIX_TREE_H */