/*----- Functions provided ------------------------------------------------*/
+/* --- @ALLOCV_SAFE_P@, @NEWV_SAFE_P@ ---
+ *
+ * Arguments: @type *p@ = pointer to a vector (for @NEWV_SAFE_P@; not
+ * evaluated)
+ * @size_t n@ = number of elements
+ * @size_t sz@ = element size (for @ALLOCV_SAFE_P@)
+ *
+ * Returns: Nonzero if the product of @n@ and @sz@ (or @sizeof(*p)@) is
+ * representable in type @size_t@.
+ */
+
+#define ALLOCV_SAFE_P(n, sz) ((n) <= (size_t)-1/(sz))
+#define NEWV_SAFE_P(p, n) (ALLOCV_SAFE_P((n), sizeof(*(p))))
+
/* --- @arena_fakerealloc@ --- *
*
* Arguments: @arena *a@ = pointer to arena block
/* --- Useful macros --- */
#define A_ALLOC(a, sz) (((a)->ops->alloc)((a), (sz)))
-#define A_REALLOC(a, p, sz, osz) (((a)->ops->realloc)((a), (p), (sz), (osz)))
+#define A_ALLOCV(a, n, sz) \
+ (ALLOCV_SAFE_P((n), (sz)) ? ((a)->ops->alloc)((a), (n)*(sz)) : 0)
+#define A_NEW(p, a) do { (p) = A_ALLOC((a), sizeof(*(p))); } while (0)
+#define A_NEWV(p, a, n) \
+ do { (p) = A_ALLOCV((a), (n), sizeof(*(p))); } while (0)
+#define A_REALLOC(a, p, sz, osz) \
+ (((a)->ops->realloc)((a), (p), (sz), (osz)))
+#define A_REALLOCV(a, p, n, on, sz) \
+ (ALLOCV_SAFE_P((n), (sz)) ? \
+ ((a)->ops->realloc)((a), (p), (n)*(sz), (on)*(sz)) : 0)
+#define A_RENEWV(q, p, a, n, on) do { \
+ (q) = !sizeof((*(p)) = (*(q))) + \
+ A_REALLOCV((a), (p), (n), (on), sizeof(*(p))); \
+} while (0)
#define A_FREE(a, p) (((a)->ops->free)((a), (p)))
/* --- Simple function equivalents --- */
extern void *a_alloc(arena */*a*/, size_t /*sz*/);
+extern void *a_allocv(arena */*a*/, size_t /*n*/, size_t /*sz*/);
extern void *a_realloc(arena */*a*/, void */*p*/,
size_t /*sz*/, size_t /*osz*/);
+extern void *a_reallocv(arena */*a*/, void */*p*/,
+ size_t /*n*/, size_t /*on*/, size_t /*sz*/);
extern void a_free(arena */*a*/, void */*p*/);
/*----- That's all, folks -------------------------------------------------*/