]>
Commit | Line | Data |
---|---|---|
4b292b55 | 1 | /* -*- mode: c; c-file-style: "openbsd" -*- */ |
db323555 VB |
2 | /* |
3 | * Copyright (c) 2012 Vincent Bernat <bernat@luffy.cx> | |
4 | * | |
5 | * Permission to use, copy, modify, and/or distribute this software for any | |
6 | * purpose with or without fee is hereby granted, provided that the above | |
7 | * copyright notice and this permission notice appear in all copies. | |
8 | * | |
9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | |
10 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | |
11 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | |
12 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | |
13 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | |
14 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | |
15 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |
16 | */ | |
17 | ||
18 | #ifndef _MARSHAL_H | |
19 | #define _MARSHAL_H | |
20 | ||
4b292b55 | 21 | #include <stddef.h> |
ff3dcc4a | 22 | #include <stdint.h> |
4b292b55 VB |
23 | #include <sys/types.h> |
24 | ||
db323555 VB |
25 | struct marshal_info; |
26 | enum marshal_subinfo_kind { | |
27 | pointer, | |
28 | substruct, | |
305e061c | 29 | ignore, |
db323555 VB |
30 | }; |
31 | #define MARSHAL_INFO_POINTER 1 | |
8b549648 | 32 | #define MARSHAL_INFO_SUB 2 |
db323555 | 33 | struct marshal_subinfo { |
8b549648 VB |
34 | size_t offset; /* Offset compared to parent structure */ |
35 | size_t offset2; /* Ancillary offset (for related data) */ | |
db323555 | 36 | enum marshal_subinfo_kind kind; /* Kind of substructure */ |
8b549648 | 37 | struct marshal_info *mi; |
db323555 | 38 | }; |
8b549648 VB |
39 | #define MARSHAL_SUBINFO_NULL \ |
40 | { \ | |
41 | .offset = 0, .offset2 = 0, .kind = ignore, .mi = NULL \ | |
42 | } | |
db323555 | 43 | struct marshal_info { |
f540397c GS |
44 | const char *name; /* Name of structure */ |
45 | size_t size; /* Size of the structure */ | |
01d467de VB |
46 | #if defined __GNUC__ && __GNUC__ < 3 |
47 | /* With gcc 2.96, flexible arrays are not supported, even with | |
48 | * -std=gnu99. And with gcc 3.x, zero-sized arrays cannot be statically | |
49 | * initialized (with more than one element). */ | |
50 | struct marshal_subinfo pointers[0]; /* Pointer to other structures */ | |
51 | #else | |
db323555 | 52 | struct marshal_subinfo pointers[]; /* Pointer to other structures */ |
01d467de | 53 | #endif |
db323555 | 54 | }; |
da781141 | 55 | /* Special case for strings */ |
6bf5e749 VB |
56 | extern struct marshal_info marshal_info_string; |
57 | extern struct marshal_info marshal_info_fstring; | |
58 | extern struct marshal_info marshal_info_ignore; | |
db323555 VB |
59 | |
60 | /* Declare a new marshal_info struct named after the type we want to | |
61 | marshal. The marshalled type has to be a structure. */ | |
6bf5e749 VB |
62 | #define MARSHAL_INFO(type) marshal_info_##type |
63 | #ifdef MARSHAL_EXPORT | |
f540397c GS |
64 | # define MARSHAL_HELPER_FUNCTIONS(type, ttype) \ |
65 | ssize_t type##_serialize(ttype *source, void *buffer); \ | |
66 | ssize_t type##_serialize(ttype *source, void *buffer) \ | |
67 | { \ | |
68 | return marshal_serialize(type, source, buffer); \ | |
69 | } \ | |
70 | size_t type##_unserialize(void *buffer, size_t len, ttype **destination); \ | |
71 | size_t type##_unserialize(void *buffer, size_t len, ttype **destination) \ | |
72 | { \ | |
73 | void *p; \ | |
74 | size_t rc; \ | |
75 | rc = marshal_unserialize(type, buffer, len, &p); \ | |
76 | if (rc <= 0) return rc; \ | |
77 | *destination = p; \ | |
78 | return rc; \ | |
8b549648 VB |
79 | } |
80 | # define MARSHAL_BEGIN(type) \ | |
81 | struct marshal_info MARSHAL_INFO( \ | |
82 | type) = { .name = #type, .size = sizeof(struct type), .pointers = { | |
83 | # define MARSHAL_ADD(_kind, type, subtype, member) \ | |
84 | { .offset = offsetof(struct type, member), \ | |
85 | .offset2 = 0, \ | |
86 | .kind = _kind, \ | |
87 | .mi = &MARSHAL_INFO(subtype) }, | |
88 | # define MARSHAL_FSTR(type, member, len) \ | |
89 | { .offset = offsetof(struct type, member), \ | |
90 | .offset2 = offsetof(struct type, len), \ | |
91 | .kind = pointer, \ | |
92 | .mi = &marshal_info_fstring }, | |
93 | # define MARSHAL_END(type) \ | |
94 | MARSHAL_SUBINFO_NULL \ | |
95 | } \ | |
96 | } \ | |
97 | ; \ | |
98 | MARSHAL_HELPER_FUNCTIONS(type, struct type) | |
6bf5e749 | 99 | #else |
8b549648 VB |
100 | # define MARSHAL_HELPER_FUNCTIONS(type, ttype) \ |
101 | ssize_t type##_serialize(ttype *, void *); \ | |
102 | size_t type##_unserialize(void *, size_t, ttype **); | |
103 | # define MARSHAL_BEGIN(type) extern struct marshal_info MARSHAL_INFO(type); | |
104 | # define MARSHAL_ADD(...) | |
105 | # define MARSHAL_FSTR(...) | |
106 | # define MARSHAL_END(type) MARSHAL_HELPER_FUNCTIONS(type, struct type) | |
6bf5e749 VB |
107 | #endif |
108 | /* Shortcuts */ | |
109 | #define MARSHAL_POINTER(...) MARSHAL_ADD(pointer, ##__VA_ARGS__) | |
110 | #define MARSHAL_SUBSTRUCT(...) MARSHAL_ADD(substruct, ##__VA_ARGS__) | |
111 | #define MARSHAL_STR(type, member) MARSHAL_ADD(pointer, type, string, member) | |
112 | #define MARSHAL_IGNORE(type, member) MARSHAL_ADD(ignore, type, ignore, member) | |
8b549648 VB |
113 | #define MARSHAL_TQE(type, field) \ |
114 | MARSHAL_POINTER(type, type, field.tqe_next) \ | |
115 | MARSHAL_IGNORE(type, field.tqe_prev) | |
6bf5e749 VB |
116 | /* Support for TAILQ list is partial. Access to last and previous |
117 | elements is not available. Some operations are therefore not | |
4e90a9e0 | 118 | possible. However, TAILQ_FOREACH is still |
6bf5e749 | 119 | available. */ |
8b549648 VB |
120 | #define MARSHAL_TQH(type, subtype) \ |
121 | MARSHAL_POINTER(type, subtype, tqh_first) \ | |
122 | MARSHAL_IGNORE(type, tqh_last) | |
123 | #define MARSHAL_SUBTQ(type, subtype, field) \ | |
124 | MARSHAL_POINTER(type, subtype, field.tqh_first) \ | |
125 | MARSHAL_IGNORE(type, field.tqh_last) | |
126 | #define MARSHAL(type) \ | |
127 | MARSHAL_BEGIN(type) \ | |
128 | MARSHAL_END(type) | |
129 | #define MARSHAL_TQ(type, subtype) \ | |
130 | MARSHAL_BEGIN(type) \ | |
131 | MARSHAL_TQH(type, subtype) \ | |
132 | MARSHAL_END(type) | |
db323555 VB |
133 | |
134 | /* Serialization */ | |
8b549648 VB |
135 | ssize_t marshal_serialize_(struct marshal_info *, void *, void **, int, void *, int) |
136 | __attribute__((nonnull(1, 2, 3))); | |
137 | #define marshal_serialize(type, o, output) \ | |
138 | marshal_serialize_(&MARSHAL_INFO(type), o, output, 0, NULL, 0) | |
db323555 VB |
139 | |
140 | /* Unserialization */ | |
8b549648 VB |
141 | size_t marshal_unserialize_(struct marshal_info *, void *, size_t, void **, void *, int, |
142 | int) __attribute__((nonnull(1, 2, 4))); | |
db323555 | 143 | #define marshal_unserialize(type, o, l, input) \ |
8b549648 | 144 | marshal_unserialize_(&MARSHAL_INFO(type), o, l, input, NULL, 0, 0) |
db323555 | 145 | |
8b549648 VB |
146 | #define marshal_repair_tailq(type, head, field) \ |
147 | do { \ | |
148 | struct type *__item, *__item_next; \ | |
149 | (head)->tqh_last = &(head)->tqh_first; \ | |
150 | for (__item = TAILQ_FIRST(head); __item != NULL; __item = __item_next) { \ | |
151 | __item_next = TAILQ_NEXT(__item, field); \ | |
152 | __item->field.tqe_prev = (head)->tqh_last; \ | |
153 | *(head)->tqh_last = __item; \ | |
154 | (head)->tqh_last = &__item->field.tqe_next; \ | |
155 | } \ | |
156 | } while (0) | |
2e043f72 | 157 | |
db323555 | 158 | #endif |