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