changeset 672:c49478852aaf

buf: now separate library
author David Demelier <markand@malikania.fr>
date Thu, 24 Mar 2022 07:29:36 +0100
parents 2bee2b6b6386
children a7c0227f64f5
files c/buf/Makefile c/buf/buf-test.c c/buf/buf.c.in c/buf/buf.h.in
diffstat 4 files changed, 0 insertions(+), 917 deletions(-) [+]
line wrap: on
line diff
--- a/c/buf/Makefile	Thu Mar 24 07:29:22 2022 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,46 +0,0 @@
-#
-# Makefile -- simple string buffer for C
-#
-# Copyright (c) 2016-2019 David Demelier <markand@malikania.fr>
-#
-# Permission to use, copy, modify, and/or distribute this software for any
-# purpose with or without fee is hereby granted, provided that the above
-# copyright notice and this permission notice appear in all copies.
-#
-# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
-# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
-# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-#
-
-.POSIX:
-
-CC=             cc
-SED=            sed
-CFLAGS=         -O3 -DNDEBUG
-NAMESPACE=
-
-NAMESPACE_L=    `echo ${NAMESPACE} | tr "[[:upper:]]" "[[:lower:]]"`
-NAMESPACE_U=    `echo ${NAMESPACE} | tr "[[:lower:]]" "[[:upper:]]"`
-
-INCS=           -I../../extern/libgreatest
-
-all: ${NAMESPACE}buf.h ${NAMESPACE}buf.c
-
-${NAMESPACE}buf.h ${NAMESPACE}buf.c: buf.h.in buf.c.in
-	sed "s/%ns%/${NAMESPACE_L}/g;s/%NS%/${NAMESPACE_U}/g" < buf.h.in > ${NAMESPACE}buf.h
-	sed "s/%ns%/${NAMESPACE_L}/g;s/%NS%/${NAMESPACE_U}/g" < buf.c.in > ${NAMESPACE}buf.c
-
-buf-test: buf.h buf.c buf-test.c
-	${CC} ${INCS} ${CFLAGS} buf.c buf-test.c -o $@ ${LDFLAGS}
-
-tests: buf-test
-	./buf-test
-
-clean:
-	rm -f buf.h buf.c buf-test
-
-.PHONY: all clean tests
--- a/c/buf/buf-test.c	Thu Mar 24 07:29:22 2022 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,302 +0,0 @@
-/*
- * test.c -- test basic buffers
- *
- * Copyright (c) 2016-2019 David Demelier <markand@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#define GREATEST_USE_ABBREVS 0
-#include <greatest.h>
-
-#include "buf.h"
-
-GREATEST_TEST
-init(void)
-{
-	struct buf b;
-
-	/* No allocation with buf_init. */
-	buf_init(&b);
-	GREATEST_ASSERT(!b.data);
-	GREATEST_ASSERT(!b.capacity);
-	GREATEST_ASSERT(!b.length);
-
-	/* Must stay zero'ed. */
-	buf_finish(&b);
-	GREATEST_ASSERT(!b.data);
-	GREATEST_ASSERT(!b.capacity);
-	GREATEST_ASSERT(!b.length);
-
-	GREATEST_PASS();
-}
-
-GREATEST_SUITE(basics)
-{
-	GREATEST_RUN_TEST(init);
-}
-
-GREATEST_TEST
-reserve(void)
-{
-	struct buf b;
-
-	/* Reserve allocates but does not change length. */
-	buf_init(&b);
-	buf_reserve(&b, 100U);
-	GREATEST_ASSERT(b.data);
-	GREATEST_ASSERT_EQ(b.length, 0U);
-	GREATEST_ASSERT_EQ(b.capacity, 100U);
-	buf_finish(&b);
-
-	GREATEST_PASS();
-}
-
-GREATEST_TEST
-resize(void)
-{
-	struct buf b;
-
-	/* Resize actually change the length with the specified character. */
-	buf_init(&b);
-	buf_resize(&b, 10, 'a');
-	GREATEST_ASSERT_STR_EQ(b.data, "aaaaaaaaaa");
-	GREATEST_ASSERT_EQ(b.length, 10U);
-	GREATEST_ASSERT_EQ(b.capacity, 10U);
-	buf_finish(&b);
-
-	GREATEST_PASS();
-}
-
-GREATEST_TEST
-shrink(void)
-{
-	struct buf b;
-
-	/* Reserve and then shrink, it should be 0. */
-	buf_init(&b);
-	buf_reserve(&b, 10U);
-	buf_shrink(&b);
-	GREATEST_ASSERT(b.data);
-	GREATEST_ASSERT_EQ(b.length, 0U);
-	GREATEST_ASSERT_EQ(b.capacity, 0U);
-	buf_finish(&b);
-
-	GREATEST_PASS();
-}
-
-GREATEST_SUITE(allocs)
-{
-	GREATEST_RUN_TEST(reserve);
-	GREATEST_RUN_TEST(resize);
-}
-
-GREATEST_TEST
-output_char(void)
-{
-	struct buf b;
-
-	buf_init(&b);
-
-	/* This will allocate one byte and then increase by power of two. */
-	buf_putc(&b, 'a');
-	GREATEST_ASSERT_STR_EQ(b.data, "a");
-	GREATEST_ASSERT_EQ(b.length, 1U);
-	GREATEST_ASSERT_EQ(b.capacity, 1U);
-
-	buf_putc(&b, 'b');
-	GREATEST_ASSERT_STR_EQ(b.data, "ab");
-	GREATEST_ASSERT_EQ(b.length, 2U);
-	GREATEST_ASSERT_EQ(b.capacity, 2U);
-
-	buf_putc(&b, 'c');
-	GREATEST_ASSERT_STR_EQ(b.data, "abc");
-	GREATEST_ASSERT_EQ(b.length, 3U);
-	GREATEST_ASSERT_EQ(b.capacity, 4U);
-
-	/* No reallocation since there is still one byte left. */
-	buf_putc(&b, 'd');
-	GREATEST_ASSERT_STR_EQ(b.data, "abcd");
-	GREATEST_ASSERT_EQ(b.length, 4U);
-	GREATEST_ASSERT_EQ(b.capacity, 4U);
-
-	/* New reallocation here. */
-	buf_putc(&b, 'e');
-	GREATEST_ASSERT_STR_EQ(b.data, "abcde");
-	GREATEST_ASSERT_EQ(b.length, 5U);
-	GREATEST_ASSERT_EQ(b.capacity, 8U);
-	buf_finish(&b);
-
-	GREATEST_PASS();
-}
-
-GREATEST_TEST
-output_string(void)
-{
-	struct buf b;
-
-	buf_init(&b);
-
-	/* This will allocate an initial buffer of 10. */
-	buf_puts(&b, "abcdefghij");
-	GREATEST_ASSERT_STR_EQ(b.data, "abcdefghij");
-	GREATEST_ASSERT_EQ(b.length, 10U);
-	GREATEST_ASSERT_EQ(b.capacity, 10U);
-
-	/* This will multiply the capacity to 20 and increase length to 14. */
-	buf_puts(&b, "klmn");
-	GREATEST_ASSERT_STR_EQ(b.data, "abcdefghijklmn");
-	GREATEST_ASSERT_EQ(b.length, 14U);
-	GREATEST_ASSERT_EQ(b.capacity, 20U);
-	buf_finish(&b);
-
-	GREATEST_PASS();
-}
-
-GREATEST_TEST
-output_printf(void)
-{
-	struct buf b;
-
-	buf_init(&b);
-
-	/* This will allocate string of 6 characters. */
-	buf_printf(&b, "%d%d", 123, 456);
-	GREATEST_ASSERT_STR_EQ(b.data, "123456");
-	GREATEST_ASSERT_EQ(b.length, 6U);
-	GREATEST_ASSERT_EQ(b.capacity, 6U);
-
-	/* This will multiply the capacity to 12 and increase length to 10. */
-	buf_printf(&b, "%s", "hoho");
-	GREATEST_ASSERT_STR_EQ(b.data, "123456hoho");
-	GREATEST_ASSERT_EQ(b.length, 10U);
-	GREATEST_ASSERT_EQ(b.capacity, 12U);
-	buf_finish(&b);
-
-	GREATEST_PASS();
-}
-
-GREATEST_SUITE(output)
-{
-	GREATEST_RUN_TEST(output_char);
-	GREATEST_RUN_TEST(output_string);
-	GREATEST_RUN_TEST(output_printf);
-}
-
-GREATEST_TEST
-clones_sub(void)
-{
-	struct buf b = { 0 };
-	struct buf s1, s2;
-
-	buf_puts(&b, "0123456789");
-
-	/* Copy only the portion from 1 to 3. */
-	buf_sub(&s1, &b, 1, 3);
-	GREATEST_ASSERT_STR_EQ(s1.data, "123");
-	GREATEST_ASSERT_EQ(s1.length, 3U);
-	GREATEST_ASSERT_EQ(s1.capacity, 3U);
-	buf_finish(&s1);
-
-	/* Copy whole string starting from 4. */
-	buf_sub(&s2, &b, 4, -1);
-	GREATEST_ASSERT_STR_EQ(s2.data, "456789");
-	GREATEST_ASSERT_EQ(s2.length, 6U);
-	GREATEST_ASSERT_EQ(s2.capacity, 6U);
-	buf_finish(&s2);
-	buf_finish(&b);
-
-	GREATEST_PASS();
-}
-
-GREATEST_TEST
-clones_dup(void)
-{
-	struct buf b = { 0 };
-	struct buf d;
-
-	buf_puts(&b, "0123456789");
-	buf_dup(&d, &b);
-	GREATEST_ASSERT(b.data != d.data);
-	GREATEST_ASSERT_STR_EQ(d.data, "0123456789");
-	GREATEST_ASSERT_EQ(d.length, 10U);
-	GREATEST_ASSERT_EQ(d.capacity, 10U);
-	buf_finish(&d);
-
-	GREATEST_PASS();
-}
-
-GREATEST_SUITE(clones)
-{
-	GREATEST_RUN_TEST(clones_sub);
-	GREATEST_RUN_TEST(clones_dup);
-}
-
-GREATEST_TEST
-misc_erase(void)
-{
-	struct buf b = { 0 };
-
-	buf_puts(&b, "0123456789");
-
-	/* Only remove portion from 1 to 3, capacity must not change. */
-	buf_erase(&b, 1, 3);
-	GREATEST_ASSERT_STR_EQ(b.data, "0456789");
-	GREATEST_ASSERT_EQ(b.length, 7U);
-	GREATEST_ASSERT_EQ(b.capacity, 10U);
-
-	/* Remove from 4 to the end. */
-	buf_erase(&b, 1, -1);
-	GREATEST_ASSERT_STR_EQ(b.data, "0");
-	GREATEST_ASSERT_EQ(b.length, 1U);
-	GREATEST_ASSERT_EQ(b.capacity, 10U);
-	buf_finish(&b);
-
-	GREATEST_PASS();
-}
-
-GREATEST_TEST
-misc_clear(void)
-{
-	struct buf b = { 0 };
-
-	/* Clear should only reduce the length capacity must not change. */
-	buf_puts(&b, "hello world");
-	buf_clear(&b);
-	GREATEST_ASSERT_STR_EQ(b.data, "");
-	GREATEST_ASSERT_EQ(b.length, 0U);
-	GREATEST_ASSERT_EQ(b.capacity, 11U);
-	buf_finish(&b);
-
-	GREATEST_PASS();
-}
-
-GREATEST_SUITE(misc)
-{
-	GREATEST_RUN_TEST(misc_erase);
-	GREATEST_RUN_TEST(misc_clear);
-}
-
-GREATEST_MAIN_DEFS();
-
-int
-main(int argc, char **argv)
-{
-	GREATEST_MAIN_BEGIN();
-	GREATEST_RUN_SUITE(basics);
-	GREATEST_RUN_SUITE(allocs);
-	GREATEST_RUN_SUITE(output);
-	GREATEST_RUN_SUITE(clones);
-	GREATEST_RUN_SUITE(misc);
-	GREATEST_MAIN_END();
-}
--- a/c/buf/buf.c.in	Thu Mar 24 07:29:22 2022 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,331 +0,0 @@
-/*
- * %ns%buf.c -- simple string buffer for C
- *
- * Copyright (c) 2016-2019 David Demelier <markand@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <assert.h>
-#include <errno.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "%ns%buf.h"
-
-/*
- * User/developer options.
- *
- * - %NS%BUF_MALLOC: defaults to malloc
- * - %NS%BUF_REALLOC: defaults to realloc
- * - %NS%BUF_FREE: defaults to free
- */
-
-#if !defined(%NS%BUF_MALLOC)
-#	define %NS%BUF_MALLOC malloc
-#endif
-
-#if !defined(%NS%BUF_REALLOC)
-#	define %NS%BUF_REALLOC realloc
-#endif
-
-#if !defined(%NS%BUF_FREE)
-#	define %NS%BUF_FREE free
-#endif
-
-/*
- * Try to increase the buffer length by a power of two until we have enough
- * space to fit `desired'.
- *
- * Detects overflow and return false if happened or reallocation could not
- * occur.
- */
-static bool
-growdbl(struct %ns%buf *b, size_t desired)
-{
-	size_t newcap = b->capacity;
-	void *newptr;
-
-	while (desired > newcap - b->length) {
-		const size_t r = newcap * 2;
-
-		if (r / newcap != 2) {
-			errno = EOVERFLOW;
-			return false;
-		}
-
-		newcap = r;
-	}
-
-	/* At this step we must have enough room. */
-	assert(newcap - b->length >= desired);
-
-	if (!(newptr = %NS%BUF_REALLOC(b->data, newcap + 1)))
-		return false;
-
-	b->data = newptr;
-	b->capacity = newcap;
-
-	return true;
-}
-
-/*
- * Try to allocate just enough space for the `desired' amount of space. This is
- * only used when the buffer is already too large but hasn't reached SIZE_MAX
- * yet.
- *
- * Returns false if allocation failed.
- */
-static bool
-growmin(struct %ns%buf *b, size_t desired)
-{
-	size_t newcap;
-	void *newptr;
-
-	if (desired >= SIZE_MAX - b->length) {
-		errno = ENOMEM;
-		return false;
-	}
-
-	/* Don't forget to keep what's remaining between capacity and length. */
-	newcap = b->capacity + (desired - (b->capacity - b->length));
-
-	/* Try to reallocate. */
-	if (!(newptr = %NS%BUF_REALLOC(b->data, newcap + 1)))
-		return false;
-
-	b->data = newptr;
-	b->capacity = newcap;
-
-	return true;
-}
-
-static bool
-grow(struct %ns%buf *b, size_t desired)
-{
-	const size_t avail = b->capacity - b->length;
-
-	if (avail >= desired)
-		return true;
-
-	if (!b->capacity) {
-		if (!(b->data = %NS%BUF_MALLOC(desired + 1)))
-			return false;
-
-		b->capacity = desired;
-	} else if (!growdbl(b, desired) && !growmin(b, desired))
-		return false;
-
-	return true;
-}
-
-void
-%ns%buf_init(struct %ns%buf *b)
-{
-	assert(b);
-
-	memset(b, 0, sizeof (struct %ns%buf));
-}
-
-bool
-%ns%buf_reserve(struct %ns%buf *b, size_t amount)
-{
-	if (!grow(b, amount))
-		return false;
-
-	return true;
-}
-
-bool
-%ns%buf_resize(struct %ns%buf *b, size_t amount, char ch)
-{
-	if (!grow(b, amount))
-		return false;
-
-	memset(&b->data[b->length], ch, amount);
-	b->length += amount;
-	b->data[b->length] = 0;
-
-	return true;
-}
-
-bool
-%ns%buf_shrink(struct %ns%buf *b)
-{
-	void *newptr = %NS%BUF_REALLOC(b->data, b->length + 1);
-
-	if (!newptr)
-		return false;
-
-	b->data = newptr;
-	b->capacity = b->length;
-
-	return true;
-}
-
-void
-%ns%buf_erase(struct %ns%buf *b, size_t pos, size_t count)
-{
-	assert(b);
-	assert(pos <= b->length);
-
-	if (count > b->length - pos) {
-		/* Optimize whole erase at pos. */
-		b->data[pos] = 0;
-		b->length = pos;
-	} else {
-		memmove(&b->data[pos], &b->data[pos + count], b->length - count);
-		b->length -= count;
-	}
-}
-
-bool
-%ns%buf_putc(struct %ns%buf *b, char c)
-{
-	assert(b);
-
-	if (!grow(b, 1))
-		return false;
-
-	b->data[b->length++] = c;
-	b->data[b->length] = 0;
-
-	return true;
-}
-
-bool
-%ns%buf_puts(struct %ns%buf *b, const char *s)
-{
-	assert(b);
-	assert(s);
-
-	const size_t len = strlen(s);
-
-	if (!grow(b, len))
-		return false;
-
-	strcpy(&b->data[b->length], s);
-	b->length += len;
-
-	return true;
-}
-
-bool
-%ns%buf_printf(struct %ns%buf *b, const char *fmt, ...)
-{
-	assert(b);
-	assert(fmt);
-
-	va_list ap;
-	bool ret;
-
-	va_start(ap, fmt);
-	ret = %ns%buf_vprintf(b, fmt, ap);
-	va_end(ap);
-
-	return ret;
-}
-
-bool
-%ns%buf_vprintf(struct %ns%buf *b, const char *fmt, va_list args)
-{
-	assert(b);
-	assert(fmt);
-
-	va_list ap;
-	int amount;
-
-	/* Determine length. */
-	va_copy(ap, args);
-	amount = vsnprintf(NULL, 0, fmt, ap);
-	va_end(ap);
-
-	if (amount < 0)
-		return false;
-
-	/* Do actual copy. */
-	if (!grow(b, amount))
-		return false;
-
-	va_copy(ap, args);
-	amount = vsprintf(&b->data[b->length], fmt, ap);
-	va_end(ap);
-
-	if (amount < 0)
-		return false;
-
-	b->length += amount;
-
-	return true;
-}
-
-bool
-%ns%buf_sub(struct %ns%buf *b, const struct %ns%buf *src, size_t pos, size_t count)
-{
-	assert(b);
-	assert(src);
-	assert(pos <= src->length);
-
-	memset(b, 0, sizeof (struct %ns%buf));
-
-	if (count >= src->length)
-		count = src->length - pos;
-	if (!(b->data = %NS%BUF_MALLOC(count + 1)))
-		return false;
-
-	strncpy(b->data, &src->data[pos], count);
-	b->length = count;
-	b->capacity = count;
-	b->data[b->length] = 0;
-
-	return true;
-}
-
-bool
-%ns%buf_dup(struct %ns%buf *b, const struct %ns%buf *src)
-{
-	assert(b);
-	assert(src);
-
-	memset(b, 0, sizeof (struct %ns%buf));
-
-	if (!(b->data = %NS%BUF_MALLOC(src->length + 1)))
-		return false;
-
-	strcpy(b->data, src->data);
-	b->capacity = src->length;
-	b->length = src->length;
-
-	return true;
-}
-
-void
-%ns%buf_clear(struct %ns%buf *b)
-{
-	assert(b);
-
-	if (b->data)
-		b->data[b->length = 0] = 0;
-}
-
-void
-%ns%buf_finish(struct %ns%buf *b)
-{
-	assert(b);
-
-	%NS%BUF_FREE(b->data);
-	b->data = NULL;
-	b->capacity = b->length = 0;
-}
--- a/c/buf/buf.h.in	Thu Mar 24 07:29:22 2022 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,238 +0,0 @@
-/*
- * %ns%buf.h -- simple string buffer for C
- *
- * Copyright (c) 2016-2019 David Demelier <markand@malikania.fr>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef %NS%BUF_H
-#define %NS%BUF_H
-
-/**
- * \file %ns%buf.h
- * \brief Simple string buffer for C
- *
- * This module is meant to be copied directly into your source code and adapted
- * to your needs.
- *
- * # Allocation strategy
- *
- * This module will always try to allocate twice the existing buffer capacity
- * unless it reaches an overflow. If overflow occurs, it will try to reallocate
- * only the required portion instead. In any case, on 64-bits machine the
- * maximum number is usually around 18.5PB which is far from what the system
- * will allow.
- *
- * Functions use standard `malloc(3)`, `realloc(3)` and `free(3)` functions, if
- * custom allocations are desired, simply edit %ns%buf.c and adapt BUF_ macros
- * at the top of the file.
- */
-
-#include <stdarg.h>
-#include <stdbool.h>
-#include <stddef.h>
-
-/**
- * \brief Buffer structure.
- *
- * You can initialize this structure with 0 before use.
- *
- * You may modify the data member yourself but make sure length member is set
- * accordingly if you change its length.
- *
- * The capacity member contains the available size **without** including the
- * null terminator, this means that a capacity of 5 means you can write 5
- * characters plus the null terminator as every function always allocate one
- * more byte to terminate strings.
- */
-struct %ns%buf {
-	char *data;             /*!< (RW) String data. */
-	size_t length;          /*!< (RO) String length */
-	size_t capacity;        /*!< (RO) Capacity **not** including null */
-};
-
-/**
- * Initialize the string.
- *
- * This is equivalent to `memset(b, 0, sizeof (struct buf))`.
- *
- * \pre b != NULL
- * \param b the buffer to initialize to 0
- */
-void
-%ns%buf_init(struct %ns%buf *b);
-
-/**
- * Reserve more storage to avoid reallocations.
- *
- * This function only change capacity and may reallocate the buffer, length
- * is unchanged.
- *
- * \pre b != NULL
- * \param b the buffer to grow
- * \param desired the additional space to request
- * \return false on error and sets errno
- */
-bool
-%ns%buf_reserve(struct %ns%buf *b, size_t desired);
-
-/**
- * Resize the string and sets character into the new storage area.
- *
- * In contrast to \ref %ns%buf_reserve, this function change the string length
- * and update the new storage with the given character. Use '\0' if you only
- * want to change the length.
- *
- * \pre b != NULL
- * \param b the buffer to grow
- * \param desired the additional space to request
- * \param ch the character to fill (use '\0' if not needed)
- * \return false on error and sets errno
- */
-bool
-%ns%buf_resize(struct %ns%buf *b, size_t desired, char ch);
-
-/**
- * Reallocate the string to the string's length.
- *
- * If the function could not reallocate the memory, the old string buffer is
- * kept so it is not strictly necessary to check the result.
- *
- * \pre b != NULL
- * \param b the buffer to grow
- * \return true if the string buffer was actually shrinked
- */
-bool
-%ns%buf_shrink(struct %ns%buf *b);
-
-/**
- * Erase a portion of the string.
- *
- * \pre b != NULL
- * \pre pos <= b->length
- * \param b the string buffer
- * \param pos the beginning of the portion
- * \param count the number of characters to remove or -1 to remove up to the end
- */
-void
-%ns%buf_erase(struct %ns%buf *b, size_t pos, size_t count);
-
-/**
- * Put a single character.
- *
- * \note This function can be slow for large amount of data
- * \pre b != NULL
- * \param b the string buffer
- * \param c the character to append
- * \return false on error and sets errno
- */
-bool
-%ns%buf_putc(struct %ns%buf *b, char c);
-
-/**
- * Put a string.
- *
- * \pre b != NULL
- * \pre s != NULL
- * \param b the string buffer
- * \param s the string to append
- * \return false on error and sets errno
- */
-bool
-%ns%buf_puts(struct %ns%buf *b, const char *s);
-
-/**
- * Append to the string using printf(3) format.
- *
- * \pre b != NULL
- * \pre fmt != NULL
- * \param b the string buffer
- * \param fmt the printf(3) format string
- * \param ... additional arguments
- * \return false on error and sets errno
- */
-bool
-%ns%buf_printf(struct %ns%buf *b, const char *fmt, ...);
-
-/**
- * Similar to \ref %ns%buf_printf but using `va_list`.
- *
- * \pre b != NULL
- * \pre fmt != NULL
- * \param b the string buffer
- * \param fmt the printf(3) format string
- * \param ap the variadic arguments pointer
- * \return false on error and sets errno
- */
-bool
-%ns%buf_vprintf(struct %ns%buf *b, const char *fmt, va_list ap);
-
-/**
- * Cut a portion of the string pointed by src into b.
- *
- * The pointer b must not contain data as it will be overriden and may be let
- * uninitialized.
- *
- * \pre b != NULL
- * \pre src != NULL
- * \pre pos <= b->length
- * \param b the string buffer
- * \param src the source origin
- * \param pos the beginning of the portion
- * \param count the number of characters to remove or -1 to split up to the end
- * \return false on error and sets errno
- */
-bool
-%ns%buf_sub(struct %ns%buf *b, const struct %ns%buf *src, size_t pos, size_t count);
-
-/**
- * Duplicate a string buffer.
- *
- * The pointer b must not contain data as it will be overriden and may be let
- * uninitialized.
- *
- * \pre b != NULL
- * \pre src != NULL
- * \param b the string buffer
- * \param src the source origin
- * \return false on error and sets errno
- */
-bool
-%ns%buf_dup(struct %ns%buf *b, const struct %ns%buf *src);
-
-/**
- * Clear the buffer.
- *
- * This function only change the string length, use \ref %ns%buf_shrink if you
- * want to reduce memory usage.
- *
- * \pre b != NULL
- * \param b the string to update
- */
-void
-%ns%buf_clear(struct %ns%buf *b);
-
-/**
- * Clear the buffer.
- *
- * This function will effectively free the data member and set all members to
- * 0.
- *
- * \pre b != NULL
- * \param b the buffer to clear
- */
-void
-%ns%buf_finish(struct %ns%buf *b);
-
-#endif /* !%NS%BUF_H */