xref: /openbsd-src/usr.sbin/smtpd/tree.c (revision d3140113bef2b86d3af61dd20c05a8630ff966c2)
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