|
Packit |
e9ba0d |
/* -*- mode: c; c-file-style: "openbsd" -*- */
|
|
Packit |
e9ba0d |
/*
|
|
Packit |
e9ba0d |
* Copyright (c) 2012 Vincent Bernat <bernat@luffy.cx>
|
|
Packit |
e9ba0d |
*
|
|
Packit |
e9ba0d |
* Permission to use, copy, modify, and/or distribute this software for any
|
|
Packit |
e9ba0d |
* purpose with or without fee is hereby granted, provided that the above
|
|
Packit |
e9ba0d |
* copyright notice and this permission notice appear in all copies.
|
|
Packit |
e9ba0d |
*
|
|
Packit |
e9ba0d |
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
Packit |
e9ba0d |
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
Packit |
e9ba0d |
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
Packit |
e9ba0d |
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
Packit |
e9ba0d |
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
Packit |
e9ba0d |
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
Packit |
e9ba0d |
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
Packit |
e9ba0d |
*/
|
|
Packit |
e9ba0d |
|
|
Packit |
e9ba0d |
#ifndef _MARSHAL_H
|
|
Packit |
e9ba0d |
#define _MARSHAL_H
|
|
Packit |
e9ba0d |
|
|
Packit |
e9ba0d |
#include <stddef.h>
|
|
Packit |
e9ba0d |
#include <sys/types.h>
|
|
Packit |
e9ba0d |
|
|
Packit |
e9ba0d |
struct marshal_info;
|
|
Packit |
e9ba0d |
enum marshal_subinfo_kind {
|
|
Packit |
e9ba0d |
pointer,
|
|
Packit |
e9ba0d |
substruct,
|
|
Packit |
e9ba0d |
ignore,
|
|
Packit |
e9ba0d |
};
|
|
Packit |
e9ba0d |
#define MARSHAL_INFO_POINTER 1
|
|
Packit |
e9ba0d |
#define MARSHAL_INFO_SUB 2
|
|
Packit |
e9ba0d |
struct marshal_subinfo {
|
|
Packit |
e9ba0d |
size_t offset; /* Offset compared to parent structure */
|
|
Packit |
e9ba0d |
size_t offset2; /* Ancillary offset (for related data) */
|
|
Packit |
e9ba0d |
enum marshal_subinfo_kind kind; /* Kind of substructure */
|
|
Packit |
e9ba0d |
struct marshal_info *mi;
|
|
Packit |
e9ba0d |
};
|
|
Packit |
e9ba0d |
#define MARSHAL_SUBINFO_NULL { .offset = 0, .offset2 = 0, .kind = ignore, .mi = NULL }
|
|
Packit |
e9ba0d |
struct marshal_info {
|
|
Packit |
e9ba0d |
char *name; /* Name of structure */
|
|
Packit |
e9ba0d |
size_t size; /* Size of the structure */
|
|
Packit |
e9ba0d |
#if defined __GNUC__ && __GNUC__ < 3
|
|
Packit |
e9ba0d |
/* With gcc 2.96, flexible arrays are not supported, even with
|
|
Packit |
e9ba0d |
* -std=gnu99. And with gcc 3.x, zero-sized arrays cannot be statically
|
|
Packit |
e9ba0d |
* initialized (with more than one element). */
|
|
Packit |
e9ba0d |
struct marshal_subinfo pointers[0]; /* Pointer to other structures */
|
|
Packit |
e9ba0d |
#else
|
|
Packit |
e9ba0d |
struct marshal_subinfo pointers[]; /* Pointer to other structures */
|
|
Packit |
e9ba0d |
#endif
|
|
Packit |
e9ba0d |
};
|
|
Packit |
e9ba0d |
/* Special case for strings */
|
|
Packit |
e9ba0d |
extern struct marshal_info marshal_info_string;
|
|
Packit |
e9ba0d |
extern struct marshal_info marshal_info_fstring;
|
|
Packit |
e9ba0d |
extern struct marshal_info marshal_info_ignore;
|
|
Packit |
e9ba0d |
|
|
Packit |
e9ba0d |
/* Declare a new marshal_info struct named after the type we want to
|
|
Packit |
e9ba0d |
marshal. The marshalled type has to be a structure. */
|
|
Packit |
e9ba0d |
#define MARSHAL_INFO(type) marshal_info_##type
|
|
Packit |
e9ba0d |
#ifdef MARSHAL_EXPORT
|
|
Packit |
e9ba0d |
#define MARSHAL_HELPER_FUNCTIONS(type, ttype) \
|
|
Packit |
e9ba0d |
ssize_t \
|
|
Packit |
e9ba0d |
type ## _serialize(ttype *source, void *buffer) { \
|
|
Packit |
e9ba0d |
return marshal_serialize(type, \
|
|
Packit |
e9ba0d |
source, buffer); \
|
|
Packit |
e9ba0d |
} \
|
|
Packit |
e9ba0d |
size_t \
|
|
Packit |
e9ba0d |
type ## _unserialize(void *buffer, size_t len, \
|
|
Packit |
e9ba0d |
ttype **destination) { \
|
|
Packit |
e9ba0d |
void *p; \
|
|
Packit |
e9ba0d |
size_t rc; \
|
|
Packit |
e9ba0d |
rc = marshal_unserialize(type, \
|
|
Packit |
e9ba0d |
buffer, len, &p); \
|
|
Packit |
e9ba0d |
if (rc <= 0) return rc; \
|
|
Packit |
e9ba0d |
*destination = p; \
|
|
Packit |
e9ba0d |
return rc; \
|
|
Packit |
e9ba0d |
}
|
|
Packit |
e9ba0d |
#define MARSHAL_BEGIN(type) struct marshal_info MARSHAL_INFO(type) = \
|
|
Packit |
e9ba0d |
{ \
|
|
Packit |
e9ba0d |
.name = #type, \
|
|
Packit |
e9ba0d |
.size = sizeof(struct type), \
|
|
Packit |
e9ba0d |
.pointers = {
|
|
Packit |
e9ba0d |
#define MARSHAL_ADD(_kind, type, subtype, member) \
|
|
Packit |
e9ba0d |
{ .offset = offsetof(struct type, member), \
|
|
Packit |
e9ba0d |
.offset2 = 0, \
|
|
Packit |
e9ba0d |
.kind = _kind, \
|
|
Packit |
e9ba0d |
.mi = &MARSHAL_INFO(subtype) },
|
|
Packit |
e9ba0d |
#define MARSHAL_FSTR(type, member, len) \
|
|
Packit |
e9ba0d |
{ .offset = offsetof(struct type, member), \
|
|
Packit |
e9ba0d |
.offset2 = offsetof(struct type, len), \
|
|
Packit |
e9ba0d |
.kind = pointer, \
|
|
Packit |
e9ba0d |
.mi = &marshal_info_fstring },
|
|
Packit |
e9ba0d |
#define MARSHAL_END(type) MARSHAL_SUBINFO_NULL }}; \
|
|
Packit |
e9ba0d |
MARSHAL_HELPER_FUNCTIONS(type, struct type)
|
|
Packit |
e9ba0d |
#else
|
|
Packit |
e9ba0d |
#define MARSHAL_HELPER_FUNCTIONS(type, ttype) \
|
|
Packit |
e9ba0d |
ssize_t type ## _serialize(ttype*, void*); \
|
|
Packit |
e9ba0d |
size_t type ## _unserialize(void*, size_t, ttype**);
|
|
Packit |
e9ba0d |
#define MARSHAL_BEGIN(type) extern struct marshal_info MARSHAL_INFO(type);
|
|
Packit |
e9ba0d |
#define MARSHAL_ADD(...)
|
|
Packit |
e9ba0d |
#define MARSHAL_FSTR(...)
|
|
Packit |
e9ba0d |
#define MARSHAL_END(type) MARSHAL_HELPER_FUNCTIONS(type, struct type)
|
|
Packit |
e9ba0d |
#endif
|
|
Packit |
e9ba0d |
/* Shortcuts */
|
|
Packit |
e9ba0d |
#define MARSHAL_POINTER(...) MARSHAL_ADD(pointer, ##__VA_ARGS__)
|
|
Packit |
e9ba0d |
#define MARSHAL_SUBSTRUCT(...) MARSHAL_ADD(substruct, ##__VA_ARGS__)
|
|
Packit |
e9ba0d |
#define MARSHAL_STR(type, member) MARSHAL_ADD(pointer, type, string, member)
|
|
Packit |
e9ba0d |
#define MARSHAL_IGNORE(type, member) MARSHAL_ADD(ignore, type, ignore, member)
|
|
Packit |
e9ba0d |
#define MARSHAL_TQE(type, field) \
|
|
Packit |
e9ba0d |
MARSHAL_POINTER(type, type, field.tqe_next) \
|
|
Packit |
e9ba0d |
MARSHAL_IGNORE(type, field.tqe_prev)
|
|
Packit |
e9ba0d |
/* Support for TAILQ list is partial. Access to last and previous
|
|
Packit |
e9ba0d |
elements is not available. Some operations are therefore not
|
|
Packit |
e9ba0d |
possible. However, TAILQ_FOREACH is still
|
|
Packit |
e9ba0d |
available. */
|
|
Packit |
e9ba0d |
#define MARSHAL_TQH(type, subtype) \
|
|
Packit |
e9ba0d |
MARSHAL_POINTER(type, subtype, tqh_first) \
|
|
Packit |
e9ba0d |
MARSHAL_IGNORE(type, tqh_last)
|
|
Packit |
e9ba0d |
#define MARSHAL_SUBTQ(type, subtype, field) \
|
|
Packit |
e9ba0d |
MARSHAL_POINTER(type, subtype, field.tqh_first) \
|
|
Packit |
e9ba0d |
MARSHAL_IGNORE(type, field.tqh_last)
|
|
Packit |
e9ba0d |
#define MARSHAL(type) \
|
|
Packit |
e9ba0d |
MARSHAL_BEGIN(type) \
|
|
Packit |
e9ba0d |
MARSHAL_END(type)
|
|
Packit |
e9ba0d |
#define MARSHAL_TQ(type, subtype) \
|
|
Packit |
e9ba0d |
MARSHAL_BEGIN(type) \
|
|
Packit |
e9ba0d |
MARSHAL_TQH(type, subtype) \
|
|
Packit |
e9ba0d |
MARSHAL_END(type)
|
|
Packit |
e9ba0d |
|
|
Packit |
e9ba0d |
/* Serialization */
|
|
Packit |
e9ba0d |
ssize_t marshal_serialize_(struct marshal_info *, void *, void **, int, void *, int)
|
|
Packit |
e9ba0d |
__attribute__((nonnull (1, 2, 3) ));
|
|
Packit |
e9ba0d |
#define marshal_serialize(type, o, output) marshal_serialize_(&MARSHAL_INFO(type), o, output, 0, NULL, 0)
|
|
Packit |
e9ba0d |
|
|
Packit |
e9ba0d |
/* Unserialization */
|
|
Packit |
e9ba0d |
size_t marshal_unserialize_(struct marshal_info *, void *, size_t, void **, void*, int, int)
|
|
Packit |
e9ba0d |
__attribute__((nonnull (1, 2, 4) ));
|
|
Packit |
e9ba0d |
#define marshal_unserialize(type, o, l, input) \
|
|
Packit |
e9ba0d |
marshal_unserialize_(&MARSHAL_INFO(type), o, l, input, NULL, 0, 0)
|
|
Packit |
e9ba0d |
|
|
Packit |
e9ba0d |
#define marshal_repair_tailq(type, head, field) \
|
|
Packit |
e9ba0d |
do { \
|
|
Packit |
e9ba0d |
struct type *__item, *__item_next; \
|
|
Packit |
e9ba0d |
(head)->tqh_last = &(head)->tqh_first; \
|
|
Packit |
e9ba0d |
for (__item = TAILQ_FIRST(head); \
|
|
Packit |
e9ba0d |
__item != NULL; \
|
|
Packit |
e9ba0d |
__item = __item_next) { \
|
|
Packit |
e9ba0d |
__item_next = TAILQ_NEXT(__item, field); \
|
|
Packit |
e9ba0d |
__item->field.tqe_prev = (head)->tqh_last; \
|
|
Packit |
e9ba0d |
*(head)->tqh_last = __item; \
|
|
Packit |
e9ba0d |
(head)->tqh_last = &__item->field.tqe_next; \
|
|
Packit |
e9ba0d |
} \
|
|
Packit |
e9ba0d |
} while(0)
|
|
Packit |
e9ba0d |
|
|
Packit |
e9ba0d |
#endif
|