x-struct-str.c 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. /*
  2. * A helper routine to copy the strings between differing structures.
  3. */
  4. #include <stdlib.h>
  5. #include <string.h>
  6. #include <limits.h>
  7. #include "mph.h"
  8. #define MAX_OFFSETS 10
  9. #define OFFSET_SHIFT 1
  10. #define lstr_at(p, n) (*(char**)(((char*)(p))+(n >> OFFSET_SHIFT)))
  11. #define str_at(p, n) ( \
  12. (((n) & MPH_STRING_OFFSET_MASK) == MPH_STRING_OFFSET_ARRAY) \
  13. ? (char*)(p) + (n >> OFFSET_SHIFT) \
  14. : lstr_at(p, n) \
  15. )
  16. char* MPH_INTERNAL
  17. _mph_copy_structure_strings (
  18. void *to, const mph_string_offset_t *to_offsets,
  19. const void *from, const mph_string_offset_t *from_offsets,
  20. size_t num_strings)
  21. {
  22. int i;
  23. size_t buflen;
  24. int len[MAX_OFFSETS];
  25. char *buf, *cur = NULL;
  26. g_assert (num_strings < MAX_OFFSETS);
  27. for (i = 0; i < num_strings; ++i) {
  28. lstr_at (to, to_offsets[i]) = NULL;
  29. }
  30. buflen = num_strings;
  31. for (i = 0; i < num_strings; ++i) {
  32. len[i] = strlen (str_at(from, from_offsets[i]));
  33. if (len[i] < INT_MAX - buflen)
  34. buflen += len[i];
  35. else
  36. len[i] = -1;
  37. }
  38. cur = buf = malloc (buflen);
  39. if (buf == NULL) {
  40. return NULL;
  41. }
  42. for (i = 0; i < num_strings; ++i) {
  43. if (len[i] > 0) {
  44. lstr_at (to, to_offsets[i]) =
  45. strcpy (cur, str_at (from, from_offsets[i]));
  46. cur += (len[i] +1);
  47. }
  48. }
  49. return buf;
  50. }
  51. #ifdef TEST
  52. #include <stdio.h>
  53. struct foo {
  54. char *a;
  55. int b;
  56. char *c;
  57. char d[10];
  58. };
  59. struct bar {
  60. int b;
  61. char *a;
  62. double d;
  63. char *c;
  64. char *e;
  65. };
  66. int
  67. main ()
  68. {
  69. /* test copying foo to bar */
  70. struct foo f = {"hello", 42, "world", "!!"};
  71. struct bar b;
  72. mph_string_offset_t foo_offsets[] = {
  73. MPH_STRING_OFFSET(struct foo, a, MPH_STRING_OFFSET_PTR),
  74. MPH_STRING_OFFSET(struct foo, c, MPH_STRING_OFFSET_PTR),
  75. MPH_STRING_OFFSET(struct foo, d, MPH_STRING_OFFSET_ARRAY)
  76. };
  77. mph_string_offset_t bar_offsets[] = {
  78. MPH_STRING_OFFSET(struct bar, a, MPH_STRING_OFFSET_PTR),
  79. MPH_STRING_OFFSET(struct bar, c, MPH_STRING_OFFSET_PTR),
  80. MPH_STRING_OFFSET(struct bar, e, MPH_STRING_OFFSET_PTR)
  81. };
  82. char *buf;
  83. buf = _mph_copy_structure_strings (&b, bar_offsets,
  84. &f, foo_offsets, 3);
  85. printf ("b.a=%s\n", b.a);
  86. printf ("b.c=%s\n", b.c);
  87. printf ("b.e=%s\n", b.e);
  88. return 0;
  89. }
  90. #endif