Z_UNUSED(opaque);
zng_free(ptr);
}
+
+/* Since we support custom memory allocators, some which might not align memory as we expect,
+ * we have to ask for extra memory and return an aligned pointer. */
+void Z_INTERNAL *zng_calloc_aligned(zng_calloc_func zalloc, void *opaque, unsigned items, unsigned size, unsigned align) {
+ uintptr_t return_ptr, original_ptr;
+ int32_t alloc_size, align_diff;
+ void *ptr;
+
+ /* Allocate enough memory for proper alignment and to store the original memory pointer */
+ alloc_size = sizeof(void *) + (items * size) + align;
+ ptr = zalloc(opaque, 1, alloc_size);
+ if (!ptr)
+ return NULL;
+
+ /* Calculate return pointer address with space enough to store original pointer */
+ align_diff = align - ((uintptr_t)ptr % align);
+ return_ptr = (uintptr_t)ptr + align_diff;
+ if (align_diff < sizeof(void *))
+ return_ptr += align;
+
+ /* Store the original pointer for free() */
+ original_ptr = return_ptr - sizeof(void *);
+ memcpy((void *)original_ptr, &ptr, sizeof(void *));
+
+ /* Return properly aligned pointer in allocation */
+ return (void *)return_ptr;
+}
+
+void Z_INTERNAL zng_cfree_aligned(zng_cfree_func zfree, void *opaque, void *ptr) {
+ if (!ptr)
+ return;
+
+ /* Calculate offset to original memory allocation pointer */
+ void *original_ptr = (void *)((uintptr_t)ptr - sizeof(void *));
+ void *free_ptr = *(void **)original_ptr;
+
+ /* Free original memory allocation */
+ zfree(opaque, free_ptr);
+}
void Z_INTERNAL *zng_calloc(void *opaque, unsigned items, unsigned size);
void Z_INTERNAL zng_cfree(void *opaque, void *ptr);
-#define ZALLOC(strm, items, size) (*((strm)->zalloc))((strm)->opaque, (items), (size))
-#define ZFREE(strm, addr) (*((strm)->zfree))((strm)->opaque, (void *)(addr))
+typedef void *zng_calloc_func(void *opaque, unsigned items, unsigned size);
+typedef void zng_cfree_func(void *opaque, void *ptr);
+
+void Z_INTERNAL *zng_calloc_aligned(zng_calloc_func zalloc, void *opaque, unsigned items, unsigned size, unsigned align);
+void Z_INTERNAL zng_cfree_aligned(zng_cfree_func zfree, void *opaque, void *ptr);
+
+#define ZALLOC(strm, items, size) zng_calloc_aligned((strm)->zalloc, (strm)->opaque, (items), (size), 64)
+#define ZFREE(strm, addr) zng_cfree_aligned((strm)->zfree, (strm)->opaque, (void *)(addr))
+
#define TRY_FREE(s, p) {if (p) ZFREE(s, p);}
#endif /* ZUTIL_H_ */