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 { .offset = 0, .offset2 = 0, .kind = ignore, .mi = NULL } 40 struct marshal_info { 41 char *name; /* Name of structure */ 42 size_t size; /* Size of the structure */ 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 49 struct marshal_subinfo pointers[]; /* Pointer to other structures */ 50 #endif 51 }; 52 /* Special case for strings */ 53 extern struct marshal_info marshal_info_string; 54 extern struct marshal_info marshal_info_fstring; 55 extern struct marshal_info marshal_info_ignore; 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. */ 59 #define MARSHAL_INFO(type) marshal_info_##type 60 #ifdef MARSHAL_EXPORT 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 } 78 #define MARSHAL_BEGIN(type) struct marshal_info MARSHAL_INFO(type) = \ 79 { \ 80 .name = #type, \ 81 .size = sizeof(struct type), \ 82 .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) MARSHAL_SUBINFO_NULL }}; \ 94 MARSHAL_HELPER_FUNCTIONS(type, struct type) 95 #else 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); 100 #define MARSHAL_ADD(...) 101 #define MARSHAL_FSTR(...) 102 #define MARSHAL_END(type) MARSHAL_HELPER_FUNCTIONS(type, struct type) 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) 109 #define MARSHAL_TQE(type, field) \ 110 MARSHAL_POINTER(type, type, field.tqe_next) \ 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 114 possible. However, TAILQ_FOREACH is still 115 available. */ 116 #define MARSHAL_TQH(type, subtype) \ 117 MARSHAL_POINTER(type, subtype, tqh_first) \ 118 MARSHAL_IGNORE(type, tqh_last) 119 #define MARSHAL_SUBTQ(type, subtype, field) \ 120 MARSHAL_POINTER(type, subtype, field.tqh_first) \ 121 MARSHAL_IGNORE(type, field.tqh_last) 122 #define MARSHAL(type) \ 123 MARSHAL_BEGIN(type) \ 124 MARSHAL_END(type) 125 #define MARSHAL_TQ(type, subtype) \ 126 MARSHAL_BEGIN(type) \ 127 MARSHAL_TQH(type, subtype) \ 128 MARSHAL_END(type) 129 130 /* Serialization */ 131 ssize_t marshal_serialize_(struct marshal_info *, void *, void **, int, void *, int) 132 __attribute__((nonnull (1, 2, 3) )); 133 #define marshal_serialize(type, o, output) marshal_serialize_(&MARSHAL_INFO(type), o, output, 0, NULL, 0) 134 135 /* Unserialization */ 136 size_t marshal_unserialize_(struct marshal_info *, void *, size_t, void **, void*, int, int) 137 __attribute__((nonnull (1, 2, 4) )); 138 #define marshal_unserialize(type, o, l, input) \ 139 marshal_unserialize_(&MARSHAL_INFO(type), o, l, input, NULL, 0, 0) 140 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 155 #endif 156