1 /* EINA - EFL data type library
2  * Copyright (C) 2008 Cedric Bail
3  *
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.
8  *
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.
13  *
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/>.
17  */
18 
19 #ifndef EINA_RBTREE_H__
20 #define EINA_RBTREE_H__
21 
22 #include <stdlib.h>
23 
24 #include "eina_types.h"
25 #include "eina_error.h"
26 #include "eina_iterator.h"
27 
28 /**
29  * @addtogroup Eina_Rbtree_Group Red-Black tree
30  *
31  * @brief These functions provide Red-Black tree management.
32  *
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 functions never allocate any data, making
37  * them particularly useful for memory management.
38  */
39 
40 /**
41  * @addtogroup Eina_Data_Types_Group Data Types
42  *
43  * @{
44  */
45 
46 /**
47  * @addtogroup Eina_Containers_Group Containers
48  *
49  * @{
50  */
51 
52 /**
53  * @defgroup Eina_Rbtree_Group Red-Black tree
54  *
55  * @{
56  */
57 
58 /**
59  * @typedef Eina_Rbtree_Color
60  * node color.
61  */
62 typedef enum {
63    EINA_RBTREE_RED,
64    EINA_RBTREE_BLACK
65 } Eina_Rbtree_Color;
66 
67 /**
68  * @typedef Eina_Rbtree_Direction
69  * walk direction.
70  */
71 typedef enum {
72    EINA_RBTREE_LEFT = 0,
73    EINA_RBTREE_RIGHT = 1
74 } Eina_Rbtree_Direction;
75 
76 /**
77  * @typedef Eina_Rbtree
78  * Type for a Red-Black tree node. It should be inlined into user's type.
79  */
80 typedef struct _Eina_Rbtree Eina_Rbtree;
81 struct _Eina_Rbtree
82 {
83    Eina_Rbtree      *son[2];
84 
85    unsigned int color : 1;
86 };
87 
88 /**
89  * @def EINA_RBTREE
90  * recommended way to declare the inlined Eina_Rbtree in your type.
91  *
92  * @code
93  * struct my_type {
94  *    EINA_RBTREE;
95  *    int my_value;
96  *    char *my_name;
97  * };
98  * @endcode
99  *
100  * @see EINA_RBTREE_GET()
101  */
102 #define EINA_RBTREE Eina_Rbtree __rbtree
103 
104 /**
105  * @def EINA_RBTREE_GET
106  * access the inlined node if it was created with #EINA_RBTREE.
107  */
108 #define EINA_RBTREE_GET(Rbtree) (&((Rbtree)->__rbtree))
109 
110 /**
111  * @def EINA_RBTREE_CONTAINER_GET
112  * find back the container of a red black tree.
113  */
114 #define EINA_RBTREE_CONTAINER_GET(Ptr, Type) ((Type *)((char *)Ptr - offsetof(Type, __rbtree)))
115 
116 /**
117  * @typedef Eina_Rbtree_Cmp_Node_Cb
118  * Function used to compare two nodes and see which direction to navigate.
119  */
120 typedef Eina_Rbtree_Direction (*Eina_Rbtree_Cmp_Node_Cb)(const Eina_Rbtree *left, const Eina_Rbtree *right, void *data);
121 
122 /**
123  * @def EINA_RBTREE_CMP_NODE_CB
124  * Cast using #Eina_Rbtree_Cmp_Node_Cb
125  */
126 #define EINA_RBTREE_CMP_NODE_CB(Function) ((Eina_Rbtree_Cmp_Node_Cb)Function)
127 
128 /**
129  * @typedef Eina_Rbtree_Cmp_Key_Cb
130  * Function used compare node with a given key of specified length.
131  */
132 typedef int (*Eina_Rbtree_Cmp_Key_Cb)(const Eina_Rbtree *node, const void *key, int length, void *data);
133 
134 /**
135  * @def EINA_RBTREE_CMP_KEY_CB
136  * Cast using #Eina_Rbtree_Cmp_Key_Cb
137  */
138 #define EINA_RBTREE_CMP_KEY_CB(Function) ((Eina_Rbtree_Cmp_Key_Cb)Function)
139 
140 /**
141  * @typedef Eina_Rbtree_Free_Cb
142  * Function used to free a node.
143  */
144 typedef void (*Eina_Rbtree_Free_Cb)(Eina_Rbtree *node, void *data);
145 
146 /**
147  * @def EINA_RBTREE_FREE_CB
148  * Cast using #Eina_Rbtree_Free_Cb
149  */
150 #define EINA_RBTREE_FREE_CB(Function) ((Eina_Rbtree_Free_Cb)Function)
151 
152 /**
153  * @brief Inserts a new node inside an existing red black tree.
154  *
155  * @param[in,out] root The root of an existing valid red black tree.
156  * @param[in] node The new node to insert.
157  * @param[in] cmp The callback that is able to compare two nodes.
158  * @param[in] data Private data to help the compare function.
159  * @return The new root of the red black tree.
160  *
161  * This function inserts a new node in a valid red black tree. @c NULL is
162  * an empty valid red black tree. The resulting new tree is a valid red
163  * black tree. This function doesn't allocate any data.
164  */
165 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;
166 
167 /**
168  * @brief Removes a node from an existing red black tree.
169  *
170  * @param[in,out] root The root of a valid red black tree.
171  * @param[in] node The node to remove from the tree.
172  * @param[in] cmp The callback that is able to compare two nodes.
173  * @param[in] data Private data to help the compare function.
174  * @return The new root of the red black tree.
175  *
176  * This function removes a new node in a valid red black tree that should
177  * contain the node that you are removing. This function will return @c NULL
178  * when the red black tree got empty. This function doesn't free any data.
179  */
180 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;
181 
182 /**
183  * @brief Deletes all nodes from a valid red black tree.
184  *
185  * @param[in,out] root The root of a valid red black tree.
186  * @param[in] func The callback that will free each node.
187  * @param[in] data Private data to help the compare function.
188  */
189 EAPI void                  eina_rbtree_delete(Eina_Rbtree *root, Eina_Rbtree_Free_Cb func, void *data) EINA_ARG_NONNULL(2);
190 
191 /**
192  * @brief Searches tree for a key using a comparison function.
193  *
194  * @param[in,out] root The root of a valid red black tree.
195  * @param[in] key The key value to search for.
196  * @param[in] length The length of the specified key.
197  * @param[in] cmp Callback routine to compare two nodes.
198  * @param[in] data Private data to help the compare function.
199  *
200  * @return The first matching node found in the red black tree, or
201  * @p root if nothing was found.
202  */
203 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;
204 
205 
206 /**
207  * @brief Returns a new prefix iterator associated with a rbtree.
208  *
209  * @param[in] root The root of rbtree.
210  * @return A new iterator.
211  *
212  * This function returns a newly allocated iterator associated with @p
213  * root. It will iterate the tree using prefix walk. If @p root is @c
214  * NULL, this function still returns a valid iterator that will always
215  * return false on eina_iterator_next(), thus keeping API sane.
216  *
217  * If the memory cannot be allocated, @c NULL is returned.
218  * Otherwise, a valid iterator is returned.
219  *
220  * @warning if the rbtree structure changes then the iterator becomes
221  *    invalid! That is, if you add or remove nodes this iterator
222  *    behavior is undefined and your program may crash!
223  */
224 EAPI Eina_Iterator        *eina_rbtree_iterator_prefix(const Eina_Rbtree *root) EINA_MALLOC EINA_WARN_UNUSED_RESULT;
225 
226 /**
227  * @brief Returns a new prefix iterator associated with a rbtree.
228  *
229  * @param[in] root The root of rbtree.
230  * @return A new iterator.
231  *
232  * This function returns a newly allocated iterator associated with @p
233  * root. It will iterate the tree using infix walk. If @p root is @c
234  * NULL, this function still returns a valid iterator that will always
235  * return false on eina_iterator_next(), thus keeping API sane.
236  *
237  * If the memory cannot be allocated, @c NULL is returned.
238  * Otherwise, a valid iterator is returned.
239  *
240  * @warning if the rbtree structure changes then the iterator becomes
241  *    invalid! That is, if you add or remove nodes this iterator
242  *    behavior is undefined and your program may crash!
243  */
244 EAPI Eina_Iterator        *eina_rbtree_iterator_infix(const Eina_Rbtree *root) EINA_MALLOC EINA_WARN_UNUSED_RESULT;
245 
246 /**
247  * @brief Returns a new prefix iterator associated with a rbtree.
248  *
249  * @param[in] root The root of rbtree.
250  * @return A new iterator.
251  *
252  * This function returns a newly allocated iterator associated with @p
253  * root. It will iterate the tree using postfix walk. If @p root is @c
254  * NULL, this function still returns a valid iterator that will always
255  * return false on eina_iterator_next(), thus keeping API sane.
256  *
257  * If the memory cannot be allocated, @c NULL is returned.
258  * Otherwise, a valid iterator is returned.
259  *
260  * @warning if the rbtree structure changes then the iterator becomes
261  *    invalid! That is, if you add or remove nodes this iterator
262  *    behavior is undefined and your program may crash!
263  */
264 EAPI Eina_Iterator        *eina_rbtree_iterator_postfix(const Eina_Rbtree *root) EINA_MALLOC EINA_WARN_UNUSED_RESULT;
265 
266 #include "eina_inline_rbtree.x"
267 
268 /**
269  * @}
270  */
271 
272 /**
273  * @}
274  */
275 
276 /**
277  * @}
278  */
279 
280 #endif
281