open62541 1.3.12
Open source implementation of OPC UA
Loading...
Searching...
No Matches
ziptree.h
Go to the documentation of this file.
1/** This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
4 *
5 * Copyright 2018, 2021 (c) Julius Pfrommer
6 */
7
8#ifndef ZIPTREE_H_
9#define ZIPTREE_H_
10
11#include <stddef.h>
12
13#ifdef _MSC_VER
14# define ZIP_INLINE __inline
15#else
16# define ZIP_INLINE inline
17#endif
18
19/** Prevent warnings on unused static inline functions for some compilers */
20#if defined(__GNUC__) || defined(__clang__)
21# define ZIP_UNUSED __attribute__((unused))
22#else
23# define ZIP_UNUSED
24#endif
25
26#ifdef __cplusplus
27extern "C" {
28#endif
29
30/** Reusable zip tree implementation. The style is inspired by the BSD
31 * sys/queue.h linked list definition.
32 *
33 * Zip trees were developed in: Tarjan, R. E., Levy, C. C., and Timmel, S. "Zip
34 * Trees." arXiv preprint arXiv:1806.06726 (2018). The original definition was
35 * modified so that several elements with the same key can be inserted. However,
36 * ZIP_FIND will only return the topmost of these elements in the tree.
37 *
38 * The ZIP_ENTRY definitions are to be contained in the tree entries themselves.
39 * Use ZIP_FUNCTIONS to define the signature of the zip tree functions. */
40
41#define ZIP_HEAD(name, type) \
42struct name { \
43 struct type *root; \
44}
45
46#define ZIP_ENTRY(type) \
47struct { \
48 struct type *left; \
49 struct type *right; \
50 unsigned char rank; \
51}
52
58
59typedef enum ZIP_CMP (*zip_cmp_cb)(const void *key1, const void *key2);
60
61#define ZIP_INIT(head) do { (head)->root = NULL; } while (0)
62#define ZIP_ROOT(head) (head)->root
63#define ZIP_LEFT(elm, field) (elm)->field.left
64#define ZIP_RIGHT(elm, field) (elm)->field.right
65#define ZIP_RANK(elm, field) (elm)->field.rank
66
67/** Internal definitions. Don't use directly. */
68
69typedef void (*__zip_iter_cb)(void *elm, void *context);
70
71void *
72__ZIP_INSERT(zip_cmp_cb cmp, unsigned short fieldoffset,
73 unsigned short keyoffset, void *root, void *elm);
74
75void *
76__ZIP_REMOVE(zip_cmp_cb cmp, unsigned short fieldoffset,
77 unsigned short keyoffset, void *root, void *elm);
78
79void *
80__ZIP_FIND(zip_cmp_cb cmp, unsigned short fieldoffset,
81 unsigned short keyoffset, void *root,
82 const void *key);
83
84void
85__ZIP_ITER(unsigned short fieldoffset, __zip_iter_cb cb,
86 void *context, void *elm);
87
88void * __ZIP_MIN(unsigned short fieldoffset, void *elm);
89void * __ZIP_MAX(unsigned short fieldoffset, void *elm);
90
91/** Zip trees are a probabilistic data structure. Entries are assigned a
92 * (non-negative) rank k with probability 1/2^{k+1}. A uniformly sampled random
93 * number has to be supplied with the insert method. __ZIP_FFS32 extracts from
94 * it least significant nonzero bit of a 32bit number. This then has the correct
95 * distribution. */
96unsigned char __ZIP_FFS32(unsigned int v);
97
98/** Generate zip tree method definitions with the ZIP_FUNCTIONS macro. The
99 * comparison method "cmp" defined for every zip tree has the signature
100 *
101 * enum ZIP_CMP cmpDateTime(const keytype *a, const keytype *b); */
102
103#define ZIP_INSERT(name, head, elm, rank) name##_ZIP_INSERT(head, elm, rank)
104#define ZIP_REMOVE(name, head, elm) name##_ZIP_REMOVE(head, elm)
105#define ZIP_FIND(name, head, key) name##_ZIP_FIND(head, key)
106#define ZIP_MIN(name, head) name##_ZIP_MIN(head)
107#define ZIP_MAX(name, head) name##_ZIP_MAX(head)
108#define ZIP_ITER(name, head, cb, d) name##_ZIP_ITER(head, cb, d)
109
110#define ZIP_FUNCTIONS(name, type, field, keytype, keyfield, cmp) \
111ZIP_UNUSED static ZIP_INLINE void \
112name##_ZIP_INSERT(struct name *head, struct type *elm, \
113 unsigned int r) { \
114 ZIP_RANK(elm, field) = __ZIP_FFS32(r); \
115 ZIP_ROOT(head) = (struct type*) \
116 __ZIP_INSERT(cmp, offsetof(struct type, field), \
117 offsetof(struct type, keyfield), \
118 ZIP_ROOT(head), elm); \
119} \
120 \
121ZIP_UNUSED static ZIP_INLINE void \
122name##_ZIP_REMOVE(struct name *head, struct type *elm) { \
123 ZIP_ROOT(head) = (struct type*) \
124 __ZIP_REMOVE(cmp, offsetof(struct type, field), \
125 offsetof(struct type, keyfield), \
126 ZIP_ROOT(head), elm); \
127} \
128 \
129ZIP_UNUSED static ZIP_INLINE struct type * \
130name##_ZIP_FIND(struct name *head, const keytype *key) { \
131 return (struct type*)__ZIP_FIND(cmp, offsetof(struct type, field), \
132 offsetof(struct type, keyfield), \
133 ZIP_ROOT(head), key); \
134} \
135 \
136ZIP_UNUSED static ZIP_INLINE struct type * \
137name##_ZIP_MIN(struct name *head) { \
138 return (struct type *)__ZIP_MIN(offsetof(struct type, field), \
139 ZIP_ROOT(head)); \
140} \
141 \
142ZIP_UNUSED static ZIP_INLINE struct type * \
143name##_ZIP_MAX(struct name *head) { \
144 return (struct type *)__ZIP_MAX(offsetof(struct type, field), \
145 ZIP_ROOT(head)); \
146} \
147 \
148typedef void (*name##_cb)(struct type *elm, void *context); \
149 \
150ZIP_UNUSED static ZIP_INLINE void \
151name##_ZIP_ITER(struct name *head, name##_cb cb, void *context) { \
152 __ZIP_ITER(offsetof(struct type, field), (__zip_iter_cb)cb, \
153 context, ZIP_ROOT(head)); \
154}
155
156#ifdef __cplusplus
157} /* extern "C" */
158#endif
159
160#endif /* ZIPTREE_H_ */
unsigned char __ZIP_FFS32(unsigned int v)
Zip trees are a probabilistic data structure.
void(* __zip_iter_cb)(void *elm, void *context)
Internal definitions.
Definition ziptree.h:69
void * __ZIP_MAX(unsigned short fieldoffset, void *elm)
ZIP_CMP
Definition ziptree.h:53
@ ZIP_CMP_LESS
Definition ziptree.h:54
@ ZIP_CMP_EQ
Definition ziptree.h:55
@ ZIP_CMP_MORE
Definition ziptree.h:56
void * __ZIP_FIND(zip_cmp_cb cmp, unsigned short fieldoffset, unsigned short keyoffset, void *root, const void *key)
void * __ZIP_INSERT(zip_cmp_cb cmp, unsigned short fieldoffset, unsigned short keyoffset, void *root, void *elm)
enum ZIP_CMP(* zip_cmp_cb)(const void *key1, const void *key2)
Definition ziptree.h:59
void * __ZIP_REMOVE(zip_cmp_cb cmp, unsigned short fieldoffset, unsigned short keyoffset, void *root, void *elm)
void * __ZIP_MIN(unsigned short fieldoffset, void *elm)
void __ZIP_ITER(unsigned short fieldoffset, __zip_iter_cb cb, void *context, void *elm)