.size = 0,
.pointers = {{ .mi = NULL }},
};
+struct marshal_info marshal_info__fstring = {
+ .name = "fixed string",
+ .size = 0,
+ .pointers = {{ .mi = NULL }},
+};
/* List of already seen pointers */
struct ref {
/* Serialize the given object. */
size_t
_marshal_serialize(struct marshal_info *mi, void *unserialized, void **input,
- int skip, void *_refs)
+ int skip, void *_refs, int osize)
{
/* Check if we have already serialized this one. */
struct ref_l *refs = _refs;
int size = mi->size;
if (!strcmp(mi->name, "null string"))
size = strlen((char *)unserialized) + 1;
+ else if (!strcmp(mi->name, "fixed string"))
+ size = osize;
/* Allocate serialized structure */
size_t len = sizeof(struct marshal_serialized) + (skip?0:size);
if (source == NULL) continue;
} else
source = (void *)((unsigned char *)unserialized + current->offset);
+ memcpy(&osize, (unsigned char*)unserialized + current->offset2, sizeof(int));
sublen = _marshal_serialize(current->mi,
source, &target,
- current->kind == substruct, refs);
+ current->kind == substruct, refs, osize);
if (sublen == -1) {
LLOG_WARNX("unable to serialize substructure %s for %s",
current->mi->name, mi->name);
/* Unserialize the given object. */
size_t
_marshal_unserialize(struct marshal_info *mi, void *buffer, size_t len, void **output,
- void *_pointers, int skip)
+ void *_pointers, int skip, int osize)
{
int total_len = sizeof(struct marshal_serialized) + (skip?0:mi->size);
struct marshal_serialized *serialized = buffer;
/* Special cases */
int size = mi->size;
- if (!strcmp(mi->name, "null string")) {
- size = strnlen((char *)serialized->object,
- len - sizeof(struct marshal_serialized)) + 1;
- if (size == len - sizeof(struct marshal_serialized) + 1) {
+ if (!strcmp(mi->name, "null string") || !strcmp(mi->name, "fixed string")) {
+ switch (mi->name[0]) {
+ case 'n': size = strnlen((char *)serialized->object,
+ len - sizeof(struct marshal_serialized)) + 1; break;
+ case 'f': size = osize; break;
+ }
+ if (size > len - sizeof(struct marshal_serialized)) {
LLOG_WARNX("data to deserialize contains a string too long");
total_len = 0;
goto unmarshal_error;
if (already) continue;
}
/* Deserialize */
+ memcpy(&osize, (unsigned char *)*output + current->offset2, sizeof(int));
sublen = _marshal_unserialize(current->mi,
(unsigned char *)buffer + total_len, len - total_len, &new, pointers,
- current->kind == substruct);
+ current->kind == substruct, osize);
if (sublen == 0) {
LLOG_WARNX("unable to serialize substructure %s for %s",
current->mi->name, mi->name);
enum marshal_subinfo_kind {
pointer,
substruct,
- string,
};
#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;
};
};
/* Special case for strings */
extern struct marshal_info marshal_info__string;
+extern struct marshal_info marshal_info__fstring;
/* Declare a new marshal_info struct named after the type we want to
marshal. The marshalled type has to be a structure. */
.name = #type, \
.size = sizeof(struct type), \
.pointers = {
-#define MARSHAL_ADD(_kind, type, subtype, member) \
- { .offset = offsetof(struct type, member), \
- .kind = _kind, \
+#define MARSHAL_ADD(_kind, type, subtype, member) \
+ { .offset = offsetof(struct type, member), \
+ .kind = _kind, \
.mi = &marshal_info_##subtype },
#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_FSTR(type, member, len) \
+ { .offset = offsetof(struct type, member), \
+ .offset2 = offsetof(struct type, len), \
+ .kind = pointer, \
+ .mi = &marshal_info__fstring },
#define MARSHAL_TQE(type, field) \
MARSHAL_POINTER(type, type, field.tqe_next) \
MARSHAL_POINTER(type, type, field.tqe_prev)
MARSHAL_END
/* Serialization */
-size_t _marshal_serialize(struct marshal_info *, void *, void **, int, void *);
-#define marshal_serialize(type, o, output) _marshal_serialize(&marshal_info_##type, o, output, 0, NULL)
+size_t _marshal_serialize(struct marshal_info *, void *, void **, int, void *, int);
+#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);
+size_t _marshal_unserialize(struct marshal_info *, void *, size_t, void **, void*, int, int);
#define marshal_unserialize(type, o, l, input) \
- _marshal_unserialize(&marshal_info_##type, o, l, (void **)input, NULL, 0)
+ _marshal_unserialize(&marshal_info_##type, o, l, (void **)input, NULL, 0, 0)
#endif
free(destination);
}
END_TEST
+struct struct_fixedstring {
+ int s1;
+ char *s2;
+ int s2_len;
+ char *s3;
+};
+MARSHAL_BEGIN(struct_fixedstring)
+MARSHAL_FSTR(struct_fixedstring, s2, s2_len)
+MARSHAL_STR(struct_fixedstring, s3)
+MARSHAL_END;
+
+START_TEST(test_fixed_string) {
+ struct struct_fixedstring source = {
+ .s1 = 44444,
+ .s2 = "String 2 Bla",
+ .s2_len = 8,
+ .s3 = "String 3",
+ };
+ struct struct_fixedstring *destination;
+ void *buffer;
+ size_t len, len2;
+
+ len = marshal_serialize(struct_fixedstring, &source, &buffer);
+ fail_unless(len > 0, "Unable to serialize");
+ memset(&source, 0, sizeof(struct struct_string));
+ len2 = marshal_unserialize(struct_fixedstring, buffer, len, &destination);
+ fail_unless(len2 > 0, "Unable to deserialize");
+ free(buffer);
+ ck_assert_int_eq(len, len2);
+ ck_assert_int_eq(destination->s1, 44444);
+ ck_assert_int_eq(destination->s2_len, 8);
+ ck_assert_int_eq(destination->s2[0], 'S');
+ ck_assert_int_eq(destination->s2[2], 'r');
+ ck_assert_int_eq(destination->s2[4], 'n');
+ ck_assert_int_eq(destination->s2[5], 'g');
+ ck_assert_int_eq(destination->s2[6], ' ');
+ ck_assert_int_eq(destination->s2[7], '2');
+ ck_assert_str_eq(destination->s3, "String 3");
+ free(destination->s2); free(destination->s3);
+ free(destination);
+}
+END_TEST
Suite *
marshal_suite(void)
tcase_add_test(tc_marshal, test_simple_list);
tcase_add_test(tc_marshal, test_embedded_list);
tcase_add_test(tc_marshal, test_string);
+ tcase_add_test(tc_marshal, test_fixed_string);
suite_add_tcase(s, tc_marshal);
return s;