]>
Commit | Line | Data |
---|---|---|
1bf9f027 DL |
1 | /* |
2 | * Copyright (c) 2015-16 David Lamparter, for NetDEF, Inc. | |
3 | * | |
db2d8df6 DL |
4 | * Permission to use, copy, modify, and distribute this software for any |
5 | * purpose with or without fee is hereby granted, provided that the above | |
6 | * copyright notice and this permission notice appear in all copies. | |
1bf9f027 | 7 | * |
db2d8df6 DL |
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | |
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | |
11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | |
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | |
13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | |
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |
1bf9f027 DL |
15 | */ |
16 | ||
17 | #ifndef _QOBJ_H | |
18 | #define _QOBJ_H | |
19 | ||
20 | #include <stdint.h> | |
21 | #include <stdlib.h> | |
22 | #include <stddef.h> | |
23 | ||
24 | /* reserve a specific amount of bytes for a struct, which can grow up to | |
25 | * that size (or be dummy'd out if not needed) | |
26 | * | |
27 | * note the padding's array size will be an error if it gets negative or zero; | |
28 | * this is intentional to prevent the struct from growing beyond the allocated | |
29 | * space. | |
30 | */ | |
31 | #define RESERVED_SPACE_STRUCT(name, fieldname, size) \ | |
32 | struct { \ | |
33 | struct name fieldname; \ | |
34 | char padding ## fieldname[size - sizeof(struct name)]; \ | |
35 | }; | |
36 | ||
37 | /* don't need struct definitions for these here. code actually using | |
38 | * these needs to define the struct *before* including this header. | |
39 | * HAVE_QOBJ_xxx should be defined to +1 in that case, like this: | |
40 | * | |
41 | * #if defined(HAVE_QOBJ_NODETYPE_CLI) && HAVE_QOBJ_NODETYPE_CLI < 0 | |
42 | * #error include files are in wrong order | |
43 | * #else | |
44 | * #define HAVE_QOBJ_NODETYPE_CLI 1 | |
45 | * struct qobj_nodetype_cli { ... } | |
46 | * #endif | |
47 | */ | |
48 | #ifndef HAVE_QOBJ_NODETYPE_CLI | |
49 | #define HAVE_QOBJ_NODETYPE_CLI -1 | |
50 | struct qobj_nodetype_cli { int dummy; }; | |
51 | #endif | |
52 | ||
53 | #ifndef HAVE_QOBJ_NODETYPE_CAPNP | |
54 | #define HAVE_QOBJ_NODETYPE_CAPNP -1 | |
55 | struct qobj_nodetype_capnp { int dummy; }; | |
56 | #endif | |
57 | ||
58 | /* each different kind of object will have a global variable of this type, | |
59 | * which can be used by various other pieces to store type-related bits. | |
60 | * type equality can be tested as pointer equality. (cf. QOBJ_GET_TYPESAFE) | |
61 | */ | |
62 | struct qobj_nodetype { | |
63 | ptrdiff_t node_member_offset; | |
64 | RESERVED_SPACE_STRUCT(qobj_nodetype_cli, cli, 256) | |
65 | RESERVED_SPACE_STRUCT(qobj_nodetype_capnp, capnp, 256) | |
66 | }; | |
67 | ||
68 | /* anchor to be embedded somewhere in the object's struct */ | |
69 | struct qobj_node { | |
70 | uint64_t nid; | |
71 | struct qobj_nodetype *type; | |
72 | }; | |
73 | ||
74 | #define QOBJ_FIELDS \ | |
75 | struct qobj_node qobj_node; | |
76 | ||
77 | /* call these at the end of any _create function (QOBJ_REG) | |
78 | * and beginning of any _destroy function (QOBJ_UNREG) */ | |
79 | #define QOBJ_REG(n, structname) \ | |
80 | qobj_reg(&n->qobj_node, &qobj_t_ ## structname) | |
81 | #define QOBJ_UNREG(n) \ | |
82 | qobj_unreg(&n->qobj_node) | |
83 | ||
84 | /* internals - should not be directly used without a good reason*/ | |
85 | void qobj_reg(struct qobj_node *node, struct qobj_nodetype *type); | |
86 | void qobj_unreg(struct qobj_node *node); | |
87 | struct qobj_node *qobj_get(uint64_t id); | |
88 | void *qobj_get_typed(uint64_t id, struct qobj_nodetype *type); | |
89 | ||
90 | /* type declarations */ | |
91 | #define DECLARE_QOBJ_TYPE(structname) \ | |
92 | extern struct qobj_nodetype qobj_t_ ## structname; | |
93 | #define DEFINE_QOBJ_TYPE(structname) \ | |
94 | struct qobj_nodetype qobj_t_ ## structname = { \ | |
95 | .node_member_offset = \ | |
96 | (ptrdiff_t)offsetof(struct structname, qobj_node) \ | |
97 | }; | |
98 | #define DEFINE_QOBJ_TYPE_INIT(structname, ...) \ | |
99 | struct qobj_nodetype qobj_t_ ## structname = { \ | |
100 | .node_member_offset = \ | |
101 | (ptrdiff_t)offsetof(struct structname, qobj_node), \ | |
102 | __VA_ARGS__ \ | |
103 | }; | |
104 | ||
105 | /* ID dereference with typecheck. | |
106 | * will return NULL if id not found or wrong type. */ | |
107 | #define QOBJ_GET_TYPESAFE(id, structname) \ | |
108 | ((struct structname *)qobj_get_typed((id), &qobj_t_ ## structname)) | |
109 | ||
110 | #define QOBJ_ID(ptr) \ | |
111 | ((ptr)->qobj_node.nid) | |
3c5070be DL |
112 | #define QOBJ_ID_0SAFE(ptr) \ |
113 | ({ typeof (ptr) _ptr = (ptr); _ptr ? _ptr->qobj_node.nid : 0ULL; }) | |
1bf9f027 DL |
114 | |
115 | void qobj_init(void); | |
116 | void qobj_finish(void); | |
117 | ||
118 | #endif /* _QOBJ_H */ |