Merge pull request #5714 from alexischr/update_bockbuild
[mono.git] / support / x-struct-str.c
index 68925ed2cf87d2841509099e0457a0b73c836acd..5124af71fc948720d20fb6be1a350e0974615bc2 100644 (file)
 
 #define MAX_OFFSETS 10
 
-#define str_at(p, n) (*(char**)(((char*)p)+n))
+#define OFFSET_SHIFT 1
 
-char* MPH_INTERNAL
+#define lstr_at(p, n) (*(char**)(((char*)(p))+(n >> OFFSET_SHIFT)))
+
+#define str_at(p, n) (                                          \
+               (((n) & MPH_STRING_OFFSET_MASK) == MPH_STRING_OFFSET_ARRAY) \
+               ? (char*)(p) + (n >> OFFSET_SHIFT)                          \
+               : lstr_at(p, n)                                             \
+)
+
+char*
 _mph_copy_structure_strings (
-       void *to,         const size_t *to_offsets, 
-       const void *from, const size_t *from_offsets, 
+       void *to,         const mph_string_offset_t *to_offsets, 
+       const void *from, const mph_string_offset_t *from_offsets, 
        size_t num_strings)
 {
        int i;
@@ -26,12 +34,13 @@ _mph_copy_structure_strings (
        g_assert (num_strings < MAX_OFFSETS);
 
        for (i = 0; i < num_strings; ++i) {
-               str_at (to, to_offsets[i]) = NULL;
+               lstr_at (to, to_offsets[i]) = NULL;
        }
 
        buflen = num_strings;
        for (i = 0; i < num_strings; ++i) {
-               len[i] = strlen (str_at(from, from_offsets[i]));
+               const char* s = str_at(from, from_offsets[i]);
+               len [i] = s ? strlen (s) : 0;
                if (len[i] < INT_MAX - buflen)
                        buflen += len[i];
                else
@@ -45,7 +54,7 @@ _mph_copy_structure_strings (
 
        for (i = 0; i < num_strings; ++i) {
                if (len[i] > 0) {
-                       str_at (to, to_offsets[i]) = 
+                       lstr_at (to, to_offsets[i]) = 
                                strcpy (cur, str_at (from, from_offsets[i]));
                        cur += (len[i] +1);
                }
@@ -56,12 +65,19 @@ _mph_copy_structure_strings (
 
 #ifdef TEST
 
+/*
+ * To run the tests:
+ * $ gcc -DTEST -I.. `pkg-config --cflags --libs glib-2.0` x-struct-str.c
+ * $ ./a.out
+ */
+
 #include <stdio.h>
 
 struct foo {
        char *a;
        int   b;
        char *c;
+       char d[10];
 };
 
 struct bar {
@@ -69,22 +85,39 @@ struct bar {
        char  *a;
        double d;
        char  *c;
+       char  *e;
 };
 
 int
 main ()
 {
        /* test copying foo to bar */
-       struct foo f = {"hello", 42, "world"};
+       struct foo f = {"hello", 42, "world", "!!"};
        struct bar b;
-       size_t foo_offsets[] = {offsetof(struct foo, a), offsetof(struct foo, c)};
-       size_t bar_offsets[] = {offsetof(struct bar, a), offsetof(struct bar, c)};
+       mph_string_offset_t foo_offsets[] = {
+               MPH_STRING_OFFSET(struct foo, a, MPH_STRING_OFFSET_PTR),
+               MPH_STRING_OFFSET(struct foo, c, MPH_STRING_OFFSET_PTR),
+               MPH_STRING_OFFSET(struct foo, d, MPH_STRING_OFFSET_ARRAY)
+       };
+       mph_string_offset_t bar_offsets[] = {
+               MPH_STRING_OFFSET(struct bar, a, MPH_STRING_OFFSET_PTR), 
+               MPH_STRING_OFFSET(struct bar, c, MPH_STRING_OFFSET_PTR), 
+               MPH_STRING_OFFSET(struct bar, e, MPH_STRING_OFFSET_PTR)
+       };
        char *buf;
 
        buf = _mph_copy_structure_strings (&b, bar_offsets, 
-                       &f, foo_offsets, 2);
+                       &f, foo_offsets, 3);
+       printf ("b.a=%s\n", b.a);
+       printf ("b.c=%s\n", b.c);
+       printf ("b.e=%s\n", b.e);
+
+       f.c = NULL;
+       buf = _mph_copy_structure_strings (&b, bar_offsets, 
+                       &f, foo_offsets, 3);
        printf ("b.a=%s\n", b.a);
        printf ("b.c=%s\n", b.c);
+       printf ("b.e=%s\n", b.e);
 
        return 0;
 }