]> git.ipfire.org Git - thirdparty/bird.git/blame - lib/hash.h
Merge branch 'add-path'
[thirdparty/bird.git] / lib / hash.h
CommitLineData
bf139664
OZ
1
2
6a8d3f1c 3#define HASH(type) struct { type **data; uint count, order; }
bf139664 4#define HASH_TYPE(v) typeof(** (v).data)
6a8d3f1c
OZ
5#define HASH_SIZE(v) (1 << (v).order)
6#define HASH_MASK(v) ((1 << (v).order)-1)
bf139664 7
6a8d3f1c
OZ
8
9#define HASH_INIT(v,pool,init_order) \
bf139664 10 ({ \
6a8d3f1c
OZ
11 (v).count = 0; \
12 (v).order = (init_order); \
13 (v).data = mb_allocz(pool, HASH_SIZE(v) * sizeof(* (v).data)); \
bf139664
OZ
14 })
15
6a8d3f1c 16#define HASH_FIND(v,id,key...) \
bf139664 17 ({ \
6a8d3f1c
OZ
18 uint _h = id##_FN((key)) & HASH_MASK(v); \
19 HASH_TYPE(v) *_n = (v).data[_h]; \
20 while (_n && !id##_EQ(id##_KEY(_n), (key))) \
21 _n = id##_NEXT(_n); \
bf139664
OZ
22 _n; \
23 })
24
6a8d3f1c 25#define HASH_INSERT(v,id,node) \
bf139664 26 ({ \
6a8d3f1c
OZ
27 uint _h = id##_FN(id##_KEY((node))) & HASH_MASK(v); \
28 HASH_TYPE(v) **_nn = (v).data + _h; \
29 id##_NEXT(node) = *_nn; \
bf139664 30 *_nn = node; \
6a8d3f1c 31 (v).count++; \
bf139664
OZ
32 })
33
6a8d3f1c 34#define HASH_DO_REMOVE(v,id,_nn) \
bf139664 35 ({ \
bf139664
OZ
36 HASH_TYPE(v) *_n = *_nn; \
37 if (_n) \
6a8d3f1c
OZ
38 { \
39 *_nn = id##_NEXT(_n); \
40 (v).count--; \
41 } \
bf139664
OZ
42 _n; \
43 })
44
6a8d3f1c
OZ
45#define HASH_DELETE(v,id,key...) \
46 ({ \
47 uint _h = id##_FN((key)) & HASH_MASK(v); \
48 HASH_TYPE(v) **_nn = (v).data + _h; \
49 \
50 while ((*_nn) && !id##_EQ(id##_KEY((*_nn)), (key))) \
51 _nn = &(id##_NEXT((*_nn))); \
52 \
53 HASH_DO_REMOVE(v,id,_nn); \
54 })
55
bf139664
OZ
56#define HASH_REMOVE(v,id,node) \
57 ({ \
6a8d3f1c
OZ
58 uint _h = id##_FN(id##_KEY((node))) & HASH_MASK(v); \
59 HASH_TYPE(v) **_nn = (v).data + _h; \
60 \
bf139664 61 while ((*_nn) && (*_nn != (node))) \
6a8d3f1c 62 _nn = &(id##_NEXT((*_nn))); \
bf139664 63 \
6a8d3f1c 64 HASH_DO_REMOVE(v,id,_nn); \
bf139664
OZ
65 })
66
67
6a8d3f1c
OZ
68#define HASH_REHASH(v,id,pool,step) \
69 ({ \
70 HASH_TYPE(v) *_n, *_n2, **_od; \
71 uint _i, _s; \
72 \
73 _s = HASH_SIZE(v); \
74 _od = (v).data; \
75 (v).count = 0; \
76 (v).order += (step); \
77 (v).data = mb_allocz(pool, HASH_SIZE(v) * sizeof(* (v).data)); \
78 \
79 for (_i = 0; _i < _s; _i++) \
80 for (_n = _od[_i]; _n && (_n2 = id##_NEXT(_n), 1); _n = _n2) \
81 HASH_INSERT(v, id, _n); \
82 \
83 mb_free(_od); \
84 })
85
86#define HASH_DEFINE_REHASH_FN(id, type) \
87 static void id##_REHASH_FN(void *v, pool *p, int step) \
88 { HASH_REHASH(* (HASH(type) *) v, id, p, step); }
89
90#define HASH_TRY_REHASH_UP(v,id,pool) \
91 ({ \
92 if (((v).order < id##_REHASH_MAX) && ((v).count > HASH_SIZE(v))) \
93 id##_REHASH_FN(&v, pool, 1); \
94 })
95
96#define HASH_TRY_REHASH_DOWN(v,id,pool) \
97 ({ \
98 if (((v).order > id##_REHASH_MIN) && ((v).count < HASH_SIZE(v)/2)) \
99 id##_REHASH_FN(&v, pool, -1); \
100 })
bf139664
OZ
101
102#define HASH_WALK(v,next,n) \
103 do { \
104 HASH_TYPE(v) *n; \
105 uint _i; \
6a8d3f1c
OZ
106 uint _s = HASH_SIZE(v); \
107 for (_i = 0; _i < _s; _i++) \
bf139664
OZ
108 for (n = (v).data[_i]; n; n = n->next)
109
110#define HASH_WALK_END } while (0)
111
112
113#define HASH_WALK_DELSAFE(v,next,n) \
114 do { \
115 HASH_TYPE(v) *n, *_next; \
116 uint _i; \
6a8d3f1c
OZ
117 uint _s = HASH_SIZE(v); \
118 for (_i = 0; _i < _s; _i++) \
bf139664
OZ
119 for (n = (v).data[_i]; n && (_next = n->next, 1); n = _next)
120
121#define HASH_WALK_DELSAFE_END } while (0)
122
bf139664 123