1*d3140113Seric /* $OpenBSD: tree.c,v 1.8 2021/06/14 17:58:16 eric Exp $ */
272bc847cSeric
372bc847cSeric /*
472bc847cSeric * Copyright (c) 2012 Eric Faurot <eric@openbsd.org>
572bc847cSeric *
672bc847cSeric * Permission to use, copy, modify, and distribute this software for any
772bc847cSeric * purpose with or without fee is hereby granted, provided that the above
872bc847cSeric * copyright notice and this permission notice appear in all copies.
972bc847cSeric *
1072bc847cSeric * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
1172bc847cSeric * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1272bc847cSeric * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1372bc847cSeric * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1472bc847cSeric * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1572bc847cSeric * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1672bc847cSeric * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1772bc847cSeric */
1872bc847cSeric
1972bc847cSeric #include <sys/tree.h>
2072bc847cSeric
2172bc847cSeric #include <inttypes.h>
2272bc847cSeric #include <stdlib.h>
2372bc847cSeric
24fd4beb3eSgilles #include "tree.h"
25ff01b044Seric #include "log.h"
2672bc847cSeric
2772bc847cSeric struct treeentry {
2872bc847cSeric SPLAY_ENTRY(treeentry) entry;
2972bc847cSeric uint64_t id;
3072bc847cSeric void *data;
3172bc847cSeric };
3272bc847cSeric
3372bc847cSeric static int treeentry_cmp(struct treeentry *, struct treeentry *);
3472bc847cSeric
35299c4efeSeric SPLAY_PROTOTYPE(_tree, treeentry, entry, treeentry_cmp);
3672bc847cSeric
3772bc847cSeric int
tree_check(struct tree * t,uint64_t id)3872bc847cSeric tree_check(struct tree *t, uint64_t id)
3972bc847cSeric {
4072bc847cSeric struct treeentry key;
4172bc847cSeric
4272bc847cSeric key.id = id;
43299c4efeSeric return (SPLAY_FIND(_tree, &t->tree, &key) != NULL);
4472bc847cSeric }
4572bc847cSeric
4672bc847cSeric void *
tree_set(struct tree * t,uint64_t id,void * data)4772bc847cSeric tree_set(struct tree *t, uint64_t id, void *data)
4872bc847cSeric {
4972bc847cSeric struct treeentry *entry, key;
5072bc847cSeric char *old;
5172bc847cSeric
5272bc847cSeric key.id = id;
53299c4efeSeric if ((entry = SPLAY_FIND(_tree, &t->tree, &key)) == NULL) {
54299c4efeSeric if ((entry = malloc(sizeof *entry)) == NULL)
55ff01b044Seric fatal("tree_set: malloc");
5672bc847cSeric entry->id = id;
57299c4efeSeric SPLAY_INSERT(_tree, &t->tree, entry);
5872bc847cSeric old = NULL;
59299c4efeSeric t->count += 1;
6072bc847cSeric } else
6172bc847cSeric old = entry->data;
6272bc847cSeric
6372bc847cSeric entry->data = data;
6472bc847cSeric
6572bc847cSeric return (old);
6672bc847cSeric }
6772bc847cSeric
6872bc847cSeric void
tree_xset(struct tree * t,uint64_t id,void * data)6972bc847cSeric tree_xset(struct tree *t, uint64_t id, void *data)
7072bc847cSeric {
7172bc847cSeric struct treeentry *entry;
7272bc847cSeric
73299c4efeSeric if ((entry = malloc(sizeof *entry)) == NULL)
74ff01b044Seric fatal("tree_xset: malloc");
7572bc847cSeric entry->id = id;
7672bc847cSeric entry->data = data;
77299c4efeSeric if (SPLAY_INSERT(_tree, &t->tree, entry))
78ff01b044Seric fatalx("tree_xset(%p, 0x%016"PRIx64 ")", t, id);
79299c4efeSeric t->count += 1;
8072bc847cSeric }
8172bc847cSeric
8272bc847cSeric void *
tree_get(struct tree * t,uint64_t id)8372bc847cSeric tree_get(struct tree *t, uint64_t id)
8472bc847cSeric {
8572bc847cSeric struct treeentry key, *entry;
8672bc847cSeric
8772bc847cSeric key.id = id;
88299c4efeSeric if ((entry = SPLAY_FIND(_tree, &t->tree, &key)) == NULL)
8972bc847cSeric return (NULL);
9072bc847cSeric
9172bc847cSeric return (entry->data);
9272bc847cSeric }
9372bc847cSeric
9472bc847cSeric void *
tree_xget(struct tree * t,uint64_t id)9572bc847cSeric tree_xget(struct tree *t, uint64_t id)
9672bc847cSeric {
9772bc847cSeric struct treeentry key, *entry;
9872bc847cSeric
9972bc847cSeric key.id = id;
100299c4efeSeric if ((entry = SPLAY_FIND(_tree, &t->tree, &key)) == NULL)
101ff01b044Seric fatalx("tree_get(%p, 0x%016"PRIx64 ")", t, id);
10272bc847cSeric
10372bc847cSeric return (entry->data);
10472bc847cSeric }
10572bc847cSeric
10672bc847cSeric void *
tree_pop(struct tree * t,uint64_t id)10772bc847cSeric tree_pop(struct tree *t, uint64_t id)
10872bc847cSeric {
10972bc847cSeric struct treeentry key, *entry;
11072bc847cSeric void *data;
11172bc847cSeric
11272bc847cSeric key.id = id;
113299c4efeSeric if ((entry = SPLAY_FIND(_tree, &t->tree, &key)) == NULL)
11472bc847cSeric return (NULL);
11572bc847cSeric
11672bc847cSeric data = entry->data;
117299c4efeSeric SPLAY_REMOVE(_tree, &t->tree, entry);
11872bc847cSeric free(entry);
119299c4efeSeric t->count -= 1;
12072bc847cSeric
12172bc847cSeric return (data);
12272bc847cSeric }
12372bc847cSeric
12472bc847cSeric void *
tree_xpop(struct tree * t,uint64_t id)12572bc847cSeric tree_xpop(struct tree *t, uint64_t id)
12672bc847cSeric {
12772bc847cSeric struct treeentry key, *entry;
12872bc847cSeric void *data;
12972bc847cSeric
13072bc847cSeric key.id = id;
131299c4efeSeric if ((entry = SPLAY_FIND(_tree, &t->tree, &key)) == NULL)
132ff01b044Seric fatalx("tree_xpop(%p, 0x%016" PRIx64 ")", t, id);
13372bc847cSeric
13472bc847cSeric data = entry->data;
135299c4efeSeric SPLAY_REMOVE(_tree, &t->tree, entry);
13672bc847cSeric free(entry);
137299c4efeSeric t->count -= 1;
13872bc847cSeric
13972bc847cSeric return (data);
14072bc847cSeric }
14172bc847cSeric
14272bc847cSeric int
tree_poproot(struct tree * t,uint64_t * id,void ** data)14372bc847cSeric tree_poproot(struct tree *t, uint64_t *id, void **data)
14472bc847cSeric {
14572bc847cSeric struct treeentry *entry;
14672bc847cSeric
147299c4efeSeric entry = SPLAY_ROOT(&t->tree);
14872bc847cSeric if (entry == NULL)
14972bc847cSeric return (0);
15072bc847cSeric if (id)
15172bc847cSeric *id = entry->id;
15272bc847cSeric if (data)
15372bc847cSeric *data = entry->data;
154299c4efeSeric SPLAY_REMOVE(_tree, &t->tree, entry);
15572bc847cSeric free(entry);
156299c4efeSeric t->count -= 1;
157299c4efeSeric
15872bc847cSeric return (1);
15972bc847cSeric }
16072bc847cSeric
16172bc847cSeric int
tree_root(struct tree * t,uint64_t * id,void ** data)16272bc847cSeric tree_root(struct tree *t, uint64_t *id, void **data)
16372bc847cSeric {
16472bc847cSeric struct treeentry *entry;
16572bc847cSeric
166299c4efeSeric entry = SPLAY_ROOT(&t->tree);
16772bc847cSeric if (entry == NULL)
16872bc847cSeric return (0);
16972bc847cSeric if (id)
17072bc847cSeric *id = entry->id;
17172bc847cSeric if (data)
17272bc847cSeric *data = entry->data;
17372bc847cSeric return (1);
17472bc847cSeric }
17572bc847cSeric
17672bc847cSeric int
tree_iter(struct tree * t,void ** hdl,uint64_t * id,void ** data)17772bc847cSeric tree_iter(struct tree *t, void **hdl, uint64_t *id, void **data)
17872bc847cSeric {
17972bc847cSeric struct treeentry *curr = *hdl;
18072bc847cSeric
18172bc847cSeric if (curr == NULL)
182299c4efeSeric curr = SPLAY_MIN(_tree, &t->tree);
18372bc847cSeric else
184299c4efeSeric curr = SPLAY_NEXT(_tree, &t->tree, curr);
18572bc847cSeric
18672bc847cSeric if (curr) {
18772bc847cSeric *hdl = curr;
18872bc847cSeric if (id)
18972bc847cSeric *id = curr->id;
19072bc847cSeric if (data)
19172bc847cSeric *data = curr->data;
19272bc847cSeric return (1);
19372bc847cSeric }
19472bc847cSeric
19572bc847cSeric return (0);
19672bc847cSeric }
19772bc847cSeric
1984fe02f32Seric int
tree_iterfrom(struct tree * t,void ** hdl,uint64_t k,uint64_t * id,void ** data)1994fe02f32Seric tree_iterfrom(struct tree *t, void **hdl, uint64_t k, uint64_t *id, void **data)
2004fe02f32Seric {
2014fe02f32Seric struct treeentry *curr = *hdl, key;
2024fe02f32Seric
2034fe02f32Seric if (curr == NULL) {
2044fe02f32Seric if (k == 0)
205299c4efeSeric curr = SPLAY_MIN(_tree, &t->tree);
2064fe02f32Seric else {
2074fe02f32Seric key.id = k;
208299c4efeSeric curr = SPLAY_FIND(_tree, &t->tree, &key);
2094fe02f32Seric if (curr == NULL) {
210299c4efeSeric SPLAY_INSERT(_tree, &t->tree, &key);
211299c4efeSeric curr = SPLAY_NEXT(_tree, &t->tree, &key);
212299c4efeSeric SPLAY_REMOVE(_tree, &t->tree, &key);
2134fe02f32Seric }
2144fe02f32Seric }
2154fe02f32Seric } else
216299c4efeSeric curr = SPLAY_NEXT(_tree, &t->tree, curr);
2174fe02f32Seric
2184fe02f32Seric if (curr) {
2194fe02f32Seric *hdl = curr;
2204fe02f32Seric if (id)
2214fe02f32Seric *id = curr->id;
2224fe02f32Seric if (data)
2234fe02f32Seric *data = curr->data;
2244fe02f32Seric return (1);
2254fe02f32Seric }
2264fe02f32Seric
2274fe02f32Seric return (0);
2284fe02f32Seric }
2294fe02f32Seric
23072bc847cSeric void
tree_merge(struct tree * dst,struct tree * src)23172bc847cSeric tree_merge(struct tree *dst, struct tree *src)
23272bc847cSeric {
23372bc847cSeric struct treeentry *entry;
23472bc847cSeric
235299c4efeSeric while (!SPLAY_EMPTY(&src->tree)) {
236299c4efeSeric entry = SPLAY_ROOT(&src->tree);
237299c4efeSeric SPLAY_REMOVE(_tree, &src->tree, entry);
238299c4efeSeric if (SPLAY_INSERT(_tree, &dst->tree, entry))
239ff01b044Seric fatalx("tree_merge: duplicate");
24072bc847cSeric }
241299c4efeSeric dst->count += src->count;
242299c4efeSeric src->count = 0;
24372bc847cSeric }
24472bc847cSeric
24572bc847cSeric static int
treeentry_cmp(struct treeentry * a,struct treeentry * b)24672bc847cSeric treeentry_cmp(struct treeentry *a, struct treeentry *b)
24772bc847cSeric {
24872bc847cSeric if (a->id < b->id)
24972bc847cSeric return (-1);
25072bc847cSeric if (a->id > b->id)
25172bc847cSeric return (1);
25272bc847cSeric return (0);
25372bc847cSeric }
25472bc847cSeric
255299c4efeSeric SPLAY_GENERATE(_tree, treeentry, entry, treeentry_cmp);
256