summaryrefslogtreecommitdiffstats
path: root/src/strbuf.c
blob: 7b4884554651f9ee08187e7efc8103af19f766df (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
#include "strbuf.h"

#include "util.h"

#include <stdio.h>
#include <stdarg.h>
#include <string.h>

void
strbuf_init(struct strbuf *strbuf)
{
	strbuf->buf = NULL;
	strbuf->cap = 0;
}

void
strbuf_deinit(struct strbuf *strbuf)
{
	free(strbuf->buf);
}

void
strbuf_clear(struct strbuf *strbuf)
{
	if (!strbuf->buf)
		strbuf_append(strbuf, "");

	strbuf->buf[0] = '\0';
}

void
strbuf_append(struct strbuf *strbuf, const char *fmt, ...)
{
	va_list ap, cpy;
	ssize_t slen;
	int blen;

	va_copy(cpy, ap);

	blen = strbuf->buf ? strlen(strbuf->buf) : 0;

	va_start(cpy, fmt);
	slen = vsnprintf(NULL, 0, fmt, cpy);
	if (slen < 0) ERROR(SYSTEM, "snprintf");
	va_end(cpy);

	if (blen + slen + 1 > strbuf->cap) {
		strbuf->cap = blen + slen + 1;
		strbuf->buf = realloc(strbuf->buf, strbuf->cap);
		if (!strbuf->buf) ERROR(SYSTEM, "realloc");
	}

	va_start(ap, fmt);
	vsnprintf(strbuf->buf + blen, slen + 1, fmt, ap);
	va_end(ap);
}