Line | Count | Source (jump to first uncovered line) |
1 | | /* -*- mode: c; c-file-style: "openbsd" -*- */ |
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 | | |
21 | | #include <stddef.h> |
22 | | #include <stdint.h> |
23 | | #include <sys/types.h> |
24 | | |
25 | | struct marshal_info; |
26 | | enum marshal_subinfo_kind { |
27 | | pointer, |
28 | | substruct, |
29 | | ignore, |
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 */ |
35 | | size_t offset2; /* Ancillary offset (for related data) */ |
36 | | enum marshal_subinfo_kind kind; /* Kind of substructure */ |
37 | | struct marshal_info *mi; |
38 | | }; |
39 | | #define MARSHAL_SUBINFO_NULL \ |
40 | | { \ |
41 | | .offset = 0, .offset2 = 0, .kind = ignore, .mi = NULL \ |
42 | | } |
43 | | struct marshal_info { |
44 | | const char *name; /* Name of structure */ |
45 | | size_t size; /* Size of the structure */ |
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 |
52 | | struct marshal_subinfo pointers[]; /* Pointer to other structures */ |
53 | | #endif |
54 | | }; |
55 | | /* Special case for strings */ |
56 | | extern struct marshal_info marshal_info_string; |
57 | | extern struct marshal_info marshal_info_fstring; |
58 | | extern struct marshal_info marshal_info_ignore; |
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. */ |
62 | 0 | #define MARSHAL_INFO(type) marshal_info_##type |
63 | | #ifdef MARSHAL_EXPORT |
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 | 0 | { \ |
68 | 0 | return marshal_serialize(type, source, buffer); \ |
69 | 0 | } \ Unexecuted instantiation: lldpd_ppvid_serialize Unexecuted instantiation: lldpd_vlan_serialize Unexecuted instantiation: lldpd_pi_serialize Unexecuted instantiation: lldpd_med_policy_serialize Unexecuted instantiation: lldpd_med_loc_serialize Unexecuted instantiation: lldpd_med_power_serialize Unexecuted instantiation: lldpd_dot3_power_serialize Unexecuted instantiation: lldpd_mgmt_serialize Unexecuted instantiation: lldpd_chassis_serialize Unexecuted instantiation: lldpd_custom_serialize Unexecuted instantiation: lldpd_port_serialize Unexecuted instantiation: lldpd_port_set_serialize Unexecuted instantiation: lldpd_config_serialize Unexecuted instantiation: lldpd_hardware_serialize Unexecuted instantiation: lldpd_interface_serialize Unexecuted instantiation: lldpd_interface_list_serialize Unexecuted instantiation: lldpd_neighbor_change_serialize |
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 | 0 | { \ |
73 | 0 | void *p; \ |
74 | 0 | size_t rc; \ |
75 | 0 | rc = marshal_unserialize(type, buffer, len, &p); \ |
76 | 0 | if (rc <= 0) return rc; \ |
77 | 0 | *destination = p; \ |
78 | 0 | return rc; \ |
79 | 0 | } Unexecuted instantiation: lldpd_ppvid_unserialize Unexecuted instantiation: lldpd_vlan_unserialize Unexecuted instantiation: lldpd_pi_unserialize Unexecuted instantiation: lldpd_med_policy_unserialize Unexecuted instantiation: lldpd_med_loc_unserialize Unexecuted instantiation: lldpd_med_power_unserialize Unexecuted instantiation: lldpd_dot3_power_unserialize Unexecuted instantiation: lldpd_mgmt_unserialize Unexecuted instantiation: lldpd_chassis_unserialize Unexecuted instantiation: lldpd_custom_unserialize Unexecuted instantiation: lldpd_port_unserialize Unexecuted instantiation: lldpd_port_set_unserialize Unexecuted instantiation: lldpd_config_unserialize Unexecuted instantiation: lldpd_hardware_unserialize Unexecuted instantiation: lldpd_interface_unserialize Unexecuted instantiation: lldpd_interface_list_unserialize Unexecuted instantiation: lldpd_neighbor_change_unserialize |
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) |
99 | | #else |
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) |
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) |
113 | | #define MARSHAL_TQE(type, field) \ |
114 | | MARSHAL_POINTER(type, type, field.tqe_next) \ |
115 | | MARSHAL_IGNORE(type, field.tqe_prev) |
116 | | /* Support for TAILQ list is partial. Access to last and previous |
117 | | elements is not available. Some operations are therefore not |
118 | | possible. However, TAILQ_FOREACH is still |
119 | | available. */ |
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) |
133 | | |
134 | | /* Serialization */ |
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 | 0 | marshal_serialize_(&MARSHAL_INFO(type), o, output, 0, NULL, 0) |
139 | | |
140 | | /* Unserialization */ |
141 | | size_t marshal_unserialize_(struct marshal_info *, void *, size_t, void **, void *, int, |
142 | | int) __attribute__((nonnull(1, 2, 4))); |
143 | | #define marshal_unserialize(type, o, l, input) \ |
144 | 0 | marshal_unserialize_(&MARSHAL_INFO(type), o, l, input, NULL, 0, 0) |
145 | | |
146 | | #define marshal_repair_tailq(type, head, field) \ |
147 | 0 | do { \ |
148 | 0 | struct type *__item, *__item_next; \ |
149 | 0 | (head)->tqh_last = &(head)->tqh_first; \ |
150 | 0 | for (__item = TAILQ_FIRST(head); __item != NULL; __item = __item_next) { \ |
151 | 0 | __item_next = TAILQ_NEXT(__item, field); \ |
152 | 0 | __item->field.tqe_prev = (head)->tqh_last; \ |
153 | 0 | *(head)->tqh_last = __item; \ |
154 | 0 | (head)->tqh_last = &__item->field.tqe_next; \ |
155 | 0 | } \ |
156 | 0 | } while (0) |
157 | | |
158 | | #endif |