@@@ fltfmt mess
[mLib] / mem / growbuf.h
index ec78bcd..f829f91 100644 (file)
 
 /*----- 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