unsigned char object[0];
};
+struct marshal_info marshal_info__string = {
+ .name = "null string",
+ .size = 0,
+ .pointers = {{ .mi = NULL }},
+};
+
/* List of already seen pointers */
struct ref {
TAILQ_ENTRY(ref) next;
return 0;
}
- size_t len = sizeof(struct marshal_serialized) + (skip?0:mi->size);
+ /* Handle special cases. */
+ int size = mi->size;
+ if (!strcmp(mi->name, "null string"))
+ size = strlen((char *)unserialized) + 1;
+
+ /* Allocate serialized structure */
+ size_t len = sizeof(struct marshal_serialized) + (skip?0:size);
struct marshal_serialized *serialized = calloc(1, len);
if (!serialized) {
LLOG_WARNX("unable to allocate memory to serialize structure %s",
/* First, serialize the main structure */
if (!skip)
- memcpy(serialized->object, unserialized, mi->size);
+ memcpy(serialized->object, unserialized, size);
/* Then, serialize inner structures */
struct marshal_subinfo *current;
TAILQ_INIT(pointers);
}
+ /* 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) {
+ LLOG_WARNX("data to deserialize contains a string too long");
+ total_len = 0;
+ goto unmarshal_error;
+ }
+ total_len += size;
+ }
+
/* First, the main structure */
if (!skip) {
- if ((*output = marshal_alloc(pointers, mi->size, serialized->orig)) == NULL) {
+ if ((*output = marshal_alloc(pointers, size, serialized->orig)) == NULL) {
LLOG_WARNX("unable to allocate memory to unserialize structure %s",
mi->name);
total_len = 0;
goto unmarshal_error;
}
- memcpy(*output, serialized->object, mi->size);
+ memcpy(*output, serialized->object, size);
}
/* Then, each substructure */
enum marshal_subinfo_kind {
pointer,
substruct,
+ string,
};
#define MARSHAL_INFO_POINTER 1
#define MARSHAL_INFO_SUB 2
size_t size; /* Size of the structure */
struct marshal_subinfo pointers[]; /* Pointer to other structures */
};
+/* Special case for strings */
+extern struct marshal_info marshal_info__string;
/* Declare a new marshal_info struct named after the type we want to
marshal. The marshalled type has to be a structure. */
.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_TQE(type, field) \
MARSHAL_POINTER(type, type, field.tqe_next) \
MARSHAL_POINTER(type, type, field.tqe_prev)
}
END_TEST
+struct struct_string {
+ int s1;
+ char *s2;
+ char *s3;
+};
+MARSHAL_BEGIN(struct_string)
+MARSHAL_STR(struct_string, s2)
+MARSHAL_STR(struct_string, s3)
+MARSHAL_END;
+
+START_TEST(test_string) {
+ struct struct_string source = {
+ .s1 = 44444,
+ .s2 = "String 2",
+ .s3 = "String 3",
+ };
+ struct struct_string *destination;
+ void *buffer;
+ size_t len, len2;
+
+ len = marshal_serialize(struct_string, &source, &buffer);
+ fail_unless(len > 0, "Unable to serialize");
+ memset(&source, 0, sizeof(struct struct_string));
+ len2 = marshal_unserialize(struct_string, 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_str_eq(destination->s2, "String 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_too_small_unmarshal);
tcase_add_test(tc_marshal, test_simple_list);
tcase_add_test(tc_marshal, test_embedded_list);
+ tcase_add_test(tc_marshal, test_string);
suite_add_tcase(s, tc_marshal);
return s;