782
#define ALLOC_ARRAY(x, alloc) (x) = xmalloc(st_mult(sizeof(*(x)), (alloc)))
783
#define REALLOC_ARRAY(x, alloc) (x) = xrealloc((x), st_mult(sizeof(*(x)), (alloc)))
784
785
+/*
786
+ * These functions help you allocate structs with flex arrays, and copy
787
+ * the data directly into the array. For example, if you had:
788
+ *
789
+ * struct foo {
790
+ * int bar;
791
+ * char name[FLEX_ARRAY];
792
+ * };
793
+ *
794
+ * you can do:
795
+ *
796
+ * struct foo *f;
797
+ * FLEX_ALLOC_MEM(f, name, src, len);
798
+ *
799
+ * to allocate a "foo" with the contents of "src" in the "name" field.
800
+ * The resulting struct is automatically zero'd, and the flex-array field
801
+ * is NUL-terminated (whether the incoming src buffer was or not).
802
+ *
803
+ * The FLEXPTR_* variants operate on structs that don't use flex-arrays,
804
+ * but do want to store a pointer to some extra data in the same allocated
805
+ * block. For example, if you have:
806
+ *
807
+ * struct foo {
808
+ * char *name;
809
+ * int bar;
810
+ * };
811
+ *
812
+ * you can do:
813
+ *
814
+ * struct foo *f;
815
+ * FLEX_ALLOC_STR(f, name, src);
816
+ *
817
+ * and "name" will point to a block of memory after the struct, which will be
818
+ * freed along with the struct (but the pointer can be repointed anywhere).
819
+ *
820
+ * The *_STR variants accept a string parameter rather than a ptr/len
821
+ * combination.
822
+ *
823
+ * Note that these macros will evaluate the first parameter multiple
824
+ * times, and it must be assignable as an lvalue.
825
+ */
826
+#define FLEX_ALLOC_MEM(x, flexname, buf, len) do { \
827
+ (x) = NULL; /* silence -Wuninitialized for offset calculation */ \
828
+ (x) = xalloc_flex(sizeof(*(x)), (char *)(&((x)->flexname)) - (char *)(x), (buf), (len)); \
829
+} while (0)
830
+#define FLEXPTR_ALLOC_MEM(x, ptrname, buf, len) do { \
831
+ (x) = xalloc_flex(sizeof(*(x)), sizeof(*(x)), (buf), (len)); \
832
+ (x)->ptrname = (void *)((x)+1); \
833
+} while(0)
834
+#define FLEX_ALLOC_STR(x, flexname, str) \
835
+ FLEX_ALLOC_MEM((x), flexname, (str), strlen(str))
836
+#define FLEXPTR_ALLOC_STR(x, ptrname, str) \
837
+ FLEXPTR_ALLOC_MEM((x), ptrname, (str), strlen(str))
838
+
839
+static inline void *xalloc_flex(size_t base_len, size_t offset,
840
+ const void *src, size_t src_len)
841
+{
842
+ unsigned char *ret = xcalloc(1, st_add3(base_len, src_len, 1));
843
+ memcpy(ret + offset, src, src_len);
844
+ return ret;
845
+}
846
+
847
static inline char *xstrdup_or_null(const char *str)
848
{
849
return str ? xstrdup(str) : NULL;