forked from aligrudi/neatmkfn
-
Notifications
You must be signed in to change notification settings - Fork 0
/
sbuf.c
97 lines (83 loc) · 1.73 KB
/
sbuf.c
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
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
/* Variable Length String Buffer */
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "mkfn.h"
#define MAX(a, b) ((a) < (b) ? (b) : (a))
#define ALIGN(n, a) (((n) + (a) - 1) & ~((a) - 1))
#define NEXTSZ(o, r) ALIGN(MAX((o) * 2, (o) + (r)), SBUFSZ)
#define SBUFSZ 128
struct sbuf {
char *s; /* allocated buffer */
int s_n; /* length of the string stored in s[] */
int s_sz; /* size of memory allocated for s[] */
};
static void sbuf_extend(struct sbuf *sbuf, int newsz)
{
char *s = sbuf->s;
sbuf->s_sz = newsz;
sbuf->s = malloc(sbuf->s_sz);
if (sbuf->s_n)
memcpy(sbuf->s, s, sbuf->s_n);
free(s);
}
struct sbuf *sbuf_make(void)
{
struct sbuf *sb = malloc(sizeof(*sb));
memset(sb, 0, sizeof(*sb));
return sb;
}
char *sbuf_buf(struct sbuf *sb)
{
if (!sb->s)
sbuf_extend(sb, 1);
sb->s[sb->s_n] = '\0';
return sb->s;
}
char *sbuf_done(struct sbuf *sb)
{
char *s = sbuf_buf(sb);
free(sb);
return s;
}
void sbuf_free(struct sbuf *sb)
{
free(sb->s);
free(sb);
}
void sbuf_chr(struct sbuf *sbuf, int c)
{
if (sbuf->s_n + 2 >= sbuf->s_sz)
sbuf_extend(sbuf, NEXTSZ(sbuf->s_sz, 1));
sbuf->s[sbuf->s_n++] = c;
}
void sbuf_mem(struct sbuf *sbuf, char *s, int len)
{
if (sbuf->s_n + len + 1 >= sbuf->s_sz)
sbuf_extend(sbuf, NEXTSZ(sbuf->s_sz, len + 1));
memcpy(sbuf->s + sbuf->s_n, s, len);
sbuf->s_n += len;
}
void sbuf_str(struct sbuf *sbuf, char *s)
{
sbuf_mem(sbuf, s, strlen(s));
}
int sbuf_len(struct sbuf *sbuf)
{
return sbuf->s_n;
}
void sbuf_cut(struct sbuf *sb, int len)
{
if (sb->s_n > len)
sb->s_n = len;
}
void sbuf_printf(struct sbuf *sbuf, char *s, ...)
{
char buf[256];
va_list ap;
va_start(ap, s);
vsnprintf(buf, sizeof(buf), s, ap);
va_end(ap);
sbuf_str(sbuf, buf);
}