1 #ifndef _UL_GAVLFLESINT_H
2 #define _UL_GAVLFLESINT_H
10 /* Declaration of tree with first/last enhanced speed functions with internal node */
11 #define GAVL_FLES_INT_DEC(cust_prefix, cust_root_t, cust_item_t, cust_key_t,\
12 cust_root_field, cust_item_node, cust_item_key, cust_cmp_fnc) \
14 static inline cust_item_t * \
15 cust_prefix##_node2item(const cust_root_t *root, const gavl_node_t *node) \
16 {return (cust_item_t*)((char*)node-(long)&((cust_item_t*)0)->cust_item_node);}\
18 static inline cust_key_t *\
19 cust_prefix##_node2key(const cust_root_t *root, gavl_node_t *node)\
20 { return &(cust_prefix##_node2item(root, node)->cust_item_key);}\
22 void cust_prefix##_init_root_field(cust_root_t *root);\
23 int cust_prefix##_search_node(const cust_root_t *root, cust_key_t *key, gavl_node_t **nodep);\
24 cust_item_t *cust_prefix##_find(const cust_root_t *root, cust_key_t *key);\
25 cust_item_t *cust_prefix##_find_first(const cust_root_t *root, cust_key_t *key);\
26 cust_item_t *cust_prefix##_find_after(const cust_root_t *root, cust_key_t *key);\
27 int cust_prefix##_insert(cust_root_t *root, cust_item_t *item);\
28 cust_item_t *cust_prefix##_cut_first(cust_root_t *root);\
29 int cust_prefix##_delete_node(cust_root_t *root, gavl_node_t *node);\
30 int cust_prefix##_delete(cust_root_t *root, cust_item_t *item);\
31 static inline gavl_node_t *\
32 cust_prefix##_first_node(const cust_root_t *root)\
34 return root->cust_root_field.first;\
36 static inline gavl_node_t *\
37 cust_prefix##_last_node(const cust_root_t *root)\
39 return root->cust_root_field.last;\
41 static inline cust_item_t *\
42 cust_prefix##_first(const cust_root_t *root)\
44 gavl_node_t *n=cust_prefix##_first_node(root);\
45 return n?cust_prefix##_node2item(root,n):NULL;\
47 static inline cust_item_t *\
48 cust_prefix##_last(const cust_root_t *root)\
50 gavl_node_t *n=cust_prefix##_last_node(root);\
51 return n?cust_prefix##_node2item(root,n):NULL;\
53 static inline cust_item_t *\
54 cust_prefix##_next(const cust_root_t *root, cust_item_t *item)\
56 gavl_node_t *n=gavl_next_node(&item->cust_item_node);\
57 return n?cust_prefix##_node2item(root,n):NULL;\
59 static inline cust_item_t *\
60 cust_prefix##_prev(const cust_root_t *root, cust_item_t *item)\
62 gavl_node_t *n=gavl_prev_node(&item->cust_item_node);\
63 return n?cust_prefix##_node2item(root,n):NULL;\
66 cust_prefix##_is_empty(const cust_root_t *root)\
68 return !root->cust_root_field.root;\
71 UL_ITBASE_SORT_DEC(cust_prefix, cust_root_t, cust_item_t, cust_key_t)
75 * GAVL_FLES_INT_IMP - Implementation of new custom tree with fast first/last functions
76 * @cust_prefix: defines prefix for builded function names
77 * @cust_root_t: user defined structure type of root of the tree
78 * @cust_item_t: user defined structure type of items stored in the tree
79 * @cust_key_t: type of the key used for sorting of the items
80 * @cust_root_field: the field of the root structure pointing to the tree root node
81 * @cust_item_node: the field of item structure used for chaining of items
82 * @cust_item_key: the key field of item structure defining order of items
83 * @cust_cmp_fnc: the keys compare function
85 * This version of custom tree implementation allows multiple items with same
86 * key value to be stored in tree.
87 * There are two macros designed for building custom AVL trees. The macro
88 * %GAVL_CUST_NODE_INT_DEC declares functions for custom tree manipulations
89 * and is intended for use in header files.
90 * The macro %GAVL_CUST_NODE_INT_REP_IMP builds implementations for non-inlined
91 * functions declared by %GAVL_CUST_NODE_INT_DEC. The @cust_cmp_fnc is used
92 * for comparison of item keys in the search and insert functions. The types
93 * of two input arguments of @cust_cmp_fnc functions must correspond
94 * with @cust_key_t type. Return value should be positive for case when
95 * the first pointed key value is greater then second, negative for reverse
96 * case and zero for equal pointed values.
98 #define GAVL_FLES_INT_IMP(cust_prefix, cust_root_t, cust_item_t, cust_key_t,\
99 cust_root_field, cust_item_node, cust_item_key, cust_cmp_fnc,\
100 cust_ins_fl, cust_first_change, cust_last_change, cust_empty_state) \
102 void cust_prefix##_init_root_field(cust_root_t *root)\
104 root->cust_root_field.root=NULL;\
105 root->cust_root_field.first=NULL;\
106 root->cust_root_field.last=NULL;\
107 root->cust_root_field.count=0;\
110 int cust_prefix##_search_node4(const cust_root_t *root, cust_key_t *key, gavl_node_t **nodep, int mode)\
114 n=p=root->cust_root_field.root;\
116 cmp=cust_cmp_fnc(cust_prefix##_node2key(root,n),key);\
120 }else if((cmp<0)||(mode&GAVL_FAFTER)){\
126 if(!cmp && (mode&GAVL_FFIRST)){\
128 cmp=cust_cmp_fnc(cust_prefix##_node2key(root,n),key);\
132 while((n=n->right)){\
133 cmp=cust_cmp_fnc(cust_prefix##_node2key(root,n),key);\
148 int cust_prefix##_search_node(const cust_root_t *root, cust_key_t *key, gavl_node_t **nodep)\
150 return cust_prefix##_search_node4(root, key, nodep, 0);\
153 cust_item_t *cust_prefix##_find(const cust_root_t *root, cust_key_t *key)\
156 if(cust_prefix##_search_node4(root, key, &node, 0))\
158 return cust_prefix##_node2item(root,node);\
161 cust_item_t *cust_prefix##_find_first(const cust_root_t *root, cust_key_t *key)\
164 if(cust_prefix##_search_node4(root, key, &n, GAVL_FFIRST))\
166 return cust_prefix##_node2item(root,n);\
169 cust_item_t *cust_prefix##_find_after(const cust_root_t *root, cust_key_t *key)\
172 if(cust_prefix##_search_node4(root, key, &node, GAVL_FAFTER)<=0){\
173 if(node) node=gavl_next_node(node);\
175 return node?cust_prefix##_node2item(root,node):NULL;\
178 int cust_prefix##_insert(cust_root_t *root, cust_item_t *item)\
181 gavl_node_t *where, *n2add;\
183 cmp=cust_prefix##_search_node4(root, &item->cust_item_key, &where, cust_ins_fl);\
184 if(!cmp && !(cust_ins_fl&GAVL_FAFTER)) return -1;\
185 n2add=&item->cust_item_node;\
186 if(!root->cust_root_field.root){\
187 root->cust_root_field.first=root->cust_root_field.last=n2add;\
188 cust_first_change; cust_last_change;\
189 }else if((cmp>0)&&(where==root->cust_root_field.first)){\
190 root->cust_root_field.first=n2add;\
192 }else if((cmp<=0)&&(where==root->cust_root_field.last)){\
193 root->cust_root_field.last=n2add;\
196 root->cust_root_field.count++;\
197 return gavl_insert_primitive_at(&root->cust_root_field.root, n2add, where, cmp);\
200 int cust_prefix##_delete_node(cust_root_t *root, gavl_node_t *node)\
203 /*check if node is inserted into tree*/\
204 for(p=node; p->parent; p=p->parent);\
205 if(p!=root->cust_root_field.root)\
207 if(root->cust_root_field.first==node){\
208 if(root->cust_root_field.last==node){\
209 root->cust_root_field.first=root->cust_root_field.last=NULL;\
212 root->cust_root_field.first=gavl_next_node(node);\
215 }else if(root->cust_root_field.last==node){\
216 root->cust_root_field.last=gavl_prev_node(node);\
219 root->cust_root_field.count--;\
220 return gavl_delete_primitive(&root->cust_root_field.root, node);\
223 int cust_prefix##_delete(cust_root_t *root, cust_item_t *item)\
226 if(!item) return -1;\
227 n=&item->cust_item_node;\
228 return cust_prefix##_delete_node(root, n);\
231 cust_item_t *cust_prefix##_cut_first(cust_root_t *root)\
234 gavl_node_t **np=&root->cust_root_field.root;\
235 if(!(n=root->cust_root_field.first))\
237 if(n->parent) np=&n->parent->left;\
240 p->parent=n->parent;\
241 while(p->left) p=p->left;\
242 root->cust_root_field.first=p;\
245 if(!(root->cust_root_field.first=n->parent)){\
246 root->cust_root_field.last=n->parent;\
252 for(p=n->parent;p;p=p->parent)\
253 if(p->hdiff++<0) break;\
254 n->parent=n->left=n->right=NULL;\
255 root->cust_root_field.count--;\
256 return cust_prefix##_node2item(root,n);\
264 #endif /* _UL_GAVLFLESINT_H */