/*----- Macros provided ---------------------------------------------------*/
-/* --- @GROWBUF_LIMIT@ --- *
+/* --- @GROWBUF__LIMIT@ --- *
*
- * Arguments: @size_t granule@ = allocation granule
+ * Arguments: @szty@ = an unsigned type
+ * @size_t granule@ = allocation granule
*
- * Returns: The largest number %$n$% such that the total size of %$n$%
+ * Returns: The largest number %$n$% such that %$n$% is representable in
+ * a value of the given @szty@ and the total size of %$n$%
* objects, each of size @granule@, can be represented in a
- * @size_t@.
+ * value of type @size_t@.
*/
-#define GROWBUF_LIMIT(granule) (~(size_t)0/(granule))
+#define GROWBUF__LIMIT(szty, granule) \
+ (~(szty)0 < ~(size_t)0/(granule) ? \
+ ~(szty)0 : ~(size_t)0/(granule))
/* --- @GROWBUF_SIZE@ --- *
*
- * Arguments: @size_t sz@ = the current size (updated)
- * @size_t want@ = the desired minimum size
- * @size_t init@ = a suitable initial size
- * @size_t granule@ = the allocation granule size
+ * Arguments: @szty@ = an unsigned type
+ * @szty sz@ = the current size (updated)
+ * @szty want@ = the desired minimum size
+ * @szty init@ = a suitable initial size
+ * @szty granule@ = the allocation granule size
*
* Returns: ---
*
* positive size at least as large as @want@.
*/
-#define GROWBUF_SIZE(sz, want, init, granule) do { \
- size_t _sz_ = (sz), _want_ = (want); \
+#define GROWBUF_SIZE(szty, sz, want, init, granule) do { \
+ szty _sz_ = (sz), _want_ = (want); \
\
- assert(_want_ < GROWBUF_LIMIT(granule)/2); \
+ assert(_want_ < GROWBUF__LIMIT(szty, granule)/2); \
if (!_sz_) _sz_ = (init); \
while (_sz_ < _want_) _sz_ *= 2; \
(sz) = _sz_; \
/* --- @GROWBUF_EXTEND@, @GROWBUF_REPLACE@ --- *
*
- * Arguments: @arena *a@ = pointer to an arena
+ * Arguments: @szty@ = an unsigned type
+ * @arena *a@ = pointer to an arena
* @type *buf@ = pointer to some buffer, possibly null (updated)
- * @size_t sz@ = current buffer size (updated)
- * @size_t want@ = desired minimum size
- * @size_t init@ = a suitable initial size
+ * @szty sz@ = current buffer size (updated)
+ * @szty want@ = desired minimum size
+ * @szty init@ = a suitable initial size
* @size_t granule@ = the allocation granule size
*
* Returns: ---
* @GROWBUF_REPLACE@ discards the existing contents.
*/
-#define GROWBUF_EXTEND(a, buf, sz, want, init, granule) do { \
- size_t _sz0 = (sz), _sz = _sz0, _want = (want), _gr = (granule); \
+#define GROWBUF_EXTEND(szty, a, buf, sz, want, init, granule) do { \
+ szty _sz0 = (sz), _sz = _sz0, _want = (want); \
+ size_t _gr = (granule); \
void *_p = (buf); \
arena *_a = (a); \
\
if (_sz < _want) { \
- GROWBUF_SIZE(_sz, _want, init, _gr); \
+ GROWBUF_SIZE(szty, _sz, _want, init, _gr); \
if (!_p) _p = x_alloc(_a, _sz*_gr); \
else _p = x_realloc(_a, _p, _sz*_gr, _sz0*_gr); \
(buf) = _p; (sz) = _sz; \
} \
} while (0)
-#define GROWBUF_REPLACE(a, buf, sz, want, init, granule) do { \
- size_t _sz0 = (sz), _sz = _sz0, _want = (want), _gr = (granule); \
+#define GROWBUF_REPLACE(szty, a, buf, sz, want, init, granule) do { \
+ szty _sz0 = (sz), _sz = _sz0, _want = (want); \
+ size_t _gr = (granule); \
void *_p = (buf); \
arena *_a = (a); \
\
if (_sz < _want) { \
- GROWBUF_SIZE(_sz, want, init, _gr); \
+ GROWBUF_SIZE(szty, _sz, want, init, _gr); \
if (_p) x_free(_a, _p); \
_p = x_alloc(_a, _sz*_gr); \
(buf) = _p; (sz) = _sz; \
} \
} while (0)
+/* --- @GROWBUF_RENEWV@, @GROWBUF_REPLACEV@ --- *
+ *
+ * Arguments: @szty@ = an unsigned type
+ * @arena *a@ = pointer to an arena
+ * @type *buf@ = pointer to some buffer, possibly null (updated)
+ * @szty sz@ = current buffer size (updated)
+ * @szty want@ = desired minimum size
+ * @szty init@ = a suitable initial size
+ *
+ * Returns: ---
+ *
+ * Use: These are the same as @GROWBUF_EXTEND@ and @GROWBUF_REPLACE@,
+ * except that the @granule@ is implicitly taken as
+ * @sizeof(*buf)@.
+ *
+ * @GROWBUF_RENEWV@ preserves the contents of the buffer;
+ * @GROWBUF_REPLACEV@ discards the existing contents.
+ */
+
+#define GROWBUF_RENEWV(szty, a, buf, sz, want, init) \
+ GROWBUF_EXTEND(szty, a, buf, sz, want, init, sizeof(*buf))
+
+#define GROWBUF_REPLACEV(szty, a, buf, sz, want, init) \
+ GROWBUF_REPLACE(szty, a, buf, sz, want, init, sizeof(*buf))
+
/*----- That's all, folks -------------------------------------------------*/
#ifdef __cplusplus