]>
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 | |
32 | #define MARSHAL_INFO_SUB 2 | |
33 | struct marshal_subinfo { | |
34 | size_t offset; /* Offset compared to parent structure */ | |
ca4ed9da | 35 | size_t offset2; /* Ancillary offset (for related data) */ |
db323555 VB |
36 | enum marshal_subinfo_kind kind; /* Kind of substructure */ |
37 | struct marshal_info *mi; | |
38 | }; | |
01d467de | 39 | #define MARSHAL_SUBINFO_NULL { .offset = 0, .offset2 = 0, .kind = ignore, .mi = NULL } |
db323555 VB |
40 | struct marshal_info { |
41 | char *name; /* Name of structure */ | |
42 | size_t size; /* Size of the structure */ | |
01d467de VB |
43 | #if defined __GNUC__ && __GNUC__ < 3 |
44 | /* With gcc 2.96, flexible arrays are not supported, even with | |
45 | * -std=gnu99. And with gcc 3.x, zero-sized arrays cannot be statically | |
46 | * initialized (with more than one element). */ | |
47 | struct marshal_subinfo pointers[0]; /* Pointer to other structures */ | |
48 | #else | |
db323555 | 49 | struct marshal_subinfo pointers[]; /* Pointer to other structures */ |
01d467de | 50 | #endif |
db323555 | 51 | }; |
da781141 | 52 | /* Special case for strings */ |
6bf5e749 VB |
53 | extern struct marshal_info marshal_info_string; |
54 | extern struct marshal_info marshal_info_fstring; | |
55 | extern struct marshal_info marshal_info_ignore; | |
db323555 VB |
56 | |
57 | /* Declare a new marshal_info struct named after the type we want to | |
58 | marshal. The marshalled type has to be a structure. */ | |
6bf5e749 VB |
59 | #define MARSHAL_INFO(type) marshal_info_##type |
60 | #ifdef MARSHAL_EXPORT | |
985a4cb5 VB |
61 | #define MARSHAL_HELPER_FUNCTIONS(type, ttype) \ |
62 | ssize_t \ | |
63 | type ## _serialize(ttype *source, void *buffer) { \ | |
64 | return marshal_serialize(type, \ | |
65 | source, buffer); \ | |
66 | } \ | |
67 | size_t \ | |
68 | type ## _unserialize(void *buffer, size_t len, \ | |
69 | ttype **destination) { \ | |
70 | void *p; \ | |
71 | size_t rc; \ | |
72 | rc = marshal_unserialize(type, \ | |
73 | buffer, len, &p); \ | |
74 | if (rc <= 0) return rc; \ | |
75 | *destination = p; \ | |
76 | return rc; \ | |
77 | } | |
6bf5e749 | 78 | #define MARSHAL_BEGIN(type) struct marshal_info MARSHAL_INFO(type) = \ |
db323555 VB |
79 | { \ |
80 | .name = #type, \ | |
81 | .size = sizeof(struct type), \ | |
82 | .pointers = { | |
ca4ed9da VB |
83 | #define MARSHAL_ADD(_kind, type, subtype, member) \ |
84 | { .offset = offsetof(struct type, member), \ | |
01d467de | 85 | .offset2 = 0, \ |
ca4ed9da | 86 | .kind = _kind, \ |
6bf5e749 | 87 | .mi = &MARSHAL_INFO(subtype) }, |
ca4ed9da VB |
88 | #define MARSHAL_FSTR(type, member, len) \ |
89 | { .offset = offsetof(struct type, member), \ | |
90 | .offset2 = offsetof(struct type, len), \ | |
91 | .kind = pointer, \ | |
6bf5e749 | 92 | .mi = &marshal_info_fstring }, |
985a4cb5 VB |
93 | #define MARSHAL_END(type) MARSHAL_SUBINFO_NULL }}; \ |
94 | MARSHAL_HELPER_FUNCTIONS(type, struct type) | |
6bf5e749 | 95 | #else |
985a4cb5 VB |
96 | #define MARSHAL_HELPER_FUNCTIONS(type, ttype) \ |
97 | ssize_t type ## _serialize(ttype*, void*); \ | |
98 | size_t type ## _unserialize(void*, size_t, ttype**); | |
99 | #define MARSHAL_BEGIN(type) extern struct marshal_info MARSHAL_INFO(type); | |
6bf5e749 VB |
100 | #define MARSHAL_ADD(...) |
101 | #define MARSHAL_FSTR(...) | |
985a4cb5 | 102 | #define MARSHAL_END(type) MARSHAL_HELPER_FUNCTIONS(type, struct type) |
6bf5e749 VB |
103 | #endif |
104 | /* Shortcuts */ | |
105 | #define MARSHAL_POINTER(...) MARSHAL_ADD(pointer, ##__VA_ARGS__) | |
106 | #define MARSHAL_SUBSTRUCT(...) MARSHAL_ADD(substruct, ##__VA_ARGS__) | |
107 | #define MARSHAL_STR(type, member) MARSHAL_ADD(pointer, type, string, member) | |
108 | #define MARSHAL_IGNORE(type, member) MARSHAL_ADD(ignore, type, ignore, member) | |
5e73393b VB |
109 | #define MARSHAL_TQE(type, field) \ |
110 | MARSHAL_POINTER(type, type, field.tqe_next) \ | |
6bf5e749 VB |
111 | MARSHAL_IGNORE(type, field.tqe_prev) |
112 | /* Support for TAILQ list is partial. Access to last and previous | |
113 | elements is not available. Some operations are therefore not | |
4e90a9e0 | 114 | possible. However, TAILQ_FOREACH is still |
6bf5e749 | 115 | available. */ |
5e73393b VB |
116 | #define MARSHAL_TQH(type, subtype) \ |
117 | MARSHAL_POINTER(type, subtype, tqh_first) \ | |
6bf5e749 | 118 | MARSHAL_IGNORE(type, tqh_last) |
5e73393b VB |
119 | #define MARSHAL_SUBTQ(type, subtype, field) \ |
120 | MARSHAL_POINTER(type, subtype, field.tqh_first) \ | |
6bf5e749 | 121 | MARSHAL_IGNORE(type, field.tqh_last) |
5e73393b VB |
122 | #define MARSHAL(type) \ |
123 | MARSHAL_BEGIN(type) \ | |
985a4cb5 | 124 | MARSHAL_END(type) |
5e73393b VB |
125 | #define MARSHAL_TQ(type, subtype) \ |
126 | MARSHAL_BEGIN(type) \ | |
127 | MARSHAL_TQH(type, subtype) \ | |
985a4cb5 | 128 | MARSHAL_END(type) |
db323555 VB |
129 | |
130 | /* Serialization */ | |
aa015c26 VB |
131 | ssize_t marshal_serialize_(struct marshal_info *, void *, void **, int, void *, int) |
132 | __attribute__((nonnull (1, 2, 3) )); | |
6bf5e749 | 133 | #define marshal_serialize(type, o, output) marshal_serialize_(&MARSHAL_INFO(type), o, output, 0, NULL, 0) |
db323555 VB |
134 | |
135 | /* Unserialization */ | |
aa015c26 VB |
136 | size_t marshal_unserialize_(struct marshal_info *, void *, size_t, void **, void*, int, int) |
137 | __attribute__((nonnull (1, 2, 4) )); | |
db323555 | 138 | #define marshal_unserialize(type, o, l, input) \ |
0e940d8d | 139 | marshal_unserialize_(&MARSHAL_INFO(type), o, l, input, NULL, 0, 0) |
db323555 | 140 | |
2e043f72 VB |
141 | #define marshal_repair_tailq(type, head, field) \ |
142 | do { \ | |
143 | struct type *__item, *__item_next; \ | |
144 | (head)->tqh_last = &(head)->tqh_first; \ | |
145 | for (__item = TAILQ_FIRST(head); \ | |
146 | __item != NULL; \ | |
147 | __item = __item_next) { \ | |
148 | __item_next = TAILQ_NEXT(__item, field); \ | |
149 | __item->field.tqe_prev = (head)->tqh_last; \ | |
150 | *(head)->tqh_last = __item; \ | |
151 | (head)->tqh_last = &__item->field.tqe_next; \ | |
152 | } \ | |
153 | } while(0) | |
154 | ||
db323555 | 155 | #endif |