]> git.proxmox.com Git - mirror_frr.git/blame - lib/typerb.h
Merge pull request #4756 from vincentbernat/fix/doc-aspath
[mirror_frr.git] / lib / typerb.h
CommitLineData
80911bc2
DL
1/*
2 * The following Red-Black tree implementation is based off code with
3 * original copyright:
4 *
5 * Copyright (c) 2016 David Gwynne <dlg@openbsd.org>
6 *
7 * Permission to use, copy, modify, and distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
10 *
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 */
19
20#ifndef _FRR_TYPERB_H
21#define _FRR_TYPERB_H
22
23#include "typesafe.h"
24
eea3c899
RW
25#ifdef __cplusplus
26extern "C" {
27#endif
28
80911bc2
DL
29struct typed_rb_entry {
30 struct typed_rb_entry *rbt_parent;
31 struct typed_rb_entry *rbt_left;
32 struct typed_rb_entry *rbt_right;
33 unsigned int rbt_color;
34};
35
36struct typed_rb_root {
37 struct typed_rb_entry *rbt_root;
38 size_t count;
39};
40
41struct typed_rb_entry *typed_rb_insert(struct typed_rb_root *,
42 struct typed_rb_entry *rbe,
43 int (*cmpfn)(
44 const struct typed_rb_entry *a,
45 const struct typed_rb_entry *b));
46void typed_rb_remove(struct typed_rb_root *, struct typed_rb_entry *rbe);
47struct typed_rb_entry *typed_rb_find(struct typed_rb_root *,
48 const struct typed_rb_entry *rbe,
49 int (*cmpfn)(
50 const struct typed_rb_entry *a,
51 const struct typed_rb_entry *b));
52struct typed_rb_entry *typed_rb_find_gteq(struct typed_rb_root *,
53 const struct typed_rb_entry *rbe,
54 int (*cmpfn)(
55 const struct typed_rb_entry *a,
56 const struct typed_rb_entry *b));
57struct typed_rb_entry *typed_rb_find_lt(struct typed_rb_root *,
58 const struct typed_rb_entry *rbe,
59 int (*cmpfn)(
60 const struct typed_rb_entry *a,
61 const struct typed_rb_entry *b));
62struct typed_rb_entry *typed_rb_min(struct typed_rb_root *);
63struct typed_rb_entry *typed_rb_next(struct typed_rb_entry *);
64
65#define _PREDECL_RBTREE(prefix) \
66struct prefix ## _head { struct typed_rb_root rr; }; \
67struct prefix ## _item { struct typed_rb_entry re; };
68
69#define INIT_RBTREE_UNIQ(var) { }
70#define INIT_RBTREE_NONUNIQ(var) { }
71
72#define _DECLARE_RBTREE(prefix, type, field, cmpfn_nuq, cmpfn_uq) \
73 \
74macro_inline void prefix ## _init(struct prefix##_head *h) \
75{ \
76 memset(h, 0, sizeof(*h)); \
77} \
78macro_inline void prefix ## _fini(struct prefix##_head *h) \
79{ \
80 memset(h, 0, sizeof(*h)); \
81} \
82macro_inline type *prefix ## _add(struct prefix##_head *h, type *item) \
83{ \
84 struct typed_rb_entry *re; \
85 re = typed_rb_insert(&h->rr, &item->field.re, cmpfn_uq); \
86 return container_of_null(re, type, field.re); \
87} \
88macro_inline type *prefix ## _find_gteq(struct prefix##_head *h, \
89 const type *item) \
90{ \
91 struct typed_rb_entry *re; \
92 re = typed_rb_find_gteq(&h->rr, &item->field.re, cmpfn_nuq); \
93 return container_of_null(re, type, field.re); \
94} \
95macro_inline type *prefix ## _find_lt(struct prefix##_head *h, \
96 const type *item) \
97{ \
98 struct typed_rb_entry *re; \
99 re = typed_rb_find_lt(&h->rr, &item->field.re, cmpfn_nuq); \
100 return container_of_null(re, type, field.re); \
101} \
102macro_inline void prefix ## _del(struct prefix##_head *h, type *item) \
103{ \
104 typed_rb_remove(&h->rr, &item->field.re); \
105} \
106macro_inline type *prefix ## _pop(struct prefix##_head *h) \
107{ \
108 struct typed_rb_entry *re; \
109 re = typed_rb_min(&h->rr); \
110 if (!re) \
111 return NULL; \
112 typed_rb_remove(&h->rr, re); \
113 return container_of(re, type, field.re); \
114} \
115macro_pure type *prefix ## _first(struct prefix##_head *h) \
116{ \
117 struct typed_rb_entry *re; \
118 re = typed_rb_min(&h->rr); \
119 return container_of_null(re, type, field.re); \
120} \
121macro_pure type *prefix ## _next(struct prefix##_head *h, type *item) \
122{ \
123 struct typed_rb_entry *re; \
124 re = typed_rb_next(&item->field.re); \
125 return container_of_null(re, type, field.re); \
126} \
127macro_pure type *prefix ## _next_safe(struct prefix##_head *h, type *item) \
128{ \
129 struct typed_rb_entry *re; \
130 re = item ? typed_rb_next(&item->field.re) : NULL; \
131 return container_of_null(re, type, field.re); \
132} \
133macro_pure size_t prefix ## _count(struct prefix##_head *h) \
134{ \
135 return h->rr.count; \
136} \
137/* ... */
138
139#define PREDECL_RBTREE_UNIQ(prefix) \
140 _PREDECL_RBTREE(prefix)
141#define DECLARE_RBTREE_UNIQ(prefix, type, field, cmpfn) \
142 \
143macro_inline int prefix ## __cmp(const struct typed_rb_entry *a, \
144 const struct typed_rb_entry *b) \
145{ \
146 return cmpfn(container_of(a, type, field.re), \
147 container_of(b, type, field.re)); \
148} \
149macro_inline type *prefix ## _find(struct prefix##_head *h, const type *item) \
150{ \
151 struct typed_rb_entry *re; \
152 re = typed_rb_find(&h->rr, &item->field.re, &prefix ## __cmp); \
153 return container_of_null(re, type, field.re); \
154} \
155 \
156_DECLARE_RBTREE(prefix, type, field, prefix ## __cmp, prefix ## __cmp) \
157/* ... */
158
159#define PREDECL_RBTREE_NONUNIQ(prefix) \
160 _PREDECL_RBTREE(prefix)
161#define DECLARE_RBTREE_NONUNIQ(prefix, type, field, cmpfn) \
162 \
163macro_inline int prefix ## __cmp(const struct typed_rb_entry *a, \
164 const struct typed_rb_entry *b) \
165{ \
166 return cmpfn(container_of(a, type, field.re), \
167 container_of(b, type, field.re)); \
168} \
169macro_inline int prefix ## __cmp_uq(const struct typed_rb_entry *a, \
170 const struct typed_rb_entry *b) \
171{ \
172 int cmpval = cmpfn(container_of(a, type, field.re), \
173 container_of(b, type, field.re)); \
174 if (cmpval) \
175 return cmpval; \
176 if (a < b) \
177 return -1; \
178 if (a > b) \
179 return 1; \
180 return 0; \
181} \
182 \
183_DECLARE_RBTREE(prefix, type, field, prefix ## __cmp, prefix ## __cmp_uq) \
184/* ... */
185
eea3c899
RW
186#ifdef __cplusplus
187}
188#endif
189
80911bc2 190#endif /* _FRR_TYPERB_H */