chiark / gitweb /
@@@ random mess
[mLib] / struct / buf.c
index 88934c9f23ce44ffaf2d25f04bc5d1298969dc81..10e05444b9b84051302b0ff719305063d6d69278 100644 (file)
@@ -146,7 +146,7 @@ int buf_tryextend(buf *b, size_t sz)
 
   db = (dbuf *)b; len = DBLEN(db); want = sz + len;
   if (db->sz < want) {
-    GROWBUF_EXTEND(db->a, db->_b.base, db->sz, want, 64, 1);
+    GROWBUF_EXTEND(size_t, db->a, db->_b.base, db->sz, want, 64, 1);
     db->_b.p = db->_b.base + len;
   }
   db->_b.limit = db->_b.base + db->sz;
@@ -200,6 +200,83 @@ int buf_put(buf *b, const void *p, size_t sz)
 int (dbuf_put)(dbuf *db, const void *p, size_t sz)
   { return (dbuf_put(db, p, sz)); }
 
+/* --- @{,d}buf_fill@ --- *
+ *
+ * Arguments:  @buf *b@ or @dbuf *db@ = pointer to a buffer block
+ *             @int ch@ = fill character
+ *             @size_t sz@ = size to fill
+ *
+ * Returns:    Zero if it worked, nonzero if there wasn't enough space.
+ *
+ * Use:                Write @sz@ bytes with value @ch@ to the buffer, as if with
+ *             @memset@.
+ */
+
+int buf_fill(buf *b, int ch, size_t sz)
+{
+  void *p;
+
+  p = buf_get(b, sz); if (!p) return (-1);
+  if (sz) memset(p, ch, sz);
+  return (0);
+}
+int (dbuf_fill)(dbuf *db, int ch, size_t sz)
+  { return (dbuf_fill(db, ch, sz)); }
+
+/* --- @align_step@ --- *
+ *
+ * Arguments:  @buf *b@ = pointer to a buffer block
+ *             @size_t m, a@ = alignment parameters
+ *
+ * Returns:    The number of bytes to skip or fill.
+ */
+
+static size_t align_step(buf *b, size_t m, size_t a)
+{
+  if (m < 2) return (0);
+  else if (!(m&(m - 1))) return ((a - BLEN(b))&(m - 1));
+  else return ((a + m - BLEN(b)%m)%m);
+}
+
+/* --- @{,d}buf_alignskip@ --- *
+ *
+ * Arguments:  @buf *b@ or @dbuf *db@ = pointer to a buffer block
+ *             @size_t m, a@ = alignment multiple and offset
+ *
+ * Returns:    Zero if it worked, nonzero if there wasn't enough space.
+ *
+ * Use:                Advance the buffer position as little as possible such that
+ *             it is @a@ greater than a multiple of @m@.  This doesn't write
+ *             anything to the buffer, so it's probably not suitable for
+ *             output: use @buf_alignfill@ instead.
+ */
+
+int buf_alignskip(buf *b, size_t m, size_t a)
+{
+  if (!buf_get(b, align_step(b, m, a))) return (-1);
+  else return (0);
+}
+int (dbuf_alignskip)(dbuf *db, size_t m, size_t a)
+  { return (dbuf_alignskip(db, m, a)); }
+
+/* --- @{,d}buf_alignfill@ --- *
+ *
+ * Arguments:  @buf *b@ or @dbuf *db@ = pointer to a buffer block
+ *             @int ch@ = fill character
+ *             @size_t m, a@ = alignment multiple and offset
+ *
+ * Returns:    Zero if it worked, nonzero if there wasn't enough space.
+ *
+ * Use:                Fill the buffer with as few copies of @ch@ as possible, as if
+ *             by @memset@, to advance the buffer position to a value @a@
+ *             greater than a multiple of @m@.
+ */
+
+int buf_alignfill(buf *b, int ch, size_t m, size_t a)
+  { return (buf_fill(b, ch, align_step(b, m, a))); }
+int (dbuf_alignfill)(dbuf *db, int ch, size_t m, size_t a)
+  { return (dbuf_alignfill(db, ch, m, a)); }
+
 /* --- @{,d}buf_getbyte@ --- *
  *
  * Arguments:  @buf *b@ or @dbuf *db@ = pointer to a buffer block