chiark / gitweb /
@@@ fltfmt mess
[mLib] / mem / arena.h
index 82f6cd6c1a20c994cabc4d37ebdd19de9e7fda7b..fad4fa9e4bc0eab6ad0c94597b42d01d83a27ac2 100644 (file)
@@ -58,6 +58,20 @@ extern arena arena_stdlib;           /* Arena based on @malloc@/@free@ */
 
 /*----- 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
@@ -77,14 +91,30 @@ extern void *arena_fakerealloc(arena */*a*/, void */*p*/,
 /* --- 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 -------------------------------------------------*/