1 /* EINA - EFL data type library
2 * Copyright (C) 2008 Cedric Bail
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library;
16 * if not, see <http://www.gnu.org/licenses/>.
19 #ifndef EINA_RBTREE_H__
20 #define EINA_RBTREE_H__
24 #include "eina_types.h"
25 #include "eina_error.h"
26 #include "eina_iterator.h"
29 * @addtogroup Eina_Rbtree_Group Red-Black tree
31 * @brief These functions provide Red-Black trees management.
33 * For a brief description look at http://en.wikipedia.org/wiki/Red-black_tree .
34 * This code is largely inspired from a tutorial written by Julienne Walker at :
35 * http://eternallyconfuzzled.com/tuts/datastructures/jsw_tut_rbtree.aspx . The
36 * main difference is that this set of function never allocate any data, making
37 * them particularly useful for memory management.
41 * @addtogroup Eina_Data_Types_Group Data Types
47 * @addtogroup Eina_Containers_Group Containers
53 * @defgroup Eina_Rbtree_Group Red-Black tree
59 * @typedef Eina_Rbtree_Color
68 * @typedef Eina_Rbtree_Direction
74 } Eina_Rbtree_Direction;
77 * @typedef Eina_Rbtree
78 * Type for a Red-Black tree node. It should be inlined into user's type.
80 typedef struct _Eina_Rbtree Eina_Rbtree;
85 Eina_Rbtree_Color color : 1;
90 * recommended way to declare the inlined Eina_Rbtree in your type.
100 * @see EINA_RBTREE_GET()
102 #define EINA_RBTREE Eina_Rbtree __rbtree
105 * @def EINA_RBTREE_GET
106 * access the inlined node if it was created with #EINA_RBTREE.
108 #define EINA_RBTREE_GET(Rbtree) (&((Rbtree)->__rbtree))
111 * @def EINA_RBTREE_CONTAINER_GET
112 * find back the container of an red black tree.
114 #define EINA_RBTREE_CONTAINER_GET(Ptr, Type) ((Type *)((char *)Ptr - offsetof(Type, __rbtree)))
117 * @typedef Eina_Rbtree_Cmp_Node_Cb
118 * Function used compare two nodes and see which direction to navigate.
120 typedef Eina_Rbtree_Direction (*Eina_Rbtree_Cmp_Node_Cb)(const Eina_Rbtree *left, const Eina_Rbtree *right, void *data);
123 * @def EINA_RBTREE_CMP_NODE_CB
124 * Cast using #Eina_Rbtree_Cmp_Node_Cb
126 #define EINA_RBTREE_CMP_NODE_CB(Function) ((Eina_Rbtree_Cmp_Node_Cb)Function)
129 * @typedef Eina_Rbtree_Cmp_Key_Cb
130 * Function used compare node with a given key of specified length.
132 typedef int (*Eina_Rbtree_Cmp_Key_Cb)(const Eina_Rbtree *node, const void *key, int length, void *data);
134 * @def EINA_RBTREE_CMP_KEY_CB
135 * Cast using #Eina_Rbtree_Cmp_Key_Cb
137 #define EINA_RBTREE_CMP_KEY_CB(Function) ((Eina_Rbtree_Cmp_Key_Cb)Function)
140 * @typedef Eina_Rbtree_Free_Cb
141 * Function used free a node.
143 typedef void (*Eina_Rbtree_Free_Cb)(Eina_Rbtree *node, void *data);
145 * @def EINA_RBTREE_FREE_CB
146 * Cast using #Eina_Rbtree_Free_Cb
148 #define EINA_RBTREE_FREE_CB(Function) ((Eina_Rbtree_Free_Cb)Function)
152 * @brief Insert a new node inside an existing red black tree.
154 * @param root The root of an exisiting valid red black tree.
155 * @param node The new node to insert.
156 * @param cmp The callback that is able to compare two nodes.
157 * @param data Private data to help the compare function.
158 * @return The new root of the red black tree.
160 * This function insert a new node in a valid red black tree. @c NULL is
161 * an empty valid red black tree. The resulting new tree is a valid red
162 * black tree. This function doesn't allocate any data.
164 EAPI Eina_Rbtree *eina_rbtree_inline_insert(Eina_Rbtree *root, Eina_Rbtree *node, Eina_Rbtree_Cmp_Node_Cb cmp, const void *data) EINA_ARG_NONNULL(2, 3) EINA_WARN_UNUSED_RESULT;
167 * @brief Remove a node from an existing red black tree.
169 * @param root The root of a valid red black tree.
170 * @param node The node to remove from the tree.
171 * @param cmp The callback that is able to compare two nodes.
172 * @param data Private data to help the compare function.
173 * @return The new root of the red black tree.
175 * This function remove a new node in a valid red black tree that should
176 * contain the node that you are removing. This function will return @c NULL
177 * when the red black tree got empty. This function doesn't free any data.
179 EAPI Eina_Rbtree *eina_rbtree_inline_remove(Eina_Rbtree *root, Eina_Rbtree *node, Eina_Rbtree_Cmp_Node_Cb cmp, const void *data) EINA_ARG_NONNULL(2, 3) EINA_WARN_UNUSED_RESULT;
182 * @brief Delete all nodes from a valid red black tree.
184 * @param root The root of a valid red black tree.
185 * @param func The callback that will free each node.
186 * @param data Private data to help the compare function.
189 EAPI void eina_rbtree_delete(Eina_Rbtree *root, Eina_Rbtree_Free_Cb func, void *data) EINA_ARG_NONNULL(2);
191 static inline Eina_Rbtree *eina_rbtree_inline_lookup(const Eina_Rbtree *root, const void *key, int length, Eina_Rbtree_Cmp_Key_Cb cmp, const void *data) EINA_PURE EINA_ARG_NONNULL(2, 4) EINA_WARN_UNUSED_RESULT;
195 * @brief Returned a new prefix iterator associated to a rbtree.
197 * @param root The root of rbtree.
198 * @return A new iterator.
200 * This function returns a newly allocated iterator associated to @p
201 * root. It will iterate the tree using prefix walk. If @p root is @c
202 * NULL, this function still returns a valid iterator that will always
203 * return false on eina_iterator_next(), thus keeping API sane.
205 * If the memory can not be allocated, @c NULL is returned
206 * and #EINA_ERROR_OUT_OF_MEMORY is set. Otherwise, a valid iterator is
209 * @warning if the rbtree structure changes then the iterator becomes
210 * invalid! That is, if you add or remove nodes this iterator
211 * behavior is undefined and your program may crash!
213 EAPI Eina_Iterator *eina_rbtree_iterator_prefix(const Eina_Rbtree *root) EINA_MALLOC EINA_WARN_UNUSED_RESULT;
216 * @brief Returned a new prefix iterator associated to a rbtree.
218 * @param root The root of rbtree.
219 * @return A new iterator.
221 * This function returns a newly allocated iterator associated to @p
222 * root. It will iterate the tree using infix walk. If @p root is @c
223 * NULL, this function still returns a valid iterator that will always
224 * return false on eina_iterator_next(), thus keeping API sane.
226 * If the memory can not be allocated, @c NULL is returned
227 * and #EINA_ERROR_OUT_OF_MEMORY is set. Otherwise, a valid iterator is
230 * @warning if the rbtree structure changes then the iterator becomes
231 * invalid! That is, if you add or remove nodes this iterator
232 * behavior is undefined and your program may crash!
234 EAPI Eina_Iterator *eina_rbtree_iterator_infix(const Eina_Rbtree *root) EINA_MALLOC EINA_WARN_UNUSED_RESULT;
237 * @brief Returned a new prefix iterator associated to a rbtree.
239 * @param root The root of rbtree.
240 * @return A new iterator.
242 * This function returns a newly allocated iterator associated to @p
243 * root. It will iterate the tree using postfix walk. If @p root is @c
244 * NULL, this function still returns a valid iterator that will always
245 * return false on eina_iterator_next(), thus keeping API sane.
247 * If the memory can not be allocated, @c NULL is returned
248 * and #EINA_ERROR_OUT_OF_MEMORY is set. Otherwise, a valid iterator is
251 * @warning if the rbtree structure changes then the iterator becomes
252 * invalid! That is, if you add or remove nodes this iterator
253 * behavior is undefined and your program may crash!
255 EAPI Eina_Iterator *eina_rbtree_iterator_postfix(const Eina_Rbtree *root) EINA_MALLOC EINA_WARN_UNUSED_RESULT;
257 #include "eina_inline_rbtree.x"