1 /*******************************************************************
2 uLan Utilities Library - C library of basic reusable constructions
4 ul_gavlrepcust.h - custom trees with allowed repeat of keys
6 (C) Copyright 2003-2004 by Pavel Pisa - Originator
8 The uLan utilities library can be used, copied and modified under
10 - GPL - GNU General Public License
11 - LGPL - GNU Lesser General Public License
12 - MPL - Mozilla Public License
13 - and other licenses added by project originators
14 Code can be modified and re-distributed under any combination
15 of the above listed licenses. If contributor does not agree with
16 some of the licenses, he/she can delete appropriate line.
17 Warning, if you delete all lines, you are not allowed to
18 distribute source code and/or binaries utilizing code.
20 See files COPYING and README for details.
22 *******************************************************************/
24 #ifndef _UL_GAVLREPCUST_H
25 #define _UL_GAVLREPCUST_H
34 * GAVL_CUST_NODE_INT_REP_IMP - Implementation of new custom tree with internal node allowed item repeat
35 * @cust_prefix: defines prefix for builded function names
36 * @cust_root_t: user defined structure type of root of the tree
37 * @cust_item_t: user defined structure type of items stored in the tree
38 * @cust_key_t: type of the key used for sorting of the items
39 * @cust_root_node: the field of the root structure pointing to the tree root node
40 * @cust_item_node: the field of item structure used for chaining of items
41 * @cust_item_key: the key field of item structure defining order of items
42 * @cust_cmp_fnc: the keys compare function
44 * This version of custom tree implementation allows multiple items with same
45 * key value to be stored in tree.
46 * There are two macros designed for building custom AVL trees. The macro
47 * %GAVL_CUST_NODE_INT_DEC declares functions for custom tree manipulations
48 * and is intended for use in header files.
49 * The macro %GAVL_CUST_NODE_INT_REP_IMP builds implementations for non-inlined
50 * functions declared by %GAVL_CUST_NODE_INT_DEC. The @cust_cmp_fnc is used
51 * for comparison of item keys in the search and insert functions. The types
52 * of two input arguments of @cust_cmp_fnc functions must correspond
53 * with @cust_key_t type. Return value should be positive for case when
54 * the first pointed key value is greater then second, negative for reverse
55 * case and zero for equal pointed values.
57 #define GAVL_CUST_NODE_INT_REP_IMP(cust_prefix, cust_root_t, cust_item_t, cust_key_t,\
58 cust_root_node, cust_item_node, cust_item_key, cust_cmp_fnc) \
60 void cust_prefix##_init_root_field(cust_root_t *root)\
62 root->cust_root_node=NULL;\
65 int cust_prefix##_search_node4(const cust_root_t *root, cust_key_t const *key, gavl_node_t **nodep, int mode)\
69 n=p=root->cust_root_node;\
71 cmp=cust_cmp_fnc(cust_prefix##_node2key(root,n),key);\
75 }else if((cmp<0)||(mode&GAVL_FAFTER)){\
81 if(!cmp && (mode&GAVL_FFIRST)){\
83 cmp=cust_cmp_fnc(cust_prefix##_node2key(root,n),key);\
88 cmp=cust_cmp_fnc(cust_prefix##_node2key(root,n),key);\
103 int cust_prefix##_search_node(const cust_root_t *root, cust_key_t const *key, gavl_node_t **nodep)\
105 return cust_prefix##_search_node4(root, key, nodep, 0);\
108 cust_item_t *cust_prefix##_find(const cust_root_t *root, cust_key_t const *key)\
111 if(cust_prefix##_search_node4(root, key, &node, 0))\
113 return cust_prefix##_node2item(root,node);\
116 cust_item_t *cust_prefix##_find_first(const cust_root_t *root, cust_key_t const *key)\
119 if(cust_prefix##_search_node4(root, key, &n, GAVL_FFIRST))\
121 return cust_prefix##_node2item(root,n);\
124 cust_item_t *cust_prefix##_find_after(const cust_root_t *root, cust_key_t const *key)\
127 if(cust_prefix##_search_node4(root, key, &node, GAVL_FAFTER)<=0){\
128 if(node) node=gavl_next_node(node);\
130 return node?cust_prefix##_node2item(root,node):NULL;\
133 int cust_prefix##_insert(cust_root_t *root, cust_item_t *item)\
136 gavl_node_t *where, *n2add;\
138 cmp=cust_prefix##_search_node4(root, &item->cust_item_key, &where, GAVL_FAFTER);\
139 n2add=&item->cust_item_node;\
140 return gavl_insert_primitive_at(&root->cust_root_node, n2add, where, cmp);\
143 int cust_prefix##_delete_node(cust_root_t *root, gavl_node_t *node)\
145 return gavl_delete_primitive(&root->cust_root_node, node);\
148 int cust_prefix##_delete(cust_root_t *root, cust_item_t *item)\
151 if(!item) return -1;\
152 n=&item->cust_item_node;\
153 /*check if node is inserted into tree*/\
154 for(p=n; p->parent; p=p->parent);\
155 if(p!=root->cust_root_node)\
157 return gavl_delete_primitive(&root->cust_root_node, n);\
160 gavl_node_t *cust_prefix##_first_node(const cust_root_t *root)\
162 gavl_node_t *n=root->cust_root_node;\
169 gavl_node_t *cust_prefix##_last_node(const cust_root_t *root)\
171 gavl_node_t *n=root->cust_root_node;\
183 #endif /* _UL_GAVLREPCUST_H */