X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~mdw/git/mLib/blobdiff_plain/b1a20beee623c83315c3ce21abc7bcce103c6efb..3fec494b9a24b7835b3efb33e61b01146fc08201:/struct/buf.c diff --git a/struct/buf.c b/struct/buf.c index 67cc30e..10e0544 100644 --- a/struct/buf.c +++ b/struct/buf.c @@ -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