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